Merge branch 'hotfix/2.9.1' of ssh://172.20.0.1/var/git/espo/backend into hotfix/2.9.1

This commit is contained in:
yuri
2015-01-22 15:14:25 +02:00
6 changed files with 453 additions and 83 deletions
+7 -7
View File
@@ -39,7 +39,6 @@ class FieldManager
protected $customOptionName = 'isCustom';
public function __construct(Metadata $metadata, Language $language)
{
$this->metadata = $metadata;
@@ -122,7 +121,8 @@ class FieldManager
'links.'.$name,
);
$res = $this->getMetadata()->delete($unsets, $this->metadataType, $scope);
$this->getMetadata()->delete($this->metadataType, $scope, $unsets);
$res = $this->getMetadata()->save();
$res &= $this->deleteLabel($name, $scope);
return (bool) $res;
@@ -132,25 +132,25 @@ class FieldManager
{
$fieldDef = $this->normalizeDefs($name, $fieldDef, $scope);
$data = Json::encode($fieldDef);
$res = $this->getMetadata()->set($data, $this->metadataType, $scope);
$this->getMetadata()->set($this->metadataType, $scope, $fieldDef);
$res = $this->getMetadata()->save();
return $res;
}
protected function setTranslatedOptions($name, $value, $scope)
{
return $this->getLanguage()->set($name, $value, 'options', $scope);
return $this->getLanguage()->set($scope, 'options', $name, $value);
}
protected function setLabel($name, $value, $scope)
{
return $this->getLanguage()->set($name, $value, 'fields', $scope);
return $this->getLanguage()->set($scope, 'fields', $name, $value);
}
protected function deleteLabel($name, $scope)
{
$this->getLanguage()->delete($name, 'fields', $scope);
$this->getLanguage()->delete($scope, 'fields', $name);
return $this->getLanguage()->save();
}
+43 -20
View File
@@ -220,7 +220,6 @@ class Language
}
$this->clearChanges();
$this->init(true);
return (bool) $result;
}
@@ -234,6 +233,7 @@ class Language
{
$this->changedData = array();
$this->deletedData = array();
$this->init(true);
}
/**
@@ -253,53 +253,76 @@ class Language
/**
* Set/change a label
* @param string | array $label
* @param mixed $value
* @param string $category
*
* @param string $scope
* @param string $category
* @param string | array $name
* @param mixed $value
*
* @return void
*/
public function set($label, $value, $category = 'labels', $scope = 'Global')
public function set($scope, $category, $name, $value)
{
if (is_array($label)) {
foreach ($label as $rowLabel => $rowValue) {
$this->set($rowLabel, $rowValue, $category, $scope);
if (is_array($name)) {
foreach ($name as $rowLabel => $rowValue) {
$this->set($scope, $category, $rowLabel, $rowValue);
}
return;
}
$this->changedData[$scope][$category][$label] = $value;
$this->changedData[$scope][$category][$name] = $value;
$currentLanguage = $this->getLanguage();
$this->data[$currentLanguage][$scope][$category][$label] = $value;
if (!isset($this->data[$currentLanguage])) {
$this->init();
}
$this->data[$currentLanguage][$scope][$category][$name] = $value;
$this->undelete($scope, $category, $name);
}
/**
* Remove a label
*
* @param string $label
* @param string $name
* @param string $category
* @param string $scope
*
* @return void
*/
public function delete($label, $category = 'labels', $scope = 'Global')
public function delete($scope, $category, $name)
{
if (is_array($label)) {
foreach ($label as $rowLabel) {
$this->delete($rowLabel, $category, $scope);
if (is_array($name)) {
foreach ($name as $rowLabel) {
$this->delete($scope, $category, $rowLabel);
}
return;
}
$this->deletedData[$scope][$category][] = $label;
$this->deletedData[$scope][$category][] = $name;
$currentLanguage = $this->getLanguage();
if (isset($this->data[$currentLanguage][$scope][$category][$label])) {
unset($this->data[$currentLanguage][$scope][$category][$label]);
if (!isset($this->data[$currentLanguage])) {
$this->init();
}
if (isset($this->changedData[$scope][$category][$label])) {
unset($this->changedData[$scope][$category][$label]);
if (isset($this->data[$currentLanguage][$scope][$category][$name])) {
unset($this->data[$currentLanguage][$scope][$category][$name]);
}
if (isset($this->changedData[$scope][$category][$name])) {
unset($this->changedData[$scope][$category][$name]);
}
}
protected function undelete($scope, $category, $name)
{
if (isset($this->deletedData[$scope][$category])) {
foreach ($this->deletedData[$scope][$category] as $key => $labelName) {
if ($name === $labelName) {
unset($this->deletedData[$scope][$category][$key]);
}
}
}
}
+113 -22
View File
@@ -61,6 +61,10 @@ class Metadata
*/
protected $defaultModuleOrder = 10;
private $deletedData = array();
private $changedData = array();
public function __construct(\Espo\Core\Utils\Config $config, \Espo\Core\Utils\File\Manager $fileManager)
{
$this->config = $config;
@@ -213,52 +217,139 @@ class Metadata
/**
* Set Metadata data
* Ex. $type= menu, $scope= Account then will be created a file metadataFolder/menu/Account.json
* 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
* @param string $type - ex. menu
* @param string $scope - Account
*
* @return bool
*/
public function set($data, $type, $scope)
public function set($key1, $key2, $data)
{
$path = $this->paths['customPath'];
$newData = array(
$key1 => array(
$key2 => $data,
),
);
$result = $this->getFileManager()->mergeContents(array($path, $type, $scope.'.json'), $data, true);
if ($result === false) {
throw new Error("Error saving metadata. See log file for details.");
}
$this->changedData = Util::merge($this->changedData, $newData);
$this->meta = Util::merge($this->getData(), $newData);
$this->init(true);
return $result;
$this->undelete($key1, $key2, $data);
}
/**
* Unset some fields and other stuff in metadat
*
* @param string $key1
* @param string $key2
* @param array | string $unsets Ex. 'fields.name'
* @param string $type Ex. 'entityDefs'
* @param string $scope
*
* @return bool
*/
public function delete($unsets, $type, $scope)
public function delete($key1, $key2, $unsets)
{
if (!is_array($unsets)) {
$unsets = (array) $unsets;
}
$normalizedData = array(
'__APPEND__',
);
$metaUnsetData = array();
foreach ($unsets as $unsetItem) {
$normalizedData[] = $unsetItem;
$metaUnsetData[] = implode('.', array($key1, $key2, $unsetItem));
}
$unsetData = array(
$key1 => array(
$key2 => $normalizedData,
),
);
$this->deletedData = Util::merge($this->deletedData, $unsetData);
$this->deletedData = Util::unsetInArrayByValue('__APPEND__', $this->deletedData);
$this->meta = Util::unsetInArray($this->getData(), $metaUnsetData);
}
/**
* Undelete the deleted items
*
* @param string $key1
* @param string $key2
* @param array $data
* @return void
*/
protected function undelete($key1, $key2, $data)
{
if (isset($this->deletedData[$key1][$key2])) {
foreach ($this->deletedData[$key1][$key2] as $unsetIndex => $unsetItem) {
$value = Util::getValueByKey($data, $unsetItem);
if (isset($value)) {
unset($this->deletedData[$key1][$key2][$unsetIndex]);
}
}
}
}
/**
* Clear unsaved changes
*
* @return void
*/
public function clearChanges()
{
$this->changedData = array();
$this->deletedData = array();
$this->init(true);
}
/**
* Save changes
*
* @return bool
*/
public function save()
{
$path = $this->paths['customPath'];
$result = $this->getFileManager()->unsetContents(array($path, $type, $scope.'.json'), $unsets, true);
if ($result == false) {
$GLOBALS['log']->warning('Delete metadata items available only for custom code.');
$result = true;
if (!empty($this->changedData)) {
foreach ($this->changedData as $key1 => $keyData) {
foreach ($keyData as $key2 => $data) {
if (!empty($data)) {
$result &= $this->getFileManager()->mergeContents(array($path, $key1, $key2.'.json'), $data, true);
}
}
}
}
$this->init(true);
if (!empty($this->deletedData)) {
foreach ($this->deletedData as $key1 => $keyData) {
foreach ($keyData as $key2 => $unsetData) {
if (!empty($unsetData)) {
$rowResult = $this->getFileManager()->unsetContents(array($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;
}
}
}
}
return $result;
if ($result == false) {
throw new Error("Error saving metadata. See log file for details.");
}
$this->clearChanges();
return (bool) $result;
}
public function getOrmMetadata($reload = false)
{
if (!empty($this->ormMeta) && is_array($this->ormMeta) && !$reload) {
+3 -4
View File
@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -89,7 +89,7 @@ class FieldManagerTest extends \PHPUnit_Framework_TestCase
->method('get')
->will($this->returnValue($data));
$this->assertTrue($this->object->update('name', $data, 'Account'));
$this->object->update('name', $data, 'Account');
}
public function testUpdateCustomFieldIsNotChanged()
@@ -138,10 +138,9 @@ class FieldManagerTest extends \PHPUnit_Framework_TestCase
"isCustom" => true,
);
$this->assertTrue($this->object->update('varName', $data, 'CustomEntity'));
$this->object->update('varName', $data, 'CustomEntity');
}
public function testRead()
{
$data = array(
+111 -11
View File
@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -80,7 +80,6 @@ class LanguageTest extends \PHPUnit_Framework_TestCase
$this->object->setLanguage($originalLang);
}
public function testGetLangCacheFile()
{
$cacheFile = $this->cacheFile;
@@ -96,7 +95,6 @@ class LanguageTest extends \PHPUnit_Framework_TestCase
$this->object->setLanguage($originalLang);
}
public function testGetData()
{
$result = array (
@@ -142,7 +140,6 @@ class LanguageTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($result, $this->reflection->invokeMethod('getData', array()));
}
public function testGet()
{
$result = array (
@@ -204,7 +201,6 @@ class LanguageTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($result, $this->object->translate('language', 'options', 'Global', $requiredOptions));
}
public function testTranslateArray()
{
$input = array(
@@ -227,20 +223,124 @@ class LanguageTest extends \PHPUnit_Framework_TestCase
public function testSet()
{
$label = 'TEST';
$this->object->set('label', $label, 'fields', 'User');
$this->object->set('User', 'fields', 'label', $label);
$this->assertEquals($label, $this->object->translate('label', 'fields', 'User'));
$result = array(
'User' => array(
'fields' => array(
'label' => 'TEST',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('changedData'));
$label2 = 'TEST2';
$this->object->set('name', $label2, 'fields', 'User');
$this->object->set('User', 'fields', 'name', $label2);
$this->assertEquals($label2, $this->object->translate('name', 'fields', 'User'));
$result = array(
'User' => array(
'fields' => array(
'label' => 'TEST',
'name' => 'TEST2',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('changedData'));
$label3 = 'TEST3';
$this->object->set('name', $label3, 'fields', 'Account');
$this->object->set('Account', 'fields', 'name', $label3);
$this->assertEquals($label3, $this->object->translate('name', 'fields', 'Account'));
$this->reflection->invokeMethod('init', array(true));
$result = array(
'User' => array(
'fields' => array(
'label' => 'TEST',
'name' => 'TEST2',
),
),
'Account' => array(
'fields' => array(
'name' => 'TEST3',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('changedData'));
$this->object->clearChanges();
$this->assertEquals(array(), $this->reflection->getProperty('changedData'));
$this->assertNotEquals('TEST', $this->object->get('User', 'fields', 'label'));
}
public function testDelete()
{
$this->object->delete('User', 'fields', 'label');
$this->assertNull($this->object->get('User.fields.label'));
$result = array(
'User' => array(
'fields' => array(
'label',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
$this->object->delete('User', 'fields', 'name');
$this->assertNull($this->object->get('User.fields.name'));
$result = array(
'User' => array(
'fields' => array(
'label',
'name',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
$this->object->clearChanges();
$this->assertNotNull($this->object->get('User.fields.label'));
$this->assertNotNull($this->object->get('User.fields.name'));
$this->assertEquals(array(), $this->reflection->getProperty('deletedData'));
}
public function testUndelete()
{
$this->object->delete('User', 'fields', 'label');
$this->assertNull($this->object->get('User.fields.label'));
$this->object->delete('User', 'fields', 'name');
$this->assertNull($this->object->get('User.fields.name'));
$label = 'TEST';
$this->object->set('User', 'fields', 'label', $label);
$this->assertEquals($label, $this->object->translate('label', 'fields', 'User'));
$result = array(
'User' => array(
'fields' => array(
1 => 'name',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
$label2 = 'TEST2';
$this->object->set('User', 'fields', 'name', $label2);
$this->assertEquals($label2, $this->object->translate('name', 'fields', 'User'));
$result = array(
'User' => array(
'fields' => array(
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
}
}
?>
+176 -19
View File
@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -24,52 +24,209 @@ namespace tests\Espo\Core\Utils;
use tests\ReflectionHelper;
class MetadataTest extends \PHPUnit_Framework_TestCase
{
protected $object;
protected $objects;
protected $reflection;
protected $defaultCacheFile = 'tests/testData/Utils/Metadata/metadata.php';
protected $cacheFile = 'tests/testData/cache/metadata.php';
protected $ormCacheFile = 'tests/testData/Utils/Metadata/ormMetadata.php';
protected function setUp()
{
{
/*copy defaultCacheFile file to cache*/
if (!file_exists($this->cacheFile)) {
copy($this->defaultCacheFile, $this->cacheFile);
}
$this->objects['config'] = $this->getMockBuilder('\Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock();
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
$this->objects['Unifier'] = $this->getMockBuilder('\Espo\Core\Utils\File\Unifier')->disableOriginalConstructor()->getMock();
//set to use cache
$this->objects['config']
->expects($this->any())
->method('get')
->will($this->returnValue(true));
->will($this->returnValue(true));
$this->object = new \Espo\Core\Utils\Metadata($this->objects['config'], $this->objects['fileManager']);
$this->reflection = new ReflectionHelper($this->object);
$this->reflection->setProperty('cacheFile', 'tests/testData/Utils/Metadata/metadata.php');
$this->reflection->setProperty('ormCacheFile', 'tests/testData/Utils/Metadata/ormMetadata.php');
$this->reflection = new ReflectionHelper($this->object);
$this->reflection->setProperty('cacheFile', $this->cacheFile);
$this->reflection->setProperty('ormCacheFile', $this->ormCacheFile);
}
protected function tearDown()
{
$this->object = NULL;
}
function testGet()
{
public function testGet()
{
$result = 'System';
$this->assertEquals($result, $this->object->get('app.adminPanel.system.label'));
$this->assertEquals($result, $this->object->get('app.adminPanel.system.label'));
$result = 'fields';
$this->assertArrayHasKey($result, $this->object->get('entityDefs.User'));
}
$this->assertArrayHasKey($result, $this->object->get('entityDefs.User'));
}
public function testSet()
{
$data = array (
'fields' =>
array (
'name' =>
array (
'required' => false,
'maxLength' => 150,
'view' => 'Views.Test.Custom',
),
),
);
$this->object->set('entityDefs', 'Attachment', $data);
$this->assertEquals('Views.Test.Custom', $this->object->get('entityDefs.Attachment.fields.name.view'));
$this->assertEquals(150, $this->object->get('entityDefs.Attachment.fields.name.maxLength'));
$result = array(
'entityDefs' => array(
'Attachment' => $data
),
);
$this->assertEquals($result, $this->reflection->getProperty('changedData'));
}
$data = array (
'fields' =>
array (
'name' =>
array (
'maxLength' => 200,
),
),
);
$this->object->set('entityDefs', 'Attachment', $data);
$this->assertEquals(200, $this->object->get('entityDefs.Attachment.fields.name.maxLength'));
$this->assertEquals('Views.Test.Custom', $this->object->get('entityDefs.Attachment.fields.name.view'));
?>
$result = array(
'entityDefs' => array(
'Attachment' => array (
'fields' =>
array (
'name' =>
array (
'required' => false,
'maxLength' => 200,
'view' => 'Views.Test.Custom',
),
),
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('changedData'));
$this->object->clearChanges();
$this->assertEquals(array(), $this->reflection->getProperty('changedData'));
$this->assertNull($this->object->get('entityDefs.Attachment.fields.name.view'));
}
public function testDelete()
{
$data = array (
'fields.name.type',
);
$this->object->delete('entityDefs', 'Attachment', $data);
$this->assertNull($this->object->get('entityDefs.Attachment.fields.name.type'));
$result = array(
'entityDefs' => array(
'Attachment' => array(
'fields.name.type',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
$data = array (
'fields.name.required',
);
$this->object->delete('entityDefs', 'Attachment', $data);
$this->assertNull($this->object->get('entityDefs.Attachment.fields.name.required'));
$result = array(
'entityDefs' => array(
'Attachment' => array(
'fields.name.type',
'fields.name.required',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
$this->object->init(false);
$this->assertNotNull($this->object->get('entityDefs.Attachment.fields.name.type'));
$this->assertNotNull($this->object->get('entityDefs.Attachment.fields.name.required'));
$this->object->clearChanges();
$this->assertEquals(array(), $this->reflection->getProperty('deletedData'));
}
public function testUndelete()
{
$data = array (
'fields.name.type',
'fields.name.required',
);
$this->object->delete('entityDefs', 'Attachment', $data);
$this->assertNull($this->object->get('entityDefs.Attachment.fields.name.type'));
$data = array (
'fields' =>
array (
'name' =>
array (
'type' => 'enum',
),
),
);
$this->object->set('entityDefs', 'Attachment', $data);
$this->assertEquals('enum', $this->object->get('entityDefs.Attachment.fields.name.type'));
$result = array(
'entityDefs' => array(
'Attachment' => array(
1 => 'fields.name.required',
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
$data = array (
'fields' =>
array (
'name' =>
array (
'required' => true,
),
),
);
$this->object->set('entityDefs', 'Attachment', $data);
$this->assertEquals(true, $this->object->get('entityDefs.Attachment.fields.name.required'));
$result = array(
'entityDefs' => array(
'Attachment' => array(
),
),
);
$this->assertEquals($result, $this->reflection->getProperty('deletedData'));
}
}