ORM metadata convertation and database Schema building
This commit is contained in:
@@ -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',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
+90
-129
@@ -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;
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -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();
|
||||
}
|
||||
}
|
||||
+38
-48
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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' =>
|
||||
|
||||
@@ -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,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"
|
||||
]
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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'])) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user