diff --git a/application/Espo/Core/Application.php b/application/Espo/Core/Application.php index 4e26402246..396da464de 100644 --- a/application/Espo/Core/Application.php +++ b/application/Espo/Core/Application.php @@ -23,7 +23,7 @@ class Application $this->container = new Container(); $GLOBALS['log'] = $this->log = $this->container->get('log'); - + set_error_handler(array($this->getLog(), 'catchError'), E_ALL); set_exception_handler(array($this->getLog(), 'catchException')); @@ -79,15 +79,13 @@ class Application $this->getMetadata()->init($isNotCached); if ($isNotCached) { - $doctrineConverter = new \Espo\Core\Doctrine\Converter\Base($this->container->get('entityManager'), $this->getMetadata(), $this->container->get('fileManager')); + $schema = new \Espo\Core\Utils\Database\Schema($this->container->get('config'), $this->getMetadata(), $this->container->get('fileManager')); - if ($doctrineConverter->process()) { - try{ - $doctrineConverter->getDoctrineHelper()->rebuildDatabase(); - } catch (\Exception $e) { - $GLOBALS['log']->add('EXCEPTION', 'Fault to rebuildDatabase'.'. Details: '.$e->getMessage()); - } - } + try{ + $schema->rebuild(); + } catch (\Exception $e) { + $GLOBALS['log']->add('EXCEPTION', 'Fault to rebuild database schema'.'. Details: '.$e->getMessage()); + } } } @@ -96,12 +94,10 @@ class Application $container = $this->getContainer(); $slim = $this->getSlim(); $serviceFactory = $this->getServiceFactory(); - $auth = new \Espo\Core\Utils\Api\Auth($container->get('entityManager'), $container); $this->getSlim()->add($auth); - $this->getSlim()->hook('slim.before.dispatch', function () use ($slim, $container) { $conditions = $slim->router()->getCurrentRoute()->getConditions(); diff --git a/application/Espo/Core/Doctrine/Converter/Association.php b/application/Espo/Core/Doctrine/Converter/Association.php deleted file mode 100644 index a4162eeea4..0000000000 --- a/application/Espo/Core/Doctrine/Converter/Association.php +++ /dev/null @@ -1,197 +0,0 @@ - array( - 'manyToOne' => array( - $params['usLinkName'] => array( - 'targetEntity' => $params['targetEntity'], - 'joinColumn' => array( - 'name' => $params['usLinkName'].'_id', - 'referencedColumnName' => 'id', - ), - ), - ), - ), - ); - } - - - public function oneToManyUnidirectionalWithJoinTable($params, $foreignParams) - { - return array ( - $params['entityName'] => - array ( - 'manyToMany' => - array ( - $params['usLinkName'] => - array ( - 'targetEntity' => $params['targetEntity'], - 'joinTable' => - array ( - 'name' => $params['joinTable'], - 'joinColumns' => - array ( - $params['usEntityName'].'_id' => - array ( - 'referencedColumnName' => 'id', - ), - ), - 'inverseJoinColumns' => - array ( - $foreignParams['usEntityName'].'_id' => - array ( - 'referencedColumnName' => 'id', - 'unique' => true, - ), - ), - ), - ), - ), - ), - ); - } - - - public function manyToManyBidirectional($params, $foreignParams) - { - return array ( - $params['entityName'] => - array ( - 'manyToMany' => - array ( - $params['usLinkName'] => - array ( - 'targetEntity' => $params['targetEntity'], - 'inversedBy' => $foreignParams['usLinkName'], - 'joinTable' => - array ( - 'name' => $params['joinTable'], - 'joinColumns' => - array ( - $params['usEntityName'].'_id' => - array ( - 'referencedColumnName' => 'id', - ), - ), - 'inverseJoinColumns' => - array ( - $foreignParams['usEntityName'].'_id' => - array ( - 'referencedColumnName' => 'id', - ), - ), - ), - ), - ), - ), - - $foreignParams['entityName'] => - array ( - 'manyToMany' => - array ( - $foreignParams['usLinkName'] => - array ( - 'targetEntity' => $foreignParams['targetEntity'], - 'mappedBy' => $params['usLinkName'], - ), - ), - ), - ); - } - - public function oneToOneUnidirectional($params, $foreignParams) - { - return array ( - $params['entityName'] => - array ( - 'oneToOne' => - array ( - $params['usLinkName'] => - array ( - 'targetEntity' => $params['targetEntity'], - 'joinColumn' => - array ( - 'name' => $params['usLinkName'].'_id', - 'referencedColumnName' => 'id', - ), - ), - ), - ), - ); - } - - public function oneToOneBidirectional($params, $foreignParams) - { - return array ( - $params['entityName'] => - array ( - 'oneToOne' => - array ( - $params['usLinkName'] => - array ( - 'targetEntity' => $params['targetEntity'], - 'mappedBy' => $foreignParams['usLinkName'], - ), - ), - ), - - $foreignParams['entityName'] => - array ( - 'oneToOne' => - array ( - $foreignParams['usLinkName'] => - array ( - 'targetEntity' => $foreignParams['targetEntity'], - 'inversedBy' => $params['usLinkName'], - 'joinColumn' => - array ( - 'name' => $params['usLinkName'].'_id', - 'referencedColumnName' => 'id', - ), - ), - ), - ), - ); - } - - public function oneToManySelfReferencing($params, $foreignParams) - { - return array ( - 'Category' => - array ( - 'type' => 'entity', - 'oneToMany' => - array ( - 'children' => - array ( - 'targetEntity' => 'Category', - 'mappedBy' => 'parent', - ), - ), - 'manyToOne' => - array ( - 'parent' => - array ( - 'targetEntity' => 'Category', - 'inversedBy' => 'children', - ), - ), - ), - ); - } - - - - - - - -} \ No newline at end of file diff --git a/application/Espo/Core/Doctrine/Helper.php b/application/Espo/Core/Doctrine/Helper.php deleted file mode 100644 index 6ceaab3578..0000000000 --- a/application/Espo/Core/Doctrine/Helper.php +++ /dev/null @@ -1,101 +0,0 @@ -entityManager = $entityManager; - - $this->schemaTool = new \Doctrine\ORM\Tools\SchemaTool($this->getEntityManager()); - $this->entityGenerator = new \Doctrine\ORM\Tools\EntityGenerator(); - - $this->disconnectedClassMetadataFactory = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory(); - $this->disconnectedClassMetadataFactory->setEntityManager($this->getEntityManager()); // $em is EntityManager instance - } - - protected function getEntityManager() - { - return $this->entityManager; - } - - protected function getSchemaTool() - { - return $this->schemaTool; - } - - protected function getDisconnectedClassMetadataFactory() - { - return $this->disconnectedClassMetadataFactory; - } - - protected function getEntityGenerator() - { - return $this->entityGenerator; - } - - - - /** - * Rebuild a database accordinly to metadata - * - * @return bool - */ - public function rebuildDatabase() - { - $GLOBALS['log']->add('DEBUG', 'EspoConverter:rebuildDatabase() - start rebuild database'); - - $classes = $this->getDisconnectedClassMetadataFactory()->getAllMetadata(); - $this->getSchemaTool()->updateSchema($classes); - - $GLOBALS['log']->add('DEBUG', 'EspoConverter:rebuildDatabase() - end rebuild database'); - - return true; //always true, because updateSchema just returns the VOID - } - - - /** - * Rebuild a database accordinly to metadata - * - * @return bool - */ - public function generateEntities($classNames) - { - if (!is_array($classNames)) { - $classNames= (array) $classNames; - } - - $metadata= array(); - foreach($classNames as $className) { - $metadata[]= $this->getDisconnectedClassMetadataFactory()->getMetadataFor($className); - } - - if (!empty($metadata)) { - $GLOBALS['log']->add('DEBUG', 'EspoConverter:generateEntities() - start generate Entities'); - - $this->getEntityGenerator()->setGenerateAnnotations(false); - $this->getEntityGenerator()->setGenerateStubMethods(true); - $this->getEntityGenerator()->setRegenerateEntityIfExists(false); - $this->getEntityGenerator()->setUpdateEntityIfExists(false); - $this->getEntityGenerator()->generate($metadata, 'application'); - - $GLOBALS['log']->add('DEBUG', 'EspoConverter:generateEntities() - end generate Entities'); - - return true; //always true, because generate just returns the VOID - } - - return false; - } - - -} \ No newline at end of file diff --git a/application/Espo/Core/Doctrine/ORM/Mapping/Driver/EspoPHPDriver.php b/application/Espo/Core/Doctrine/ORM/Mapping/Driver/EspoPHPDriver.php deleted file mode 100644 index 0ca1637b8c..0000000000 --- a/application/Espo/Core/Doctrine/ORM/Mapping/Driver/EspoPHPDriver.php +++ /dev/null @@ -1,679 +0,0 @@ -getElement($className); - - if ($element['type'] == 'entity') { - if (isset($element['repositoryClass'])) { - $metadata->setCustomRepositoryClass($element['repositoryClass']); - } - if (isset($element['readOnly']) && $element['readOnly'] == true) { - $metadata->markReadOnly(); - } - } else if ($element['type'] == 'mappedSuperclass') { - $metadata->setCustomRepositoryClass( - isset($element['repositoryClass']) ? $element['repositoryClass'] : null - ); - $metadata->isMappedSuperclass = true; - } else { - throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); - } - - // Evaluate root level properties - $table = array(); - if (isset($element['table'])) { - $table['name'] = $element['table']; - } - $metadata->setPrimaryTable($table); - - // Evaluate named queries - if (isset($element['namedQueries'])) { - foreach ($element['namedQueries'] as $name => $queryMapping) { - if (is_string($queryMapping)) { - $queryMapping = array('query' => $queryMapping); - } - - if ( ! isset($queryMapping['name'])) { - $queryMapping['name'] = $name; - } - - $metadata->addNamedQuery($queryMapping); - } - } - - // Evaluate named native queries - if (isset($element['namedNativeQueries'])) { - foreach ($element['namedNativeQueries'] as $name => $mappingElement) { - if (!isset($mappingElement['name'])) { - $mappingElement['name'] = $name; - } - $metadata->addNamedNativeQuery(array( - 'name' => $mappingElement['name'], - 'query' => isset($mappingElement['query']) ? $mappingElement['query'] : null, - 'resultClass' => isset($mappingElement['resultClass']) ? $mappingElement['resultClass'] : null, - 'resultSetMapping' => isset($mappingElement['resultSetMapping']) ? $mappingElement['resultSetMapping'] : null, - )); - } - } - - // Evaluate sql result set mappings - if (isset($element['sqlResultSetMappings'])) { - foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) { - if (!isset($resultSetMapping['name'])) { - $resultSetMapping['name'] = $name; - } - - $entities = array(); - $columns = array(); - if (isset($resultSetMapping['entityResult'])) { - foreach ($resultSetMapping['entityResult'] as $entityResultElement) { - $entityResult = array( - 'fields' => array(), - 'entityClass' => isset($entityResultElement['entityClass']) ? $entityResultElement['entityClass'] : null, - 'discriminatorColumn' => isset($entityResultElement['discriminatorColumn']) ? $entityResultElement['discriminatorColumn'] : null, - ); - - if (isset($entityResultElement['fieldResult'])) { - foreach ($entityResultElement['fieldResult'] as $fieldResultElement) { - $entityResult['fields'][] = array( - 'name' => isset($fieldResultElement['name']) ? $fieldResultElement['name'] : null, - 'column' => isset($fieldResultElement['column']) ? $fieldResultElement['column'] : null, - ); - } - } - - $entities[] = $entityResult; - } - } - - - if (isset($resultSetMapping['columnResult'])) { - foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) { - $columns[] = array( - 'name' => isset($columnResultAnnot['name']) ? $columnResultAnnot['name'] : null, - ); - } - } - - $metadata->addSqlResultSetMapping(array( - 'name' => $resultSetMapping['name'], - 'entities' => $entities, - 'columns' => $columns - )); - } - } - - /* not implemented specially anyway. use table = schema.table - if (isset($element['schema'])) { - $metadata->table['schema'] = $element['schema']; - }*/ - - if (isset($element['inheritanceType'])) { - $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType']))); - - if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) { - // Evaluate discriminatorColumn - if (isset($element['discriminatorColumn'])) { - $discrColumn = $element['discriminatorColumn']; - $metadata->setDiscriminatorColumn(array( - 'name' => isset($discrColumn['name']) ? (string)$discrColumn['name'] : null, - 'type' => isset($discrColumn['type']) ? (string)$discrColumn['type'] : null, - 'length' => isset($discrColumn['length']) ? (string)$discrColumn['length'] : null, - 'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string)$discrColumn['columnDefinition'] : null - )); - } else { - $metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255)); - } - - // Evaluate discriminatorMap - if (isset($element['discriminatorMap'])) { - $metadata->setDiscriminatorMap($element['discriminatorMap']); - } - } - } - - - // Evaluate changeTrackingPolicy - if (isset($element['changeTrackingPolicy'])) { - $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' - . strtoupper($element['changeTrackingPolicy']))); - } - - // Evaluate indexes - if (isset($element['indexes'])) { - foreach ($element['indexes'] as $name => $index) { - if ( ! isset($index['name'])) { - $index['name'] = $name; - } - - if (is_string($index['columns'])) { - $columns = explode(',', $index['columns']); - $columns = array_map('trim', $columns); - } else { - $columns = $index['columns']; - } - - $metadata->table['indexes'][$index['name']] = array( - 'columns' => $columns - ); - } - } - - // Evaluate uniqueConstraints - if (isset($element['uniqueConstraints'])) { - foreach ($element['uniqueConstraints'] as $name => $unique) { - if ( ! isset($unique['name'])) { - $unique['name'] = $name; - } - - if (is_string($unique['columns'])) { - $columns = explode(',', $unique['columns']); - $columns = array_map('trim', $columns); - } else { - $columns = $unique['columns']; - } - - $metadata->table['uniqueConstraints'][$unique['name']] = array( - 'columns' => $columns - ); - } - } - - if (isset($element['options'])) { - $metadata->table['options'] = $element['options']; - } - - $associationIds = array(); - if (isset($element['id'])) { - // Evaluate identifier settings - foreach ($element['id'] as $name => $idElement) { - if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) { - $associationIds[$name] = true; - continue; - } - - $mapping = array( - 'id' => true, - 'fieldName' => $name - ); - - if (isset($idElement['type'])) { - $mapping['type'] = $idElement['type']; - } - - if (isset($idElement['column'])) { - $mapping['columnName'] = $idElement['column']; - } - - if (isset($idElement['length'])) { - $mapping['length'] = $idElement['length']; - } - - if (isset($idElement['columnDefinition'])) { - $mapping['columnDefinition'] = $idElement['columnDefinition']; - } - - $metadata->mapField($mapping); - - if (isset($idElement['generator'])) { - $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' - . strtoupper($idElement['generator']['strategy']))); - } - // Check for SequenceGenerator/TableGenerator definition - if (isset($idElement['sequenceGenerator'])) { - $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']); - } else if (isset($idElement['customIdGenerator'])) { - $customGenerator = $idElement['customIdGenerator']; - $metadata->setCustomGeneratorDefinition(array( - 'class' => (string) $customGenerator['class'] - )); - } else if (isset($idElement['tableGenerator'])) { - throw MappingException::tableIdGeneratorNotImplemented($className); - } - } - } - - // Evaluate fields - if (isset($element['fields'])) { - foreach ($element['fields'] as $name => $fieldMapping) { - - $mapping = $this->columnToArray($name, $fieldMapping); - - if (isset($fieldMapping['id'])) { - $mapping['id'] = true; - if (isset($fieldMapping['generator']['strategy'])) { - $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' - . strtoupper($fieldMapping['generator']['strategy']))); - } - } - - if (isset($mapping['version'])) { - $metadata->setVersionMapping($mapping); - unset($mapping['version']); - } - - $metadata->mapField($mapping); - } - } - - // Evaluate oneToOne relationships - if (isset($element['oneToOne'])) { - foreach ($element['oneToOne'] as $name => $oneToOneElement) { - $mapping = array( - 'fieldName' => $name, - 'targetEntity' => $oneToOneElement['targetEntity'] - ); - - if (isset($associationIds[$mapping['fieldName']])) { - $mapping['id'] = true; - } - - if (isset($oneToOneElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']); - } - - if (isset($oneToOneElement['mappedBy'])) { - $mapping['mappedBy'] = $oneToOneElement['mappedBy']; - } else { - if (isset($oneToOneElement['inversedBy'])) { - $mapping['inversedBy'] = $oneToOneElement['inversedBy']; - } - - $joinColumns = array(); - - if (isset($oneToOneElement['joinColumn'])) { - $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']); - } else if (isset($oneToOneElement['joinColumns'])) { - foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinColumns'] = $joinColumns; - } - - if (isset($oneToOneElement['cascade'])) { - $mapping['cascade'] = $oneToOneElement['cascade']; - } - - if (isset($oneToOneElement['orphanRemoval'])) { - $mapping['orphanRemoval'] = (bool)$oneToOneElement['orphanRemoval']; - } - - $metadata->mapOneToOne($mapping); - } - } - - // Evaluate oneToMany relationships - if (isset($element['oneToMany'])) { - foreach ($element['oneToMany'] as $name => $oneToManyElement) { - $mapping = array( - 'fieldName' => $name, - 'targetEntity' => $oneToManyElement['targetEntity'], - 'mappedBy' => $oneToManyElement['mappedBy'] - ); - - if (isset($oneToManyElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']); - } - - if (isset($oneToManyElement['cascade'])) { - $mapping['cascade'] = $oneToManyElement['cascade']; - } - - if (isset($oneToManyElement['orphanRemoval'])) { - $mapping['orphanRemoval'] = (bool)$oneToManyElement['orphanRemoval']; - } - - if (isset($oneToManyElement['orderBy'])) { - $mapping['orderBy'] = $oneToManyElement['orderBy']; - } - - if (isset($oneToManyElement['indexBy'])) { - $mapping['indexBy'] = $oneToManyElement['indexBy']; - } - - $metadata->mapOneToMany($mapping); - } - } - - // Evaluate manyToOne relationships - if (isset($element['manyToOne'])) { - foreach ($element['manyToOne'] as $name => $manyToOneElement) { - $mapping = array( - 'fieldName' => $name, - 'targetEntity' => $manyToOneElement['targetEntity'] - ); - - if (isset($associationIds[$mapping['fieldName']])) { - $mapping['id'] = true; - } - - if (isset($manyToOneElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']); - } - - if (isset($manyToOneElement['inversedBy'])) { - $mapping['inversedBy'] = $manyToOneElement['inversedBy']; - } - - $joinColumns = array(); - - if (isset($manyToOneElement['joinColumn'])) { - $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']); - } else if (isset($manyToOneElement['joinColumns'])) { - foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinColumns'] = $joinColumns; - - if (isset($manyToOneElement['cascade'])) { - $mapping['cascade'] = $manyToOneElement['cascade']; - } - - $metadata->mapManyToOne($mapping); - } - } - - // Evaluate manyToMany relationships - if (isset($element['manyToMany'])) { - foreach ($element['manyToMany'] as $name => $manyToManyElement) { - $mapping = array( - 'fieldName' => $name, - 'targetEntity' => $manyToManyElement['targetEntity'] - ); - - if (isset($manyToManyElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']); - } - - if (isset($manyToManyElement['mappedBy'])) { - $mapping['mappedBy'] = $manyToManyElement['mappedBy']; - } else if (isset($manyToManyElement['joinTable'])) { - - $joinTableElement = $manyToManyElement['joinTable']; - $joinTable = array( - 'name' => $joinTableElement['name'] - ); - - if (isset($joinTableElement['schema'])) { - $joinTable['schema'] = $joinTableElement['schema']; - } - - foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - $mapping['joinTable'] = $joinTable; - } - - if (isset($manyToManyElement['inversedBy'])) { - $mapping['inversedBy'] = $manyToManyElement['inversedBy']; - } - - if (isset($manyToManyElement['cascade'])) { - $mapping['cascade'] = $manyToManyElement['cascade']; - } - - if (isset($manyToManyElement['orderBy'])) { - $mapping['orderBy'] = $manyToManyElement['orderBy']; - } - - if (isset($manyToManyElement['indexBy'])) { - $mapping['indexBy'] = $manyToManyElement['indexBy']; - } - - if (isset($manyToManyElement['orphanRemoval'])) { - $mapping['orphanRemoval'] = (bool)$manyToManyElement['orphanRemoval']; - } - - $metadata->mapManyToMany($mapping); - } - } - - // Evaluate associationOverride - if (isset($element['associationOverride']) && is_array($element['associationOverride'])) { - - foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) { - $override = array(); - - // Check for joinColumn - if (isset($associationOverrideElement['joinColumn'])) { - $joinColumns = array(); - foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $name; - } - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - $override['joinColumns'] = $joinColumns; - } - - // Check for joinTable - if (isset($associationOverrideElement['joinTable'])) { - - $joinTableElement = $associationOverrideElement['joinTable']; - $joinTable = array( - 'name' => $joinTableElement['name'] - ); - - if (isset($joinTableElement['schema'])) { - $joinTable['schema'] = $joinTableElement['schema']; - } - - foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $name; - } - - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $name; - } - - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - $override['joinTable'] = $joinTable; - } - - $metadata->setAssociationOverride($fieldName, $override); - } - } - - // Evaluate associationOverride - if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) { - - foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) { - $mapping = $this->columnToArray($fieldName, $attributeOverrideElement); - $metadata->setAttributeOverride($fieldName, $mapping); - } - } - - // Evaluate lifeCycleCallbacks - if (isset($element['lifecycleCallbacks'])) { - foreach ($element['lifecycleCallbacks'] as $type => $methods) { - foreach ($methods as $method) { - $metadata->addLifecycleCallback($method, constant('Doctrine\ORM\Events::' . $type)); - } - } - } - - // populate ClassMetadataInfo instance from $data - - } - - /** - * Constructs a joinColumn mapping array based on the information - * found in the given join column element. - * - * @param array $joinColumnElement The array join column element - * @return array The mapping array. - */ - private function joinColumnToArray($joinColumnElement) - { - $joinColumn = array(); - if (isset($joinColumnElement['referencedColumnName'])) { - $joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName']; - } - - if (isset($joinColumnElement['name'])) { - $joinColumn['name'] = (string) $joinColumnElement['name']; - } - - if (isset($joinColumnElement['fieldName'])) { - $joinColumn['fieldName'] = (string) $joinColumnElement['fieldName']; - } - - if (isset($joinColumnElement['unique'])) { - $joinColumn['unique'] = (bool) $joinColumnElement['unique']; - } - - if (isset($joinColumnElement['nullable'])) { - $joinColumn['nullable'] = (bool) $joinColumnElement['nullable']; - } - - if (isset($joinColumnElement['onDelete'])) { - $joinColumn['onDelete'] = $joinColumnElement['onDelete']; - } - - if (isset($joinColumnElement['columnDefinition'])) { - $joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition']; - } - - return $joinColumn; - } - - /** - * Parse the given column as array - * - * @param string $fieldName - * @param array $column - * @return array - */ - private function columnToArray($fieldName, $column) - { - $mapping = array( - 'fieldName' => $fieldName - ); - - if (isset($column['type'])) { - $params = explode('(', $column['type']); - $column['type'] = $params[0]; - $mapping['type'] = $column['type']; - - if (isset($params[1])) { - $column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1); - } - } - - if (isset($column['column'])) { - $mapping['columnName'] = $column['column']; - } - - if (isset($column['length'])) { - $mapping['length'] = $column['length']; - } - - if (isset($column['precision'])) { - $mapping['precision'] = $column['precision']; - } - - if (isset($column['scale'])) { - $mapping['scale'] = $column['scale']; - } - - if (isset($column['unique'])) { - $mapping['unique'] = (bool)$column['unique']; - } - - if (isset($column['options'])) { - $mapping['options'] = $column['options']; - } - - if (isset($column['nullable'])) { - $mapping['nullable'] = $column['nullable']; - } - - if (isset($column['version']) && $column['version']) { - $mapping['version'] = $column['version']; - } - - if (isset($column['columnDefinition'])) { - $mapping['columnDefinition'] = $column['columnDefinition']; - } - - return $mapping; - } - - /** - * {@inheritdoc} - */ - protected function loadMappingFile($file) - { - if (strpos($file, "\n") === false && is_file($file)) { - if (false === is_readable($file)) { - throw new MappingException(sprintf('File "%s" is not readable.', $file)); - } - - return include($file); - } - } - -} \ No newline at end of file diff --git a/application/Espo/Core/Loaders/EntityManager.php b/application/Espo/Core/Loaders/EntityManager.php index d3a9400e76..ceee12b80a 100644 --- a/application/Espo/Core/Loaders/EntityManager.php +++ b/application/Espo/Core/Loaders/EntityManager.php @@ -28,10 +28,11 @@ class EntityManager 'dbname' => $config->get('database.dbname'), 'user' => $config->get('database.user'), 'password' => $config->get('database.password'), + 'metadata' => $this->getContainer()->get('metadata')->getEspoMetadata(), ); - - $entityManager = new \Espo\Core\ORM\EntityManager($params); - $entityManager->setEspoMetadata($container->get('metadata')); + + $entityManager = new \Espo\Core\ORM\EntityManager($params); + $entityManager->setEspoMetadata($this->getContainer()->get('metadata')); return $entityManager; } diff --git a/application/Espo/Core/Utils/Api/Auth.php b/application/Espo/Core/Utils/Api/Auth.php index d44b8c15db..4765d7efd6 100644 --- a/application/Espo/Core/Utils/Api/Auth.php +++ b/application/Espo/Core/Utils/Api/Auth.php @@ -10,7 +10,7 @@ class Auth extends \Slim\Middleware private $container; - public function __construct(\Espo\Core\EntityManager $entityManager, \Espo\Core\Container $container) + public function __construct(\Espo\Core\ORM\EntityManager $entityManager, \Espo\Core\Container $container) { $this->entityManager = $entityManager; $this->container = $container; @@ -48,14 +48,13 @@ class Auth extends \Slim\Middleware $username = $authKey; $password = $authSec; - - $user = $this->entityManager->getRepository('User')->findOne(array('username' => $username)); + $user = $this->entityManager->getRepository('User')->findOne(array('userName' => $username)); if ($user) { if ($password == $user->get('password')) { $this->container->setUser($user); $isAuthenticated = true; } - } + } if ($isAuthenticated) { $this->next->call(); diff --git a/application/Espo/Core/Utils/Config.php b/application/Espo/Core/Utils/Config.php index 8ef378a9b7..dfc6e01865 100644 --- a/application/Espo/Core/Utils/Config.php +++ b/application/Espo/Core/Utils/Config.php @@ -52,13 +52,18 @@ class Config */ public function get($name) { - $contentObj = $this->getConfig(); + $keys = explode('.', $name); - if (isset($contentObj->$name)) { - return $contentObj->$name; - } + $lastBranch = $this->getConfig(); + foreach($keys as $keyName) { + if (isset($lastBranch->$keyName) && is_object($lastBranch)) { + $lastBranch = $lastBranch->$keyName; + } else { + return null; + } + } - return null; + return $lastBranch; } diff --git a/application/Espo/Core/Utils/Database/Converter.php b/application/Espo/Core/Utils/Database/Converter.php new file mode 100644 index 0000000000..a806e6def5 --- /dev/null +++ b/application/Espo/Core/Utils/Database/Converter.php @@ -0,0 +1,100 @@ +metadata = $metadata; + + $this->ormConverter = new Converters\Orm($this->metadata); + + $this->schemaConverter = new Converters\Schema(); + } + + + protected function getMetadata() + { + return $this->metadata; + } + + protected function getOrmConverter() + { + return $this->ormConverter; + } + + protected function getSchemaConverter() + { + return $this->schemaConverter; + } + + + public function getSchemaFromMetadata() + { + return $this->schemaFromMetadata; + } + + protected function setSchemaFromMetadata(\Doctrine\DBAL\Schema\Schema $schema) + { + $this->schemaFromMetadata = $schema; + } + + /** + * Main method of convertation from metadata to orm metadata and database schema + * + * @return bool + */ + public function process() + { + $GLOBALS['log']->add('Debug', 'Converter:process() - Start: converting metadata to orm format and database schema'); + + $entityDefs = $this->getMetadata()->get('entityDefs'); + + $databaseMeta = array(); + foreach($entityDefs as $entityName => $entityMeta) { + + if (empty($entityMeta)) { + $GLOBALS['log']->add('ERROR', 'Converter:process(), Entity:'.$entityName.' - metadata cannot be converted into database format'); + continue; + } + + $databaseMeta = Util::merge($databaseMeta, $this->getOrmConverter()->process($entityName, $entityMeta, $entityDefs)); + } + + $schema = $this->getSchemaConverter()->process($databaseMeta, $entityDefs); + $this->setSchemaFromMetadata($schema); + + //save database meta to a file espoMetadata.php + $result = $this->getMetadata()->setEspoMetadata($databaseMeta); + + + $GLOBALS['log']->add('Debug', 'Converter:process() - End: converting metadata to orm format and database schema, result=['.$result.']'); + + return $result; + } + + + + +} + + +?> \ No newline at end of file diff --git a/application/Espo/Core/Doctrine/Converter/Base.php b/application/Espo/Core/Utils/Database/Converters/Orm.php similarity index 56% rename from application/Espo/Core/Doctrine/Converter/Base.php rename to application/Espo/Core/Utils/Database/Converters/Orm.php index b5a81e5f3e..7d14bbd3cc 100644 --- a/application/Espo/Core/Doctrine/Converter/Base.php +++ b/application/Espo/Core/Utils/Database/Converters/Orm.php @@ -1,151 +1,81 @@ 255, + 'int' => 11, + ); + /* * //pair espo:doctrine */ protected $fieldAccordances = array( 'type' => 'type', - 'maxLength' => 'length', + 'maxLength' => 'len', 'default' => array( 'condition' => '^javascript:', 'conditionEquals' => false, 'value' => array( - 'options' => array ( - 'default' => '{0}', - ), + 'default' => '{0}', ), ), ); - /** - * @var array $meta - metadata array - */ - private $meta; - - - public function __construct(\Espo\Core\EntityManager $entityManager, \Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\File\Manager $fileManager) + public function __construct(\Espo\Core\Utils\Metadata $metadata) { - $this->entityManager = $entityManager; - $this->metadata = $metadata; - $this->fileManager = $fileManager; + $this->metadata = $metadata; - $this->doctrineHelper = new \Espo\Core\Doctrine\Helper($this->getEntityManager()->getWrapped()); - - $this->linkConverter = new \Espo\Core\Doctrine\Converter\Link($this->metadata); + $this->links = new \Espo\Core\Utils\Database\Links($this->metadata); } - protected function getEntityManager() - { - return $this->entityManager; - } protected function getMetadata() { return $this->metadata; } - protected function getFileManager() + protected function getLinks() { - return $this->fileManager; + return $this->links; } - protected function getDoctrineHelper() + + + //convertToDatabaseFormat + public function process($entityName, $entityMeta, $entityDefs) { - return $this->doctrineHelper; + $ormMeta = array(); + $ormMeta[$entityName] = array( + 'fields' => array( + ), + 'relations' => array( + ), + ); + + $ormMeta[$entityName]['fields'] = $this->convertFields($entityName, $entityMeta); + + $convertedLinks = $this->convertLinks($entityName, $entityMeta, $entityDefs); + + return Util::merge($ormMeta, $convertedLinks); } - protected function getLinkConverter() - { - return $this->linkConverter; - } - - /** - * Metadata conversion from Espo format into Doctrine - * - * @param object $meta - * - * @return bool - */ - - //public function process() - public function process() - { - //echo '
';
- $GLOBALS['log']->add('Debug', 'Metadata:get() - converting to doctrine metadata');
-
- $entityDefs = $this->getMetadata()->get('entityDefs');
-
- $convertedMeta = array();
- foreach($entityDefs as $entityName => $entityMeta) {
-
- //echo '['.$entityName.']
';
-
- if (empty($entityMeta)) {
- $GLOBALS['log']->add('ERROR', 'EspoConverter:convert(), Entity:'.$entityName.' - metadata cannot be converted into Doctrine format');
- continue;
- }
-
- $convertedMeta[$entityName] = array(
- 'type' => 'entity',
- 'table' => Util::fromCamelCase($entityName, '_'), //TODO: if need to convert to underscore
- 'id' => array(
- 'id' => array(
- 'type' => 'string',
- 'generator' => array('strategy' => 'UUID'),
- )
- ),
- );
-
- $convertedMeta[$entityName]['fields'] = $this->convertFields($entityName, $entityMeta);
-
- $convertedLinks = $this->convertLinks($entityName, $entityMeta, $entityDefs, $convertedMeta);
-
- //$convertedMeta = Util::merge($convertedMeta, $convertedLinks); //for link is need to define for two entities at once
- }
- /*echo '
';
- print_r($convertedMeta);
- exit;*/
-
- return;
-
- //save doctrine meta to files
- $cacheDir = $this->getMetadata()->getMetaConfig()->doctrineCache;
- $this->getFileManager()->removeFilesInDir($cacheDir); //remove all existing files
-
- $result= true;
- foreach ($convertedMeta as $entityName => $doctineMeta) {
- $entityFullName = $this->getMetadata()->getEntityPath($entityName);
- $doctrineMeta = array($entityFullName => $doctineMeta);
-
- //create a doctrine metadata file like "Espo.Entities.User.php"
- $fileName = str_replace('\\', '.', $entityFullName).'.php';
- $result &= $this->getFileManager()->setContent($this->getFileManager()->getPHPFormat($doctrineMeta), $cacheDir, $fileName);
- //END: create a doctrine metadata file
- }
- //END: save doctrine meta to files
-
- return $result;
- }
-
/**
* Metadata conversion from Espo format into Doctrine
@@ -157,19 +87,27 @@ class Base
*/
protected function convertFields($entityName, $entityMeta)
{
- $outputMeta = array();
+ $outputMeta = array(
+ 'id' => array(
+ 'type' => Entity::ID,
+ ),
+ );
+
foreach($entityMeta['fields'] as $fieldName => $fieldParams) {
- $fieldName = Util::fromCamelCase($fieldName, '_');
+ //$fieldName = Util::fromCamelCase($fieldName, '_');
//check if "fields" option exists in $fieldMeta
+ $fieldParams['type'] = isset($fieldParams['type']) ? $fieldParams['type'] : '';
+
$fieldTypeMeta = $this->getMetadata()->get('fields.'.$fieldParams['type']);
if (isset($fieldTypeMeta['fields']) && is_array($fieldTypeMeta['fields'])) {
$namingType = isset($fieldTypeMeta['naming']) ? $fieldTypeMeta['naming'] : $this->defaultNaming;
foreach($fieldTypeMeta['fields'] as $subFieldName => $subFieldParams) {
- $subFieldNameNaming = Util::fromCamelCase( Util::getNaming($fieldName, $subFieldName, $namingType, '_'), '_' );
+ //$subFieldNameNaming = Util::fromCamelCase( Util::getNaming($fieldName, $subFieldName, $namingType, '_'), '_' );
+ $subFieldNameNaming = Util::getNaming($fieldName, $subFieldName, $namingType);
if (!isset($entityMeta['fields'][$subFieldNameNaming])) {
$subFieldDefs = $this->convertField($entityName, $subFieldName, $subFieldParams);
if ($subFieldDefs !== false) {
@@ -186,16 +124,22 @@ class Base
}
}
-
/*Make actions for different types like "link", "linkMultiple", "linkParent" */
}
+
+ if (!isset($outputMeta['deleted'])) {
+ $outputMeta['deleted'] = array(
+ 'type' => Entity::BOOL,
+ 'default' => 0,
+ );
+ }
+
return $outputMeta;
}
- /*It can be moved to separate file*/
protected function convertField($entityName, $fieldName, array $fieldParams)
{
//set default type if exists
@@ -206,34 +150,46 @@ class Base
$fieldTypeMeta = $this->getMetadata()->get('fields.'.$fieldParams['type']);
- //check if field need to be saved in database
- if ( (isset($fieldParams['db']) && $fieldParams['db'] === false) || (isset($fieldTypeMeta['database']['db']) && !$fieldTypeMeta['database']['db'] === false) ) {
- return false;
- } //END: check if field need to be saved in database
+ //check if need to skip this field into database metadata
+ if (isset($fieldTypeMeta['database']['skip']) && $fieldTypeMeta['database']['skip'] === true) {
+ return false;
+ }
$fieldDefs = $this->getInitValues($fieldParams);
+ //check if field need to be saved in database
+ //TODO change entytyDefs from db:false to notStorable:true
+ if ( (isset($fieldParams['db']) && $fieldParams['db'] === false) || (isset($fieldTypeMeta['database']['notStorable']) && !$fieldTypeMeta['database']['notStorable'] === true) ) {
+ $fieldDefs['notStorable'] = true;
+ } //END: check if field need to be saved in database
+
//merge database options from field definition
if (isset($fieldTypeMeta['database'])) {
$fieldDefs = Util::merge($fieldDefs, $fieldTypeMeta['database']);
}
+ //check and set a field length
+ if (!isset($fieldDefs['len']) && in_array($fieldDefs['type'], array_keys($this->defaultLength))) {
+ $fieldDefs['len'] = $this->defaultLength[$fieldDefs['type']];
+ } //END: check and set a field length
+
return $fieldDefs;
}
- protected function convertLinks($entityName, $entityMeta, array $entityDefs, array $convertedMeta)
+ protected function convertLinks($entityName, $entityMeta, array $entityDefs)
{
if (!isset($entityMeta['links'])) {
return array();
}
+ $relationships = array();
foreach($entityMeta['links'] as $linkName => $linkParams) {
//echo $linkName.'
';
//print_r($linkParams);
- $linkEntityName = $this->getLinkConverter()->getLinkEntityName($entityName, $linkParams);
+ $linkEntityName = $this->getLinks()->getLinkEntityName($entityName, $linkParams);
//print_r($entityDefs[$linkEntityName]['links']);
//print_r($convertedMeta[$linkEntityName]);
@@ -242,29 +198,38 @@ class Base
$foreignLink = $this->getForeignLink($linkName, $linkParams, $entityDefs[$linkEntityName]);
- $method = $currentType;
+ $method = $currentType;
+ unset($reverseMethod);
if ($foreignLink !== false) {
$method .= '-'.$foreignLink['params']['type'];
+ $reverseMethod = Util::toCamelCase( $foreignLink['params']['type'].'-'.$currentType );
}
$method = Util::toCamelCase($method);
- /*if ($method == 'belongsToParent') {
+ //echo
+ /*if ($method == 'hasManyBelongsTo' || $reverseMethod == 'belongshasManyBelongsToTo') {
die($entityName.' - '.$linkName);
}*/
- if (method_exists($this->getLinkConverter(), $method)) {
- $convertedLink = $this->getLinkConverter()->process($method, $entityName, array('name'=>$linkName, 'params'=>$linkParams), $foreignLink);
- //print_r($convertedLink);
+ if (method_exists($this->getLinks(), $method)) { //ex. hasManyHasMany
+ $convertedLink = $this->getLinks()->process($method, $entityName, array('name'=>$linkName, 'params'=>$linkParams), $foreignLink);
+ } else if (method_exists($this->getLinks(), $currentType)) { //ex. hasMany
+ $convertedLink = $this->getLinks()->process($currentType, $entityName, array('name'=>$linkName, 'params'=>$linkParams), $foreignLink);
}
+ /*else if (isset($reverseMethod) && method_exists($this->getLinks(), $reverseMethod)) {
+ $convertedLink = $this->getLinks()->process($reverseMethod, $entityName, $foreignLink, array('name'=>$linkName, 'params'=>$linkParams));
+ } */
+
+ //$relationships = Util::merge($relationships, $convertedLink);
+ $relationships = Util::merge($convertedLink, $relationships);
+
//echo $method.' = '.$currentType.' - '.$foreignLink['type'].'
';
-
-
}
- return $convertedMeta;
+ return $relationships;
}
@@ -329,8 +294,4 @@ class Base
return $values;
}
-
-}
-
-
-?>
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/application/Espo/Core/Utils/Database/Converters/Schema.php b/application/Espo/Core/Utils/Database/Converters/Schema.php
new file mode 100644
index 0000000000..77d2e46a03
--- /dev/null
+++ b/application/Espo/Core/Utils/Database/Converters/Schema.php
@@ -0,0 +1,112 @@
+ 'varchar',
+ 'len' => '24',
+ );
+
+ //pair espo::doctrine
+ protected $allowedDbFieldParams = array(
+ 'len' => 'length',
+ 'default' => 'default',
+ );
+
+ public function __construct()
+ {
+ $this->dbalSchema = new \Doctrine\DBAL\Schema\Schema();
+
+ $this->typeList = array_keys(\Doctrine\DBAL\Types\Type::getTypesMap());
+ }
+
+ protected function getDbalSchema()
+ {
+ return $this->dbalSchema;
+ }
+
+
+
+ //convertToSchema
+ public function process(array $databaseMeta, $entityDefs)
+ {
+ $schema = $this->getDbalSchema();
+
+ $tables = array();
+ foreach ($databaseMeta as $entityName => $entityParams) {
+
+ $tables[$entityName] = $schema->createTable( Util::toUnderScore($entityName) );
+
+ $primaryColumns = array();
+ foreach ($entityParams['fields'] as $fieldName => $fieldParams) {
+
+ if (isset($fieldParams['notStorable']) && $fieldParams['notStorable']) {
+ continue;
+ }
+
+ if ($fieldParams['type'] == 'id') {
+ $primaryColumns[] = Util::toUnderScore($fieldName);
+ }
+
+ switch ($fieldParams['type']) {
+ case 'id':
+ $primaryColumns[] = Util::toUnderScore($fieldName);
+
+ case 'id':
+ case 'foreignId':
+ $fieldParams = $this->idParams;
+ break;
+
+ case 'array':
+ case 'json_array':
+ $fieldParams['default'] = ''; //for db type TEXT can't be defined a default value
+ break;
+ }
+
+ if (!in_array($fieldParams['type'], $this->typeList)) {
+ $GLOBALS['log']->add('DEBUG', 'Field type ['.$fieldParams['type'].'] does not exist '.$entityName.':'.$fieldName);
+ continue;
+ }
+
+ //echo Util::toUnderScore($fieldName).', '.$fieldParams['type'].', '.print_r($this->getDbFieldParams($fieldParams),1).'
';
+
+ $tables[$entityName]->addColumn(Util::toUnderScore($fieldName), $fieldParams['type'], $this->getDbFieldParams($fieldParams));
+ }
+
+ $tables[$entityName]->setPrimaryKey($primaryColumns);
+ }
+
+ /* foreach ($databaseMeta as $entityName => $entityParams) {
+
+ foreach ($databaseMeta['relations'] as $relationName => $relationParams) {
+ $myForeign->addForeignKeyConstraint($myTable, array("user_id"), array("id"), array("onUpdate" => "CASCADE"));
+ }
+ }*/
+
+ return $schema;
+ }
+
+
+ protected function getDbFieldParams($fieldParams)
+ {
+ $dbFieldParams = array();
+
+ foreach($this->allowedDbFieldParams as $espoName => $dbalName) {
+
+ if (isset($fieldParams[$espoName])) {
+ $dbFieldParams[$dbalName] = $fieldParams[$espoName];
+ }
+ }
+
+ return $dbFieldParams;
+ }
+}
\ No newline at end of file
diff --git a/application/Espo/Core/Utils/Database/FieldTypes/Bool.php b/application/Espo/Core/Utils/Database/FieldTypes/Bool.php
new file mode 100644
index 0000000000..a9f68cd502
--- /dev/null
+++ b/application/Espo/Core/Utils/Database/FieldTypes/Bool.php
@@ -0,0 +1,45 @@
+getBooleanTypeDeclarationSQL($fieldDeclaration);
+ }
+
+
+ public function convertToDatabaseValue($value, AbstractPlatform $platform)
+ {
+ return $platform->convertBooleans($value);
+ }
+
+
+ public function convertToPHPValue($value, AbstractPlatform $platform)
+ {
+ return (null === $value) ? null : (bool) $value;
+ }
+
+ public function getBindingType()
+ {
+ return \PDO::PARAM_BOOL;
+ }
+}
\ No newline at end of file
diff --git a/application/Espo/Core/Utils/Database/FieldTypes/Int.php b/application/Espo/Core/Utils/Database/FieldTypes/Int.php
new file mode 100644
index 0000000000..f328b3637c
--- /dev/null
+++ b/application/Espo/Core/Utils/Database/FieldTypes/Int.php
@@ -0,0 +1,35 @@
+getIntegerTypeDeclarationSQL($fieldDeclaration);
+ }
+
+
+ public function convertToPHPValue($value, AbstractPlatform $platform)
+ {
+ return (null === $value) ? null : (int) $value;
+ }
+
+
+ public function getBindingType()
+ {
+ return \PDO::PARAM_INT;
+ }
+}
\ No newline at end of file
diff --git a/application/Espo/Core/Doctrine/Types/Password.php b/application/Espo/Core/Utils/Database/FieldTypes/Password.php
similarity index 88%
rename from application/Espo/Core/Doctrine/Types/Password.php
rename to application/Espo/Core/Utils/Database/FieldTypes/Password.php
index e85b4c39f1..b9bf67d5b1 100644
--- a/application/Espo/Core/Doctrine/Types/Password.php
+++ b/application/Espo/Core/Utils/Database/FieldTypes/Password.php
@@ -1,5 +1,6 @@
getVarcharTypeDeclarationSQL($fieldDeclaration);
@@ -24,9 +30,6 @@ class Password extends Type
return $value;
} */
- public function getName()
- {
- return self::PASSWORD;
- }
+
}
diff --git a/application/Espo/Core/Utils/Database/FieldTypes/Varchar.php b/application/Espo/Core/Utils/Database/FieldTypes/Varchar.php
new file mode 100644
index 0000000000..c0fd317834
--- /dev/null
+++ b/application/Espo/Core/Utils/Database/FieldTypes/Varchar.php
@@ -0,0 +1,29 @@
+getVarcharTypeDeclarationSQL($fieldDeclaration);
+ //return 'varchar';
+ }
+
+
+ public function getDefaultLength(AbstractPlatform $platform)
+ {
+ return $platform->getVarcharDefaultLength();
+ }
+}
\ No newline at end of file
diff --git a/application/Espo/Core/Doctrine/Converter/Link.php b/application/Espo/Core/Utils/Database/Links.php
similarity index 52%
rename from application/Espo/Core/Doctrine/Converter/Link.php
rename to application/Espo/Core/Utils/Database/Links.php
index cbf0aae490..94f9544f2c 100644
--- a/application/Espo/Core/Doctrine/Converter/Link.php
+++ b/application/Espo/Core/Utils/Database/Links.php
@@ -1,21 +1,21 @@
metadata = $metadata;
- $this->association = new \Espo\Core\Doctrine\Converter\Association();
+ $this->relations = new \Espo\Core\Utils\Database\Relations();
}
protected function getMetadata()
@@ -23,9 +23,9 @@ class Link
return $this->metadata;
}
- protected function getAssociation()
+ protected function getRelations()
{
- return $this->association;
+ return $this->relations;
}
@@ -34,46 +34,27 @@ class Link
if (isset($link['params'])) {
return isset($link['params']['entity']) ? $link['params']['entity'] : $entityName;
}
+ /*if (!isset($link['entity']) && isset($link['entities'])) {
+ return $link['entities'];
+ } */
return isset($link['entity']) ? $link['entity'] : $entityName;
}
- public function toUnderScore($name)
- {
- return Util::fromCamelCase($name, '_');
- }
-
- protected function getJoinTable($tableName1, $tableName2)
- {
- $tables = array(
- $this->toUnderScore($tableName1),
- $this->toUnderScore($tableName2),
- );
-
- asort($tables);
-
- return implode('_', $tables);
- }
-
public function process($method, $entityName, $link, $foreignLink = array())
{
$params = array();
$params['entityName'] = $entityName;
- $params['usEntityName'] = $this->toUnderScore($entityName);
$params['link'] = $link;
- $params['usLinkName'] = $this->toUnderScore($link['name']);
$foreignParams = array();
$foreignParams['entityName'] = $this->getLinkEntityName($entityName, $link);
- $foreignParams['usEntityName'] = $this->toUnderScore($foreignParams['entityName']);
$foreignParams['link'] = $foreignLink;
- $foreignParams['usLinkName'] = $this->toUnderScore($foreignParams['link']['name']);
-
- $params['targetEntity'] = $this->getMetadata()->getEntityPath($foreignParams['entityName']);
- $foreignParams['targetEntity'] = $this->getMetadata()->getEntityPath($params['entityName']);
-
- $params['joinTable'] = $foreignParams['targetEntity'] = $this->getJoinTable($params['entityName'], $foreignParams['entityName']);
+ //$params['targetEntity'] = $this->getMetadata()->getEntityPath($foreignParams['entityName']);
+ //$foreignParams['targetEntity'] = $this->getMetadata()->getEntityPath($params['entityName']);
+ $params['targetEntity'] = $foreignParams['entityName'];
+ $foreignParams['targetEntity'] = $params['entityName'];
if (method_exists($this, $method)) {
return $this->$method($params, $foreignParams);
@@ -86,49 +67,59 @@ class Link
protected function belongsTo($params, $foreignParams)
{
- return $this->getAssociation()->manyToOneUnidirectional($params, $foreignParams);
+ return $this->getRelations()->belongsTo($params, $foreignParams);
}
-
//TODO: hook for teams
protected function hasMany($params, $foreignParams)
{
- return $this->getAssociation()->oneToManyUnidirectionalWithJoinTable($params, $foreignParams);
+ return $this->getRelations()->hasMany($params, $foreignParams);
}
protected function hasManyHasMany($params, $foreignParams)
{
- return $this->getAssociation()->manyToManyBidirectional($params, $foreignParams);
+ return $this->getRelations()->manyMany($params, $foreignParams);
}
- protected function hasOne($params, $foreignParams)
- {
- return $this->getAssociation()->oneToOneUnidirectional($params, $foreignParams);
- }
- protected function hasOneBelongsTo($params, $foreignParams)
+ protected function hasChildren($params, $foreignParams)
{
- return $this->getAssociation()->oneToOneBidirectional($params, $foreignParams);
+ return $this->getRelations()->hasChildren($params, $foreignParams);
}
protected function belongsToParent($params, $foreignParams)
{
- return $this->getAssociation()->oneToManySelfReferencing($params, $foreignParams);
+ return $this->getRelations()->belongsToParent($params, $foreignParams);
}
+ /*protected function hasChildrenBelongsToParent()
+ {
+ return $this->getRelations()->hasChildren($params, $foreignParams);
+ }*/
+
+ /*protected function hasManyBelongsTo($params, $foreignParams)
+ {
+ $hasMany = $this->getRelations()->hasMany($params, $foreignParams);
+ $belongsTo = $this->getRelations()->belongsTo($foreignParams, $params);
+ //$belongsTo [Contact] [relations] [account] ['foreignKey'] = 'id'; ???
+
+ return Util::merge($hasMany, $belongsTo);
+ } */
+
+
/*
- +[0] => belongsTo
+ [0] => belongsTo
[1] => belongsToParent
[2] => hasManyBelongsToParent
- +[3] => hasMany
+ [3] => hasMany
[4] => hasChildrenBelongsToParent
- +[5] => hasOne
- +[6] => hasManyHasMany
+ [5] => hasOne
+ [6] => hasManyHasMany
[7] => hasManyBelongsTo
[8] => hasChildrenHasMany
[9] => hasChildren
@@ -161,7 +152,6 @@ class Link
[7] => hasManyHasMany
[8] => hasManyBelongsTo
[9] => hasChildrenHasMany
- [10] => hasChildren
[11] => belongsToHasMany
[12] => joint
*/
diff --git a/application/Espo/Core/Utils/Database/Relations.php b/application/Espo/Core/Utils/Database/Relations.php
new file mode 100644
index 0000000000..d91efd5497
--- /dev/null
+++ b/application/Espo/Core/Utils/Database/Relations.php
@@ -0,0 +1,179 @@
+getSortEntities($tableName1, $tableName2);
+
+ return Util::toCamelCase( implode('-', $tables) );
+ }
+
+
+
+
+ //todo sedine in foreign fieldDefs a key for current
+ public function manyMany($params, $foreignParams)
+ {
+ $sortedEntities = $this->getSortEntities($params['entityName'], $foreignParams['entityName']);
+
+ $relation = array();
+ if (strtolower($params['entityName']) == strtolower($sortedEntities[0])) {
+ $relation = array(
+ $params['entityName'] => array(
+ 'relations' => array(
+ $params['link']['name'] => array(
+ 'type' => Entity::MANY_MANY,
+ 'entity' => $params['targetEntity'],
+ 'relationName' => $this->getJoinTable($params['entityName'], $foreignParams['entityName']),
+ 'key' => 'id', //todo specify 'key'
+ 'foreignKey' => 'id', //todo specify 'foreignKey'
+ 'midKeys' => array(
+ $sortedEntities[0].'Id',
+ $sortedEntities[1].'Id',
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ return $relation;
+ }
+
+
+ public function hasMany($params, $foreignParams)
+ {
+ $relation = array(
+ $params['entityName'] => array (
+ 'relations' => array(
+ $params['link']['name'] => array(
+ 'type' => Entity::HAS_MANY,
+ 'entity' => $params['targetEntity'],
+ 'foreignKey' => lcfirst($foreignParams['link']['name'].'Id'), //???: 'foreignKey' => $params['link']['name'].'Id',
+ ),
+ ),
+ ),
+ );
+
+ return $relation;
+ }
+
+ public function belongsTo($params, $foreignParams)
+ {
+ $relation = array (
+ $params['entityName'] => array (
+ 'fields' => array(
+ $params['link']['name'].'Name' => array(
+ 'type' => Entity::FOREIGN,
+ 'relation' => $params['link']['name'],
+ 'notStorable' => true,
+ ),
+ $params['link']['name'].'Id' => array(
+ 'type' => Entity::FOREIGN_ID,
+ ),
+ ),
+ 'relations' => array(
+ $params['link']['name'] => array(
+ 'type' => Entity::BELONGS_TO,
+ 'entity' => $params['targetEntity'],
+ 'key' => $params['link']['name'].'Id',
+ 'foreignKey' => 'id', //????
+ ),
+ ),
+ ),
+ );
+
+ if (isset($params['link']['foreign'])) { //???
+ $relation[$params['entityName']] ['fields'] [$params['link']['name'].'Name'] ['foreign'] = $params['link']['foreign'];
+ }
+
+ return $relation;
+ }
+
+ public function hasChildren($params, $foreignParams)
+ {
+ $relation = array(
+ $params['entityName'] => array (
+ 'relations' => array(
+ $params['link']['name'] => array(
+ 'type' => Entity::HAS_CHILDREN,
+ 'entity' => $params['targetEntity'],
+ 'foreignKey' => $foreignParams['link']['name'].'Id', //???: 'foreignKey' => $params['link']['name'].'Id',
+ 'foreignType' => $foreignParams['link']['name'].'Type', //???: 'foreignKey' => $params['link']['name'].'Id',
+ ),
+ ),
+ ),
+
+ /*$foreignParams['entityName'] => array (
+ 'fields' => array(
+ $foreignParams['link']['name'].'Id' => array(
+ 'type' => Entity::FOREIGN_ID,
+ ),
+ $foreignParams['link']['name'].'Type' => array(
+ 'type' => Entity::FOREIGN_TYPE,
+ ),
+ $foreignParams['link']['name'].'Name' => array(
+ 'type' => Entity::VARCHAR,
+ 'notStorable' => true,
+ ),
+ ),
+ ), */
+ );
+
+
+ return $relation;
+ }
+
+ public function belongsToParent($params, $foreignParams)
+ {
+ $relation = array();
+
+ $entities = isset($params['link']['params']['entities']) ? $params['link']['params']['entities'] : array($params['entityName']);
+
+ foreach($entities as $entity) {
+ $relation[$entity] = array (
+ 'fields' => array(
+ $params['link']['name'].'Id' => array(
+ 'type' => Entity::FOREIGN_ID,
+ ),
+ $params['link']['name'].'Type' => array(
+ 'type' => Entity::FOREIGN_TYPE,
+ ),
+ $params['link']['name'].'Name' => array(
+ 'type' => Entity::VARCHAR,
+ 'notStorable' => true,
+ ),
+ ),
+ );
+ }
+
+ return $relation;
+ }
+
+
+ public function hasOne($params, $foreignParams)
+ {
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/application/Espo/Core/Utils/Database/Schema.php b/application/Espo/Core/Utils/Database/Schema.php
new file mode 100644
index 0000000000..95cce5bf61
--- /dev/null
+++ b/application/Espo/Core/Utils/Database/Schema.php
@@ -0,0 +1,182 @@
+config = $config;
+ $this->metadata = $metadata;
+ $this->fileManager = $fileManager;
+
+ $this->comparator = new \Doctrine\DBAL\Schema\Comparator();
+ $this->initFieldTypes();
+
+ $this->converter = new \Espo\Core\Utils\Database\Converter($this->metadata);
+ }
+
+
+ protected function getConfig()
+ {
+ return $this->config;
+ }
+
+ protected function getMetadata()
+ {
+ return $this->metadata;
+ }
+
+ protected function getFileManager()
+ {
+ return $this->fileManager;
+ }
+
+ protected function getComparator()
+ {
+ return $this->comparator;
+ }
+
+ protected function getConverter()
+ {
+ return $this->converter;
+ }
+
+ public function getPlatform()
+ {
+ return $this->getConnection()->getDatabasePlatform();
+ }
+
+
+ public function getConnection()
+ {
+ if (isset($this->connection)) {
+ return $this->connection;
+ }
+
+ $dbalConfig = new \Doctrine\DBAL\Configuration();
+
+ $connectionParams = (array) $this->getConfig()->get('database');
+
+ $this->connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $dbalConfig);
+
+ return $this->connection;
+ }
+
+
+ protected function initFieldTypes()
+ {
+ $typePaths = array(
+ 'Espo/Core/Utils/Database/FieldTypes',
+ 'Espo/Custom/Core/Utils/Database/FieldTypes',
+ );
+
+ foreach($typePaths as $path) {
+
+ $typeList = $this->getFileManager()->getFileList('application/'.$path, false, '\.php$');
+ if ($typeList !== false) {
+ foreach($typeList as $name) {
+ $typeName = preg_replace('/\.php$/i', '', $name);
+ $dbalTypeName = strtolower($typeName);
+ $class = \Espo\Core\Utils\Util::toFormat($path, '\\').'\\'.$typeName;
+
+ if( ! Type::hasType($dbalTypeName) ) {
+ Type::addType($dbalTypeName, $class);
+ } else {
+ Type::overrideType($dbalTypeName, $class);
+ }
+
+ $dbTypeName = method_exists($class, 'getDbTypeName') ? $class::getDbTypeName() : $dbalTypeName;
+
+ $this->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping($dbTypeName, $dbalTypeName);
+ }
+ }
+ }
+ }
+
+
+
+ /*
+ * Rebuild database schema
+ */
+ public function rebuild()
+ {
+ if ($this->getConverter()->process() === false) {
+ return false;
+ }
+
+ $currentSchema = $this->getCurrentSchema();
+ $metadataSchema = $this->getConverter()->getSchemaFromMetadata();
+
+ $queries = $this->getDiffSql($currentSchema, $metadataSchema);
+
+ $result = true;
+ $connection = $this->getConnection();
+ foreach ($queries as $sql) {
+ try {
+ $result &= (bool) $connection->executeQuery($sql);
+ } catch (\Exception $e) {
+ $GLOBALS['log']->add('EXCEPTION', 'Rebuild database fault: '.$e);
+ }
+ }
+
+ return $result;
+ }
+
+
+
+ /*
+ * Get current database schema
+ *
+ * @return \Doctrine\DBAL\Schema\Schema
+ */
+ protected function getCurrentSchema()
+ {
+ return $this->getConnection()->getSchemaManager()->createSchema();
+ }
+
+ /*
+ * Get SQL queries of database schema
+ *
+ * @params \Doctrine\DBAL\Schema\Schema $schema
+ *
+ * @return array - array of SQL queries
+ */
+ public function toSql(\Doctrine\DBAL\Schema\SchemaDiff $schema) //Doctrine\DBAL\Schema\SchemaDiff | \Doctrine\DBAL\Schema\Schema
+ {
+ return $schema->toSaveSql($this->getPlatform());
+ //return $schema->toSql($this->getPlatform()); //it can return with DROP TABLE
+ }
+
+
+ /*
+ * Get SQL queries to get from one to another schema
+ *
+ * @return array - array of SQL queries
+ */
+ public function getDiffSql(\Doctrine\DBAL\Schema\Schema $fromSchema, \Doctrine\DBAL\Schema\Schema $toSchema)
+ {
+ $schemaDiff = $this->getComparator()->compare($fromSchema, $toSchema);
+
+ return $this->toSql($schemaDiff); //$schemaDiff->toSql($this->getPlatform());
+ }
+
+
+
+
+}
diff --git a/application/Espo/Core/Utils/File/Manager.php b/application/Espo/Core/Utils/File/Manager.php
index fd38c7131d..859195b9dd 100644
--- a/application/Espo/Core/Utils/File/Manager.php
+++ b/application/Espo/Core/Utils/File/Manager.php
@@ -44,6 +44,10 @@ class Manager
*/
function getFileList($path, $recursively=false, $filter='', $fileType='all')
{
+ if (!file_exists($path)) {
+ return false;
+ }
+
$result = array();
$cdir = scandir($path);
diff --git a/application/Espo/Core/Utils/Metadata.php b/application/Espo/Core/Utils/Metadata.php
index 7e7631fea4..a20637ba52 100644
--- a/application/Espo/Core/Utils/Metadata.php
+++ b/application/Espo/Core/Utils/Metadata.php
@@ -2,15 +2,14 @@
namespace Espo\Core\Utils;
-use Doctrine\ORM\Tools;
-
class Metadata
{
protected $metadataConfig;
- protected $doctrineMetadataName = 'defs'; //Metadata "defs" uses for creating the metadata of Doctri
protected $meta;
+ private $espoMetadata;
+
protected $scopes= array();
private $config;
@@ -189,19 +188,35 @@ class Metadata
$result= $this->getFileManager()->setContent($data, $fullPath, $scope.'.json');
- //create classes only for "defs" metadata
- /*if ($type == $this->getMetaConfig()->espoMetadataName) {
- try{
- $this->getDoctrineConverter()->generateEntities( array($this->getEntityPath($scope)) );
- } catch (\Exception $e) {
- $GLOBALS['log']->add('EXCEPTION', 'Try to generate Entities for '.$this->getEntityPath($scope).'. Details: '.$e->getMessage());
- }
- }*/
-
return $result;
}
+ public function getEspoMetadata()
+ {
+ if (!empty($this->espoMetadata)) {
+ return $this->espoMetadata;
+ }
+
+ $this->espoMetadata = $this->getFileManager()->getContent($this->getMetaConfig()->cachePath, 'espoMetadata.php');
+
+ return $this->espoMetadata;
+ }
+
+ public function setEspoMetadata(array $espoMetadata)
+ {
+ $result = $this->getFileManager()->setContentPHP($espoMetadata, $this->getMetaConfig()->cachePath, 'espoMetadata.php');
+ if ($result == false) {
+ $GLOBALS['log']->add('EXCEPTION', 'Metadata::setEspoMetadata() - Cannot save espoMetadata to a file');
+ throw new \Espo\Core\Exceptions\Error();
+ }
+
+ $this->espoMetadata = $espoMetadata;
+
+ return $result;
+ }
+
+
/**
* Unite file content to the file
*
diff --git a/application/Espo/Core/Utils/Util.php b/application/Espo/Core/Utils/Util.php
index 909bfea312..83c9ab7d66 100644
--- a/application/Espo/Core/Utils/Util.php
+++ b/application/Espo/Core/Utils/Util.php
@@ -73,6 +73,19 @@ class Util
return preg_replace_callback('/([A-Z])/', $func, $name);
}
+ /**
+ * Convert name from Camel Case format to underscore.
+ * ex. camelCase to camel_case
+ *
+ * @param string $name
+ *
+ * @return string
+ */
+ public static function toUnderScore($name)
+ {
+ return static::fromCamelCase($name, '_');
+ }
+
/**
* Merge arrays (default PHP function is not suitable)
diff --git a/application/Espo/Core/defaults/systemConfig.php b/application/Espo/Core/defaults/systemConfig.php
index 801076def3..44a9d2ea49 100644
--- a/application/Espo/Core/defaults/systemConfig.php
+++ b/application/Espo/Core/defaults/systemConfig.php
@@ -20,8 +20,6 @@ return array (
'cachePath' => 'data/cache/application',
'corePath' => 'application/Espo/Resources/metadata',
'customPath' => 'application/Espo/Modules/{*}/Resources/metadata',
- 'doctrineCache' => 'data/cache/doctrine/metadata',
- 'espoMetadataName' => 'entityDefs',
),
'layoutConfig' =>
diff --git a/application/Espo/Entities/Bug.php b/application/Espo/Entities/Bug.php
deleted file mode 100644
index c7be91de44..0000000000
--- a/application/Espo/Entities/Bug.php
+++ /dev/null
@@ -1,122 +0,0 @@
-products = new ArrayCollection();
- }
-
- public function getId()
- {
- return $this->id;
- }
-
- public function getDescription()
- {
- return $this->description;
- }
-
- public function setDescription($description)
- {
- $this->description = $description;
- }
-
- public function setCreated(DateTime $created)
- {
- $this->created = $created;
- }
-
- public function getCreated()
- {
- return $this->created;
- }
-
- public function setStatus($status)
- {
- $this->status = $status;
- }
-
- public function getStatus()
- {
- return $this->status;
- }
-
- public function setEngineer($engineer)
- {
- $engineer->assignedToBug($this);
- $this->engineer = $engineer;
- }
-
- public function setReporter($reporter)
- {
- $reporter->addReportedBug($this);
- $this->reporter = $reporter;
- }
-
- public function getEngineer()
- {
- return $this->engineer;
- }
-
- public function getReporter()
- {
- return $this->reporter;
- }
-
- public function assignToProduct($product)
- {
- $this->products[] = $product;
- }
-
- public function getProducts()
- {
- return $this->products;
- }
-
- public function close()
- {
- $this->status = "CLOSE";
- }
-}
-
-
diff --git a/application/Espo/Entities/BugRepository.php b/application/Espo/Entities/BugRepository.php
deleted file mode 100644
index 1e1daf5e2e..0000000000
--- a/application/Espo/Entities/BugRepository.php
+++ /dev/null
@@ -1,47 +0,0 @@
-getEntityManager()->createQuery($dql);
- $query->setMaxResults($number);
- return $query->getResult();
- }
-
- public function getRecentBugsArray($number = 30)
- {
- $dql = "SELECT b, e, r, p FROM Bug b JOIN b.engineer e ".
- "JOIN b.reporter r JOIN b.products p ORDER BY b.created DESC";
- $query = $this->getEntityManager()->createQuery($dql);
- $query->setMaxResults($number);
- return $query->getArrayResult();
- }
-
- public function getUsersBugs($userId, $number = 15)
- {
- $dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ".
- "WHERE b.status = 'OPEN' AND e.id = ?1 OR r.id = ?1 ORDER BY b.created DESC";
-
- return $this->getEntityManager()->createQuery($dql)
- ->setParameter(1, $userId)
- ->setMaxResults($number)
- ->getResult();
- }
-
- public function getOpenBugsByProduct()
- {
- $dql = "SELECT p.id, p.name, count(b.id) AS openBugs FROM Bug b ".
- "JOIN b.products p WHERE b.status = 'OPEN' GROUP BY p.id";
- return $this->getEntityManager()->createQuery($dql)->getScalarResult();
- }
-}
diff --git a/application/Espo/Entities/User.php b/application/Espo/Entities/User.php
index 9e6d92c2b6..2db29c3067 100644
--- a/application/Espo/Entities/User.php
+++ b/application/Espo/Entities/User.php
@@ -2,15 +2,11 @@
namespace Espo\Entities;
-use Doctrine\Common\Collections\ArrayCollection;
-
-/**
- * @Entity @Table(name="users")
- */
class User extends \Espo\ORM\Entity
{
public function isAdmin()
{
return $this->get('isAdmin');
- }
+ }
+
}
diff --git a/application/Espo/Modules/Crm/Resources/metadata/defs/Contact.json b/application/Espo/Modules/Crm/Resources/metadata/defs/Contact.json
deleted file mode 100644
index 1bee489fcc..0000000000
--- a/application/Espo/Modules/Crm/Resources/metadata/defs/Contact.json
+++ /dev/null
@@ -1 +0,0 @@
-{"module":"Test","var1":{"subvar1":"NEWsubval1","subvar55":"subval55"}}
\ No newline at end of file
diff --git a/application/Espo/Modules/Crm/Resources/metadata/defs/Product.json b/application/Espo/Modules/Crm/Resources/metadata/defs/Product.json
deleted file mode 100644
index 500d240666..0000000000
--- a/application/Espo/Modules/Crm/Resources/metadata/defs/Product.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "table":"products",
- "type":"entity",
- "id":{
- "id":{
- "type":"string",
- "generator":{
- "strategy":"UUID"
- }
- }
- },
- "fields":{
- "name":{
- "type":"string"
- }
- }
-}
diff --git a/application/Espo/Modules/Crm/Resources/metadata/defs/unset.json b/application/Espo/Modules/Crm/Resources/metadata/defs/unset.json
deleted file mode 100644
index 3f95c8cc5c..0000000000
--- a/application/Espo/Modules/Crm/Resources/metadata/defs/unset.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "Crm.Test": [
- "var1.subvar2"
- ]
-}
\ No newline at end of file
diff --git a/application/Espo/ORM/EntityFactory.php b/application/Espo/ORM/EntityFactory.php
index 3b2a4ca852..18eab322af 100644
--- a/application/Espo/ORM/EntityFactory.php
+++ b/application/Espo/ORM/EntityFactory.php
@@ -1,26 +1,26 @@
-entityManager = $entityManager;
- $this->metadata = $metadata;
- }
- public function create($name)
- {
- $className = $this->entityManager->normalizeEntityName($name);
- $defs = $this->metdata->get($name);
- $entity = new $className($defs);
- return $entity;
- }
-
-}
-
-
+entityManager = $entityManager;
+ $this->metadata = $metadata;
+ }
+ public function create($name)
+ {
+ $className = $this->entityManager->normalizeEntityName($name);
+ $defs = $this->metadata->get($name);
+ $entity = new $className($defs);
+ return $entity;
+ }
+
+}
+
+
diff --git a/application/Espo/ORM/EntityManager.php b/application/Espo/ORM/EntityManager.php
index ba7c138f4a..0bd4a98970 100644
--- a/application/Espo/ORM/EntityManager.php
+++ b/application/Espo/ORM/EntityManager.php
@@ -37,7 +37,7 @@ class EntityManager
if (!empty($params['mapperClassName'])) {
$mapperClassName = $params['mapperClassName'];
}
- $this->mapper = new $mapperClassName($pdo, $this->entityFactory);
+ $this->mapper = new $mapperClassName($this->pdo, $this->entityFactory);
$repositoryFactoryClassName = '\\Espo\\ORM\\RepositoryFactory';
if (!empty($params['repositoryFactoryClassName'])) {
diff --git a/application/Espo/Resources/metadata/defs/Bug.json b/application/Espo/Resources/metadata/defs/Bug.json
deleted file mode 100644
index b8f93aa5b2..0000000000
--- a/application/Espo/Resources/metadata/defs/Bug.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "type":"entity",
- "manyToOne":{
- "reporter":{
- "inversedBy":"reportedBugs",
- "targetEntity":"Espo\\Entities\\User"
- },
- "engineer":{
- "inversedBy":"assignedBugs",
- "targetEntity":"Espo\\Entities\\User"
- }
- },
- "fields":{
- "status":{
- "type":"string"
- },
- "description":{
- "type":"text"
- },
- "created":{
- "type":"datetime"
- }
- },
- "repositoryClass":"BugRepository",
- "table":"bugs",
- "id":{
- "id":{
- "type":"string",
- "generator":{
- "strategy":"UUID"
- }
- }
- }
-}
-
diff --git a/application/Espo/Resources/metadata/defs/User.json b/application/Espo/Resources/metadata/defs/User.json
deleted file mode 100644
index e99475ea65..0000000000
--- a/application/Espo/Resources/metadata/defs/User.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "table":"users",
- "type":"entity",
- "id":{
- "id":{
- "type":"string",
- "generator":{
- "strategy":"UUID"
- }
- }
- },
- "fields":{
- "username":{
- "type":"string(30)"
- },
- "password":{
- "type":"string(255)"
- },
- "isAdmin":{
- "type":"boolean",
- "options":{
- "default":0
- }
- }
- }
-}
diff --git a/application/Espo/Resources/metadata/entityDefs/User.json b/application/Espo/Resources/metadata/entityDefs/User.json
index 17b3e86137..77b5645d82 100644
--- a/application/Espo/Resources/metadata/entityDefs/User.json
+++ b/application/Espo/Resources/metadata/entityDefs/User.json
@@ -10,6 +10,9 @@
},
"name": {
"type": "personName"
+ },
+ "password": {
+ "type": "password"
},
"salutationName": {
"type": "enum",
diff --git a/application/Espo/Resources/metadata/fields/autoincrement.json b/application/Espo/Resources/metadata/fields/autoincrement.json
index c32640cb6f..a9e95aefea 100644
--- a/application/Espo/Resources/metadata/fields/autoincrement.json
+++ b/application/Espo/Resources/metadata/fields/autoincrement.json
@@ -6,7 +6,7 @@
"advanced":true
},
"database":{
- "type":"integer",
+ "type":"int",
"autoincrement":true
}
}
diff --git a/application/Espo/Resources/metadata/fields/base.json b/application/Espo/Resources/metadata/fields/base.json
index b9b2a2858d..8b72ad6bcb 100644
--- a/application/Espo/Resources/metadata/fields/base.json
+++ b/application/Espo/Resources/metadata/fields/base.json
@@ -4,6 +4,6 @@
"advanced":false
},
"database":{
- "db": false
+ "notStorable":true
}
}
diff --git a/application/Espo/Resources/metadata/fields/bool.json b/application/Espo/Resources/metadata/fields/bool.json
index 85dad49a48..5db27091c4 100644
--- a/application/Espo/Resources/metadata/fields/bool.json
+++ b/application/Espo/Resources/metadata/fields/bool.json
@@ -8,8 +8,5 @@
"search":{
"basic":false,
"advanced":true
- },
- "database":{
- "type":"boolean"
}
}
diff --git a/application/Espo/Resources/metadata/fields/duration.json b/application/Espo/Resources/metadata/fields/duration.json
index c936f61d65..d629720b67 100644
--- a/application/Espo/Resources/metadata/fields/duration.json
+++ b/application/Espo/Resources/metadata/fields/duration.json
@@ -1,5 +1,5 @@
-{
- "database":{
- "type":"integer"
- }
-}
+{
+ "database":{
+ "type":"int"
+ }
+}
diff --git a/application/Espo/Resources/metadata/fields/email.json b/application/Espo/Resources/metadata/fields/email.json
index e8e22e7401..2b4b87d9a0 100644
--- a/application/Espo/Resources/metadata/fields/email.json
+++ b/application/Espo/Resources/metadata/fields/email.json
@@ -15,6 +15,6 @@
"advanced":true
},
"database":{
- "type":"string"
+ "type":"varchar"
}
}
diff --git a/application/Espo/Resources/metadata/fields/enum.json b/application/Espo/Resources/metadata/fields/enum.json
index cbd7aaa78a..37332b807c 100644
--- a/application/Espo/Resources/metadata/fields/enum.json
+++ b/application/Espo/Resources/metadata/fields/enum.json
@@ -23,6 +23,6 @@
"advanced":true
},
"database":{
- "type":"string"
+ "type":"varchar"
}
}
diff --git a/application/Espo/Resources/metadata/fields/enumInt.json b/application/Espo/Resources/metadata/fields/enumInt.json
index f9b91b256c..c7c767d225 100644
--- a/application/Espo/Resources/metadata/fields/enumInt.json
+++ b/application/Espo/Resources/metadata/fields/enumInt.json
@@ -18,6 +18,6 @@
"advanced":true
},
"database":{
- "type":"integer"
+ "type":"int"
}
}
diff --git a/application/Espo/Resources/metadata/fields/int.json b/application/Espo/Resources/metadata/fields/int.json
index bd79f32114..79bd06eab6 100644
--- a/application/Espo/Resources/metadata/fields/int.json
+++ b/application/Espo/Resources/metadata/fields/int.json
@@ -21,8 +21,5 @@
"search":{
"basic":false,
"advanced":true
- },
- "database":{
- "type":"integer"
}
}
diff --git a/application/Espo/Resources/metadata/fields/link.json b/application/Espo/Resources/metadata/fields/link.json
index 748e20d4d3..7d151fa889 100644
--- a/application/Espo/Resources/metadata/fields/link.json
+++ b/application/Espo/Resources/metadata/fields/link.json
@@ -15,5 +15,8 @@
"search":{
"basic":false,
"advanced":true
+ },
+ "database":{
+ "notStorable":true
}
}
diff --git a/application/Espo/Resources/metadata/fields/linkMultiple.json b/application/Espo/Resources/metadata/fields/linkMultiple.json
index 3cb9606194..e2ba43736b 100644
--- a/application/Espo/Resources/metadata/fields/linkMultiple.json
+++ b/application/Espo/Resources/metadata/fields/linkMultiple.json
@@ -15,5 +15,8 @@
"search":{
"basic":false,
"advanced":true
+ },
+ "database":{
+ "notStorable":true
}
}
diff --git a/application/Espo/Resources/metadata/fields/linkParent.json b/application/Espo/Resources/metadata/fields/linkParent.json
index 23a9c3bc6c..5940f58c1d 100644
--- a/application/Espo/Resources/metadata/fields/linkParent.json
+++ b/application/Espo/Resources/metadata/fields/linkParent.json
@@ -16,5 +16,8 @@
"search":{
"basic":false,
"advanced":true
+ },
+ "database":{
+ "notStorable":true
}
}
diff --git a/application/Espo/Resources/metadata/fields/multienum.json b/application/Espo/Resources/metadata/fields/multienum.json
index e10385bf47..a98f0c50a0 100644
--- a/application/Espo/Resources/metadata/fields/multienum.json
+++ b/application/Espo/Resources/metadata/fields/multienum.json
@@ -17,8 +17,5 @@
"search":{
"basic":false,
"advanced":false
- },
- "database":{
- "type":"json_array"
}
}
diff --git a/application/Espo/Resources/metadata/fields/phone.json b/application/Espo/Resources/metadata/fields/phone.json
index d4e3bb2404..d7e2242c17 100644
--- a/application/Espo/Resources/metadata/fields/phone.json
+++ b/application/Espo/Resources/metadata/fields/phone.json
@@ -20,6 +20,6 @@
"advanced":true
},
"database":{
- "type":"string"
+ "type":"varchar"
}
}
diff --git a/application/Espo/Resources/metadata/fields/url.json b/application/Espo/Resources/metadata/fields/url.json
index 6b4282ec99..ee2c542225 100644
--- a/application/Espo/Resources/metadata/fields/url.json
+++ b/application/Espo/Resources/metadata/fields/url.json
@@ -19,6 +19,6 @@
"advanced":true
},
"database":{
- "type":"string"
+ "type":"varchar"
}
}
diff --git a/application/Espo/Resources/metadata/fields/varchar.json b/application/Espo/Resources/metadata/fields/varchar.json
index 6b4282ec99..8bf30f983a 100644
--- a/application/Espo/Resources/metadata/fields/varchar.json
+++ b/application/Espo/Resources/metadata/fields/varchar.json
@@ -17,8 +17,5 @@
"search":{
"basic":true,
"advanced":true
- },
- "database":{
- "type":"string"
}
}
diff --git a/testAuth.php b/testAuth.php
index 15e8a25ceb..452cb5cd10 100644
--- a/testAuth.php
+++ b/testAuth.php
@@ -11,7 +11,7 @@ class Auth extends \Slim\Middleware
private $container;
- public function __construct(\Espo\Core\EntityManager $entityManager, \Espo\Core\Container $container)
+ public function __construct($entityManager, $container)
{
$this->entityManager = $entityManager;
$this->container = $container;
@@ -33,7 +33,7 @@ class Auth extends \Slim\Middleware
if (!empty($routes[0])) {
$routeConditions = $routes[0]->getConditions();
if (isset($routeConditions['auth']) && $routeConditions['auth'] === false) {
- $this->container->setUser(new \Espo\Entities\User());
+ //$this->container->setUser(new \Espo\Entities\User());
$this->next->call();
return;
}
@@ -49,13 +49,15 @@ class Auth extends \Slim\Middleware
$username = $authKey;
$password = $authSec;
- $user = $this->entityManager->getRepository('User')->findOneBy(array('username' => $username));
+ /*$user = $this->entityManager->getRepository('User')->findOneBy(array('username' => $username));
if ($user) {
if ($password == $user->getPassword()) {
$this->container->setUser($user);
$isAuthenticated = true;
}
- }
+ } */
+
+ $isAuthenticated = true;
if ($isAuthenticated) {
$this->next->call();
diff --git a/tests/Espo/Core/Doctrine/EspoConverterTest.php b/tests/Espo/Core/Doctrine/EspoConverterTest.php
deleted file mode 100644
index 9cad46854d..0000000000
--- a/tests/Espo/Core/Doctrine/EspoConverterTest.php
+++ /dev/null
@@ -1,45 +0,0 @@
-app = $GLOBALS['app'];
- }
-
-
- protected function setUp()
- {
- $this->fixture = new \Espo\Core\Doctrine\EspoConverter($this->app->getContainer()->get('entityManager'), $this->app->getMetadata(), $this->app->getContainer()->get('fileManager'));
- }
-
- protected function tearDown()
- {
- $this->fixture = NULL;
- }
-
-
-
- function testGetFieldType()
- {
- $this->assertEquals('string', $this->fixture->getFieldType('varchar'));
- $this->assertEquals('float', $this->fixture->getFieldType('float'));
- }
-
-
-
-
-}
-
-?>
\ No newline at end of file
diff --git a/tests/Espo/Core/Utils/Database/RelationsTest.php b/tests/Espo/Core/Utils/Database/RelationsTest.php
new file mode 100644
index 0000000000..eae7a15295
--- /dev/null
+++ b/tests/Espo/Core/Utils/Database/RelationsTest.php
@@ -0,0 +1,477 @@
+app = $GLOBALS['app'];
+ }
+
+
+ protected function setUp()
+ {
+ $this->object = new \Espo\Core\Utils\Database\Relations();
+ }
+
+ protected function tearDown()
+ {
+ $this->object = NULL;
+ }
+
+
+ public function invokeMethod($methodName, array $parameters = array())
+ {
+ $reflection = new \ReflectionClass(get_class($this->object));
+ $method = $reflection->getMethod($methodName);
+ $method->setAccessible(true);
+
+ return $method->invokeArgs($this->object, $parameters);
+ }
+ //$this->invokeMethod('cryptPassword', array('passwordToCrypt'));
+
+
+
+ function testGetSortEntities()
+ {
+ $input = array(
+ 'entity1' => 'ContactTest',
+ 'entity2' => 'CallTest',
+ );
+
+ $result = array(
+ 0 => 'callTest',
+ 1 => 'contactTest',
+ );
+
+ $this->assertEquals($result, $this->invokeMethod('getSortEntities', array($input['entity1'], $input['entity2'])));
+ }
+
+
+ function testGetJoinTable()
+ {
+ $input = array(
+ 'entity1' => 'ContactTest',
+ 'entity2' => 'CallTest',
+ );
+
+ $result = 'callTestContactTest';
+
+ $this->assertEquals( $result, $this->invokeMethod('getJoinTable', array($input['entity1'], $input['entity2'])) );
+ }
+
+
+ function testManyMany()
+ {
+ $input = array(
+ 'params' => array (
+ 'entityName' => 'Call',
+ 'link' =>
+ array (
+ 'name' => 'contacts',
+ 'params' =>
+ array (
+ 'type' => 'hasMany',
+ 'entity' => 'Contact',
+ 'foreign' => 'calls',
+ ),
+ ),
+ 'targetEntity' => 'Contact',
+ ),
+
+
+ 'foreignParams' => array (
+ 'entityName' => 'Contact',
+ 'link' =>
+ array (
+ 'name' => 'calls',
+ 'params' =>
+ array (
+ 'type' => 'hasMany',
+ 'entity' => 'Call',
+ 'foreign' => 'contacts',
+ ),
+ ),
+ 'targetEntity' => 'Call',
+ ),
+ );
+
+ $result = array(
+ 'Call' =>
+ array (
+ 'relations' =>
+ array (
+ 'contacts' =>
+ array (
+ 'type' => 'manyMany',
+ 'entity' => 'Contact',
+ 'relationName' => 'callContact',
+ 'key' => 'id',
+ 'foreignKey' => 'id',
+ 'midKeys' =>
+ array (
+ 'callId',
+ 'contactId',
+ ),
+ ),
+ ),
+ ),
+ );
+
+
+ $this->assertEquals( $result, $this->invokeMethod('manyMany', array($input['params'], $input['foreignParams'])) );
+
+ //test reverse: result should be an empty array
+ $result = array();
+ $this->assertEquals( $result, $this->invokeMethod('manyMany', array($input['foreignParams'], $input['params'])) );
+ }
+
+
+ function testHasMany()
+ {
+ $input = array(
+ 'params' => array (
+ 'entityName' => 'Account',
+ 'link' =>
+ array (
+ 'name' => 'contacts',
+ 'params' =>
+ array (
+ 'type' => 'hasMany',
+ 'entity' => 'Contact',
+ 'foreign' => 'account',
+ ),
+ ),
+ 'targetEntity' => 'Contact',
+ ),
+
+ 'foreignParams' => array (
+ 'entityName' => 'Contact',
+ 'link' =>
+ array (
+ 'name' => 'account',
+ 'params' =>
+ array (
+ 'type' => 'belongsTo',
+ 'entity' => 'Account',
+ ),
+ ),
+ 'targetEntity' => 'Account',
+ ),
+ );
+
+ $result = array (
+ 'Account' =>
+ array (
+ 'relations' =>
+ array (
+ 'contacts' =>
+ array (
+ 'type' => 'hasMany',
+ 'entity' => 'Contact',
+ 'foreignKey' => 'accountId',
+ ),
+ ),
+ ),
+ );
+
+
+ $this->assertEquals( $result, $this->invokeMethod('hasMany', array($input['params'], $input['foreignParams'])) );
+ }
+
+
+ function testBelongsTo()
+ {
+ $input = array(
+ 'params' => array (
+ 'entityName' => 'Attachment',
+ 'link' =>
+ array (
+ 'name' => 'createdBy',
+ 'params' =>
+ array (
+ 'type' => 'belongsTo',
+ 'entity' => 'User',
+ ),
+ ),
+ 'targetEntity' => 'User',
+ ),
+
+ 'foreignParams' => array (
+ 'entityName' => 'User',
+ 'link' => false,
+ 'targetEntity' => 'Attachment',
+ ),
+ );
+
+ $result = array (
+ 'Attachment' =>
+ array (
+ 'fields' =>
+ array (
+ 'createdByName' =>
+ array (
+ 'type' => 'foreign',
+ 'relation' => 'createdBy',
+ 'notStorable' => true,
+ ),
+ 'createdById' =>
+ array (
+ 'type' => 'foreignId',
+ ),
+ ),
+ 'relations' =>
+ array (
+ 'createdBy' =>
+ array (
+ 'type' => 'belongsTo',
+ 'entity' => 'User',
+ 'key' => 'createdById',
+ 'foreignKey' => 'id',
+ ),
+ ),
+ ),
+ );
+
+
+ $this->assertEquals( $result, $this->invokeMethod('belongsTo', array($input['params'], $input['foreignParams'])) );
+ }
+
+
+ function testHasChildren()
+ {
+ $input = array(
+ 'params' => array (
+ 'entityName' => 'Post',
+ 'link' =>
+ array (
+ 'name' => 'notes',
+ 'params' =>
+ array (
+ "type" => "hasChildren",
+ "entity" => "Post",
+ "foreign" => "parent",
+ ),
+ ),
+ 'targetEntity' => 'Note',
+ ),
+
+ 'foreignParams' => array (
+ 'entityName' => 'Note',
+ 'link' => array (
+ 'name' => 'parent',
+ 'params' =>
+ array (
+ "type" => "belongsToParent",
+ "entities" => array("Post", "Account", "Case"),
+ "foreign" => "notes"
+ ),
+ ),
+ 'targetEntity' => 'Post',
+ ),
+ );
+
+ $result = array (
+ 'Post' =>
+ array (
+ 'relations' =>
+ array (
+ 'notes' =>
+ array (
+ 'type' => 'hasChildren',
+ 'entity' => 'Note',
+ 'foreignKey' => 'parentId',
+ 'foreignType' => 'parentType',
+ ),
+ ),
+ ),
+
+ /*'Note' => array(
+ 'fields' => array(
+ 'parentId' => array(
+ 'type' => 'foreignId',
+ ),
+ 'parentType' => array(
+ 'type' => 'foreignType',
+ ),
+ 'parentName' => array(
+ 'type' => 'varchar',
+ 'notStorable' => true,
+ ),
+ ),
+ ),*/
+ );
+
+
+ $this->assertEquals( $result, $this->invokeMethod('hasChildren', array($input['params'], $input['foreignParams'])) );
+ }
+
+
+ function testBelongsToParent_Single()
+ {
+ $input = array(
+ 'params' => array (
+ 'entityName' => 'Note',
+ 'link' =>
+ array (
+ 'name' => 'parent',
+ 'params' =>
+ array (
+ 'type' => 'belongsToParent',
+ 'foreign' => 'notes',
+ ),
+ ),
+ 'targetEntity' => 'Note',
+ ),
+
+ 'foreignParams' => array (
+ 'entityName' => 'Note',
+ 'link' =>
+ array (
+ 'name' => 'attachments',
+ 'params' =>
+ array (
+ 'type' => 'hasChildren',
+ 'entity' => 'Attachment',
+ 'foreign' => 'parent',
+ ),
+ ),
+ 'targetEntity' => 'Note',
+ ),
+ );
+
+ $result = array (
+ 'Note' =>
+ array (
+ 'fields' =>
+ array (
+ 'parentId' =>
+ array (
+ 'type' => 'foreignId',
+ ),
+ 'parentType' =>
+ array (
+ 'type' => 'foreignType',
+ ),
+ 'parentName' =>
+ array (
+ 'type' => 'varchar',
+ 'notStorable' => true,
+ ),
+ ),
+ ),
+ );
+
+ $this->assertEquals( $result, $this->invokeMethod('belongsToParent', array($input['params'], $input['foreignParams'])) );
+ }
+
+
+ function testBelongsToParent()
+ {
+ $input = array(
+ 'params' => array (
+ 'entityName' => 'Call',
+ 'link' =>
+ array (
+ 'name' => 'parent',
+ 'params' =>
+ array (
+ 'type' => 'belongsToParent',
+ 'entities' =>
+ array (
+ 'Account',
+ 'Opportunity',
+ 'Case',
+ ),
+ 'foreign' => 'calls',
+ ),
+ ),
+ 'targetEntity' => 'Call',
+ ),
+
+ 'foreignParams' => array (
+ 'entityName' => 'Call',
+ 'link' => false,
+ 'targetEntity' => 'Call',
+ ),
+ );
+
+ $result = array (
+ 'Account' =>
+ array (
+ 'fields' =>
+ array (
+ 'parentId' =>
+ array (
+ 'type' => 'foreignId',
+ ),
+ 'parentType' =>
+ array (
+ 'type' => 'foreignType',
+ ),
+ 'parentName' =>
+ array (
+ 'type' => 'varchar',
+ 'notStorable' => true,
+ ),
+ ),
+ ),
+ 'Opportunity' =>
+ array (
+ 'fields' =>
+ array (
+ 'parentId' =>
+ array (
+ 'type' => 'foreignId',
+ ),
+ 'parentType' =>
+ array (
+ 'type' => 'foreignType',
+ ),
+ 'parentName' =>
+ array (
+ 'type' => 'varchar',
+ 'notStorable' => true,
+ ),
+ ),
+ ),
+ 'Case' =>
+ array (
+ 'fields' =>
+ array (
+ 'parentId' =>
+ array (
+ 'type' => 'foreignId',
+ ),
+ 'parentType' =>
+ array (
+ 'type' => 'foreignType',
+ ),
+ 'parentName' =>
+ array (
+ 'type' => 'varchar',
+ 'notStorable' => true,
+ ),
+ ),
+ ),
+ );
+
+ $this->assertEquals( $result, $this->invokeMethod('belongsToParent', array($input['params'], $input['foreignParams'])) );
+ }
+
+
+
+
+
+
+}
\ No newline at end of file