Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend

This commit is contained in:
Yuri Kuznetsov
2014-01-16 18:13:43 +02:00
19 changed files with 508 additions and 460 deletions
@@ -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;
}
@@ -1,264 +0,0 @@
<?php
namespace Espo\Core\Utils\Database\Converters;
use Espo\Core\Utils\Util,
Espo\ORM\Entity;
class Schema
{
private $dbalSchema;
private $fileManager;
protected $typeList;
//pair espo::doctrine
protected $allowedDbFieldParams = array(
'len' => '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;
}
}
@@ -0,0 +1,43 @@
<?php
namespace Espo\Core\Utils\Database\Orm;
use Espo\Core\Utils\Util;
class Base
{
private $metadata;
public function __construct(\Espo\Core\Utils\Metadata $metadata)
{
$this->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;
}
}
@@ -1,11 +1,11 @@
<?php
namespace Espo\Core\Utils\Database\Converters;
namespace Espo\Core\Utils\Database\Orm;
use Espo\Core\Utils\Util,
Espo\ORM\Entity;
class Orm
class Converter
{
private $metadata;
private $fileManager;
@@ -57,7 +57,7 @@ class Orm
public function __construct(\Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\File\Manager $fileManager)
{
$this->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;
}
@@ -1,18 +1,16 @@
<?php
namespace Espo\Core\Utils\Database\Relations;
namespace Espo\Core\Utils\Database\Orm\Fields;
use \Espo\Core\Utils\Util;
class EntityEmailAddress
class Email extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($params, $foreignParams)
public function load($entity, $field)
{
return array(
$params['entityName'] => 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
);
}
}
@@ -0,0 +1,32 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Fields;
class LinkMultiple extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($entity, $field)
{
return array(
$entity['name'] => 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'],
),
),
);
}
}
@@ -0,0 +1,31 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Fields;
class LinkParent extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($entity, $field)
{
return array(
$entity['name'] => 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,
),
),
)
);
}
}
@@ -0,0 +1,47 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Fields;
use Espo\Core\Utils\Util;
class PersonName extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($entity, $field)
{
$foreignField = $this->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)),
),
),
),
);
}
}
@@ -1,6 +1,6 @@
<?php
namespace Espo\Core\Utils\Database\Converters;
namespace Espo\Core\Utils\Database\Orm;
use Espo\Core\Utils\Util;
@@ -38,15 +38,31 @@ class RelationManager
return isset($link['entity']) ? $link['entity'] : $entityName;
}
public function isMethodExists($methodName)
public function isRelationExists($relationName)
{
if (method_exists($this, $methodName) || method_exists($this->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);
} */
@@ -1,6 +1,6 @@
<?php
namespace Espo\Core\Utils\Database\Converters;
namespace Espo\Core\Utils\Database\Orm;
use Espo\Core\Utils\Util,
Espo\ORM\Entity;
@@ -20,28 +20,6 @@ class Relations
return $this->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';
@@ -0,0 +1,36 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Relations;
class BelongsTo extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($params, $foreignParams)
{
return array (
$params['entityName'] => 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', //????
),
),
),
);
}
}
@@ -1,8 +1,8 @@
<?php
namespace Espo\Core\Utils\Database\Relations;
namespace Espo\Core\Utils\Database\Orm\Relations;
class EntityTeam
class EntityTeam extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($params, $foreignParams)
@@ -0,0 +1,35 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Relations;
class HasChildren extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($params, $foreignParams)
{
return array(
$params['entityName'] => 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',
),
),
),
);
}
}
@@ -0,0 +1,36 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Relations;
class HasMany extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($params, $foreignParams)
{
$relation = array(
$params['entityName'] => 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;
}
}
@@ -0,0 +1,8 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Relations;
class HasManyHasMany extends ManyMany
{
}
@@ -0,0 +1,60 @@
<?php
namespace Espo\Core\Utils\Database\Orm\Relations;
use Espo\Core\Utils\Util;
class ManyMany extends \Espo\Core\Utils\Database\Orm\Base
{
public function load($params, $foreignParams)
{
return array(
$params['entityName'] => 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;
}
}
@@ -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]
*
+28 -9
View File
@@ -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;
}
}
+35
View File
@@ -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;
}
}