resource finder

This commit is contained in:
Yuri Kuznetsov
2021-06-18 15:17:21 +03:00
parent fbf05d5263
commit aa5bcf97d2
8 changed files with 375 additions and 90 deletions
+27 -21
View File
@@ -34,9 +34,10 @@ use Espo\Core\{
Utils\Util,
Utils\File\Manager as FileManager,
Utils\Metadata,
Utils\File\Unifier,
Utils\Config,
Utils\DataCache,
Utils\Resource\Reader as ResourceReader,
Utils\Resource\ReaderParams as ResourceReaderParams,
};
use Espo\{
@@ -45,12 +46,6 @@ use Espo\{
class Language
{
private $fileManager;
private $metadata;
private $unifier;
private $data = [];
private $deletedData = [];
@@ -65,17 +60,23 @@ class Language
protected $noCustom = false;
protected $paths = [
'corePath' => 'application/Espo/Resources/i18n/{language}',
'modulePath' => 'application/Espo/Modules/{*}/Resources/i18n/{language}',
'customPath' => 'custom/Espo/Custom/Resources/i18n/{language}',
];
private $customPath = 'custom/Espo/Custom/Resources/i18n/{language}';
private $resourcePath = 'i18n/{language}';
private $fileManager;
private $metadata;
private $resourceReader;
private $dataCache;
public function __construct(
?string $language,
FileManager $fileManager,
Metadata $metadata,
Unifier $unifier,
ResourceReader $resourceReader,
DataCache $dataCache,
bool $useCache = false,
bool $noCustom = false
@@ -84,7 +85,7 @@ class Language
$this->fileManager = $fileManager;
$this->metadata = $metadata;
$this->unifier = $unifier;
$this->resourceReader = $resourceReader;
$this->dataCache = $dataCache;
$this->useCache = $useCache;
@@ -220,10 +221,7 @@ class Language
*/
public function save(): bool
{
$language = $this->currentLanguage;
$path = $this->paths['customPath'];
$path = str_replace('{language}', $language, $path);
$path = str_replace('{language}', $this->currentLanguage, $this->customPath);
$result = true;
@@ -370,7 +368,7 @@ class Language
$cacheKey = $this->getCacheKey($language);
if (!$this->useCache || !$this->dataCache->has($cacheKey) || $reload) {
$paths = $this->paths;
/*$paths = $this->paths;
foreach ($paths as $k => &$path) {
$path = str_replace('{language}', $language, $path);
@@ -378,9 +376,17 @@ class Language
if ($this->noCustom) {
unset($paths['customPath']);
}
}*/
$data = $this->unifier->unify($paths, true);
$readerParams = ResourceReaderParams::create()
->withAsArray()
->withNoCustom($this->noCustom);
$path = str_replace('{language}', $language, $this->resourcePath);
$data = $this->resourceReader->read($path, $readerParams);
//$data = $this->unifier->unify($paths, true);
if (is_array($data)) {
$this->sanitizeData($data);
+15 -17
View File
@@ -32,10 +32,11 @@ namespace Espo\Core\Utils;
use Espo\Core\{
Exceptions\Error,
Utils\File\Manager as FileManager,
Utils\File\UnifierObj,
Utils\Module,
Utils\Metadata\Helper,
Utils\DataCache,
Utils\Resource\Reader as ResourceReader,
Utils\Resource\ReaderParams as ResourceReaderParams,
};
use StdClass;
@@ -48,19 +49,11 @@ class Metadata
private $useCache;
private $module;
private $metadataHelper;
private $cacheKey = 'metadata';
private $objCacheKey = 'objMetadata';
private $paths = [
'corePath' => 'application/Espo/Resources/metadata',
'modulePath' => 'application/Espo/Modules/{*}/Resources/metadata',
'customPath' => 'custom/Espo/Custom/Resources/metadata',
];
private $customPath = 'custom/Espo/Custom/Resources/metadata';
private $moduleList = null;
@@ -68,21 +61,25 @@ class Metadata
private $changedData = [];
private $metadataHelper;
private $module;
private $fileManager;
private $dataCache;
private $unifier;
private $resourceReader;
public function __construct(
FileManager $fileManager,
DataCache $dataCache,
UnifierObj $unifier,
ResourceReader $resourceReader,
bool $useCache = false
){
$this->fileManager = $fileManager;
$this->dataCache = $dataCache;
$this->unifier = $unifier;
$this->resourceReader = $resourceReader;
$this->useCache = $useCache;
@@ -186,7 +183,8 @@ class Metadata
return;
}
$this->objData = $this->unifier->unify($this->paths, true);
$this->objData = $this->resourceReader->read('metadata', ResourceReaderParams::create());
$this->objData = $this->addAdditionalFieldsObj($this->objData);
if ($this->useCache) {
@@ -359,7 +357,7 @@ class Metadata
*/
public function getCustom($key1, $key2, $default = null)
{
$filePath = $this->paths['customPath'] . "/{$key1}/{$key2}.json";
$filePath = $this->customPath . "/{$key1}/{$key2}.json";
$fileContent = $this->fileManager->getContents($filePath);
@@ -388,7 +386,7 @@ class Metadata
}
}
$filePath = $this->paths['customPath'] . "/{$key1}/{$key2}.json";
$filePath = $this->customPath . "/{$key1}/{$key2}.json";
$changedData = Json::encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
@@ -513,7 +511,7 @@ class Metadata
*/
public function save(): bool
{
$path = $this->paths['customPath'];
$path = $this->customPath;
$result = true;
@@ -0,0 +1,88 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Utils\Resource;
use Espo\Core\Utils\File\Unifier;
use Espo\Core\Utils\File\UnifierObj;
use stdClass;
/**
* Reads resource data.
*/
class Reader
{
private $paths = [
'corePath' => 'application/Espo/Resources/',
'modulePath' => 'application/Espo/Modules/{*}/Resources/',
'customPath' => 'custom/Espo/Custom/Resources/',
];
private $unifier;
private $unifierObj;
public function __construct(Unifier $unifier, UnifierObj $unifierObj)
{
$this->unifier = $unifier;
$this->unifierObj = $unifierObj;
}
/**
* Read resource data.
*
* @return stdClass|array
*/
public function read(string $path, ReaderParams $params)
{
$paths = $this->buildPaths($path, $params);
if ($params->asArray()) {
return $this->unifier->unify($paths);
}
return $this->unifierObj->unify($paths);
}
private function buildPaths(string $path, ReaderParams $params): array
{
$paths = [];
foreach ($this->paths as $key => $dir) {
$paths[$key] = $dir . $path;
}
if ($params->noCustom()) {
unset($paths['customPath']);
}
return $paths;
}
}
@@ -0,0 +1,68 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Utils\Resource;
class ReaderParams
{
private $noCustom = false;
private $asArray = false;
public static function create(): self
{
return new self();
}
public function withNoCustom(bool $noCustom = true): self
{
$obj = clone $this;
$obj->noCustom = $noCustom;
return $obj;
}
public function withAsArray(bool $asArray = true): self
{
$obj = clone $this;
$obj->asArray = $asArray;
return $obj;
}
public function noCustom(): bool
{
return $this->noCustom;
}
public function asArray(): bool
{
return $this->asArray;
}
}
@@ -30,14 +30,16 @@
namespace Espo\Tools\LabelManager;
use Espo\Core\{
Exceptions\NotFound,
Exceptions\Error,
Utils\Util,
Di,
Utils\Language,
InjectableFactory,
};
class LabelManager implements Di\DefaultLanguageAware, Di\MetadataAware, Di\FileManagerAware, Di\DataCacheAware
class LabelManager implements
Di\DefaultLanguageAware,
Di\MetadataAware,
Di\FileManagerAware,
Di\DataCacheAware
{
use Di\DefaultLanguageSetter;
use Di\MetadataSetter;
@@ -48,6 +50,13 @@ class LabelManager implements Di\DefaultLanguageAware, Di\MetadataAware, Di\File
'Global.sets',
];
private $injectableFactory;
public function __construct(InjectableFactory $injectableFactory)
{
$this->injectableFactory = $injectableFactory;
}
public function getScopeList()
{
$scopeList = [];
@@ -55,6 +64,7 @@ class LabelManager implements Di\DefaultLanguageAware, Di\MetadataAware, Di\File
$languageObj = $this->defaultLanguage;
$data = $languageObj->getAll();
foreach (array_keys($data) as $scope) {
if (!in_array($scope, $scopeList)) {
$scopeList[] = $scope;
@@ -72,7 +82,9 @@ class LabelManager implements Di\DefaultLanguageAware, Di\MetadataAware, Di\File
public function getScopeData($language, $scope)
{
$languageObj = new Language($language, $this->fileManager, $this->metadata, $this->dataCache);
$languageObj = $this->injectableFactory->createWith(Language::class, [
'language' => $language,
]);
$data = $languageObj->get($scope);
@@ -180,8 +192,14 @@ class LabelManager implements Di\DefaultLanguageAware, Di\MetadataAware, Di\File
public function saveLabels($language, $scope, $labels)
{
$languageObj = new Language($language, $this->fileManager, $this->metadata, $this->dataCache);
$languageOriginalObj = new Language($language, $this->fileManager, $this->metadata, $this->dataCache, false, true);
$languageObj = $this->injectableFactory->createWith(Language::class, [
'language' => $language,
]);
$languageOriginalObj = $this->injectableFactory->createWith(Language::class, [
'language' => $language,
'noCustom' => true,
]);
$returnDataHash = [];
+17 -6
View File
@@ -36,7 +36,9 @@ use Espo\Core\Utils\Language;
use Espo\Core\Utils\DataCache;
use Espo\Core\Utils\File\Manager as FileManager;
use Espo\Core\Utils\File\Unifier;
use Espo\Core\Utils\File\UnifierObj;
use Espo\Core\Utils\Module;
use Espo\Core\Utils\Resource\Reader;
class LanguageTest extends \PHPUnit\Framework\TestCase
{
@@ -45,9 +47,9 @@ class LanguageTest extends \PHPUnit\Framework\TestCase
protected $reflection;
protected $paths = [
'corePath' => 'tests/unit/testData/Utils/I18n/Espo/Resources/i18n/{language}',
'modulePath' => 'tests/unit/testData/Utils/I18n/Espo/Modules/{*}/Resources/i18n/{language}',
'customPath' => 'tests/unit/testData/Utils/I18n/Espo/Custom/Resources/i18n/{language}',
'corePath' => 'tests/unit/testData/Utils/I18n/Espo/Resources/',
'modulePath' => 'tests/unit/testData/Utils/I18n/Espo/Modules/{*}/Resources/',
'customPath' => 'tests/unit/testData/Utils/I18n/Espo/Custom/Resources/',
];
protected function setUp(): void
@@ -68,20 +70,29 @@ class LanguageTest extends \PHPUnit\Framework\TestCase
$module = new Module($this->fileManager);
$this->unifier = new Unifier($this->fileManager, $module);
$unifierObj = new UnifierObj($this->fileManager, $module);
$unifier = new Unifier($this->fileManager, $module);
$reader = new Reader($unifier, $unifierObj);
$this->readerReflection = new ReflectionHelper($reader);
$this->readerReflection->setProperty('paths', $this->paths);
$this->object = new Language(
null,
$this->fileManager,
$this->metadata,
$this->unifier,
$reader,
$this->dataCache,
false
);
$this->reflection = new ReflectionHelper($this->object);
$this->reflection->setProperty('paths', $this->paths);
$this->customPath = 'tests/unit/testData/Utils/I18n/Espo/Custom/Resources/i18n/{language}';
$this->reflection->setProperty('customPath', $this->customPath);
$this->reflection->setProperty('currentLanguage', 'en_US');
}
+21 -39
View File
@@ -36,7 +36,9 @@ use Espo\Core\Utils\File\Manager as FileManager;
use Espo\Core\Utils\Log;
use Espo\Core\Utils\DataCache;
use Espo\Core\Utils\File\UnifierObj;
use Espo\Core\Utils\File\Unifier;
use Espo\Core\Utils\Module;
use Espo\Core\Utils\Resource\Reader;
class MetadataTest extends \PHPUnit\Framework\TestCase
{
@@ -56,11 +58,18 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
$module = new Module($this->fileManager);
$unifier = new UnifierObj($this->fileManager, $module);
$unifierObj = new UnifierObj($this->fileManager, $module);
$unifier = new Unifier($this->fileManager, $module);
$this->object = new Metadata($this->fileManager, $this->dataCache, $unifier, true);
$reader = new Reader($unifier, $unifierObj);
$this->object = new Metadata($this->fileManager, $this->dataCache, $reader, true);
$this->reflection = new ReflectionHelper($this->object);
$this->customPath = 'tests/unit/testData/cache/metadata/custom';
$this->reflection->setProperty('customPath', $this->customPath);
}
protected function tearDown() : void
@@ -71,11 +80,9 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
public function testGet()
{
$result = 'System';
$this->assertEquals($result, $this->object->get('app.adminPanel.system.label'));
$this->assertEquals('System', $this->object->get('app.adminPanel.system.label'));
$result = 'fields';
$this->assertArrayHasKey($result, $this->object->get('entityDefs.User'));
$this->assertArrayHasKey('fields', $this->object->get('entityDefs.User'));
}
public function testSet()
@@ -238,13 +245,6 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
public function testGetCustom()
{
$customPath = 'tests/unit/testData/cache/metadata/custom';
$paths = $this->reflection->getProperty('paths');
$paths['customPath'] = $customPath;
$this->reflection->setProperty('paths', $paths);
$this->assertNull($this->object->getCustom('entityDefs', 'Lead'));
$customData = $this->object->getCustom('entityDefs', 'Lead', (object) []);
@@ -264,19 +264,11 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($data, $this->object->getCustom('entityDefs', 'Lead'));
unlink($customPath . '/entityDefs/Lead.json');
unlink($this->customPath . '/entityDefs/Lead.json');
}
public function testSaveCustom()
public function testSaveCustom1()
{
$initStatusOptions = $this->object->get('entityDefs.Lead.fields.status.options');
$customPath = 'tests/unit/testData/cache/metadata/custom';
$paths = $this->reflection->getProperty('paths');
$paths['customPath'] = $customPath;
$this->reflection->setProperty('paths', $paths);
$data = (object) [
'fields' => (object) [
'status' => (object) [
@@ -288,28 +280,18 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
$this->object->saveCustom('entityDefs', 'Lead', $data);
$savedFile = $customPath . '/entityDefs/Lead.json';
$savedFile = $this->customPath . '/entityDefs/Lead.json';
$fileContent = $this->fileManager->getContents($savedFile);
$savedData = \Espo\Core\Utils\Json::decode($fileContent);
$this->assertEquals($data, $savedData);
$initStatusOptions[] = 'Test1';
$initStatusOptions[] = 'Test2';
$this->assertEquals($initStatusOptions, $this->object->get('entityDefs.Lead.fields.status.options'));
unlink($savedFile);
}
public function testSaveCustom2()
{
$customPath = 'tests/unit/testData/cache/metadata/custom';
$paths = $this->reflection->getProperty('paths');
$paths['customPath'] = $customPath;
$this->reflection->setProperty('paths', $paths);
$initData = (object) [
'fields' => (object) [
'status' => (object) [
@@ -327,8 +309,10 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
$customData->fields->status->options = ["__APPEND__", "Test1"];
$this->object->saveCustom('entityDefs', 'Lead', $customData);
$savedFile = $customPath . '/entityDefs/Lead.json';
$savedFile = $this->customPath . '/entityDefs/Lead.json';
$fileContent = $this->fileManager->getContents($savedFile);
$savedData = \Espo\Core\Utils\Json::decode($fileContent);
$expectedData = (object) [
@@ -346,11 +330,9 @@ class MetadataTest extends \PHPUnit\Framework\TestCase
public function testGetObjects()
{
$result = 'System';
$this->assertEquals($result, $this->object->getObjects('app.adminPanel.system.label'));
$this->assertEquals('System', $this->object->getObjects('app.adminPanel.system.label'));
$result = 'fields';
$this->assertObjectHasAttribute($result, $this->object->getObjects('entityDefs.User'));
$this->assertObjectHasAttribute('fields', $this->object->getObjects('entityDefs.User'));
$this->assertObjectHasAttribute('type', $this->object->getObjects('entityDefs.User.fields.name'));
}
@@ -0,0 +1,114 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Utils\Resource;
use Espo\Core\Utils\Resource\Reader;
use Espo\Core\Utils\Resource\ReaderParams;
use Espo\Core\Utils\File\Unifier;
use Espo\Core\Utils\File\UnifierObj;
class ReaderTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Reader
*/
private $reader;
/**
* @var Unifier
*/
private $unifier;
/**
* @var UnifierObj
*/
private $unifierObj;
protected function setUp(): void
{
$this->unifier = $this->createMock(Unifier::class);
$this->unifierObj = $this->createMock(UnifierObj::class);
$this->reader = new Reader($this->unifier, $this->unifierObj);
}
public function testRead1(): void
{
$params = ReaderParams::create();
$this->unifierObj
->expects($this->once())
->method('unify')
->with([
'corePath' => 'application/Espo/Resources/test/hello',
'modulePath' => 'application/Espo/Modules/{*}/Resources/test/hello',
'customPath' => 'custom/Espo/Custom/Resources/test/hello',
])
->willReturn((object) []);
$this->reader->read('test/hello', $params);
}
public function testRead2(): void
{
$params = ReaderParams::create()
->withAsArray();
$this->unifier
->expects($this->once())
->method('unify')
->with([
'corePath' => 'application/Espo/Resources/test/hello',
'modulePath' => 'application/Espo/Modules/{*}/Resources/test/hello',
'customPath' => 'custom/Espo/Custom/Resources/test/hello',
])
->willReturn([]);
$this->reader->read('test/hello', $params);
}
public function testRead3(): void
{
$params = ReaderParams::create()
->withAsArray()
->withNoCustom();
$this->unifier
->expects($this->once())
->method('unify')
->with([
'corePath' => 'application/Espo/Resources/test/hello',
'modulePath' => 'application/Espo/Modules/{*}/Resources/test/hello',
])
->willReturn([]);
$this->reader->read('test/hello', $params);
}
}