ORM metadata convertation and database Schema building

This commit is contained in:
Taras Machyshyn
2013-12-13 19:04:56 +02:00
parent 0f6c5bd5cd
commit 9ec2b26d38
50 changed files with 1422 additions and 1555 deletions
+7 -11
View File
@@ -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();
@@ -1,197 +0,0 @@
<?php
namespace Espo\Core\Doctrine\Converter;
//use Espo\Core\Utils\Util;
class Association
{
public function manyToOneUnidirectional($params, $foreignParams)
{
return array(
$params['entityName'] => 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',
),
),
),
);
}
}
-101
View File
@@ -1,101 +0,0 @@
<?php
namespace Espo\Core\Doctrine;
class Helper
{
private $entityManager;
private $schemaTool;
private $disconnectedClassMetadataFactory;
private $entityGenerator;
public function __construct(\Doctrine\ORM\EntityManager $entityManager)
{
$this->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;
}
}
@@ -1,679 +0,0 @@
<?php
namespace Espo\Core\Doctrine\ORM\Mapping\Driver;
use Doctrine\Common\Persistence\Mapping\ClassMetadata,
Doctrine\Common\Persistence\Mapping\Driver\FileDriver,
Doctrine\ORM\Mapping\MappingException;
/**
* The JsonDriver reads the mapping metadata from .json schema files.
*
* @since 2.0
* @author Taras Machyshyn
* @author YamlDriver (part of code was taken from YamlDriver)
*/
class EspoPHPDriver extends FileDriver
{
/**
* {@inheritdoc}
*/
const DEFAULT_FILE_EXTENSION = '.php';
public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
{
parent::__construct($locator, $fileExtension);
}
/**
* {@inheritdoc}
*/
public function loadMetadataForClass($className, ClassMetadata $metadata)
{
$element = $this->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);
}
}
}
@@ -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;
}
+3 -4
View File
@@ -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();
+10 -5
View File
@@ -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;
}
@@ -0,0 +1,100 @@
<?php
namespace Espo\Core\Utils\Database;
use Espo\Core\Utils\Util,
Espo\ORM\Entity;
class Converter
{
private $metadata;
private $schemaConverter;
private $schemaFromMetadata = null;
/**
* @var array $meta - metadata array
*/
//private $meta;
public function __construct(\Espo\Core\Utils\Metadata $metadata)
{
$this->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;
}
}
?>
@@ -1,151 +1,81 @@
<?php
namespace Espo\Core\Doctrine\Converter;
namespace Espo\Core\Utils\Database\Converters;
use Espo\Core\Utils\Util;
use Espo\Core\Utils\Util,
Espo\ORM\Entity;
class Base
class Orm
{
private $entityManager;
private $metadata;
private $fileManager;
private $doctrineHelper;
private $linkConverter;
private $links;
protected $defaultFieldType = 'varchar';
protected $defaultNaming = 'postfix';
protected $defaultLength = array(
'varchar' => 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 '<pre>';
$GLOBALS['log']->add('Debug', 'Metadata:get() - converting to doctrine metadata');
$entityDefs = $this->getMetadata()->get('entityDefs');
$convertedMeta = array();
foreach($entityDefs as $entityName => $entityMeta) {
//echo '['.$entityName.']<br />';
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 '<hr />';
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.'<br />';
//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'].'<br />';
}
return $convertedMeta;
return $relationships;
}
@@ -329,8 +294,4 @@ class Base
return $values;
}
}
?>
}
@@ -0,0 +1,112 @@
<?php
namespace Espo\Core\Utils\Database\Converters;
use Espo\Core\Utils\Util;
class Schema
{
private $dbalSchema;
protected $typeList;
protected $idParams = array(
'type' => '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).'<br />';
$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;
}
}
@@ -0,0 +1,45 @@
<?php
namespace Espo\Core\Utils\Database\FieldTypes;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
class Bool extends Type
{
const BOOL = 'bool';
public function getName()
{
return self::BOOL;
}
public static function getDbTypeName()
{
return 'TINYINT';
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->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;
}
}
@@ -0,0 +1,35 @@
<?php
namespace Espo\Core\Utils\Database\FieldTypes;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
class Int extends Type
{
const INTtype = 'int';
public function getName()
{
return self::INTtype;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (int) $value;
}
public function getBindingType()
{
return \PDO::PARAM_INT;
}
}
@@ -1,5 +1,6 @@
<?php
namespace Espo\Core\Doctrine\Types;
namespace Espo\Core\Utils\Database\FieldTypes;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
@@ -8,6 +9,11 @@ class Password extends Type
{
const PASSWORD = 'password';
public function getName()
{
return self::PASSWORD;
}
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
@@ -24,9 +30,6 @@ class Password extends Type
return $value;
} */
public function getName()
{
return self::PASSWORD;
}
}
@@ -0,0 +1,29 @@
<?php
namespace Espo\Core\Utils\Database\FieldTypes;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
class Varchar extends Type
{
const VARCHAR = 'varchar';
public function getName()
{
return self::VARCHAR;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
//return 'varchar';
}
public function getDefaultLength(AbstractPlatform $platform)
{
return $platform->getVarcharDefaultLength();
}
}
@@ -1,21 +1,21 @@
<?php
namespace Espo\Core\Doctrine\Converter;
namespace Espo\Core\Utils\Database;
use Espo\Core\Utils\Util;
class Link
class Links
{
private $metadata;
private $association;
private $relations;
public function __construct(\Espo\Core\Utils\Metadata $metadata)
{
$this->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
*/
@@ -0,0 +1,179 @@
<?php
namespace Espo\Core\Utils\Database;
use Espo\Core\Utils\Util,
Espo\ORM\Entity;
class Relations
{
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) );
}
//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)
{
}
}
@@ -0,0 +1,182 @@
<?php
namespace Espo\Core\Utils\Database;
use \Doctrine\DBAL\Types\Type;
class Schema
{
private $config;
private $metadata;
private $fileManager;
private $comparator;
private $converter;
private $connection;
public function __construct(\Espo\Core\Utils\Config $config, \Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\File\Manager $fileManager)
{
$this->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());
}
}
@@ -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);
+27 -12
View File
@@ -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
*
+13
View File
@@ -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)
@@ -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' =>
-122
View File
@@ -1,122 +0,0 @@
<?php
namespace Espo\Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity(repositoryClass="BugRepository") @Table(name="bugs")
*/
class Bug
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
protected $id;
/**
* @Column(type="string")
*/
protected $description;
/**
* @Column(type="datetime")
*/
protected $created;
/**
* @Column(type="string")
*/
protected $status;
/**
* @ManyToOne(targetEntity="User", inversedBy="assignedBugs")
*/
protected $engineer;
/**
* @ManyToOne(targetEntity="User", inversedBy="reportedBugs")
*/
protected $reporter;
/**
* @ManyToMany(targetEntity="Product")
*/
protected $products;
public function __construct()
{
$this->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";
}
}
@@ -1,47 +0,0 @@
<?php
// repositories/BugRepository.php
namespace Espo\Entities;
use Doctrine\ORM\EntityRepository;
class BugRepository extends EntityRepository
{
public function getRecentBugs($number = 30)
{
//$dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ORDER BY b.created DESC";
$dql = "SELECT b FROM Bug b ORDER BY b.created DESC";
$query = $this->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();
}
}
+2 -6
View File
@@ -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');
}
}
}
@@ -1 +0,0 @@
{"module":"Test","var1":{"subvar1":"NEWsubval1","subvar55":"subval55"}}
@@ -1,17 +0,0 @@
{
"table":"products",
"type":"entity",
"id":{
"id":{
"type":"string",
"generator":{
"strategy":"UUID"
}
}
},
"fields":{
"name":{
"type":"string"
}
}
}
@@ -1,5 +0,0 @@
{
"Crm.Test": [
"var1.subvar2"
]
}
+26 -26
View File
@@ -1,26 +1,26 @@
<?php
namespace Espo\ORM;
class EntityFactory
{
protected $metadata;
protected $entityManager;
public function __construct(EntityManager $entityManager, Metadata $metadata)
{
$this->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;
}
}
<?php
namespace Espo\ORM;
class EntityFactory
{
protected $metadata;
protected $entityManager;
public function __construct(EntityManager $entityManager, Metadata $metadata)
{
$this->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;
}
}
+1 -1
View File
@@ -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'])) {
@@ -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"
}
}
}
}
@@ -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
}
}
}
}
@@ -10,6 +10,9 @@
},
"name": {
"type": "personName"
},
"password": {
"type": "password"
},
"salutationName": {
"type": "enum",
@@ -6,7 +6,7 @@
"advanced":true
},
"database":{
"type":"integer",
"type":"int",
"autoincrement":true
}
}
@@ -4,6 +4,6 @@
"advanced":false
},
"database":{
"db": false
"notStorable":true
}
}
@@ -8,8 +8,5 @@
"search":{
"basic":false,
"advanced":true
},
"database":{
"type":"boolean"
}
}
@@ -1,5 +1,5 @@
{
"database":{
"type":"integer"
}
}
{
"database":{
"type":"int"
}
}
@@ -15,6 +15,6 @@
"advanced":true
},
"database":{
"type":"string"
"type":"varchar"
}
}
@@ -23,6 +23,6 @@
"advanced":true
},
"database":{
"type":"string"
"type":"varchar"
}
}
@@ -18,6 +18,6 @@
"advanced":true
},
"database":{
"type":"integer"
"type":"int"
}
}
@@ -21,8 +21,5 @@
"search":{
"basic":false,
"advanced":true
},
"database":{
"type":"integer"
}
}
@@ -15,5 +15,8 @@
"search":{
"basic":false,
"advanced":true
},
"database":{
"notStorable":true
}
}
@@ -15,5 +15,8 @@
"search":{
"basic":false,
"advanced":true
},
"database":{
"notStorable":true
}
}
@@ -16,5 +16,8 @@
"search":{
"basic":false,
"advanced":true
},
"database":{
"notStorable":true
}
}
@@ -17,8 +17,5 @@
"search":{
"basic":false,
"advanced":false
},
"database":{
"type":"json_array"
}
}
@@ -20,6 +20,6 @@
"advanced":true
},
"database":{
"type":"string"
"type":"varchar"
}
}
@@ -19,6 +19,6 @@
"advanced":true
},
"database":{
"type":"string"
"type":"varchar"
}
}
@@ -17,8 +17,5 @@
"search":{
"basic":true,
"advanced":true
},
"database":{
"type":"string"
}
}
+6 -4
View File
@@ -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();
@@ -1,45 +0,0 @@
<?php
namespace tests\Espo\Core\Utils;
require_once('tests/testBootstrap.php');
use Espo\Utils as Utils;
class EspoConverterTest extends \PHPUnit_Framework_TestCase
{
protected $fixture;
private $app;
public function __construct()
{
$this->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'));
}
}
?>
@@ -0,0 +1,477 @@
<?php
namespace tests\Espo\Core\Utils\Database;
require_once('tests/testBootstrap.php');
use Espo\Utils as Utils;
class RelationsTest extends \PHPUnit_Framework_TestCase
{
protected $object;
private $app;
public function __construct()
{
$this->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'])) );
}
}