From 4c7d2d66f020743a23fccfe5bfeb78fa0ab04dff Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Fri, 30 Nov 2018 16:38:26 +0200 Subject: [PATCH] FieldManager: bug fixes --- application/Espo/Core/Utils/FieldManager.php | 167 +++++++++---------- application/Espo/Core/Utils/Util.php | 53 ++++++ 2 files changed, 131 insertions(+), 89 deletions(-) diff --git a/application/Espo/Core/Utils/FieldManager.php b/application/Espo/Core/Utils/FieldManager.php index 8f15c139be..fb446fbf2a 100644 --- a/application/Espo/Core/Utils/FieldManager.php +++ b/application/Espo/Core/Utils/FieldManager.php @@ -207,13 +207,11 @@ class FieldManager if (!is_null($fieldDefs['dynamicLogicVisible'])) { $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['fields'][$name]['visible'] = $fieldDefs['dynamicLogicVisible']; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } else { if ($this->getMetadata()->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'visible'])) { $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['fields'][$name]['visible'] = null; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } } @@ -223,13 +221,11 @@ class FieldManager if (!is_null($fieldDefs['dynamicLogicReadOnly'])) { $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['fields'][$name]['readOnly'] = $fieldDefs['dynamicLogicReadOnly']; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } else { if ($this->getMetadata()->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'readOnly'])) { $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['fields'][$name]['readOnly'] = null; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } } @@ -239,13 +235,11 @@ class FieldManager if (!is_null($fieldDefs['dynamicLogicRequired'])) { $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['fields'][$name]['required'] = $fieldDefs['dynamicLogicRequired']; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } else { if ($this->getMetadata()->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'required'])) { $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['fields'][$name]['required'] = null; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } } @@ -255,13 +249,11 @@ class FieldManager if (!is_null($fieldDefs['dynamicLogicOptions'])) { $this->prepareClientDefsOptionsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['options'][$name] = $fieldDefs['dynamicLogicOptions']; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } else { if ($this->getMetadata()->get(['clientDefs', $scope, 'dynamicLogic', 'options', $name])) { $this->prepareClientDefsOptionsDynamicLogic($clientDefs, $name); $clientDefs['dynamicLogic']['options'][$name] = null; - $metadataToBeSaved = true; $clientDefsToBeSet = true; } } @@ -269,13 +261,13 @@ class FieldManager if ($clientDefsToBeSet) { $this->getMetadata()->set('clientDefs', $scope, $clientDefs); + $metadataToBeSaved = true; } $entityDefs = $this->normalizeDefs($scope, $name, $fieldDefs); if (!empty($entityDefs)) { - $this->getMetadata()->set('entityDefs', $scope, $entityDefs); - $metadataToBeSaved = true; + $this->saveCustomdDefs($scope, $entityDefs); $this->isChanged = true; } @@ -430,6 +422,34 @@ class FieldManager return $this->getMetadata()->get('entityDefs'.'.'.$scope.'.fields.'.$name); } + protected function getCustomFieldDefs($scope, $name) + { + $customDefs = $this->getMetadata()->getCustom('entityDefs', $scope); + + if (isset($customDefs->fields->$name)) { + return (array) $customDefs->fields->$name; + } + } + + protected function saveCustomdDefs($scope, $newDefs) + { + $customDefs = $this->getMetadata()->getCustom('entityDefs', $scope); + + if (isset($newDefs->fields)) { + foreach ($newDefs->fields as $name => $defs) { + $customDefs->fields->$name = $defs; + } + } + + if (isset($newDefs->links)) { + foreach ($newDefs->links as $name => $defs) { + $customDefs->links->$name = $defs; + } + } + + return $this->getMetadata()->saveCustom('entityDefs', $scope, $customDefs); + } + protected function getLinkDefs($scope, $name) { return $this->getMetadata()->get('entityDefs'.'.'.$scope.'.links.'.$name); @@ -467,13 +487,19 @@ class FieldManager ] ]; + if (isset($fieldDefs['fieldManagerAdditionalParamList'])) { + foreach ($fieldDefs['fieldManagerAdditionalParamList'] as $additionalParam) { + $additionalParamList[$additionalParam->name] = [ + 'type' => $fieldDefs['type'] + ]; + } + } + $fieldDefsByType = $this->getMetadataHelper()->getFieldDefsByType($fieldDefs); if (!isset($fieldDefsByType['params'])) { return $fieldDefs; } - $filteredFieldDefs = []; - $params = []; foreach ($fieldDefsByType['params'] as $paramData) { $params[ $paramData['name'] ] = $paramData; @@ -483,25 +509,41 @@ class FieldManager $params[$paramName] = array_merge(['name' => $paramName], $paramValue); } } + + $actualCustomFieldDefs = $this->getCustomFieldDefs($scope, $name); + $actualFieldDefs = $this->getFieldDefs($scope, $name); $permittedParamList = array_keys($params); - foreach ($fieldDefs as $paramName => $paramValue) { - if (!isset($paramValue) || $paramValue === '') { - continue; - } + $filteredFieldDefs = $actualCustomFieldDefs ? $actualCustomFieldDefs : []; + foreach ($fieldDefs as $paramName => $paramValue) { if (in_array($paramName, $permittedParamList)) { switch ($params[$paramName]['type']) { case 'bool': - $fieldDefsDefaultValue = isset($params[$paramName]['default']) ? $params[$paramName]['default'] : false; + $fieldDefsDefaultValue = array_key_exists('default', $params[$paramName]) ? $params[$paramName]['default'] : false; - if ($fieldDefsDefaultValue !== $paramValue) { + $actualValue = array_key_exists($paramName, $actualFieldDefs) ? $actualFieldDefs[$paramName] : $fieldDefsDefaultValue; + + if (!Util::areValuesEqual($actualValue, $paramValue)) { $filteredFieldDefs[$paramName] = $paramValue; } break; default: - if (!isset($params[$paramName]['default']) || $params[$paramName]['default'] !== $paramValue) { + if (!array_key_exists('default', $params[$paramName]) && !array_key_exists($paramName, $actualFieldDefs)) { + $filteredFieldDefs[$paramName] = $paramValue; + break; + } + + if (array_key_exists('default', $params[$paramName])) { + $actualValue = $params[$paramName]['default']; + } + + if (array_key_exists($paramName, $actualFieldDefs)) { + $actualValue = $actualFieldDefs[$paramName]; + } + + if (!Util::areValuesEqual($actualValue, $paramValue)) { $filteredFieldDefs[$paramName] = $paramValue; } break; @@ -509,9 +551,14 @@ class FieldManager } } - $actualFieldDefs = $this->getFieldDefs($scope, $name); - if ($actualFieldDefs) { - foreach ($actualFieldDefs as $paramName => $paramValue) { + $metaFieldDefs = $this->getMetadataHelper()->getFieldDefsInFieldMeta($filteredFieldDefs); + if (isset($metaFieldDefs)) { + $filteredFieldDefs = Util::merge($metaFieldDefs, $filteredFieldDefs); + } + + if ($actualCustomFieldDefs) { + $actualCustomFieldDefs = array_diff_key($actualCustomFieldDefs, array_flip($permittedParamList)); + foreach ($actualCustomFieldDefs as $paramName => $paramValue) { if (!array_key_exists($paramName, $filteredFieldDefs)) { $filteredFieldDefs[$paramName] = $paramValue; } @@ -531,40 +578,28 @@ class FieldManager */ protected function normalizeDefs($scope, $fieldName, array $fieldDefs) { - $fieldDefs = $this->prepareFieldDefs($scope, $fieldName, $fieldDefs); + $defs = new \stdClass(); - $metaFieldDefs = $this->getMetadataHelper()->getFieldDefsInFieldMeta($fieldDefs); - if (isset($metaFieldDefs)) { - $fieldDefs = Util::merge($metaFieldDefs, $fieldDefs); - } + $normalizedFieldDefs = $this->prepareFieldDefs($scope, $fieldName, $fieldDefs); - if (isset($fieldDefs['linkDefs'])) { - $linkDefs = $fieldDefs['linkDefs']; - unset($fieldDefs['linkDefs']); - } - - $defs = array(); - - $currentFieldDefs = (array) $this->getFieldDefs($scope, $fieldName); - - $diffFieldDefs = $this->getDiffDefs($currentFieldDefs, $fieldDefs); - if (!empty($diffFieldDefs)) { - $defs['fields'] = array( - $fieldName => $diffFieldDefs, + if (!empty($normalizedFieldDefs)) { + $defs->fields = (object) array( + $fieldName => (object) $normalizedFieldDefs, ); } /** Save links for a field. */ + $linkDefs = isset($fieldDefs['linkDefs']) ? $fieldDefs['linkDefs'] : null; $metaLinkDefs = $this->getMetadataHelper()->getLinkDefsInFieldMeta($scope, $fieldDefs); - if (isset($linkDefs) || isset($metaLinkDefs)) { + if (isset($linkDefs) || isset($metaLinkDefs)) { $metaLinkDefs = isset($metaLinkDefs) ? $metaLinkDefs : array(); $linkDefs = isset($linkDefs) ? $linkDefs : array(); $normalizedLinkdDefs = Util::merge($metaLinkDefs, $linkDefs); if (!empty($normalizedLinkdDefs)) { - $defs['links'] = array( - $fieldName => $normalizedLinkdDefs, + $defs->links = (object) array( + $fieldName => (object) $normalizedLinkdDefs, ); } } @@ -572,51 +607,6 @@ class FieldManager return $defs; } - protected function getDiffDefs($defs, $newDefs) - { - $diff = array(); - - foreach ($newDefs as $optionName => $data) { - if (!array_key_exists($optionName, $defs)) { - $diff[$optionName] = $data; - continue; - } - - if (is_object($data) || is_array($data)) { - $diff[$optionName] = $data; - continue; - } - - if ($data !== $defs[$optionName]) { - $diff[$optionName] = $data; - } - } - - return $diff; - } - - /** - * Check if changed metadata defenition for a field except 'label' - * - * @param string $scope - * @param string $name - * @param array $fieldDefs - * - * @return boolean - */ - protected function isDefsChanged($scope, $name, $fieldDefs) - { - $fieldDefs = $this->prepareFieldDefs($scope, $name, $fieldDefs); - $currentFieldDefs = $this->getFieldDefs($scope, $name); - - $diffDefs = Util::arrayDiff($currentFieldDefs, $fieldDefs); - - $this->isChanged = empty($diffDefs) ? false : true; - - return $this->isChanged; - } - - protected function isLabelChanged($scope, $category, $name, $newLabel) { $currentLabel = $this->getLanguage()->get([$scope, $category, $name]); @@ -628,7 +618,6 @@ class FieldManager return false; } - public function isChanged() { return $this->isChanged; diff --git a/application/Espo/Core/Utils/Util.php b/application/Espo/Core/Utils/Util.php index fc27905e3a..8e7390a39c 100644 --- a/application/Espo/Core/Utils/Util.php +++ b/application/Espo/Core/Utils/Util.php @@ -653,4 +653,57 @@ class Util return $value; } + + public static function areValuesEqual($v1, $v2, $isUnordered = false) + { + if (is_array($v1) && is_array($v2)) { + if ($isUnordered) { + sort($v1); + sort($v2); + } + if ($v1 != $v2) { + return false; + } + foreach ($v1 as $i => $itemValue) { + if (is_object($v1[$i]) && is_object($v2[$i])) { + if (!self::areValuesEqual($v1[$i], $v2[$i])) { + return false; + } + continue; + } + if ($v1[$i] !== $v2[$i]) { + return false; + } + } + return true; + } + + if (is_object($v1) && is_object($v2)) { + if ($v1 != $v2) { + return false; + } + $a1 = get_object_vars($v1); + $a2 = get_object_vars($v2); + foreach ($v1 as $key => $itemValue) { + if (is_object($a1[$key]) && is_object($a2[$key])) { + if (!self::areValuesEqual($a1[$key], $a2[$key])) { + return false; + } + continue; + } + if (is_array($a1[$key]) && is_array($a2[$key])) { + if (!self::areValuesEqual($a1[$key], $a2[$key])) { + return false; + } + continue; + } + if ($a1[$key] !== $a2[$key]) { + return false; + } + } + return true; + } + + return $v1 === $v2; + } }