diff --git a/application/Espo/Core/Utils/FieldManager.php b/application/Espo/Core/Utils/FieldManager.php index 707e7bfef5..45169f555e 100644 --- a/application/Espo/Core/Utils/FieldManager.php +++ b/application/Espo/Core/Utils/FieldManager.php @@ -91,13 +91,17 @@ class FieldManager $res = true; if (isset($fieldDef['label'])) { - $res &= $this->setLabel($name, $fieldDef['label'], $scope); + $this->setLabel($name, $fieldDef['label'], $scope); } if (isset($fieldDef['type']) && $fieldDef['type'] == 'enum') { if (isset($fieldDef['translatedOptions'])) { - $res &= $this->setTranslatedOptions($name, $fieldDef['translatedOptions'], $scope); - } + $this->setTranslatedOptions($name, $fieldDef['translatedOptions'], $scope); + } + } + + if (isset($fieldDef['label']) || isset($fieldDef['translatedOptions'])) { + $res &= $this->getLanguage()->save(); } if ($this->isDefsChanged($name, $fieldDef, $scope)) { @@ -119,10 +123,9 @@ class FieldManager ); $res = $this->getMetadata()->delete($unsets, $this->metadataType, $scope); + $res &= $this->deleteLabel($name, $scope); - $this->deleteLabel($name, $scope); - - return $res; + return (bool) $res; } protected function setEntityDefs($name, $fieldDef, $scope) @@ -147,7 +150,8 @@ class FieldManager protected function deleteLabel($name, $scope) { - return $this->getLanguage()->delete($name, 'fields', $scope); + $this->getLanguage()->delete($name, 'fields', $scope); + return $this->getLanguage()->save(); } protected function getFieldDef($name, $scope) diff --git a/application/Espo/Core/Utils/Json.php b/application/Espo/Core/Utils/Json.php index af4d1565e4..841dee02b9 100644 --- a/application/Espo/Core/Utils/Json.php +++ b/application/Espo/Core/Utils/Json.php @@ -51,7 +51,7 @@ class Json } $error = self::getLastError(); - if ($json === null || $error) { + if ($json === null || !empty($error)) { $GLOBALS['log']->error('Json::encode():' . $error . ' - ' . print_r($value, true)); } @@ -69,6 +69,10 @@ class Json */ public static function decode($json, $assoc = false, $depth = 512, $options = 0) { + if (is_null($json) || $json === false) { + return $json; + } + if (is_array($json)) { $GLOBALS['log']->warning('Json::decode() - JSON cannot be decoded - '.$json); return false; @@ -85,14 +89,13 @@ class Json } $error = self::getLastError(); - if ($json === null || $error) { + if ($error) { $GLOBALS['log']->error('Json::decode():' . $error); } return $json; } - /** * Check if the string is JSON * @@ -110,7 +113,6 @@ class Json return static::decode($json) != null; } - /** * Get an array data (if JSON convert to array) * @@ -130,7 +132,6 @@ class Json return $returns; } - protected static function getLastError($error = null) { if (!isset($error)) { diff --git a/application/Espo/Core/Utils/Language.php b/application/Espo/Core/Utils/Language.php index 7bdf4361e1..4e8661d2bb 100644 --- a/application/Espo/Core/Utils/Language.php +++ b/application/Espo/Core/Utils/Language.php @@ -38,14 +38,11 @@ class Language * * @var array */ - private $allData = array(); + private $data = array(); - /** - * Data of current language - * - * @var array - */ - private $data = null; + private $deletedData = array(); + + private $changedData = array(); private $name = 'i18n'; @@ -175,7 +172,6 @@ class Language return $value; } - public function get($key = null, $returns = null) { $data = $this->getData(); @@ -187,12 +183,59 @@ class Language return Util::getValueByKey($data, $key, $returns); } - public function getAll() { return $this->get(); } + /** + * Save changes + * + * @return bool + */ + public function save() + { + $path = $this->paths['customPath']; + $currentLanguage = $this->getLanguage(); + + $result = true; + if (!empty($this->changedData)) { + foreach ($this->changedData as $scope => $data) { + if (!empty($data)) { + $result &= $this->getFileManager()->mergeContents(array($path, $currentLanguage, $scope.'.json'), $data, true); + } + } + } + + if (!empty($this->deletedData)) { + foreach ($this->deletedData as $scope => $unsetData) { + if (!empty($unsetData)) { + $result &= $this->getFileManager()->unsetContents(array($path, $currentLanguage, $scope.'.json'), $unsetData, true); + } + } + } + + if ($result == false) { + throw new Error("Error saving languages. See log file for details."); + } + + $this->clearChanges(); + $this->init(true); + + return (bool) $result; + } + + /** + * Clear unsaved changes + * + * @return void + */ + public function clearChanges() + { + $this->changedData = array(); + $this->deletedData = array(); + } + /** * Get data of Unifier language files * @@ -200,44 +243,64 @@ class Language */ protected function getData() { - if (!isset($this->data)) { + $currentLanguage = $this->getLanguage(); + if (!isset($this->data[$currentLanguage])) { $this->init(); } - return $this->data; + return $this->data[$currentLanguage]; } + /** + * Set/change a label + * @param string | array $label + * @param mixed $value + * @param string $category + * @param string $scope + */ public function set($label, $value, $category = 'labels', $scope = 'Global') { - $path = $this->paths['customPath']; - $currentLanguage = $this->getLanguage(); - - $data = $this->normalizeDefs($label, $value, $category); - - $result = $this->getFileManager()->mergeContents(array($path, $currentLanguage, $scope.'.json'), $data, true); - if ($result === false) { - throw new Error("Error saving languages. See log file for details."); + if (is_array($label)) { + foreach ($label as $rowLabel => $rowValue) { + $this->set($rowLabel, $rowValue, $category, $scope); + } + return; } - $this->init(true); + $this->changedData[$scope][$category][$label] = $value; - return $result; + $currentLanguage = $this->getLanguage(); + $this->data[$currentLanguage][$scope][$category][$label] = $value; } + /** + * Remove a label + * + * @param string $label + * @param string $category + * @param string $scope + * + * @return void + */ public function delete($label, $category = 'labels', $scope = 'Global') { - $path = $this->paths['customPath']; + if (is_array($label)) { + foreach ($label as $rowLabel) { + $this->delete($rowLabel, $category, $scope); + } + return; + } + + $this->deletedData[$scope][$category][] = $label; + $currentLanguage = $this->getLanguage(); + if (isset($this->data[$currentLanguage][$scope][$category][$label])) { + unset($this->data[$currentLanguage][$scope][$category][$label]); + } - $unsets = array( - $category => $label, - ); - - $result = $this->getFileManager()->unsetContents(array($path, $currentLanguage, $scope.'.json'), $unsets, true); - - $this->init(true); - - return $result; + if (isset($this->changedData[$scope][$category][$label])) { + unset($this->changedData[$scope][$category][$label]); + } } protected function init($reload = false) @@ -252,7 +315,7 @@ class Language $i18nData = Util::merge($fullData[$this->defaultLanguage], $i18nData); } - $this->allData[$i18nName] = $i18nData; + $this->data[$i18nName] = $i18nData; if ($this->getConfig()->get('useCache')) { $i18nCacheFile = str_replace('{*}', $i18nName, $this->cacheFile); @@ -266,34 +329,8 @@ class Language } $currentLanguage = $this->getLanguage(); - if (empty($this->allData[$currentLanguage])) { - $this->allData[$currentLanguage] = $this->getFileManager()->getContents($this->getLangCacheFile()); + if (empty($this->data[$currentLanguage])) { + $this->data[$currentLanguage] = $this->getFileManager()->getContents($this->getLangCacheFile()); } - - $this->data = $this->allData[$currentLanguage]; } - - protected function normalizeDefs($label, $value, $category) - { - if (!is_array($label)) { - $label = array( - $label => $value, - ); - } - - $data = array( - $category => $label, - ); - - return $data; - } - - - - - - - - - } diff --git a/application/Espo/Core/Utils/Util.php b/application/Espo/Core/Utils/Util.php index a94f34ba92..f752d0f693 100644 --- a/application/Espo/Core/Utils/Util.php +++ b/application/Espo/Core/Utils/Util.php @@ -380,7 +380,7 @@ class Util $unsetElem = $currVal . "['{$lastKey}']"; $currVal = " - if (isset({$unsetElem}) || ( is_array({$currVal}) && array_key_exists({$lastKey}, {$currVal}) )) { + if (isset({$unsetElem}) || ( is_array({$currVal}) && array_key_exists('{$lastKey}', {$currVal}) )) { unset({$unsetElem}); } "; eval($currVal); diff --git a/tests/Espo/Core/Utils/LanguageTest.php b/tests/Espo/Core/Utils/LanguageTest.php index 1ab1f71a05..d9593c3108 100644 --- a/tests/Espo/Core/Utils/LanguageTest.php +++ b/tests/Espo/Core/Utils/LanguageTest.php @@ -204,7 +204,22 @@ class LanguageTest extends \PHPUnit_Framework_TestCase $this->assertEquals($result, $this->object->translate('language.en_US', 'options')); } + public function testSet() + { + $label = 'TEST'; + $this->object->set('label', $label, 'fields', 'User'); + $this->assertEquals($label, $this->object->translate('label', 'fields', 'User')); + $label2 = 'TEST2'; + $this->object->set('name', $label2, 'fields', 'User'); + $this->assertEquals($label2, $this->object->translate('name', 'fields', 'User')); + + $label3 = 'TEST3'; + $this->object->set('name', $label3, 'fields', 'Account'); + $this->assertEquals($label3, $this->object->translate('name', 'fields', 'Account')); + + $this->reflection->invokeMethod('init', array(true)); + } }