refactoring

This commit is contained in:
Yuri Kuznetsov
2021-04-24 12:58:51 +03:00
parent 46fbd93d9b
commit e116c52ea9
8 changed files with 128 additions and 171 deletions

View File

@@ -376,64 +376,27 @@ class Manager
}
/**
* Merge file content and save it to a file.
*
* @param string | array $path
* @param string $content JSON string
* @param bool $isReturnJson
* @param string | array $removeOptions List of unset keys from content.
* @param bool $isPhp Is merge php files.
*
* @return bool | array
* Merge JSON file contents with existing and override the file.
*/
public function mergeContents($path, $content, $isReturnJson = false, $removeOptions = null, $isPhp = false)
public function mergeJsonContents(string $path, array $data): bool
{
if ($isPhp) {
$fileContent = $this->getPhpContents($path);
}
else {
$fileContent = $this->getContents($path);
$currentContents = $this->getContents($path);
if ($this->isFile($path) && $currentContents === false) {
throw new Error("FileManager: Failed to read file '{$path}'.");
}
$fullPath = $this->concatPaths($path);
$currentData = $this->isFile($path) ?
Json::decode($currentContents, true):
[];
if (file_exists($fullPath) && ($fileContent === false || empty($fileContent))) {
throw new Error('FileManager: Failed to read file [' . $fullPath .'].');
}
$mergedData = Util::merge($currentData, $data);
$savedDataArray = Json::decode($fileContent, true);
$jsonOptions = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
$newDataArray = Json::decode($content, true);
$stringData = Json::encode($mergedData, $jsonOptions);
if (isset($removeOptions)) {
$savedDataArray = Util::unsetInArray($savedDataArray, $removeOptions);
$newDataArray = Util::unsetInArray($newDataArray, $removeOptions);
}
$data = Util::merge($savedDataArray, $newDataArray);
if ($isReturnJson) {
$data = Json::encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
if ($isPhp) {
return $this->putPhpContents($path, $data);
}
return $this->putContents($path, $data);
}
/**
* Merge PHP content and save it to a file.
*
* @param string | array $path
* @param string $content JSON string
* @param string | array $removeOptions - List of unset keys from content
* @return bool
*/
public function mergePhpContents($path, $content, $removeOptions = null)
{
return $this->mergeContents($path, $content, false, $removeOptions, true);
return (bool) $this->putContents($path, $stringData);
}
/**
@@ -450,39 +413,33 @@ class Manager
}
/**
* Unset some element of content data.
*
* @param string | array $path
* @param array | string $unsets
* @return bool
* Unset specific items in a JSON file and override the file.
* Items are specified as an array of JSON paths.
*/
public function unsetContents($path, $unsets, $isJSON = true)
public function unsetJsonContents(string $path, array $unsets): bool
{
$currentData = $this->getContents($path);
if (!isset($currentData) || !$currentData) {
if (!file_exists($path)) {
return true;
}
$currentDataArray = Json::decode($currentData, true);
$currentContents = $this->getContents($path);
$unsettedData = Util::unsetInArray($currentDataArray, $unsets, true);
if (is_null($unsettedData) || (is_array($unsettedData) && empty($unsettedData))) {
$fullPath = $this->concatPaths($path);
if (!file_exists($fullPath)) {
return true;
}
return $this->unlink($fullPath);
if (!isset($currentContents) || !$currentContents) {
return true;
}
if ($isJSON) {
return $this->putContentsJson($path, $unsettedData);
$currentData = Json::decode($currentContents, true);
$unsettedData = Util::unsetInArray($currentData, $unsets, true);
if (
is_null($unsettedData) ||
(is_array($unsettedData) && empty($unsettedData))
) {
return $this->unlink($path);
}
return $this->putContents($path, $unsettedData);
return (bool) $this->putContentsJson($path, $unsettedData);
}

View File

@@ -29,9 +29,12 @@
namespace Espo\Core\Utils\File;
use Espo\Core\Utils;
use Espo\Core\Utils\Util;
use Espo\Core\Exceptions\Error;
use Throwable;
class Permission
{
private $fileManager;
@@ -89,12 +92,6 @@ class Permission
}
}
}
protected function getFileManager()
{
return $this->fileManager;
}
/**
* Get default settings.
*
@@ -179,7 +176,7 @@ class Permission
/**
* Change permissions.
*
* @param string $filename
* @param string $path
* @param int|array $octal ex. 0755, array(0644, 0755), array('file'=>0644, 'dir'=>0755).
* @param bool $recurse
*
@@ -245,7 +242,7 @@ class Permission
/**
* Change permissions recursive.
*
* @param string $filename
* @param string $path
* @param int $fileOctal - ex. 0644
* @param int $dirOctal - ex. 0755
*
@@ -263,9 +260,10 @@ class Permission
$result = $this->chmodReal($path, $dirOctal);
$allFiles = $this->getFileManager()->getFileList($path);
$allFiles = $this->fileManager->getFileList($path);
foreach ($allFiles as $item) {
$result &= $this->chmodRecurse($path . Utils\Util::getSeparator() . $item, $fileOctal, $dirOctal);
$result &= $this->chmodRecurse($path . Util::getSeparator() . $item, $fileOctal, $dirOctal);
}
return (bool) $result;
@@ -319,9 +317,9 @@ class Permission
$result = $this->chownReal($path, $user);
$allFiles = $this->getFileManager()->getFileList($path);
$allFiles = $this->fileManager->getFileList($path);
foreach ($allFiles as $item) {
$result &= $this->chownRecurse($path . Utils\Util::getSeparator() . $item, $user);
$result &= $this->chownRecurse($path . Util::getSeparator() . $item, $user);
}
return (bool) $result;
@@ -376,9 +374,9 @@ class Permission
$result = $this->chgrpReal($path, $group);
$allFiles = $this->getFileManager()->getFileList($path);
$allFiles = $this->fileManager->getFileList($path);
foreach ($allFiles as $item) {
$result &= $this->chgrpRecurse($path . Utils\Util::getSeparator() . $item, $group);
$result &= $this->chgrpRecurse($path . Util::getSeparator() . $item, $group);
}
return (bool) $result;
@@ -500,7 +498,7 @@ class Permission
try {
$this->chmod($path, $this->writablePermissions, $options['recursive']);
}
catch (\Throwable $e) {}
catch (Throwable $e) {}
/** check is writable */
$res = is_writable($path);
@@ -508,10 +506,12 @@ class Permission
if (is_dir($path)) {
try {
$name = uniqid();
$res &= $this->getFileManager()->putContents([$path, $name], 'test');
$res &= $this->getFileManager()->removeFile($name, $path);
$res &= $this->fileManager->putContents($path . '/' . $name, 'test');
$res &= $this->fileManager->removeFile($name, $path);
}
catch (\Throwable $e) {
catch (Throwable $e) {
$res = false;
}
}

View File

@@ -72,7 +72,7 @@ class Language
];
public function __construct(
?string $language = null,
?string $language,
FileManager $fileManager,
Metadata $metadata,
DataCache $dataCache = null,
@@ -81,7 +81,8 @@ class Language
) {
if ($language) {
$this->currentLanguage = $language;
} else {
}
else {
$this->currentLanguage = $this->defaultLanguage;
}
@@ -99,16 +100,6 @@ class Language
$this->unifier = new FileUnifier($this->fileManager, $this->metadata);
}
protected function getFileManager()
{
return $this->fileManager;
}
protected function getMetadata()
{
return $this->metadata;
}
protected function getUnifier()
{
return $this->unifier;
@@ -247,17 +238,22 @@ class Language
if (!empty($this->changedData)) {
foreach ($this->changedData as $scope => $data) {
if (!empty($data)) {
$result &= $this->getFileManager()->mergeContents([$path, $scope.'.json'], $data, true);
if (empty($data)) {
continue;
}
$result &= $this->fileManager->mergeJsonContents($path . "/{$scope}.json", $data);
}
}
if (!empty($this->deletedData)) {
foreach ($this->deletedData as $scope => $unsetData) {
if (!empty($unsetData)) {
$result &= $this->getFileManager()->unsetContents([$path, $scope.'.json'], $unsetData, true);
if (empty($unsetData)) {
continue;
}
$result &= $this->fileManager->unsetJsonContents($path . "/{$scope}.json", $unsetData);
}
}
@@ -322,11 +318,11 @@ class Language
/**
* Remove a label.
*
* @param string $name
* @param string $category
* @param string $scope
* @param string $scope
* @param string $category
* @param string|array $name
*/
public function delete($scope, $category, $name)
public function delete(string $scope, string $category, $name): void
{
if (is_array($name)) {
foreach ($name as $rowLabel) {

View File

@@ -38,6 +38,8 @@ use Espo\Core\{
Utils\DataCache,
};
use StdClass;
class Metadata
{
protected $data = null;
@@ -46,8 +48,6 @@ class Metadata
protected $useCache;
private $unifier;
private $objUnifier;
private $module;
@@ -75,6 +75,7 @@ class Metadata
private $changedData = [];
private $fileManager;
private $dataCache;
public function __construct(FileManager $fileManager, DataCache $dataCache, bool $useCache = false)
@@ -352,14 +353,15 @@ class Metadata
/**
* Get metadata definition in custom directory.
*
* @param string|array $key
* @param mixed $default
* @param string|array $key
* @param mixed $default
*
* @return object|mixed
* @return object
*/
public function getCustom($key1, $key2, $default = null)
{
$filePath = array($this->paths['customPath'], $key1, $key2.'.json');
$filePath = $this->paths['customPath'] . "/{$key1}/{$key2}.json";
$fileContent = $this->fileManager->getContents($filePath);
if ($fileContent) {
@@ -373,43 +375,33 @@ class Metadata
* Set and save metadata in custom directory.
* The data is not merging with existing data. Use getCustom() to get existing data.
*
* @param string $key1
* @param string $key2
* @param array $data
*
* @return boolean
* @param string $key1
* @param string $key2
* @param array|object $data
*/
public function saveCustom($key1, $key2, $data)
public function saveCustom(string $key1, string $key2, $data): void
{
if (is_object($data)) {
foreach ($data as $key => $item) {
if ($item == new \stdClass()) {
if ($item == new StdClass()) {
unset($data->$key);
}
}
}
$filePath = array($this->paths['customPath'], $key1, $key2.'.json');
$filePath = $this->paths['customPath'] . "/{$key1}/{$key2}.json";
$changedData = Json::encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$result = $this->fileManager->putContents($filePath, $changedData);
$this->fileManager->putContents($filePath, $changedData);
$this->init(true);
return true;
}
/**
* Set Metadata data.
* Ex. $key1 = menu, $key2 = Account then will be created a file metadataFolder/menu/Account.json
*
* @param string $key1
* @param string $key2
* @param JSON string $data
*
* @return bool
*/
public function set($key1, $key2, $data)
* Set Metadata data.
*/
public function set(string $key1, string $key2, $data): void
{
if (is_array($data)) {
foreach ($data as $key => $item) {
@@ -419,11 +411,11 @@ class Metadata
}
}
$newData = array(
$key1 => array(
$newData = [
$key1 => [
$key2 => $data,
),
);
],
];
$this->changedData = Util::merge($this->changedData, $newData);
$this->data = Util::merge($this->getData(), $newData);
@@ -434,13 +426,11 @@ class Metadata
/**
* Unset some fields and other stuff in metadata.
*
* @param string $key1
* @param string $key2
* @param array | string $unsets Ex. 'fields.name'
* @param array|string $unsets Ex. `fields.name`.
*
* @return bool
*/
public function delete($key1, $key2, $unsets = null)
public function delete(string $key1, string $key2, $unsets = null)
{
if (!is_array($unsets)) {
$unsets = (array) $unsets;
@@ -459,7 +449,9 @@ class Metadata
$fieldPath = [$key1, $key2, 'fields', $fieldName];
$additionalFields = $this->getMetadataHelper()->getAdditionalFieldList(
$fieldName, $this->get($fieldPath, []), $fieldDefinitionList
$fieldName,
$this->get($fieldPath, []),
$fieldDefinitionList
);
if (is_array($additionalFields)) {
@@ -524,7 +516,7 @@ class Metadata
*
* @return bool
*/
public function save()
public function save(): bool
{
$path = $this->paths['customPath'];
@@ -533,9 +525,13 @@ class Metadata
if (!empty($this->changedData)) {
foreach ($this->changedData as $key1 => $keyData) {
foreach ($keyData as $key2 => $data) {
if (!empty($data)) {
$result &= $this->fileManager->mergeContents([$path, $key1, $key2.'.json'], $data, true);
if (empty($data)) {
continue;
}
$filePath = $path . "/{$key1}/{$key2}.json";
$result &= $this->fileManager->mergeJsonContents($filePath, $data);
}
}
}
@@ -543,25 +539,27 @@ class Metadata
if (!empty($this->deletedData)) {
foreach ($this->deletedData as $key1 => $keyData) {
foreach ($keyData as $key2 => $unsetData) {
if (!empty($unsetData)) {
$rowResult = $this->fileManager->unsetContents(
[$path, $key1, $key2.'.json'], $unsetData, true
);
if ($rowResult == false) {
$GLOBALS['log']->warning(
'Metadata items ['.$key1.'.'.$key2.'] can be deleted for custom code only.'
);
}
$result &= $rowResult;
if (empty($unsetData)) {
continue;
}
$filePath = $path . "/{$key1}/{$key2}.json";
$rowResult = $this->fileManager->unsetJsonContents($filePath, $unsetData);
if (!$rowResult) {
$GLOBALS['log']->warning(
'Metadata items ['.$key1.'.'.$key2.'] can be deleted for custom code only.'
);
}
$result &= $rowResult;
}
}
}
if ($result == false) {
throw new Error("Error saving metadata. See log file for details.");
if (!$result) {
throw new Error("Error while saving metadata. See log file for details.");
}
$this->clearChanges();

View File

@@ -263,12 +263,12 @@ class EntityManager
}
if ($this->checkControllerExists($name)) {
throw new Conflict('Entity name \''.$name.'\' is not allowed.');
throw new Conflict('Entity name \''.$name.'\' is not allowed. Controller already exists.');
}
$serviceFactory = $this->getServiceFactory();
if ($serviceFactory && $serviceFactory->checKExists($name)) {
if ($serviceFactory && $serviceFactory->checkExists($name)) {
throw new Conflict('Entity name \''.$name.'\' is not allowed.');
}
@@ -486,6 +486,7 @@ class EntityManager
$this->getBaseLanguage()->save();
$layoutsPath = $templatePath . "/Layouts/{$type}";
if ($this->getFileManager()->isDir($layoutsPath)) {
$this->getFileManager()->copy($layoutsPath, 'custom/Espo/Custom/Resources/layouts/' . $name);
}

View File

@@ -550,7 +550,9 @@ class FieldManager
}
}
return $this->getMetadata()->saveCustom('entityDefs', $scope, $customDefs);
$this->getMetadata()->saveCustom('entityDefs', $scope, $customDefs);
return true;
}
protected function getLinkDefs($scope, $name)

View File

@@ -119,7 +119,9 @@ class LayoutManager
$data = Json::encode($layoutData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$result &= $this->fileManager->putContents([$layoutPath, $layoutName.'.json'], $data);
$path = $layoutPath . '/' . $layoutName . '.json';
$result &= $this->fileManager->putContents($path, $data);
}
}

View File

@@ -186,10 +186,11 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
$initData = '{"fields":{"someName":{"type":"varchar","maxLength":40},"someName2":{"type":"varchar","maxLength":36}}}';
$this->object->putContents($testPath, $initData);
$unsets = 'fields.someName2';
$this->assertTrue($this->object->unsetContents($testPath, $unsets));
$unsets = ['fields.someName2'];
$this->assertTrue($this->object->unsetJsonContents($testPath, $unsets));
$result = '{"fields":{"someName":{"type":"varchar","maxLength":40}}}';
$this->assertJsonStringEqualsJsonFile($testPath, $result);
}