diff --git a/application/Espo/Core/Utils/Database/Converter.php b/application/Espo/Core/Utils/Database/Converter.php index 4d2e264ac2..f94097f12c 100644 --- a/application/Espo/Core/Utils/Database/Converter.php +++ b/application/Espo/Core/Utils/Database/Converter.php @@ -28,7 +28,7 @@ class Converter $this->metadata = $metadata; $this->fileManager = $fileManager; - $this->ormConverter = new Converters\Orm($this->metadata, $this->fileManager); + $this->ormConverter = new Orm\Converter($this->metadata, $this->fileManager); $this->schemaConverter = new Schema\Converter($this->fileManager); } @@ -70,14 +70,14 @@ class Converter */ public function process() { - $GLOBALS['log']->add('Debug', 'Converters\Orm - Start: orm convertation'); + $GLOBALS['log']->add('Debug', 'Orm\Converter - Start: orm convertation'); $ormMeta = $this->getOrmConverter()->process(); //save database meta to a file espoMetadata.php $result = $this->getMetadata()->setOrmMetadata($ormMeta); - $GLOBALS['log']->add('Debug', 'Converters\Orm - End: orm convertation, result=['.$result.']'); + $GLOBALS['log']->add('Debug', 'Orm\Converter - End: orm convertation, result=['.$result.']'); return $result; } diff --git a/application/Espo/Core/Utils/Database/Converters/Schema.php b/application/Espo/Core/Utils/Database/Converters/Schema.php deleted file mode 100644 index 5245e1d357..0000000000 --- a/application/Espo/Core/Utils/Database/Converters/Schema.php +++ /dev/null @@ -1,264 +0,0 @@ - 'length', - 'default' => 'default', - 'notnull' => 'notnull', - 'autoincrement' => 'autoincrement', - 'unique' => 'unique', - ); - - - //todo: same array in Converters\Orm - protected $idParams = array( - 'dbType' => 'varchar', - 'len' => '24', - ); - - //todo: same array in Converters\Orm - protected $defaultLength = array( - 'varchar' => 255, - 'int' => 11, - ); - - protected $notStorableTypes = array( - 'foreign' - ); - - public function __construct(\Espo\Core\Utils\File\Manager $fileManager) - { - $this->fileManager = $fileManager; - - $this->dbalSchema = new \Doctrine\DBAL\Schema\Schema(); - - $this->typeList = array_keys(\Doctrine\DBAL\Types\Type::getTypesMap()); - } - - - protected function getFileManager() - { - return $this->fileManager; - } - - protected function getSchema() - { - return $this->dbalSchema; - } - - - //convertToSchema - public function process(array $ormMeta, $entityDefs) - { - $GLOBALS['log']->add('Debug', 'Converters\Schema - Start: building schema'); - - //check if exist files in "Tables" directory - - //END: check if exist files in "Tables" directory - - - $schema = $this->getSchema(); - - $tables = array(); - foreach ($ormMeta as $entityName => $entityParams) { - - $tables[$entityName] = $schema->createTable( Util::toUnderScore($entityName) ); - - $primaryColumns = array(); - $uniqueColumns = array(); - $indexList = array(); //list of indexes like array( array(comlumn1, column2), array(column3)) - foreach ($entityParams['fields'] as $fieldName => $fieldParams) { - - if ((isset($fieldParams['notStorable']) && $fieldParams['notStorable']) || in_array($fieldParams['type'], $this->notStorableTypes)) { - continue; - } - - switch ($fieldParams['type']) { - case 'id': - $primaryColumns[] = Util::toUnderScore($fieldName); - break; - - /*case 'array': - case 'json_array': - $fieldParams['default'] = ''; //for db type TEXT can't be defined a default value - break; - - case 'bool': - $fieldParams['default'] = intval($fieldParams['default']); - break;*/ - - case 'int': - if (isset($fieldParams['autoincrement']) && $fieldParams['autoincrement']) { - $uniqueColumns[] = Util::toUnderScore($fieldName); - } - break; - } - - $fieldType = isset($fieldParams['dbType']) ? $fieldParams['dbType'] : $fieldParams['type']; - if (!in_array($fieldType, $this->typeList)) { - $GLOBALS['log']->add('DEBUG', 'Converters\Schema::process(): Field type ['.$fieldType.'] does not exist '.$entityName.':'.$fieldName); - continue; - } - - $columnName = Util::toUnderScore($fieldName); - if (!$tables[$entityName]->hasColumn($columnName)) { - $tables[$entityName]->addColumn($columnName, $fieldType, $this->getDbFieldParams($fieldParams)); - } - - - //add index. It can be defined in entityDefs as "index" - if (isset($fieldParams['index'])) { - if ($fieldParams['index'] === true) { - $indexList[] = array($columnName); - } else if (is_string($fieldParams['index'])) { - $indexList[ $fieldParams['index'] ][] = $columnName; - } - } //END: add index - } - - $tables[$entityName]->setPrimaryKey($primaryColumns); - if (!empty($indexList)) { - foreach($indexList as $indexItem) { - $tables[$entityName]->addIndex($indexItem); - } - } - if (!empty($uniqueColumns)) { - $tables[$entityName]->addUniqueIndex($uniqueColumns); - } - } - - //check and create columns/tables for relations - foreach ($ormMeta as $entityName => $entityParams) { - - foreach ($entityParams['relations'] as $relationName => $relationParams) { - - switch ($relationParams['type']) { - case 'manyMany': - $tableName = $relationParams['relationName']; - - //check for duplication tables - if (!isset($tables[$tableName])) { //no needs to create the table if it already exists - $tables[$tableName] = $this->prepareManyMany($entityName, $relationParams, $tables); - } - break; - - case 'belongsTo': - $foreignEntity = $relationParams['entity']; - $columnName = Util::toUnderScore($relationParams['key']); - $foreignKey = Util::toUnderScore($relationParams['foreignKey']); - $tables[$entityName]->addForeignKeyConstraint($tables[$foreignEntity], array($columnName), array($foreignKey), array("onUpdate" => "CASCADE")); - break; - } - } - } - //END: check and create columns/tables for relations - - - $GLOBALS['log']->add('Debug', 'Converters\Schema - End: building schema'); - - return $schema; - } - - /** - * Prepare a relation table for the manyMany relation - * - * @param array $relationParams - * @param array $tables - * @param bool $isForeignKey - * - * @return \Doctrine\DBAL\Schema\Table - */ - protected function prepareManyMany($entityName, $relationParams, $tables) - { - $tableName = $relationParams['relationName']; - - $isForeignKey = true; - if (!isset($relationParams['key']) || !isset($relationParams['foreignKey'])) { - $isForeignKey = false; - } - - - $table = $this->getSchema()->createTable( Util::toUnderScore($tableName) ); - $table->addColumn('id', 'int', array('length'=>$this->defaultLength['int'], 'autoincrement' => true,)); //'unique' => true, - - if ($isForeignKey) { - $relationEntities = array($entityName, $relationParams['entity']); - $relationKeys = array($relationParams['key'], $relationParams['foreignKey']); - } - - //add midKeys to a schema - foreach($relationParams['midKeys'] as $index => $midKey) { - - $usMidKey = Util::toUnderScore($midKey); - $table->addColumn($usMidKey, $this->idParams['dbType'], array('length'=>$this->idParams['len'])); - - if ($isForeignKey) { - $relationKey = Util::toUnderScore($relationKeys[$index]); - $table->addForeignKeyConstraint($tables[$relationEntities[$index]], array($usMidKey), array($relationKey), array("onUpdate" => "CASCADE")); - } else { - $table->addIndex(array($usMidKey)); - } - } //END: add midKeys to a schema - - - //add additionalColumns - if (isset($relationParams['additionalColumns'])) { - foreach($relationParams['additionalColumns'] as $fieldName => $fieldParams) { - - if (!isset($fieldParams['type'])) { - $fieldParams = array_merge($fieldParams, array( - 'type' => 'varchar', - 'length' => $this->defaultLength['varchar'], - )); - } - - $table->addColumn(Util::toUnderScore($fieldName), $fieldParams['type'], $this->getDbFieldParams($fieldParams)); - } - } //END: add additionalColumns - - - $table->addColumn('deleted', 'bool', array('default' => 0)); - $table->setPrimaryKey(array("id")); - - return $table; - } - - - protected function getDbFieldParams($fieldParams) - { - $dbFieldParams = array(); - - foreach($this->allowedDbFieldParams as $espoName => $dbalName) { - - if (isset($fieldParams[$espoName])) { - $dbFieldParams[$dbalName] = $fieldParams[$espoName]; - } - } - - switch ($fieldParams['type']) { - case 'array': - case 'json_array': - $dbFieldParams['default'] = ''; //for db type TEXT can't be defined a default value - break; - - case 'bool': - $dbFieldParams['default'] = intval($dbFieldParams['default']); - break; - } - - return $dbFieldParams; - } -} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Orm/Base.php b/application/Espo/Core/Utils/Database/Orm/Base.php new file mode 100644 index 0000000000..e7e78cf560 --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Base.php @@ -0,0 +1,43 @@ +metadata = $metadata; + } + + protected function getMetadata() + { + return $this->metadata; + } + + protected function getForeignField($name, $entityName) + { + $foreignField = $this->getMetadata()->get('entityDefs.'.$entityName.'.fields.'.$name); + + if ($foreignField['type'] != 'varchar') { + $fieldDefs = $this->getMetadata()->get('fields.'.$foreignField['type']); + $naming = isset($fieldDefs['naming']) ? $fieldDefs['naming'] : 'postfix'; + + if (isset($fieldDefs['actualFields']) && is_array($fieldDefs['actualFields'])) { + $foreignFieldArray = array(); + foreach($fieldDefs['actualFields'] as $fieldName) { + if ($fieldName != 'salutation') { + $foreignFieldArray[] = Util::getNaming($name, $fieldName, $naming); + } + } + return explode('|', implode('| |', $foreignFieldArray)); //add an empty string between items + } + } + + return $name; + } + +} diff --git a/application/Espo/Core/Utils/Database/Converters/Orm.php b/application/Espo/Core/Utils/Database/Orm/Converter.php similarity index 81% rename from application/Espo/Core/Utils/Database/Converters/Orm.php rename to application/Espo/Core/Utils/Database/Orm/Converter.php index 64466f938b..050c4d0f90 100644 --- a/application/Espo/Core/Utils/Database/Converters/Orm.php +++ b/application/Espo/Core/Utils/Database/Orm/Converter.php @@ -1,11 +1,11 @@ metadata = $metadata; - $this->fileManager = $fileManager; + $this->fileManager = $fileManager; //need to featue with ormHooks. Ex. isFollowed field $this->relationManager = new RelationManager($this->metadata); } @@ -87,7 +87,7 @@ class Orm foreach($entityDefs as $entityName => $entityMeta) { if (empty($entityMeta)) { - $GLOBALS['log']->add('ERROR', 'Converters\Orm:process(), Entity:'.$entityName.' - metadata cannot be converted into ORM format'); + $GLOBALS['log']->add('ERROR', 'Orm\Converter:process(), Entity:'.$entityName.' - metadata cannot be converted into ORM format'); continue; } @@ -124,6 +124,47 @@ class Orm public function afterProcess(array $meta) { + //load custom field definitions and customCodes + foreach($meta as $entityName => &$entityParams) { + foreach($entityParams['fields'] as $fieldName => $fieldParams) { + + //load custom field definitions + $fieldType = ucfirst($fieldParams['type']); + $className = '\Espo\Custom\Core\Utils\Database\Orm\Fields\\'.$fieldType; + if (!class_exists($className)) { + $className = '\Espo\Core\Utils\Database\Orm\Fields\\'.$fieldType; + } + + if (class_exists($className) && method_exists($className, 'load')) { + $helperClass = new $className($this->metadata); + $fieldResult = $helperClass->load( + array('name' => $entityName, 'params' => $entityParams), + array('name' => $fieldName, 'params' => $fieldParams) + ); + if (isset($fieldResult['unset'])) { + $meta = Util::unsetInArray($meta, $fieldResult['unset']); + unset($fieldResult['unset']); + } + + $meta = Util::merge($meta, $fieldResult); + } //END: load custom field definitions + + + //todo move to separate file + //add a field 'isFollowed' for scopes with 'stream => true' + $scopeDefs = $this->getMetadata()->get('scopes.'.$entityName); + if (isset($scopeDefs['stream']) && $scopeDefs['stream']) { + if (!isset($entityParams['fields']['isFollowed'])) { + $entityParams['fields']['isFollowed'] = array( + 'type' => 'varchar', + 'notStorable' => true, + ); + } + } //END: add a field 'isFollowed' for stream => true + + } + } + foreach($meta as $entityName => &$entityParams) { foreach($entityParams['fields'] as $fieldName => &$fieldParams) { @@ -134,15 +175,6 @@ class Orm } break; - /*case 'foreign': - $typeDefs = $this->getRelationManager()->process('foreignType', $entityName, array( - 'name' => $fieldName, - 'foreign' => $fieldParams['foreign'], - 'entity' => $entityParams['relations'][$fieldParams['relation']]['entity'], - )); - $fieldParams = Util::merge($fieldParams, $typeDefs[$entityName]['fields'][$fieldName]); - break;*/ - case 'foreignId': $fieldParams = array_merge($fieldParams, $this->idParams); $fieldParams['notnull'] = false; @@ -156,33 +188,7 @@ class Orm case 'bool': $fieldParams['default'] = isset($fieldParams['default']) ? (bool) $fieldParams['default'] : $this->defaultValue['bool']; break; - - case 'personName': - $fieldParams['type'] = Entity::VARCHAR; - $typeDefs = $this->getRelationManager()->process('typePersonName', $entityName, array('name' => $fieldName)); - $fieldParams = Util::merge($fieldParams, $typeDefs[$entityName]['fields'][$fieldName]); - break; - - case 'email': - $typeDefs = $this->getRelationManager()->process('entityEmailAddress', $entityName, array('name' => $fieldName)); - $entityParams = Util::merge($entityParams, $typeDefs[$entityName]); - break; } - - - //todo move to separate file - //add a field 'isFollowed' for stream => true - $scopeDefs = $this->getMetadata()->get('scopes.'.$entityName); - if (isset($scopeDefs['stream']) && $scopeDefs['stream']) { - if (!isset($entityParams['fields']['isFollowed'])) { - $entityParams['fields']['isFollowed'] = array( - 'type' => 'varchar', - 'notStorable' => true, - ); - } - } - //END: add a field 'isFollowed' for stream => true - } } @@ -191,17 +197,14 @@ class Orm } - - - /** - * Metadata conversion from Espo format into Doctrine - * - * @param string $entityName - * @param array $entityMeta - * - * @return array - */ + * Metadata conversion from Espo format into Doctrine + * + * @param string $entityName + * @param array $entityMeta + * + * @return array + */ protected function convertFields($entityName, $entityMeta) { $outputMeta = array( @@ -227,7 +230,6 @@ class Orm $subField = $this->convertActualFields($entityName, $fieldName, $fieldParams, $subFieldName, $fieldTypeMeta); - //if (!isset($entityMeta['fields'][ $subField['naming'] ])) { if (!isset($outputMeta[ $subField['naming'] ])) { $subFieldDefs = $this->convertField($entityName, $subField['name'], $subField['params']); if ($subFieldDefs !== false) { @@ -244,24 +246,6 @@ class Orm } } - /*Make actions for different types like "link", "linkMultiple", "linkParent" */ - foreach($outputMeta as $fieldName => $fieldParams) { - - switch ($fieldParams['type']) { - case 'linkParent': - $linkData = $this->getRelationManager()->process('linkParent', $entityName, array('name' => $fieldName)); - $outputMeta = Util::merge($outputMeta, $linkData[$entityName]['fields']); - break; - - case 'linkMultiple': - $linkData = $this->getRelationManager()->process('linkMultiple', $entityName, array('name' => $fieldName)); - unset($outputMeta[$fieldName]); //no need "linkMultiple" field - $outputMeta = Util::merge($outputMeta, $linkData[$entityName]['fields']); - break; - } - } - - if (!isset($outputMeta['deleted'])) { $outputMeta['deleted'] = array( 'type' => Entity::BOOL, @@ -390,7 +374,7 @@ class Orm } $method = Util::toCamelCase($method); - if ( $this->getRelationManager()->isMethodExists($method) ) { //ex. hasManyHasMany + if ( $this->getRelationManager()->isRelationExists($method) ) { //ex. hasManyHasMany $convertedLink = $this->getRelationManager()->process($method, $entityName, array('name'=>$linkName, 'params'=>$linkParams), $foreignLink); } else { //ex. hasMany $convertedLink = $this->getRelationManager()->process($currentType, $entityName, array('name'=>$linkName, 'params'=>$linkParams), $foreignLink); @@ -431,17 +415,6 @@ class Orm ); } - /*$parentLinkName = strtolower($parentLinkName); - - foreach($currentEntityDefs['links'] as $linkName => $linkParams) { - if (isset($linkParams['foreign']) && strtolower($linkParams['foreign']) == $parentLinkName) { - return array( - 'name' => $linkName, - 'params' => $linkParams, - ); - } - } */ - return false; } diff --git a/application/Espo/Core/Utils/Database/Relations/EntityEmailAddress.php b/application/Espo/Core/Utils/Database/Orm/Fields/Email.php similarity index 72% rename from application/Espo/Core/Utils/Database/Relations/EntityEmailAddress.php rename to application/Espo/Core/Utils/Database/Orm/Fields/Email.php index f41e7ea7d3..d26bc06918 100644 --- a/application/Espo/Core/Utils/Database/Relations/EntityEmailAddress.php +++ b/application/Espo/Core/Utils/Database/Orm/Fields/Email.php @@ -1,18 +1,16 @@ array( + return array( + $entity['name'] => array( 'fields' => array( - $params['link']['name'] => array( + $field['name'] => array( 'select' => 'email_address.name', 'where' => array ( @@ -23,7 +21,7 @@ class EntityEmailAddress ), ), 'relations' => array( - $params['link']['name'].'es' => array( + $field['name'].'es' => array( 'type' => 'manyMany', 'entity' => 'EmailAddress', 'relationName' => 'entityEmailAddress', @@ -32,7 +30,7 @@ class EntityEmailAddress 'email_address_id', ), 'conditions' => array( - 'entityType' => $params['entityName'], + 'entityType' => $entity['name'], ), 'additionalColumns' => array( 'entityType' => array( @@ -50,4 +48,5 @@ class EntityEmailAddress ); } + } \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Orm/Fields/LinkMultiple.php b/application/Espo/Core/Utils/Database/Orm/Fields/LinkMultiple.php new file mode 100644 index 0000000000..69902115d1 --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Fields/LinkMultiple.php @@ -0,0 +1,32 @@ + array ( + 'fields' => array( + $field['name'].'Ids' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + $field['name'].'Names' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + ), + ), + 'unset' => array( + $entity['name'] => array( + 'fields.'.$field['name'], + ), + ), + ); + } + + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Orm/Fields/LinkParent.php b/application/Espo/Core/Utils/Database/Orm/Fields/LinkParent.php new file mode 100644 index 0000000000..040f2563d9 --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Fields/LinkParent.php @@ -0,0 +1,31 @@ + array ( + 'fields' => array( + $field['name'].'Id' => array( + 'type' => 'foreignId', + 'index' => $field['name'], + ), + $field['name'].'Type' => array( + 'type' => 'foreignType', + 'index' => $field['name'], + ), + $field['name'].'Name' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + ), + ) + ); + } + + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php b/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php new file mode 100644 index 0000000000..1920247706 --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php @@ -0,0 +1,47 @@ +getForeignField($field['name'], $entity['name']); + $tableName = Util::toUnderScore($entity['name']); + + $fullList = array(); //contains empty string (" ") like delimiter + $fieldList = array(); //doesn't contain empty string (" ") like delimiter + $like = array(); + foreach($foreignField as $fieldName) { + + $fieldNameTrimmed = trim($fieldName); + if (!empty($fieldNameTrimmed)) { + $columnName = $tableName.'.'.Util::toUnderScore($fieldNameTrimmed); + + $fullList[] = $fieldList[] = $columnName; + $like[] = $columnName." LIKE '{text}'"; + } else { + $fullList[] = "'".$fieldName."'"; + } + } + + return array( + $entity['name'] => array ( + 'fields' => array( + $field['name'] => array( + 'type' => 'varchar', + 'select' => "TRIM(CONCAT(".implode(", ", $fullList)."))", + 'where' => array( + 'LIKE' => "(".implode(" OR ", $like)." OR CONCAT(".implode(", ", $fullList).") LIKE '{text}')", + ), + 'orderBy' => implode(", ", array_map(function ($item) {return $item . ' {direction}';}, $fieldList)), + ), + ), + ), + ); + } + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Converters/RelationManager.php b/application/Espo/Core/Utils/Database/Orm/RelationManager.php similarity index 74% rename from application/Espo/Core/Utils/Database/Converters/RelationManager.php rename to application/Espo/Core/Utils/Database/Orm/RelationManager.php index 7a97459e78..35db25a63e 100644 --- a/application/Espo/Core/Utils/Database/Converters/RelationManager.php +++ b/application/Espo/Core/Utils/Database/Orm/RelationManager.php @@ -1,6 +1,6 @@ getRelations(), $methodName)) { - return true; + if ($this->getRelationClass($relationName) !== false) { + return true; } return false; } + protected function getRelationClass($relationName) + { + $relationName = ucfirst($relationName); + + $className = '\Espo\Custom\Core\Utils\Database\Orm\Relations\\'.$relationName; + if (!class_exists($className)) { + $className = '\Espo\Core\Utils\Database\Orm\Relations\\'.$relationName; + } + + if (class_exists($className)) { + return $className; + } + + return false; + } + public function process($method, $entityName, $link, $foreignLink = array()) { @@ -63,37 +79,32 @@ class RelationManager $params['targetEntity'] = $foreignParams['entityName']; $foreignParams['targetEntity'] = $params['entityName']; - //relationDefs defined in separate file - //todo rename to 'helperName' or other one - $helperName = isset($link['params']['relationName']) ? ucfirst($link['params']['relationName']) : ucfirst($method); + $relationName = isset($link['params']['relationName']) ? ucfirst($link['params']['relationName']) : ucfirst($method); - $className = '\Espo\Custom\Core\Utils\Database\Relations\\'.$helperName; - if (!class_exists($className)) { - $className = '\Espo\Core\Utils\Database\Relations\\'.$helperName; - } + $className = $this->getRelationClass($relationName); - if (class_exists($className) && method_exists($className, 'load')) { - $helperClass = new $className(); + if ($className !== false && method_exists($className, 'load')) { + $helperClass = new $className($this->metadata); return $helperClass->load($params, $foreignParams); } //END: relationDefs defined in separate file - if (method_exists($this, $method)) { + /*if (method_exists($this, $method)) { return $this->$method($params, $foreignParams); } else if (method_exists($this->getRelations(), $method)) { return $this->getRelations()->$method($params, $foreignParams); - } + } */ return false; } - protected function hasManyHasMany($params, $foreignParams) + /*protected function hasManyHasMany($params, $foreignParams) { - return $this->getRelations()->manyMany($params, $foreignParams); - } + return $this->process('manyMany', $params, $foreignParams); + } */ diff --git a/application/Espo/Core/Utils/Database/Converters/Relations.php b/application/Espo/Core/Utils/Database/Orm/Relations.php similarity index 84% rename from application/Espo/Core/Utils/Database/Converters/Relations.php rename to application/Espo/Core/Utils/Database/Orm/Relations.php index 27d0b7299c..ac1bb558ed 100644 --- a/application/Espo/Core/Utils/Database/Converters/Relations.php +++ b/application/Espo/Core/Utils/Database/Orm/Relations.php @@ -1,6 +1,6 @@ metadata; } - - protected function getSortEntities($entity1, $entity2) - { - $entities = array( - Util::toCamelCase(lcfirst($entity1)), - Util::toCamelCase(lcfirst($entity2)), - ); - - sort($entities); - - return $entities; - } - - - protected function getJoinTable($tableName1, $tableName2) - { - $tables = $this->getSortEntities($tableName1, $tableName2); - - return Util::toCamelCase( implode('-', $tables) ); - } - - protected function getForeignField($name, $entityName) { $foreignField = $this->getMetadata()->get('entityDefs.'.$entityName.'.fields.'.$name); @@ -66,7 +44,7 @@ class Relations //todo sedine in foreign fieldDefs a key for current - public function manyMany($params, $foreignParams) + /*public function manyMany($params, $foreignParams) { return array( $params['entityName'] => array( @@ -84,11 +62,11 @@ class Relations ), ), ), - ); - } + ); + } */ - public function hasMany($params, $foreignParams) + /*public function hasMany($params, $foreignParams) { $relation = array( $params['entityName'] => array ( @@ -103,27 +81,26 @@ class Relations ); return $relation; - } + } */ - public function belongsTo($params, $foreignParams) + /*public function belongsTo($params, $foreignParams) { $relation = array ( $params['entityName'] => array ( 'fields' => array( $params['link']['name'].'Name' => array( - 'type' => Entity::FOREIGN, + 'type' => 'foreign', 'relation' => $params['link']['name'], - //'notStorable' => true, 'foreign' => $this->getForeignField('name', $foreignParams['entityName']), ), $params['link']['name'].'Id' => array( - 'type' => Entity::FOREIGN_ID, + 'type' => 'foreignId', 'index' => true, ), ), 'relations' => array( $params['link']['name'] => array( - 'type' => Entity::BELONGS_TO, + 'type' => 'belongsTo', 'entity' => $params['targetEntity'], 'key' => $params['link']['name'].'Id', 'foreignKey' => 'id', //???? @@ -133,9 +110,9 @@ class Relations ); return $relation; - } + } */ - public function hasChildren($params, $foreignParams) + /*public function hasChildren($params, $foreignParams) { $relation = array( $params['entityName'] => array ( @@ -152,9 +129,9 @@ class Relations return $relation; - } + } */ - public function linkParent($params, $foreignParams) + /*public function linkParent($params, $foreignParams) { $relation = array(); @@ -180,10 +157,10 @@ class Relations } return $relation; - } + } */ - public function linkMultiple($params, $foreignParams) + /* public function linkMultiple($params, $foreignParams) { return array( $params['entityName'] => array ( @@ -199,10 +176,10 @@ class Relations ), ), ); - } + } */ - public function typePersonName($params, $foreignParams) + /*public function typePersonName($params, $foreignParams) { $foreignField = $this->getForeignField($params['link']['name'], $params['entityName']); $tableName = Util::toUnderScore($params['entityName']); @@ -236,14 +213,14 @@ class Relations ), ), ); - } + }*/ //public function teamRelation($params, $foreignParams) public function hasManyWithName($params, $foreignParams) { - $relationKeys = explode('-', Util::fromCamelCase($params['link']['params']['relationName'])); + $relationKeys = explode('-', Util::fromCamelCase($params['link']['params']['relationName'])); $midKeys = array(); foreach($relationKeys as $key) { $midKeys[] = $key.'Id'; diff --git a/application/Espo/Core/Utils/Database/Orm/Relations/BelongsTo.php b/application/Espo/Core/Utils/Database/Orm/Relations/BelongsTo.php new file mode 100644 index 0000000000..67208904ae --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Relations/BelongsTo.php @@ -0,0 +1,36 @@ + array ( + 'fields' => array( + $params['link']['name'].'Name' => array( + 'type' => 'foreign', + 'relation' => $params['link']['name'], + 'foreign' => $this->getForeignField('name', $foreignParams['entityName']), + ), + $params['link']['name'].'Id' => array( + 'type' => 'foreignId', + 'index' => true, + ), + ), + 'relations' => array( + $params['link']['name'] => array( + 'type' => 'belongsTo', + 'entity' => $params['targetEntity'], + 'key' => $params['link']['name'].'Id', + 'foreignKey' => 'id', //???? + ), + ), + ), + ); + } + + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Relations/EntityTeam.php b/application/Espo/Core/Utils/Database/Orm/Relations/EntityTeam.php similarity index 85% rename from application/Espo/Core/Utils/Database/Relations/EntityTeam.php rename to application/Espo/Core/Utils/Database/Orm/Relations/EntityTeam.php index 1ce711a777..dd73c1a436 100644 --- a/application/Espo/Core/Utils/Database/Relations/EntityTeam.php +++ b/application/Espo/Core/Utils/Database/Orm/Relations/EntityTeam.php @@ -1,8 +1,8 @@ array ( + 'fields' => array( + $params['link']['name'].'Ids' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + $params['link']['name'].'Names' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + ), + 'relations' => array( + $params['link']['name'] => array( + 'type' => 'hasChildren', + 'entity' => $params['targetEntity'], + 'foreignKey' => $foreignParams['link']['name'].'Id', //???: 'foreignKey' => $params['link']['name'].'Id', + 'foreignType' => $foreignParams['link']['name'].'Type', //???: 'foreignKey' => $params['link']['name'].'Id', + ), + ), + ), + ); + } + + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Orm/Relations/HasMany.php b/application/Espo/Core/Utils/Database/Orm/Relations/HasMany.php new file mode 100644 index 0000000000..d832bb014e --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Relations/HasMany.php @@ -0,0 +1,36 @@ + array ( + 'fields' => array( + $params['link']['name'].'Ids' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + $params['link']['name'].'Names' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + ), + 'relations' => array( + $params['link']['name'] => array( + 'type' => 'hasMany', + 'entity' => $params['targetEntity'], + 'foreignKey' => lcfirst($foreignParams['link']['name'].'Id'), //???: 'foreignKey' => $params['link']['name'].'Id', + ), + ), + ), + ); + + return $relation; + } + + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/Database/Orm/Relations/HasManyHasMany.php b/application/Espo/Core/Utils/Database/Orm/Relations/HasManyHasMany.php new file mode 100644 index 0000000000..be2f5262ef --- /dev/null +++ b/application/Espo/Core/Utils/Database/Orm/Relations/HasManyHasMany.php @@ -0,0 +1,8 @@ + array( + 'fields' => array( + $params['link']['name'].'Ids' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + $params['link']['name'].'Names' => array( + 'type' => 'varchar', + 'notStorable' => true, + ), + ), + 'relations' => array( + $params['link']['name'] => array( + 'type' => 'manyMany', + 'entity' => $params['targetEntity'], + 'relationName' => $this->getJoinTable($params['entityName'], $foreignParams['entityName']), + 'key' => 'id', //todo specify 'key' + 'foreignKey' => 'id', //todo specify 'foreignKey' + 'midKeys' => array( + lcfirst($params['entityName']).'Id', + lcfirst($foreignParams['entityName']).'Id', + ), + ), + ), + ), + ); + } + + protected function getJoinTable($tableName1, $tableName2) + { + $tables = $this->getSortEntities($tableName1, $tableName2); + + return Util::toCamelCase( implode('-', $tables) ); + } + + protected function getSortEntities($entity1, $entity2) + { + $entities = array( + Util::toCamelCase(lcfirst($entity1)), + Util::toCamelCase(lcfirst($entity2)), + ); + + sort($entities); + + return $entities; + } + +} \ No newline at end of file diff --git a/application/Espo/Core/Utils/File/UniteFiles.php b/application/Espo/Core/Utils/File/UniteFiles.php index 4ac81c7850..f1cffd1eb7 100644 --- a/application/Espo/Core/Utils/File/UniteFiles.php +++ b/application/Espo/Core/Utils/File/UniteFiles.php @@ -120,7 +120,7 @@ class UniteFiles } //unset content - $content= $this->uniteFilesUnset($content, $unsets); + $content= Utils\Util::unsetInArray($content, $unsets); //END: unset content /*print_r($content); @@ -165,36 +165,6 @@ class UniteFiles return array(); } - /** - * Unset content items defined in the unset.json - * - * @param array $content - * @param array $unsets - * - * @return array - */ - public function uniteFilesUnset($content, $unsets) - { - foreach($unsets as $rootKey => $unsetItem){ - if (!empty($unsetItem)){ - foreach($unsetItem as $unsetSett){ - if (!empty($unsetSett)){ - $keyItems = explode('.', $unsetSett); - $currVal = "\$content['{$rootKey}']"; - foreach($keyItems as $keyItem){ - $currVal .= "['{$keyItem}']"; - } - - $currVal = "if (isset({$currVal})) unset({$currVal});"; - eval($currVal); - } - } - } - } - - return $content; - } - /** * Load default values for selected type [metadata, layouts] * diff --git a/application/Espo/Core/Utils/Route.php b/application/Espo/Core/Utils/Route.php index 1fa8d7a5b6..6121e8a552 100644 --- a/application/Espo/Core/Utils/Route.php +++ b/application/Espo/Core/Utils/Route.php @@ -5,7 +5,7 @@ namespace Espo\Core\Utils; class Route { protected $fileName = 'routes.json'; - protected $cacheFileName = 'application/routes.php'; + protected $cacheFile = 'data/cache/application/routes.php'; protected $data = null; @@ -62,14 +62,12 @@ class Route protected function init() { - $cacheFile = Util::concatPath($this->getConfig()->get('cachePath'), $this->cacheFileName); - - if (file_exists($cacheFile) && $this->getConfig()->get('useCache')) { - $this->data = $this->getFileManager()->getContent($cacheFile); + if (file_exists($this->cacheFile) && $this->getConfig()->get('useCache')) { + $this->data = $this->getFileManager()->getContent($this->cacheFile); } else { $this->data = $this->uniteFiles(); - $result = $this->getFileManager()->setContentPHP($this->data, $cacheFile); + $result = $this->getFileManager()->setContentPHP($this->data, $this->cacheFile); if ($result == false) { $GLOBALS['log']->add('EXCEPTION', 'Route::init() - Cannot save Routes to a file'); throw new \Espo\Core\Exceptions\Error(); @@ -90,7 +88,7 @@ class Route foreach($dirList as $currentDirName) { $dirNameFull = Util::concatPath($moduleDir, $currentDirName); - $routeFile = Util::concatPath($dirNameFull, 'Resources/'.$this->fileName); + $routeFile = Util::concatPath($dirNameFull, 'Resources/'.$this->fileName); $data = $this->getAddData($data, $routeFile); } @@ -130,11 +128,32 @@ class Route return $data; } - foreach($newData as $route) { - $data[] = $route; + foreach($newData as $route) { + + $route['route'] = $this->adjustPath($route['route']); + + $data[] = $route; } return $data; } + /** + * Check and adjust the route path + * + * @param string $routePath - it can be "/App/user", "App/user" + * + * @return string - "/App/user" + */ + protected function adjustPath($routePath) + { + $routePath = trim($routePath); + + if ( substr($routePath,0,1) != '/') { + return '/'.$routePath; + } + + return $routePath; + } + } \ No newline at end of file diff --git a/application/Espo/Core/Utils/Util.php b/application/Espo/Core/Utils/Util.php index 7c87d3dae4..7bc4a5c80a 100644 --- a/application/Espo/Core/Utils/Util.php +++ b/application/Espo/Core/Utils/Util.php @@ -271,6 +271,41 @@ class Util return $newArr; } + /** + * Unset content items defined in the unset.json + * + * @param array $content + * @param array $unsets in format + array( + $entity['name'] => array( + 'fields.UnsetFieldName', + ), + ) + * + * @return array + */ + public static function unsetInArray(array $content, array $unsets) + { + foreach($unsets as $rootKey => $unsetItem){ + if (!empty($unsetItem)){ + foreach($unsetItem as $unsetSett){ + if (!empty($unsetSett)){ + $keyItems = explode('.', $unsetSett); + $currVal = "\$content['{$rootKey}']"; + foreach($keyItems as $keyItem){ + $currVal .= "['{$keyItem}']"; + } + + $currVal = "if (isset({$currVal})) unset({$currVal});"; + eval($currVal); + } + } + } + } + + return $content; + } + }