This commit is contained in:
Yuri Kuznetsov
2020-09-21 17:41:12 +03:00
20 changed files with 475 additions and 299 deletions
+63 -48
View File
@@ -31,10 +31,12 @@ namespace Espo\Core\Acl;
use Espo\Core\{
Utils\Metadata,
Utils\File\Manager as FileManager,
Utils\DataCache,
Utils\FieldUtil,
};
use StdClass;
/**
* Lists of restricted fields can be obtained from here. Restricted fields are specified in metadata > entityAcl.
*/
@@ -56,32 +58,32 @@ class GlobalRestricton
'nonAdminReadOnly' // read-only for non-admin users
];
protected $cacheFilePath = 'data/cache/application/entityAcl.php';
private $metadata;
private $fileManager;
private $fieldUtil;
private $data;
protected $cacheKey = 'entityAcl';
private $metadata;
private $dataCache;
private $fieldUtil;
public function __construct(
Metadata $metadata, FileManager $fileManager, FieldUtil $fieldUtil, bool $useCache = true
Metadata $metadata, DataCache $dataCache, FieldUtil $fieldUtil, bool $useCache = true
) {
$this->metadata = $metadata;
$this->fileManager = $fileManager;
$this->dataCache = $dataCache;
$this->fieldUtil = $fieldUtil;
$isFromCache = false;
if ($useCache) {
if (file_exists($this->cacheFilePath)) {
$this->data = include($this->cacheFilePath);
if ($this->dataCache->has($this->cacheKey)) {
$this->data = $this->dataCache->get($this->cacheKey);
$isFromCache = true;
if (!($this->data instanceof \StdClass)) {
if (! $this->data instanceof StdClass) {
$GLOBALS['log']->error("ACL GlobalRestricton: Bad data fetched from cache.");
$this->data = null;
}
}
@@ -100,25 +102,25 @@ class GlobalRestricton
protected function storeCacheFile()
{
$this->getFileManager()->putPhpContents($this->cacheFilePath, $this->data, true);
$this->dataCache->store($this->cacheKey, $this->data, true);
}
protected function buildData()
{
$scopeList = array_keys($this->getMetadata()->get(['entityDefs'], []));
$scopeList = array_keys($this->metadata->get(['entityDefs'], []));
$data = (object) [];
foreach ($scopeList as $scope) {
$fieldList = array_keys($this->getMetadata()->get(['entityDefs', $scope, 'fields'], []));
$linkList = array_keys($this->getMetadata()->get(['entityDefs', $scope, 'links'], []));
$fieldList = array_keys($this->metadata->get(['entityDefs', $scope, 'fields'], []));
$linkList = array_keys($this->metadata->get(['entityDefs', $scope, 'links'], []));
$isNotEmpty = false;
$scopeData = (object) [
'fields' => (object) [],
'attributes' => (object) [],
'links' => (object) []
'links' => (object) [],
];
foreach ($this->fieldTypeList as $type) {
@@ -126,10 +128,13 @@ class GlobalRestricton
$resultAttributeList = [];
foreach ($fieldList as $field) {
if ($this->getMetadata()->get(['entityAcl', $scope, 'fields', $field, $type])) {
if ($this->metadata->get(['entityAcl', $scope, 'fields', $field, $type])) {
$isNotEmpty = true;
$resultFieldList[] = $field;
$fieldAttributeList = $this->getFieldUtil()->getAttributeList($scope, $field);
$fieldAttributeList = $this->fieldUtil->getAttributeList($scope, $field);
foreach ($fieldAttributeList as $attribute) {
$resultAttributeList[] = $attribute;
}
@@ -141,9 +146,11 @@ class GlobalRestricton
}
foreach ($this->linkTypeList as $type) {
$resultLinkList = [];
foreach ($linkList as $link) {
if ($this->getMetadata()->get(['entityAcl', $scope, 'links', $link, $type])) {
if ($this->metadata->get(['entityAcl', $scope, 'links', $link, $type])) {
$isNotEmpty = true;
$resultLinkList[] = $link;
}
}
@@ -158,44 +165,52 @@ class GlobalRestricton
$this->data = $data;
}
protected function getMetadata()
public function getScopeRestrictedFieldList(string $scope, string $type) : array
{
return $this->metadata;
}
if (!property_exists($this->data, $scope)) {
return [];
}
if (!property_exists($this->data->$scope, 'fields')) {
return [];
}
protected function getFileManager()
{
return $this->fileManager;
}
protected function getFieldUtil()
{
return $this->fieldUtil;
}
public function getScopeRestrictedFieldList($scope, $type)
{
if (!property_exists($this->data, $scope)) return [];
if (!property_exists($this->data->$scope, 'fields')) return [];
if (!property_exists($this->data->$scope->fields, $type)) return [];
if (!property_exists($this->data->$scope->fields, $type)) {
return [];
}
return $this->data->$scope->fields->$type;
}
public function getScopeRestrictedAttributeList($scope, $type)
public function getScopeRestrictedAttributeList(string $scope, string $type) : array
{
if (!property_exists($this->data, $scope)) return [];
if (!property_exists($this->data->$scope, 'attributes')) return [];
if (!property_exists($this->data->$scope->attributes, $type)) return [];
if (!property_exists($this->data, $scope)) {
return [];
}
if (!property_exists($this->data->$scope, 'attributes')) {
return [];
}
if (!property_exists($this->data->$scope->attributes, $type)) {
return [];
}
return $this->data->$scope->attributes->$type;
}
public function getScopeRestrictedLinkList($scope, $type)
public function getScopeRestrictedLinkList(string $scope, string $type) : array
{
if (!property_exists($this->data, $scope)) return [];
if (!property_exists($this->data->$scope, 'links')) return [];
if (!property_exists($this->data->$scope->links, $type)) return [];
if (!property_exists($this->data, $scope)) {
return [];
}
if (!property_exists($this->data->$scope, 'links')) {
return [];
}
if (!property_exists($this->data->$scope->links, $type)) {
return [];
}
return $this->data->$scope->links->$type;
}
+157 -51
View File
@@ -39,7 +39,7 @@ use Espo\Core\{
Utils\Config,
Utils\Metadata,
Utils\FieldUtil,
Utils\File\Manager as FileManager,
Utils\DataCache,
};
use StdClass;
@@ -57,7 +57,7 @@ class Table
private $data = null;
protected $cacheFilePath;
protected $cacheKey;
protected $actionList = ['read', 'stream', 'edit', 'delete', 'create'];
@@ -84,17 +84,17 @@ class Table
protected $entityManager;
protected $user;
protected $config;
protected $fileManager;
protected $metadata;
protected $fieldUtil;
protected $dataCache;
public function __construct(
EntityManager $entityManager,
User $user,
Config $config = null,
FileManager $fileManager = null,
Metadata $metadata = null,
FieldUtil $fieldUtil = null
FieldUtil $fieldUtil = null,
DataCache $dataCache
) {
$this->entityManager = $entityManager;
@@ -111,39 +111,34 @@ class Table
}
$this->user = $user;
$this->metadata = $metadata;
if ($fieldUtil) {
$this->fieldUtil = $fieldUtil;
}
$this->fieldUtil = $fieldUtil;
$this->dataCache = $dataCache;
if (!$this->user->isFetched()) {
throw new Error('User must be fetched before ACL check.');
}
if ($fileManager) {
$this->fileManager = $fileManager;
}
$this->valuePermissionList = $this->metadata->get(['app', $this->type, 'valuePermissionList'], []);
$this->valuePermissionHighestLevels = $this->metadata->get(['app', $this->type, 'valuePermissionHighestLevels'], array());
$this->valuePermissionHighestLevels = $this->metadata->get(['app', $this->type, 'valuePermissionHighestLevels'], []);
$this->initCacheFilePath();
$this->initCacheKey();
if ($config && $config->get('useCache') && file_exists($this->cacheFilePath)) {
$cached = include $this->cacheFilePath;
$this->data = $cached;
} else {
if ($config && $config->get('useCache') && $this->dataCache->has($this->cacheKey)) {
$this->data = $this->dataCache->get($this->cacheKey);
}
else {
$this->load();
if ($config && $fileManager && $config->get('useCache')) {
if ($config && $config->get('useCache')) {
$this->buildCache();
}
}
}
protected function initCacheFilePath()
protected function initCacheKey()
{
$this->cacheFilePath = 'data/cache/application/acl/' . $this->getUser()->id . '.php';
$this->cacheKey = 'acl/' . $this->getUser()->id;
}
protected function getUser()
@@ -170,12 +165,16 @@ class Table
{
if (isset($this->data->table->$scope)) {
$data = $this->data->table->$scope;
if (is_string($data)) {
$data = $this->getScopeData($data);
return $data;
}
return $data;
}
return null;
}
@@ -188,6 +187,7 @@ class Table
if (isset($this->data->$permission)) {
return $this->data->$permission;
}
return 'no';
}
@@ -198,6 +198,7 @@ class Table
return $this->data->table->$scope->$action;
}
}
return 'no';
}
@@ -205,15 +206,17 @@ class Table
{
if (in_array($action, $this->booleanActionList)) {
return 'yes';
} else {
$level = $this->metadata->get(['scopes', $scope, $this->type . 'HighestLevel']);
return $level ?? 'all';
}
$level = $this->metadata->get(['scopes', $scope, $this->type . 'HighestLevel']);
return $level ?? 'all';
}
private function load()
{
$valuePermissionLists = (object)[];
$valuePermissionLists = (object) [];
foreach ($this->valuePermissionList as $permission) {
$valuePermissionLists->$permission = [];
}
@@ -227,6 +230,7 @@ class Table
foreach ($roleList as $role) {
$aclTableList[] = $role->get('data');
$fieldTableList[] = $role->get('fieldData');
foreach ($this->valuePermissionList as $permission) {
$valuePermissionLists->{$permission}[] = $role->get($permission);
}
@@ -239,16 +243,20 @@ class Table
$this->applyDisabled($aclTable, $fieldTable);
$this->applyMandatory($aclTable, $fieldTable);
$this->applyAdditional($aclTable, $fieldTable, $valuePermissionLists);
} else {
}
else {
$aclTable = (object) [];
foreach ($this->getScopeList() as $scope) {
if ($this->metadata->get("scopes.{$scope}.{$this->type}") === 'boolean') {
$aclTable->$scope = true;
} else {
if ($this->metadata->get("scopes.{$scope}.entity")) {
$aclTable->$scope = (object) [];
foreach ($this->actionList as $action) {
$aclTable->$scope->$action = 'all';
if (in_array($action, $this->booleanActionList)) {
$aclTable->$scope->$action = 'yes';
}
@@ -274,14 +282,17 @@ class Table
if (!$this->getUser()->isAdmin()) {
$permissionsDefaultsGroupName = 'permissionsDefaults';
if ($this->isStrictMode) {
$permissionsDefaultsGroupName = 'permissionsStrictDefaults';
}
foreach ($this->valuePermissionList as $permission) {
$this->data->$permission = $this->mergeValueList(
$valuePermissionLists->$permission,
$this->metadata->get(['app', $this->type, $permissionsDefaultsGroupName, $permission, 'yes'])
);
if ($this->metadata->get('app.'.$this->type.'.mandatory.' . $permission)) {
$this->data->$permission = $this->metadata->get('app.'.$this->type.'.mandatory.' . $permission);
}
@@ -291,8 +302,10 @@ class Table
foreach ($this->valuePermissionList as $permission) {
if (isset($this->valuePermissionHighestLevels[$permission])) {
$this->data->$permission = $this->valuePermissionHighestLevels[$permission];
continue;
}
$this->data->$permission = 'all';
}
}
@@ -341,6 +354,7 @@ class Table
public function getScopeForbiddenAttributeList(string $scope, string $action = 'read', string $thresholdLevel = 'no') : array
{
$key = $scope . '_'. $action . '_' . $thresholdLevel;
if (isset($this->forbiddenAttributesCache[$key])) {
return $this->forbiddenAttributesCache[$key];
}
@@ -352,10 +366,12 @@ class Table
!isset($fieldTableQuickAccess->$scope->attributes->$action)
) {
$this->forbiddenAttributesCache[$key] = [];
return [];
}
$levelList = [];
foreach ($this->fieldLevelList as $level) {
if (array_search($level, $this->fieldLevelList) >= array_search($thresholdLevel, $this->fieldLevelList)) {
$levelList[] = $level;
@@ -365,9 +381,15 @@ class Table
$attributeList = [];
foreach ($levelList as $level) {
if (!isset($fieldTableQuickAccess->$scope->attributes->$action->$level)) continue;
if (!isset($fieldTableQuickAccess->$scope->attributes->$action->$level)) {
continue;
}
foreach ($fieldTableQuickAccess->$scope->attributes->$action->$level as $attribute) {
if (in_array($attribute, $attributeList)) continue;
if (in_array($attribute, $attributeList)) {
continue;
}
$attributeList[] = $attribute;
}
}
@@ -391,10 +413,12 @@ class Table
!isset($fieldTableQuickAccess->$scope->fields->$action)
) {
$this->forbiddenFieldsCache[$key] = [];
return [];
}
$levelList = [];
foreach ($this->fieldLevelList as $level) {
if (array_search($level, $this->fieldLevelList) >= array_search($thresholdLevel, $this->fieldLevelList)) {
$levelList[] = $level;
@@ -404,9 +428,15 @@ class Table
$fieldList = [];
foreach ($levelList as $level) {
if (!isset($fieldTableQuickAccess->$scope->fields->$action->$level)) continue;
if (!isset($fieldTableQuickAccess->$scope->fields->$action->$level)) {
continue;
}
foreach ($fieldTableQuickAccess->$scope->fields->$action->$level as $field) {
if (in_array($field, $fieldList)) continue;
if (in_array($field, $fieldList)) {
continue;
}
$fieldList[] = $field;
}
}
@@ -431,6 +461,7 @@ class Table
foreach ($this->fieldActionList as $action) {
$fieldTableQuickAccess->$scope->attributes->$action = (object) [];
$fieldTableQuickAccess->$scope->fields->$action = (object) [];
foreach ($this->fieldLevelList as $level) {
$fieldTableQuickAccess->$scope->attributes->$action->$level = [];
$fieldTableQuickAccess->$scope->fields->$action->$level = [];
@@ -441,10 +472,14 @@ class Table
$attributeList = $this->getFieldUtil()->getAttributeList($scope, $field);
foreach ($this->fieldActionList as $action) {
if (!isset($fieldData->$action)) continue;
if (!isset($fieldData->$action)) {
continue;
}
foreach ($this->fieldLevelList as $level) {
if ($fieldData->$action === $level) {
$fieldTableQuickAccess->$scope->fields->$action->{$level}[] = $field;
foreach ($attributeList as $attribute) {
$fieldTableQuickAccess->$scope->attributes->$action->{$level}[] = $attribute;
}
@@ -464,6 +499,7 @@ class Table
}
$defaultsGroupName = 'default';
if ($this->isStrictMode) {
$defaultsGroupName = 'strictDefault';
}
@@ -471,19 +507,29 @@ class Table
$data = $this->metadata->get(['app', $this->type, $defaultsGroupName, 'scopeLevel'], []);
foreach ($data as $scope => $item) {
if (isset($table->$scope)) continue;
if (isset($table->$scope)) {
continue;
}
$value = $item;
if (is_array($item)) {
$value = (object) $item;
}
$table->$scope = $value;
}
$defaultFieldData = $this->metadata->get(['app', $this->type, $defaultsGroupName, 'fieldLevel'], []);
foreach ($this->getScopeList() as $scope) {
if (isset($table->$scope) && $table->$scope === false) continue;
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) continue;
if (isset($table->$scope) && $table->$scope === false) {
continue;
}
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) {
continue;
}
$fieldList = array_keys($this->getMetadata()->get("entityDefs.{$scope}.fields", []));
@@ -491,14 +537,23 @@ class Table
'app.'.$this->type.'.'.$defaultsGroupName.'.scopeFieldLevel.' . $scope, []);
foreach (array_merge($defaultFieldData, $defaultScopeFieldData) as $field => $f) {
if (!in_array($field, $fieldList)) continue;
if (!in_array($field, $fieldList)) {
continue;
}
if (!isset($fieldTable->$scope)) {
$fieldTable->$scope = (object) [];
}
if (isset($fieldTable->$scope->$field)) continue;
if (isset($fieldTable->$scope->$field)) {
continue;
}
$fieldTable->$scope->$field = (object) [];
foreach ($this->fieldActionList as $action) {
$level = 'no';
if ($f === true) {
$level = 'yes';
} else {
@@ -514,25 +569,32 @@ class Table
foreach ($this->getScopeWithAclList() as $scope) {
if (!isset($table->$scope)) {
$aclType = $this->metadata->get('scopes.' . $scope . '.' . $this->type);
if ($aclType === true) {
$aclType = $this->defaultAclType;
}
if (!empty($aclType)) {
$paramDefaultsName = 'scopeLevelTypesDefaults';
if ($this->isStrictMode) {
$paramDefaultsName = 'scopeLevelTypesStrictDefaults';
}
$defaultValue = $this->metadata->get(
['app', $this->type, $paramDefaultsName, $aclType],
$this->metadata->get(['app', $this->type, $paramDefaultsName, 'record'])
);
if (is_array($defaultValue)) {
$defaultValue = (object) $defaultValue;
}
$table->$scope = $defaultValue;
if (is_object($table->$scope)) {
$actionList = $this->getMetadata()->get(['scopes', $scope, $this->type . 'ActionList']);
if ($actionList) {
foreach (get_object_vars($table->$scope) as $action => $level) {
if (!in_array($action, $actionList)) {
@@ -556,30 +618,43 @@ class Table
foreach ($data as $scope => $item) {
$value = $item;
if (is_array($item)) {
$value = (object) $item;
}
$table->$scope = $value;
}
$mandatoryFieldData = $this->metadata->get('app.'.$this->type.'.mandatory.fieldLevel', array());
foreach ($this->getScopeList() as $scope) {
if (isset($table->$scope) && $table->$scope === false) continue;
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) continue;
if (isset($table->$scope) && $table->$scope === false) {
continue;
}
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) {
continue;
}
$fieldList = array_keys($this->getMetadata()->get("entityDefs.{$scope}.fields", []));
$mandatoryScopeFieldData = $this->metadata->get('app.'.$this->type.'.mandatory.scopeFieldLevel.' . $scope, array());
foreach (array_merge($mandatoryFieldData, $mandatoryScopeFieldData) as $field => $f) {
if (!in_array($field, $fieldList)) continue;
if (!in_array($field, $fieldList)) {
continue;
}
if (!isset($fieldTable->$scope)) {
$fieldTable->$scope = (object) [];
}
$fieldTable->$scope->$field = (object) [];
foreach ($this->fieldActionList as $action) {
$level = 'no';
if ($f === true) {
$level = 'yes';
} else {
@@ -614,6 +689,7 @@ class Table
$table->$scope = false;
unset($fieldTable->$scope);
}
foreach ($this->valuePermissionList as $permission) {
$valuePermissionLists->{$permission}[] = 'no';
}
@@ -623,29 +699,38 @@ class Table
private function mergeValueList(array $list, $defaultValue)
{
$result = null;
foreach ($list as $level) {
if ($level != 'not-set') {
if (is_null($result)) {
$result = $level;
continue;
}
if (array_search($result, $this->levelList) > array_search($level, $this->levelList)) {
$result = $level;
}
}
}
if (is_null($result)) {
$result = $defaultValue;
}
return $result;
}
protected function getScopeWithAclList()
{
$scopeList = [];
$scopes = $this->metadata->get('scopes');
foreach ($scopes as $scope => $d) {
if (empty($d['acl'])) continue;
if (empty($d['acl'])) {
continue;
}
$scopeList[] = $scope;
}
return $scopeList;
@@ -654,10 +739,13 @@ class Table
protected function getScopeList()
{
$scopeList = [];
$scopes = $this->metadata->get('scopes');
foreach ($scopes as $scope => $d) {
$scopeList[] = $scope;
}
return $scopeList;
}
@@ -668,7 +756,9 @@ class Table
foreach ($tableList as $table) {
foreach ($scopeList as $scope) {
if (!isset($table->$scope)) continue;
if (!isset($table->$scope)) {
continue;
}
$row = $table->$scope;
@@ -676,9 +766,11 @@ class Table
if (!isset($data->$scope)) {
$data->$scope = false;
}
} else if ($row === true) {
}
else if ($row === true) {
$data->$scope = true;
} else {
}
else {
if (!isset($data->$scope)) {
$data->$scope = (object) [];
}
@@ -686,7 +778,9 @@ class Table
$data->$scope = (object) [];
}
if (!is_object($row)) continue;
if (!is_object($row)) {
continue;
}
$actionList = $this->getMetadata()->get(['scopes', $scope, $this->type . 'ActionList'], $this->actionList);
@@ -726,33 +820,45 @@ class Table
private function mergeFieldTableList(array $tableList)
{
$data = (object) [];
$scopeList = $this->getScopeWithAclList();
foreach ($tableList as $table) {
foreach ($scopeList as $scope) {
if (!isset($table->$scope)) continue;
if (!isset($table->$scope)) {
continue;
}
if (!isset($data->$scope)) {
$data->$scope = (object) [];
}
if (!is_object($table->$scope)) continue;
if (!is_object($table->$scope)) {
continue;
}
$fieldList = array_keys($this->getMetadata()->get("entityDefs.{$scope}.fields", []));
foreach (get_object_vars($table->$scope) as $field => $row) {
if (!is_object($row)) continue;
if (!is_object($row)) {
continue;
}
if (!in_array($field, $fieldList)) continue;
if (!in_array($field, $fieldList)) {
continue;
}
if (!isset($data->$scope->$field)) {
$data->$scope->$field = (object) [];
}
foreach ($this->fieldActionList as $i => $action) {
if (!isset($row->$action)) continue;
if (!isset($row->$action)) {
continue;
}
$level = $row->$action;
if (!isset($data->$scope->$field->$action)) {
$data->$scope->$field->$action = $level;
} else {
@@ -775,6 +881,6 @@ class Table
private function buildCache()
{
$this->fileManager->putPhpContents($this->cacheFilePath, $this->data, true);
$this->dataCache->store($this->cacheKey, $this->data);
}
}
+6 -5
View File
@@ -43,6 +43,7 @@ use Espo\Core\{
Utils\Metadata,
Utils\FieldUtil,
Utils\File\Manager as FileManager,
Utils\DataCache,
};
use Traversable;
@@ -64,9 +65,9 @@ class Table extends \Espo\Core\Acl\Table
User $user,
Portal $portal,
Config $config = null,
FileManager $fileManager = null,
Metadata $metadata = null,
FieldUtil $fieldUtil = null
FieldUtil $fieldUtil = null,
DataCache $dataCache
) {
if (empty($portal)) {
throw new Error("No portal was passed to AclPortal\\Table constructor.");
@@ -74,7 +75,7 @@ class Table extends \Espo\Core\Acl\Table
$this->portal = $portal;
parent::__construct($entityManager, $user, $config, $fileManager, $metadata, $fieldUtil);
parent::__construct($entityManager, $user, $config, $metadata, $fieldUtil, $dataCache);
}
protected function getPortal()
@@ -82,9 +83,9 @@ class Table extends \Espo\Core\Acl\Table
return $this->portal;
}
protected function initCacheFilePath()
protected function initCacheKey()
{
$this->cacheFilePath = 'data/cache/application/acl-portal/'.$this->getPortal()->id.'/' . $this->getUser()->id . '.php';
$this->cacheKey = 'aclPortal/' . $this->getPortal()->id.'/' . $this->getUser()->id;
}
protected function getRoleList()
+26 -9
View File
@@ -37,6 +37,7 @@ use Espo\Core\{
Utils\Metadata,
Utils\Config,
Utils\Util,
Utils\DataCache,
};
/**
@@ -55,7 +56,7 @@ class HookManager
private $hooks;
protected $cacheFile = 'data/cache/application/hooks.php';
protected $cacheKey = 'hooks';
protected $ignoredMethodList = [
'__construct',
@@ -73,12 +74,14 @@ class HookManager
InjectableFactory $injectableFactory,
FileManager $fileManager,
Metadata $metadata,
Config $config
Config $config,
DataCache $dataCache
) {
$this->injectableFactory = $injectableFactory;
$this->fileManager = $fileManager;
$this->metadata = $metadata;
$this->config = $config;
$this->dataCache = $dataCache;
}
public function process(string $scope, string $hookName, $injection = null, array $options = [], array $hookData = [])
@@ -97,9 +100,14 @@ class HookManager
foreach ($hookList as $className) {
if (empty($this->hooks[$className])) {
$this->hooks[$className] = $this->createHookByClassName($className);
if (empty($this->hooks[$className])) continue;
if (empty($this->hooks[$className])) {
continue;
}
}
$hook = $this->hooks[$className];
$hook->$hookName($injection, $options, $hookData);
}
}
@@ -123,8 +131,9 @@ class HookManager
protected function loadHooks()
{
if ($this->config->get('useCache') && file_exists($this->cacheFile)) {
$this->data = $this->fileManager->getPhpContents($this->cacheFile);
if ($this->config->get('useCache') && $this->dataCache->has($this->cacheKey)) {
$this->data = $this->dataCache->get($this->cacheKey);
return;
}
@@ -134,6 +143,7 @@ class HookManager
foreach ($metadata->getModuleList() as $moduleName) {
$modulePath = str_replace('{*}', $moduleName, $this->paths['modulePath']);
$data = $this->getHookData($modulePath, $data);
}
@@ -142,13 +152,13 @@ class HookManager
$this->data = $this->sortHooks($data);
if ($this->config->get('useCache')) {
$this->fileManager->putPhpContents($this->cacheFile, $this->data);
$this->dataCache->store($this->cacheKey, $this->data);
}
}
protected function createHookByClassName(string $className) : object
{
if (!@class_exists($className)) {
if (!class_exists($className)) {
$GLOBALS['log']->error("Hook class '{$className}' does not exist.");
}
@@ -158,7 +168,7 @@ class HookManager
}
/**
* Get and merge hook data by checking the files exist in $hookDirs
* Get and merge hook data by checking the files exist in $hookDirs.
*
* @param $hookDirs - can be ['Espo/Hooks', 'Espo/Custom/Hooks', 'Espo/Modules/Crm/Hooks']
*/
@@ -172,6 +182,7 @@ class HookManager
if (!file_exists($hookDir)) {
continue;
}
$fileList = $this->fileManager->getFileList($hookDir, 1, '\.php$', true);
foreach ($fileList as $scopeName => $hookFiles) {
@@ -179,6 +190,7 @@ class HookManager
$normalizedScopeName = Util::normilizeScopeName($scopeName);
$scopeHooks = [];
foreach ($hookFiles as $hookFile) {
$hookFilePath = Util::concatPath($hookScopeDirPath, $hookFile);
$className = Util::getClassName($hookFilePath);
@@ -187,12 +199,16 @@ class HookManager
$hookMethods = array_diff($classMethods, $this->ignoredMethodList);
$hookMethods = array_filter($hookMethods, function ($item) {
if (strpos($item, 'set') === 0) return false;
if (strpos($item, 'set') === 0) {
return false;
}
return true;
});
foreach ($hookMethods as $hookType) {
$entityHookData = $hookData[$normalizedScopeName][$hookType] ?? [];
if (!$this->hookExists($className, $entityHookData)) {
$hookData[$normalizedScopeName][$hookType][] = [
'className' => $className,
@@ -241,6 +257,7 @@ class HookManager
}
$normalizedList = [];
foreach ($hookList as $hookData) {
$normalizedList[] = $hookData['className'];
}
@@ -34,6 +34,7 @@ use Espo\Core\{
Utils\Config,
Utils\File\Manager as FileManager,
Utils\Language as LanguageService,
Utils\DataCache,
};
class BaseLanguage implements Loader
@@ -41,12 +42,14 @@ class BaseLanguage implements Loader
protected $fileManager;
protected $config;
protected $metadata;
protected $dataCache;
public function __construct(FileManager $fileManager, Config $config, Metadata $metadata)
public function __construct(FileManager $fileManager, Config $config, Metadata $metadata, DataCache $dataCache)
{
$this->fileManager = $fileManager;
$this->config = $config;
$this->metadata = $metadata;
$this->dataCache = $dataCache;
}
public function load() : LanguageService
@@ -55,6 +58,7 @@ class BaseLanguage implements Loader
'en_US',
$this->fileManager,
$this->metadata,
$this->dataCache,
$this->config->get('useCache')
);
}
@@ -41,6 +41,7 @@ class DefaultLanguage extends BaseLanguage
LanguageService::detectLanguage($this->config),
$this->fileManager,
$this->metadata,
$this->dataCache,
$this->config->get('useCache')
);
}
+7 -2
View File
@@ -34,6 +34,7 @@ use Espo\Core\{
Utils\Config,
Utils\File\Manager as FileManager,
Utils\Language as LanguageService,
Utils\DataCache,
};
use Espo\Entities\Preferences;
@@ -43,13 +44,16 @@ class Language implements Loader
protected $fileManager;
protected $config;
protected $metadata;
protected $dataCache;
protected $preferences;
public function __construct(FileManager $fileManager, Config $config, Metadata $metadata, Preferences $preferences)
{
public function __construct(
FileManager $fileManager, Config $config, Metadata $metadata, DataCache $dataCache, Preferences $preferences
) {
$this->fileManager = $fileManager;
$this->config = $config;
$this->metadata = $metadata;
$this->dataCache = $dataCache;
$this->preferences = $preferences;
}
@@ -59,6 +63,7 @@ class Language implements Loader
LanguageService::detectLanguage($this->config, $this->preferences),
$this->fileManager,
$this->metadata,
$this->dataCache,
$this->config->get('useCache')
);
}
@@ -35,6 +35,7 @@ use Espo\Core\{
Utils\File\Manager as FileManager,
Portal\Utils\Language as LanguageService,
Loaders\Loader as Loader,
Utils\DataCache,
};
use Espo\Entities\{
@@ -47,15 +48,17 @@ class Language implements Loader
protected $fileManager;
protected $config;
protected $metadata;
protected $dataCache;
protected $preferences;
protected $portal;
public function __construct(
FileManager $fileManager, Config $config, Metadata $metadata, Preferences $preferences, Portal $portal
FileManager $fileManager, Config $config, Metadata $metadata, DataCache $dataCache, Preferences $preferences, Portal $portal
) {
$this->fileManager = $fileManager;
$this->config = $config;
$this->metadata = $metadata;
$this->dataCache = $dataCache;
$this->preferences = $preferences;
$this->portal = $portal;
}
@@ -66,6 +69,7 @@ class Language implements Loader
LanguageService::detectLanguage($this->config, $this->preferences),
$this->fileManager,
$this->metadata,
$this->dataCache,
$this->config->get('useCache')
);
+1 -1
View File
@@ -108,7 +108,7 @@ class DataCache
{
if (
$key === '' ||
preg_match('/[^a-zA-Z0-9\/]/i', $key) ||
preg_match('/[^a-zA-Z0-9_\/\-]/i', $key) ||
$key[0] === '/' ||
substr($key, -1) === '/'
) {
+13 -13
View File
@@ -920,19 +920,17 @@ class Manager
if (!$withObjects) {
return "<?php\n" .
"return " . var_export($content, true) . ";\n".
"?>";
"return " . var_export($content, true) . ";\n";
}
return "<?php\n" .
"return " . $this->varExport($content) . ";\n".
"?>";
"return " . $this->varExport($content) . ";\n";
}
public function varExport($variable, $level = 0)
protected function varExport($variable, int $level = 0)
{
$tab = '';
$tabElement = ' ';
$tabElement = ' ';
for ($i = 0; $i <= $level; $i++) {
$tab .= $tabElement;
@@ -941,22 +939,24 @@ class Manager
$prevTab = substr($tab, 0, strlen($tab) - strlen($tabElement));
if ($variable instanceof StdClass) {
$result = "(object) " . $this->varExport(get_object_vars($variable), $level);
return "(object) " . $this->varExport(get_object_vars($variable), $level);
}
else if (is_array($variable)) {
if (is_array($variable)) {
$array = [];
foreach ($variable as $key => $value) {
$array[] = var_export($key, true) . " => " . $this->varExport($value, $level + 1);
}
$result = "[\n" . $tab . implode(",\n" . $tab, $array) . "\n" . $prevTab . "]";
}
else {
$result = var_export($variable, true);
if (count($array) === 0) {
return "[]";
}
return "[\n" . $tab . implode(",\n" . $tab, $array) . "\n" . $prevTab . "]";
}
return $result;
return var_export($variable, true);
}
/**
+16 -14
View File
@@ -36,6 +36,7 @@ use Espo\Core\{
Utils\Metadata,
Utils\File\Unifier as FileUnifier,
Utils\Config,
Utils\DataCache,
};
use Espo\{
@@ -58,8 +59,6 @@ class Language
private $currentLanguage = null;
protected $cacheFile = 'data/cache/application/languages/{language}.php';
protected $defaultLanguage = 'en_US';
protected $useCache = false;
@@ -73,7 +72,12 @@ class Language
];
public function __construct(
?string $language = null, FileManager $fileManager, Metadata $metadata, bool $useCache = false, bool $noCustom = false
?string $language = null,
FileManager $fileManager,
Metadata $metadata,
DataCache $dataCache,
bool $useCache = false,
bool $noCustom = false
) {
if ($language) {
$this->currentLanguage = $language;
@@ -83,6 +87,7 @@ class Language
$this->fileManager = $fileManager;
$this->metadata = $metadata;
$this->dataCache = $dataCache;
$this->useCache = $useCache;
$this->noCustom = $noCustom;
@@ -135,13 +140,11 @@ class Language
$this->currentLanguage = $language;
}
protected function getCacheFile(string $language = null) : string
protected function getCacheKey(string $language = null) : string
{
$language = $language ?? $this->getLanguage();
$langCacheFile = str_replace('{language}', $language, $this->cacheFile);
return $langCacheFile;
return 'languages/' . $language;
}
/**
@@ -323,12 +326,14 @@ class Language
foreach ($name as $rowLabel) {
$this->delete($scope, $category, $rowLabel);
}
return;
}
$this->deletedData[$scope][$category][] = $name;
$currentLanguage = $this->getLanguage();
if (!isset($this->data[$currentLanguage])) {
$this->init();
}
@@ -367,9 +372,9 @@ class Language
{
if ($reload || !isset($this->data[$language])) {
$cacheFile = $this->getCacheFile($language);
$cacheKey = $this->getCacheKey($language);
if (!$this->useCache || !file_exists($cacheFile) || $reload) {
if (!$this->useCache || !$this->dataCache->has($cacheKey) || $reload) {
$paths = $this->paths;
@@ -394,15 +399,12 @@ class Language
$this->data[$language] = $data;
if ($this->useCache) {
$putResult = $this->getFileManager()->putPhpContents($cacheFile, $data);
if (!$putResult) {
$GLOBALS['log']->error("Language: Could not store cache file for {$language}");
}
$this->dataCache->store($cacheKey, $data);
}
}
if ($this->useCache) {
$this->data[$language] = $this->getFileManager()->getPhpContents($cacheFile);
$this->data[$language] = $this->dataCache->get($cacheKey);
}
}
@@ -35,34 +35,35 @@ use Espo\Core\{
Utils\File\Manager as FileManager,
Utils\Config,
Utils\Database\Converter,
Utils\DataCache,
Exceptions\Error,
};
class OrmMetadata
{
protected $data = [];
protected $data = null;
protected $cacheFile = 'data/cache/application/ormMetadata.php';
protected $metadata;
protected $fileManager;
protected $config;
protected $cacheKey = 'ormMetadata';
protected $useCache;
public function __construct(Metadata $metadata, FileManager $fileManager, Config $config)
protected $metadata;
protected $fileManager;
protected $dataCache;
protected $config;
public function __construct(Metadata $metadata, FileManager $fileManager, DataCache $dataCache, Config $config)
{
$this->metadata = $metadata;
$this->fileManager = $fileManager;
$this->dataCache = $dataCache;
$this->config = $config;
$this->useCache = $this->config->get('useCache', false);
}
protected function getConverter()
protected function getConverter() : Converter
{
if (!isset($this->converter)) {
$this->converter = new Converter($this->metadata, $this->fileManager, $this->config);
@@ -71,40 +72,22 @@ class OrmMetadata
return $this->converter;
}
protected function getFileManager()
public function getData(bool $reload = false) : array
{
return $this->fileManager;
}
protected function getConfig()
{
return $this->config;
}
public function clearData()
{
$this->ormData = null;
}
public function getData($reload = false)
{
if (!empty($this->ormData) && !$reload) {
return $data;
if (isset($this->data) && !$reload) {
return $this->data;
}
if (!file_exists($this->cacheFile) || !$this->useCache || $reload) {
$this->data = $this->getConverter()->process();
if ($this->useCache && $this->dataCache->has($this->cacheKey) && !$reload) {
$this->data = $this->dataCache->get($this->cacheKey);
if ($this->useCache) {
$result = $this->getFileManager()->putPhpContents($this->cacheFile, $this->data);
if ($result == false) {
throw new Error('OrmMetadata::getData() - Cannot save ormMetadata to cache file');
}
}
return $this->data;
}
if (empty($this->data)) {
$this->data = $this->getFileManager()->getPhpContents($this->cacheFile);
$this->data = $this->getConverter()->process();
if ($this->useCache) {
$this->dataCache->store($this->cacheKey, $this->data);
}
return $this->data;
+15 -14
View File
@@ -29,13 +29,19 @@
namespace Espo\Core\Utils;
use Espo\Core\Exceptions\Error;
use Espo\Core\{
Exceptions\Error,
Utils\Config,
Utils\Metadata,
Utils\File\Manager as FileManager,
Utils\DataCache,
};
class Route
{
protected $data = null;
protected $cacheFile = 'data/cache/application/routes.php';
protected $cacheKey = 'routes';
protected $paths = [
'corePath' => 'application/Espo/Resources/routes.json',
@@ -43,15 +49,17 @@ class Route
'customPath' => 'custom/Espo/Custom/Resources/routes.json',
];
private $fileManager;
private $config;
private $metadata;
private $fileManager;
private $dataCache;
public function __construct(Config $config, Metadata $metadata, File\Manager $fileManager)
public function __construct(Config $config, Metadata $metadata, FileManager $fileManager, DataCache $dataCache)
{
$this->config = $config;
$this->metadata = $metadata;
$this->fileManager = $fileManager;
$this->dataCache = $dataCache;
}
/**
@@ -70,8 +78,8 @@ class Route
{
$useCache = $this->config->get('useCache');
if (file_exists($this->cacheFile) && $useCache) {
$this->data = $this->fileManager->getPhpContents($this->cacheFile);
if ($this->dataCache->has($this->cacheKey) && $useCache) {
$this->data = $this->dataCache->get($this->cacheKey);
return;
}
@@ -79,17 +87,10 @@ class Route
$this->data = $this->unify();
if ($useCache) {
$result = $this->fileManager->putPhpContents($this->cacheFile, $this->data);
if ($result == false) {
throw new Error('Route - Cannot save unified routes');
}
$this->dataCache->store($this->cacheKey, $this->data);
}
}
/**
* Unify routes.
*/
protected function unify() : array
{
$data = $this->addDataFromFile([], $this->paths['customPath']);
+46 -21
View File
@@ -31,7 +31,7 @@ namespace Espo\Core\Webhook;
use Espo\Core\{
Utils\Config,
Utils\File\Manager as FileManager,
Utils\DataCache,
Utils\FieldUtil,
ORM\EntityManager,
ORM\Entity,
@@ -42,25 +42,25 @@ use Espo\Core\{
*/
class Manager
{
private $cacheFile = 'data/cache/application/webhooks.php';
private $cacheKey = 'webhooks';
protected $skipAttributeList = ['isFollowed', 'modifiedAt', 'modifiedBy'];
private $data = null;
protected $config;
protected $fileManager;
protected $dataCache;
protected $entityManager;
protected $fieldUtil;
public function __construct(
Config $config,
FileManager $fileManager,
DataCache $dataCache,
EntityManager $entityManager,
FieldUtil $fieldUtil
) {
$this->config = $config;
$this->fileManager = $fileManager;
$this->dataCache = $dataCache;
$this->entityManager = $entityManager;
$this->fieldUtil = $fieldUtil;
@@ -70,10 +70,8 @@ class Manager
private function loadData()
{
if ($this->config->get('useCache')) {
if ($this->fileManager->isFile($this->cacheFile)) {
if (file_exists($this->cacheFile)) {
$this->data = $this->fileManager->getPhpContents($this->cacheFile);
}
if ($this->dataCache->has($this->cacheKey)) {
$this->data = $this->dataCache->get($this->cacheKey);
}
}
@@ -88,7 +86,7 @@ class Manager
private function storeDataToCache()
{
$this->fileManager->putPhpContents($this->cacheFile, $this->data);
$this->dataCache->store($this->cacheKey, $this->data);
}
private function buildData()
@@ -128,13 +126,18 @@ class Manager
*/
public function removeEvent(string $event)
{
$notExists = !$this->entityManager->getRepository('Webhook')->select(['id'])->where([
'event' => $event,
'isActive' => true,
])->findOne();
$notExists = !$this->entityManager
->getRepository('Webhook')
->select(['id'])
->where([
'event' => $event,
'isActive' => true,
])
->findOne();
if ($notExists) {
unset($this->data[$event]);
if ($this->config->get('useCache')) {
$this->storeDataToCache();
}
@@ -158,7 +161,9 @@ class Manager
{
$event = $entity->getEntityType() . '.create';
if (!$this->eventExists($event)) return;
if (!$this->eventExists($event)) {
return;
}
$this->entityManager->createEntity('WebhookEventQueueItem', [
'event' => $event,
@@ -177,7 +182,9 @@ class Manager
{
$event = $entity->getEntityType() . '.delete';
if (!$this->eventExists($event)) return;
if (!$this->eventExists($event)) {
return;
}
$this->entityManager->createEntity('WebhookEventQueueItem', [
'event' => $event,
@@ -199,14 +206,20 @@ class Manager
$event = $entity->getEntityType() . '.update';
$data = (object) [];
foreach ($entity->getAttributeList() as $attribute) {
if (in_array($attribute, $this->skipAttributeList)) continue;
if (in_array($attribute, $this->skipAttributeList)) {
continue;
}
if ($entity->isAttributeChanged($attribute)) {
$data->$attribute = $entity->get($attribute);
}
}
if (!count(get_object_vars($data))) return;
if (!count(get_object_vars($data))) {
return;
}
$data->id = $entity->id;
@@ -222,14 +235,22 @@ class Manager
foreach ($this->fieldUtil->getEntityTypeFieldList($entity->getEntityType()) as $field) {
$itemEvent = $entity->getEntityType() . '.fieldUpdate.' . $field;
if (!$this->eventExists($itemEvent)) continue;
if (!$this->eventExists($itemEvent)) {
continue;
}
$attributeList = $this->fieldUtil->getActualAttributeList($entity->getEntityType(), $field);
$isChanged = false;
foreach ($attributeList as $attribute) {
if (in_array($attribute, $this->skipAttributeList)) continue;
if (in_array($attribute, $this->skipAttributeList)) {
continue;
}
if (property_exists($data, $attribute)) {
$isChanged = true;
break;
}
}
@@ -238,8 +259,12 @@ class Manager
$itemData = (object) [];
$itemData->id = $entity->id;
$attributeList = $this->fieldUtil->getAttributeList($entity->getEntityType(), $field);
foreach ($attributeList as $attribute) {
if (in_array($attribute, $this->skipAttributeList)) continue;
if (in_array($attribute, $this->skipAttributeList)) {
continue;
}
$itemData->$attribute = $entity->get($attribute);
}
@@ -70,7 +70,7 @@ class ArrayTypeTest extends \tests\integration\Core\BaseTestCase
$fieldManager->create('Account', 'testArray', $fieldDefs);
$this->getContainer()->get('dataManager')->rebuild('Account');
$this->getContainer()->get('dataManager')->rebuild(['Account']);
$app = $this->createApplication();
@@ -109,7 +109,7 @@ class ArrayTypeTest extends \tests\integration\Core\BaseTestCase
$fieldManager->update('Account', 'testArray', $fieldDefs);
$this->getContainer()->get('dataManager')->rebuild('Account');
$this->getContainer()->get('dataManager')->rebuild(['Account']);
$app = $this->createApplication();
@@ -69,7 +69,7 @@ class EnumTypeTest extends \tests\integration\Core\BaseTestCase
$fieldDefs = get_object_vars(json_decode($this->jsonFieldDefs));
$fieldManager->create('Account', 'testEnum', $fieldDefs);
$this->getContainer()->get('dataManager')->rebuild('Account');
$this->getContainer()->get('dataManager')->rebuild(['Account']);
$app = $this->createApplication();
@@ -110,7 +110,7 @@ class EnumTypeTest extends \tests\integration\Core\BaseTestCase
$fieldDefs['readOnly'] = true;
$fieldManager->update('Account', 'testEnum', $fieldDefs);
$this->getContainer()->get('dataManager')->rebuild('Account');
$this->getContainer()->get('dataManager')->rebuild(['Account']);
$app = $this->createApplication();
@@ -67,7 +67,7 @@ class VarcharTypeTest extends \tests\integration\Core\BaseTestCase
$fieldDefs = get_object_vars(json_decode($this->jsonFieldDefs));
$fieldManager->create('Account', 'testVarchar', $fieldDefs);
$this->getContainer()->get('dataManager')->rebuild('Account');
$this->getContainer()->get('dataManager')->rebuild(['Account']);
$app = $this->createApplication();
@@ -106,7 +106,7 @@ class VarcharTypeTest extends \tests\integration\Core\BaseTestCase
$fieldDefs['default'] = 'default-value';
$fieldManager->update('Account', 'testVarchar', $fieldDefs);
$this->getContainer()->get('dataManager')->rebuild('Account');
$this->getContainer()->get('dataManager')->rebuild(['Account']);
$app = $this->createApplication();
+50 -28
View File
@@ -31,6 +31,15 @@ namespace tests\unit\Espo\Core;
use tests\unit\ReflectionHelper;
use Espo\Core\{
HookManager,
InjectableFactory,
Utils\Metadata,
Utils\Config,
Utils\File\Manager as FileManager,
Utils\DataCache,
};
class HookManagerTest extends \PHPUnit\Framework\TestCase
{
protected $object;
@@ -42,23 +51,26 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
protected function setUp() : void
{
$this->objects['metadata'] =
$this->getMockBuilder('Espo\\Core\\Utils\\Metadata')->disableOriginalConstructor()->getMock();
$this->metadata =
$this->getMockBuilder(Metadata::class)->disableOriginalConstructor()->getMock();
$this->objects['config'] =
$this->getMockBuilder('Espo\\Core\\Utils\\Config')->disableOriginalConstructor()->getMock();
$this->config =
$this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
$this->objects['injectableFactory'] =
$this->getMockBuilder('Espo\\Core\\InjectableFactory')->disableOriginalConstructor()->getMock();
$this->injectableFactory =
$this->getMockBuilder(InjectableFactory::class)->disableOriginalConstructor()->getMock();
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
$this->dataCache =
$this->getMockBuilder(DataCache::class)->disableOriginalConstructor()->getMock();
$this->fileManager = new FileManager();
$this->object = new \Espo\Core\HookManager(
$this->objects['injectableFactory'],
$this->objects['fileManager'],
$this->objects['metadata'],
$this->objects['config']
$this->object = new HookManager(
$this->injectableFactory,
$this->fileManager,
$this->metadata,
$this->config,
$this->dataCache
);
$this->reflection = new ReflectionHelper($this->object);
@@ -73,9 +85,9 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
public function testIsHookExists()
{
$data = array (
'\\Espo\\Hooks\\Note\\Stream' => 8,
'\\Espo\\Hooks\\Note\\Mentions' => 9,
'\\Espo\\Hooks\\Note\\Notifications' => 14,
'Espo\\Hooks\\Note\\Stream' => 8,
'Espo\\Hooks\\Note\\Mentions' => 9,
'Espo\\Hooks\\Note\\Notifications' => 14,
);
$data = array (
@@ -93,11 +105,21 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
),
);
$this->assertTrue( $this->reflection->invokeMethod('hookExists', array('Espo\\Hooks\\Note\\Mentions', $data)) );
$this->assertTrue( $this->reflection->invokeMethod('hookExists', array('Espo\\Modules\\Crm\\Hooks\\Note\\Mentions', $data)) );
$this->assertTrue( $this->reflection->invokeMethod('hookExists', array('Espo\\Modules\\Test\\Hooks\\Note\\Mentions', $data)) );
$this->assertTrue( $this->reflection->invokeMethod('hookExists', array('Espo\\Modules\\Test\\Hooks\\Common\\Stream', $data)) );
$this->assertFalse( $this->reflection->invokeMethod('hookExists', array('Espo\\Hooks\\Note\\TestHook', $data)) );
$this->assertTrue(
$this->reflection->invokeMethod('hookExists', array('Espo\\Hooks\\Note\\Mentions', $data))
);
$this->assertTrue(
$this->reflection->invokeMethod('hookExists', array('Espo\\Modules\\Crm\\Hooks\\Note\\Mentions', $data))
);
$this->assertTrue(
$this->reflection->invokeMethod('hookExists', array('Espo\\Modules\\Test\\Hooks\\Note\\Mentions', $data))
);
$this->assertTrue(
$this->reflection->invokeMethod('hookExists', array('Espo\\Modules\\Test\\Hooks\\Common\\Stream', $data))
);
$this->assertFalse(
$this->reflection->invokeMethod('hookExists', array('Espo\\Hooks\\Note\\TestHook', $data))
);
}
public function testSortHooks()
@@ -219,12 +241,12 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase1/custom/Espo/Custom/Hooks',
));
$this->objects['config']
$this->config
->expects($this->exactly(2))
->method('get')
->will($this->returnValue(false));
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(
@@ -258,12 +280,12 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase2/custom/Espo/Custom/Hooks',
));
$this->objects['config']
$this->config
->expects($this->exactly(2))
->method('get')
->will($this->returnValue(false));
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(
@@ -298,12 +320,12 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase2/custom/Espo/Custom/Hooks',
));
$this->objects['config']
$this->config
->expects($this->exactly(2))
->method('get')
->will($this->returnValue(false));
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(
@@ -338,12 +360,12 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase3/custom/Espo/Custom/Hooks',
));
$this->objects['config']
$this->config
->expects($this->exactly(2))
->method('get')
->will($this->returnValue(false));
$this->objects['metadata']
$this->metadata
->expects($this->at(0))
->method('getModuleList')
->will($this->returnValue(array(
+18 -29
View File
@@ -31,6 +31,11 @@ namespace tests\unit\Espo\Core\Utils;
use tests\unit\ReflectionHelper;
use Espo\Core\Utils\Metadata;
use Espo\Core\Utils\Language;
use Espo\Core\Utils\DataCache;
use Espo\Core\Utils\File\Manager as FileManager;
class LanguageTest extends \PHPUnit\Framework\TestCase
{
protected $object;
@@ -39,8 +44,6 @@ class LanguageTest extends \PHPUnit\Framework\TestCase
protected $reflection;
protected $cacheFile = 'tests/unit/testData/cache/application/languages/{language}.php';
protected $paths = [
'corePath' => 'tests/unit/testData/Utils/I18n/Espo/Resources/i18n/{language}',
'modulePath' => 'tests/unit/testData/Utils/I18n/Espo/Modules/{*}/Resources/i18n/{language}',
@@ -49,22 +52,24 @@ class LanguageTest extends \PHPUnit\Framework\TestCase
protected function setUp() : void
{
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
$this->fileManager = new FileManager();
$this->dataCache = $this->getMockBuilder(DataCache::class)->disableOriginalConstructor()->getMock();
$this->objects['metadata'] = $this->getMockBuilder('\Espo\Core\Utils\Metadata')->disableOriginalConstructor()->getMock();
$this->objects['metadata']->expects($this->any())
->method('getModuleList')
->will($this->returnValue(
[
'Crm',
]
));
$this->metadata = $this->getMockBuilder(Metadata::class)->disableOriginalConstructor()->getMock();
$this->object = new \Espo\Core\Utils\Language(null, $this->objects['fileManager'], $this->objects['metadata'], false);
$this->metadata->expects($this->any())
->method('getModuleList')
->will($this->returnValue(
[
'Crm',
]
));
$this->object = new Language(null, $this->fileManager, $this->metadata, $this->dataCache, false);
$this->reflection = new ReflectionHelper($this->object);
$this->reflection->setProperty('cacheFile', $this->cacheFile);
$this->reflection->setProperty('paths', $this->paths);
$this->reflection->setProperty('currentLanguage', 'en_US');
}
@@ -74,7 +79,6 @@ class LanguageTest extends \PHPUnit\Framework\TestCase
$this->object = NULL;
}
public function testLanguage()
{
$this->assertEquals('en_US', $this->object->getLanguage());
@@ -86,21 +90,6 @@ class LanguageTest extends \PHPUnit\Framework\TestCase
$this->object->setLanguage($originalLang);
}
public function testGetLangCacheFile()
{
$cacheFile = $this->cacheFile;
$result = str_replace('{language}', 'en_US', $cacheFile);
$this->assertEquals($result, $this->reflection->invokeMethod('getCacheFile'));
$originalLang = $this->object->getLanguage();
$this->object->setLanguage('lang_TEST');
$result = str_replace('{language}', 'lang_TEST', $cacheFile);
$this->assertEquals($result, $this->reflection->invokeMethod('getCacheFile'));
$this->object->setLanguage($originalLang);
}
public function testGetData()
{
$result = [
+19 -18
View File
@@ -31,6 +31,14 @@ namespace tests\unit\Espo\Core\Utils;
use tests\unit\ReflectionHelper;
use Espo\Core\{
Utils\Route,
Utils\Config,
Utils\File\Manager as FileManager,
Utils\Metadata,
Utils\DataCache,
};
class RouteTest extends \PHPUnit\Framework\TestCase
{
protected $object;
@@ -41,24 +49,17 @@ class RouteTest extends \PHPUnit\Framework\TestCase
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\\Espo\\Core\\Container')->disableOriginalConstructor()->getMock();
$this->config = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
$this->fileManager = new FileManager();
$this->objects['config'] = $this->getMockBuilder('\\Espo\\Core\\Utils\\Config')->disableOriginalConstructor()->getMock();
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
$this->objects['metadata'] = $this->getMockBuilder('\\Espo\\Core\\Utils\\Metadata')->disableOriginalConstructor()->getMock();
$this->metadata = $this->getMockBuilder(Metadata::class)->disableOriginalConstructor()->getMock();
$map = array(
array('config', $this->objects['config']),
array('metadata', $this->objects['metadata']),
array('fileManager', $this->objects['fileManager']),
$this->dataCache = $this->getMockBuilder(DataCache::class)->disableOriginalConstructor()->getMock();
$this->object = new Route(
$this->config, $this->metadata, $this->fileManager, $this->dataCache
);
$this->objects['container']
->expects($this->any())
->method('get')
->will($this->returnValueMap($map));
$this->object = new \Espo\Core\Utils\Route($this->objects['config'], $this->objects['metadata'], $this->objects['fileManager']);
$this->reflection = new ReflectionHelper($this->object);
}
@@ -76,7 +77,7 @@ class RouteTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase1/custom/Espo/Custom/Resources/routes.json',
));
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(
@@ -165,7 +166,7 @@ class RouteTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase2/custom/Espo/Custom/Resources/routes.json',
));
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(
@@ -252,7 +253,7 @@ class RouteTest extends \PHPUnit\Framework\TestCase
'customPath' => $this->filesPath . '/testCase3/custom/Espo/Custom/Resources/routes.json',
));
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(
@@ -342,7 +343,7 @@ class RouteTest extends \PHPUnit\Framework\TestCase
$this->reflection->setProperty('paths', $paths);
$this->objects['metadata']
$this->metadata
->expects($this->once())
->method('getModuleList')
->will($this->returnValue(array(