doctrine converter (unfinished)
This commit is contained in:
@@ -79,11 +79,11 @@ class Application
|
||||
$this->getMetadata()->init($isNotCached);
|
||||
|
||||
if ($isNotCached) {
|
||||
$doctrineConverter = new \Espo\Core\Doctrine\EspoConverter($this->container->get('entityManager'), $this->getMetadata(), $this->container->get('fileManager'));
|
||||
$doctrineConverter = new \Espo\Core\Doctrine\Converter\Base($this->container->get('entityManager'), $this->getMetadata(), $this->container->get('fileManager'));
|
||||
|
||||
if ($doctrineConverter->convertToDoctrine()) {
|
||||
if ($doctrineConverter->process()) {
|
||||
try{
|
||||
$doctrineConverter->rebuildDatabase();
|
||||
$doctrineConverter->getDoctrineHelper()->rebuildDatabase();
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->add('EXCEPTION', 'Fault to rebuildDatabase'.'. Details: '.$e->getMessage());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
<?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',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Doctrine\Converter;
|
||||
|
||||
use Espo\Core\Utils\Util;
|
||||
|
||||
class Base
|
||||
{
|
||||
private $entityManager;
|
||||
private $metadata;
|
||||
private $fileManager;
|
||||
private $doctrineHelper;
|
||||
private $linkConverter;
|
||||
|
||||
protected $defaultFieldType = 'varchar';
|
||||
protected $defaultNaming = 'postfix';
|
||||
|
||||
/*
|
||||
* //pair espo:doctrine
|
||||
*/
|
||||
protected $fieldAccordances = array(
|
||||
'type' => 'type',
|
||||
'maxLength' => 'length',
|
||||
'default' => array(
|
||||
'condition' => '^javascript:',
|
||||
'conditionEquals' => false,
|
||||
'value' => array(
|
||||
'options' => array (
|
||||
'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)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
|
||||
$this->doctrineHelper = new \Espo\Core\Doctrine\Helper($this->getEntityManager()->getWrapped());
|
||||
|
||||
$this->linkConverter = new \Espo\Core\Doctrine\Converter\Link($this->metadata);
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->entityManager;
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
protected function getDoctrineHelper()
|
||||
{
|
||||
return $this->doctrineHelper;
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* @param string $entityName
|
||||
* @param array $entityMeta
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function convertFields($entityName, $entityMeta)
|
||||
{
|
||||
$outputMeta = array();
|
||||
foreach($entityMeta['fields'] as $fieldName => $fieldParams) {
|
||||
|
||||
$fieldName = Util::fromCamelCase($fieldName, '_');
|
||||
|
||||
//check if "fields" option exists in $fieldMeta
|
||||
$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, '_'), '_' );
|
||||
if (!isset($entityMeta['fields'][$subFieldNameNaming])) {
|
||||
$subFieldDefs = $this->convertField($entityName, $subFieldName, $subFieldParams);
|
||||
if ($subFieldDefs !== false) {
|
||||
$outputMeta[$subFieldNameNaming] = $subFieldDefs; //push fieldDefs to the main array
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
$fieldDefs = $this->convertField($entityName, $fieldName, $fieldParams);
|
||||
if ($fieldDefs !== false) {
|
||||
$outputMeta[$fieldName] = $fieldDefs; //push fieldDefs to the main array
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Make actions for different types like "link", "linkMultiple", "linkParent" */
|
||||
}
|
||||
|
||||
return $outputMeta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*It can be moved to separate file*/
|
||||
protected function convertField($entityName, $fieldName, array $fieldParams)
|
||||
{
|
||||
//set default type if exists
|
||||
if (!isset($fieldParams['type']) || empty($fieldParams['type'])) {
|
||||
$GLOBALS['log']->add('WARNING', 'Field type does not exist for '.$entityName.':'.$fieldName.'. Use default type ['.$this->defaultFieldType.']');
|
||||
$fieldParams['type'] = $this->defaultFieldType;
|
||||
} //END: set default type if exists
|
||||
|
||||
$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
|
||||
|
||||
$fieldDefs = $this->getInitValues($fieldParams);
|
||||
|
||||
//merge database options from field definition
|
||||
if (isset($fieldTypeMeta['database'])) {
|
||||
$fieldDefs = Util::merge($fieldDefs, $fieldTypeMeta['database']);
|
||||
}
|
||||
|
||||
return $fieldDefs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function convertLinks($entityName, $entityMeta, array $entityDefs, array $convertedMeta)
|
||||
{
|
||||
if (!isset($entityMeta['links'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach($entityMeta['links'] as $linkName => $linkParams) {
|
||||
//echo $linkName.'<br />';
|
||||
//print_r($linkParams);
|
||||
|
||||
$linkEntityName = $this->getLinkConverter()->getLinkEntityName($entityName, $linkParams);
|
||||
//print_r($entityDefs[$linkEntityName]['links']);
|
||||
//print_r($convertedMeta[$linkEntityName]);
|
||||
|
||||
$currentType = $linkParams['type'];
|
||||
$parentType = '';
|
||||
|
||||
$foreignLink = $this->getForeignLink($linkName, $linkParams, $entityDefs[$linkEntityName]);
|
||||
|
||||
$method = $currentType;
|
||||
if ($foreignLink !== false) {
|
||||
$method .= '-'.$foreignLink['params']['type'];
|
||||
}
|
||||
$method = Util::toCamelCase($method);
|
||||
|
||||
|
||||
/*if ($method == 'belongsToParent') {
|
||||
die($entityName.' - '.$linkName);
|
||||
}*/
|
||||
|
||||
|
||||
if (method_exists($this->getLinkConverter(), $method)) {
|
||||
$convertedLink = $this->getLinkConverter()->process($method, $entityName, array('name'=>$linkName, 'params'=>$linkParams), $foreignLink);
|
||||
//print_r($convertedLink);
|
||||
}
|
||||
|
||||
//echo $method.' = '.$currentType.' - '.$foreignLink['type'].'<br />';
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $convertedMeta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get foreign Link
|
||||
*
|
||||
* @param string $parentLinkName
|
||||
* @param array $parentLinkParams
|
||||
* @param array $currentEntityDefs
|
||||
*
|
||||
* @return array - in format array('name', 'params')
|
||||
*/
|
||||
protected function getForeignLink($parentLinkName, $parentLinkParams, $currentEntityDefs)
|
||||
{
|
||||
if (isset($parentLinkParams['foreign']) && isset($currentEntityDefs['links'][$parentLinkParams['foreign']])) {
|
||||
return array(
|
||||
'name' => $parentLinkParams['foreign'],
|
||||
'params' => $currentEntityDefs['links'][$parentLinkParams['foreign']],
|
||||
);
|
||||
}
|
||||
|
||||
$parentLinkName = strtolower($parentLinkName);
|
||||
|
||||
foreach($currentEntityDefs['links'] as $linkName => $linkParams) {
|
||||
if (isset($linkParams['foreign']) && strtolower($linkParams['foreign']) == $parentLinkName) {
|
||||
return array(
|
||||
'name' => $linkName,
|
||||
'params' => $linkParams,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function getInitValues(array $fieldParams)
|
||||
{
|
||||
$values = array();
|
||||
foreach($this->fieldAccordances as $espoType => $doctrineType) {
|
||||
|
||||
if (isset($fieldParams[$espoType]) && !empty($fieldParams[$espoType])) {
|
||||
|
||||
if (is_array($doctrineType)) {
|
||||
|
||||
$conditionRes = false;
|
||||
if (!is_array($fieldParams[$espoType])) {
|
||||
$conditionRes = preg_match('/'.$doctrineType['condition'].'/i', $fieldParams[$espoType]);
|
||||
}
|
||||
|
||||
if (!$conditionRes || ($conditionRes && $conditionRes === $doctrineType['conditionEquals']) ) {
|
||||
$value = is_array($fieldParams[$espoType]) ? json_encode($fieldParams[$espoType]) : $fieldParams[$espoType];
|
||||
$values = Util::merge( $values, Util::replaceInArray('{0}', $value, $doctrineType['value']) );
|
||||
}
|
||||
} else {
|
||||
$values[$doctrineType] = $fieldParams[$espoType];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Doctrine\Converter;
|
||||
|
||||
use Espo\Core\Utils\Util;
|
||||
|
||||
class Link
|
||||
{
|
||||
private $metadata;
|
||||
|
||||
private $association;
|
||||
|
||||
|
||||
public function __construct(\Espo\Core\Utils\Metadata $metadata)
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
|
||||
$this->association = new \Espo\Core\Doctrine\Converter\Association();
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function getAssociation()
|
||||
{
|
||||
return $this->association;
|
||||
}
|
||||
|
||||
|
||||
public function getLinkEntityName($entityName, $link)
|
||||
{
|
||||
if (isset($link['params'])) {
|
||||
return isset($link['params']['entity']) ? $link['params']['entity'] : $entityName;
|
||||
}
|
||||
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']);
|
||||
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->$method($params, $foreignParams);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function belongsTo($params, $foreignParams)
|
||||
{
|
||||
return $this->getAssociation()->manyToOneUnidirectional($params, $foreignParams);
|
||||
}
|
||||
|
||||
|
||||
//TODO: hook for teams
|
||||
protected function hasMany($params, $foreignParams)
|
||||
{
|
||||
return $this->getAssociation()->oneToManyUnidirectionalWithJoinTable($params, $foreignParams);
|
||||
}
|
||||
|
||||
|
||||
protected function hasManyHasMany($params, $foreignParams)
|
||||
{
|
||||
return $this->getAssociation()->manyToManyBidirectional($params, $foreignParams);
|
||||
}
|
||||
|
||||
protected function hasOne($params, $foreignParams)
|
||||
{
|
||||
return $this->getAssociation()->oneToOneUnidirectional($params, $foreignParams);
|
||||
}
|
||||
|
||||
protected function hasOneBelongsTo($params, $foreignParams)
|
||||
{
|
||||
return $this->getAssociation()->oneToOneBidirectional($params, $foreignParams);
|
||||
}
|
||||
|
||||
|
||||
protected function belongsToParent($params, $foreignParams)
|
||||
{
|
||||
return $this->getAssociation()->oneToManySelfReferencing($params, $foreignParams);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
+[0] => belongsTo
|
||||
[1] => belongsToParent
|
||||
[2] => hasManyBelongsToParent
|
||||
+[3] => hasMany
|
||||
[4] => hasChildrenBelongsToParent
|
||||
+[5] => hasOne
|
||||
+[6] => hasManyHasMany
|
||||
[7] => hasManyBelongsTo
|
||||
[8] => hasChildrenHasMany
|
||||
[9] => hasChildren
|
||||
[10] => belongsToHasMany
|
||||
[11] => joint
|
||||
|
||||
|
||||
[0] => belongsTo
|
||||
[1] => belongsToParent
|
||||
[2] => hasManyBelongsToParent
|
||||
[3] => hasMany
|
||||
[4] => hasChildrenBelongsToParent
|
||||
[5] => belongsToParentHasChildren
|
||||
[6] => hasOne
|
||||
[7] => hasManyBelongsTo
|
||||
[8] => hasManyHasMany
|
||||
[9] => belongsToHasMany
|
||||
[10] => joint
|
||||
|
||||
|
||||
|
||||
|
||||
[0] => belongsTo
|
||||
[1] => belongsToParent
|
||||
[2] => hasManyBelongsToParent
|
||||
[3] => hasMany
|
||||
[4] => hasChildrenBelongsToParent
|
||||
[5] => belongsToParentHasChildren
|
||||
[6] => hasOne
|
||||
[7] => hasManyHasMany
|
||||
[8] => hasManyBelongsTo
|
||||
[9] => hasChildrenHasMany
|
||||
[10] => hasChildren
|
||||
[11] => belongsToHasMany
|
||||
[12] => joint
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Doctrine;
|
||||
|
||||
use Espo\Core\Utils\Util;
|
||||
|
||||
class EspoConverter
|
||||
{
|
||||
private $entityManager;
|
||||
private $metadata;
|
||||
private $fileManager;
|
||||
private $schemaTool;
|
||||
private $disconnectedClassMetadataFactory;
|
||||
private $entityGenerator;
|
||||
|
||||
protected $defaultFieldType = 'varchar';
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
|
||||
$this->doctrineHelper = new \Espo\Core\Doctrine\Helper($this->getEntityManager()->getWrapped());
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->entityManager;
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
protected function getSchemaTool()
|
||||
{
|
||||
return $this->schemaTool;
|
||||
}
|
||||
|
||||
protected function getDisconnectedClassMetadataFactory()
|
||||
{
|
||||
return $this->disconnectedClassMetadataFactory;
|
||||
}
|
||||
|
||||
protected function getEntityGenerator()
|
||||
{
|
||||
return $this->entityGenerator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function setMeta(array $meta)
|
||||
{
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
protected function getMeta()
|
||||
{
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
protected function getFieldMeta($type = '')
|
||||
{
|
||||
$meta = $this->getMeta();
|
||||
if (empty($type)) {
|
||||
return $meta['fields'];
|
||||
}
|
||||
else if (isset($meta['fields'][$type])) {
|
||||
return $meta['fields'][$type];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Metadata conversion from Espo format into Doctrine
|
||||
*
|
||||
* @param object $meta
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function convertToDoctrine()
|
||||
{
|
||||
$GLOBALS['log']->add('Debug', 'Metadata:get() - converting to doctrine metadata');
|
||||
|
||||
$meta = $this->getMetadata()->getAll();
|
||||
|
||||
return; //TODO
|
||||
$this->setMeta($meta);
|
||||
|
||||
$cacheDir = $this->getMetadata()->getMetaConfig()->doctrineCache;
|
||||
$this->getFileManager()->removeFilesInDir($cacheDir); //remove all existing files
|
||||
|
||||
//create files named like "Espo.Entities.User.php"
|
||||
|
||||
$convertedMeta = array();
|
||||
foreach($meta[$this->getMetadata()->getMetaConfig()->espoMetadataName] as $entityName => $metaRow) {
|
||||
|
||||
$convertedMeta[$entityName] = $this->convert($entityName, $metaRow);
|
||||
//$convertedMeta = Util::merge($convertedMeta, $this->convert($entityName, $metaRow)); //for link is need to define for two entities at once
|
||||
}
|
||||
|
||||
|
||||
/*echo '<pre>';
|
||||
print_r($convertedMeta);
|
||||
exit;*/
|
||||
|
||||
//save doctrine meta to files
|
||||
$result= true;
|
||||
foreach ($convertedMeta as $entityName => $doctineMeta) {
|
||||
$entityFullName = $this->getMetadata()->getEntityPath($entityName);
|
||||
$doctrineMeta = array($entityFullName => $doctineMeta);
|
||||
|
||||
//create a doctrine metadata file
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Metadata conversion from Espo format into Doctrine
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
//NEED TO CHANGE
|
||||
protected function convert($entityName, $meta)
|
||||
{
|
||||
if (empty($meta)) {
|
||||
$GLOBALS['log']->add('ERROR', 'EspoConverter:convert(), Entity:'.$entityName.' - metadata cannot be converted into Doctrine format');
|
||||
}
|
||||
|
||||
//conversion functionality
|
||||
$outputMeta = array(
|
||||
'type' => 'entity',
|
||||
'table' => $entityName, //TODO: if need to convert to underscore
|
||||
'id' => array(
|
||||
'id' => array(
|
||||
'type' => 'string',
|
||||
'generator' => array('strategy' => 'UUID'),
|
||||
)
|
||||
),
|
||||
'fields' => array(
|
||||
),
|
||||
);
|
||||
|
||||
$outputMeta = Util::merge($outputMeta, $this->convertFields($entityName, $meta));
|
||||
//$outputMeta = Util::merge($outputMeta, $this->convertLinks($meta));
|
||||
//END: conversion functionality
|
||||
|
||||
|
||||
return $outputMeta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*It can be moved to separate file*/
|
||||
protected function convertFields($entityName, array $meta)
|
||||
{
|
||||
$metaFields = $meta['fields'];
|
||||
|
||||
$convertedMetaFields = array();
|
||||
foreach($meta['fields'] as $fieldName => $fieldParams) {
|
||||
|
||||
//set default type if exists
|
||||
if (!isset($fieldParams['type']) || !empty($fieldParams['type'])) {
|
||||
$GLOBALS['log']->add('WARNING', 'Field type does not exist for '.$entityName.':'.$fieldName.'. Use default type ['.$this->defaultFieldType.']');
|
||||
$fieldParams['type'] = $this->defaultFieldType;
|
||||
} //END: set default type if exists
|
||||
|
||||
$fieldMeta = $this->getFieldMeta($fieldParams['type']);
|
||||
|
||||
//check if field need to be saved in database
|
||||
if ( (isset($fieldParams['db']) && $fieldParams['db'] === false) || (isset($fieldMeta['database']['db']) && !$fieldMeta['database']['db'] === false) ) {
|
||||
continue;
|
||||
} //END: check if field need to be saved in database
|
||||
|
||||
$convertedMetaFields[$fieldName] = $this->getInitValues($fieldParams);
|
||||
|
||||
|
||||
/*echo '<pre>';
|
||||
print_r($convertedMetaFields[$fieldName]);
|
||||
exit;*/
|
||||
|
||||
//convert type
|
||||
$convertedMetaFields[$fieldName]['type'] = $this->getFieldType($fieldParams['type']);
|
||||
//END: convert type
|
||||
}
|
||||
|
||||
|
||||
/*echo '<br />'.$entityName.'<pre>';
|
||||
print_r($convertedMetaFields); */
|
||||
}
|
||||
|
||||
protected function getFieldType($espoType)
|
||||
{
|
||||
$fieldMeta = $this->getFieldMeta($espoType);
|
||||
|
||||
if (isset($fieldMeta['database']['type']) && !empty($fieldMeta['database']['type'])) {
|
||||
return $fieldMeta['database']['type'];
|
||||
}
|
||||
|
||||
return $espoType;
|
||||
}
|
||||
|
||||
protected function getInitValues(array $fieldParams)
|
||||
{
|
||||
//pair espo:doctrine
|
||||
$convertRules = array(
|
||||
'type' => 'type',
|
||||
'maxLength' => 'length',
|
||||
'default' => array(
|
||||
'condition' => '!(^javascript)',
|
||||
'json' => '{"options":{"default":{0}}}',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
$values = array();
|
||||
foreach($convertRules as $espoType => $doctrineType) {
|
||||
|
||||
if (isset($fieldParams[$espoType]) && !empty($fieldParams[$espoType])) {
|
||||
|
||||
if (is_array($doctrineType)) {
|
||||
|
||||
//print_r($fieldParams);
|
||||
//echo $doctrineType['condition'].' '.$fieldParams[$espoType];
|
||||
|
||||
//if (preg_match('/'.$doctrineType['condition'].'/i', $fieldParams[$espoType])) {
|
||||
$jsonValue = json_encode($fieldParams[$espoType]);
|
||||
$jsonRes = str_replace('{0}', $jsonValue, $doctrineType['json']);
|
||||
$values = Util::merge($values, json_decode($jsonRes, true));
|
||||
//}
|
||||
} else {
|
||||
$values[$doctrineType] = $fieldParams[$espoType];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected function convertLinks(array $meta)
|
||||
{
|
||||
$metaFields = $meta['links'];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -13,7 +13,7 @@ class Helper
|
||||
private $entityGenerator;
|
||||
|
||||
|
||||
public function __construct(\Espo\Core\EntityManager $entityManager)
|
||||
public function __construct(\Doctrine\ORM\EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
|
||||
@@ -45,4 +45,57 @@ class Helper
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -49,13 +49,13 @@ class Util
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toCamelCase($name, $capitaliseFirstChar=false)
|
||||
public static function toCamelCase($name, $capitaliseFirstChar = false, $symbol = '-')
|
||||
{
|
||||
if($capitaliseFirstChar) {
|
||||
$name[0] = strtoupper($name[0]);
|
||||
}
|
||||
$func = create_function('$c', 'return strtoupper($c[1]);');
|
||||
return preg_replace_callback('/-([a-z])/', $func, $name);
|
||||
return preg_replace_callback('/'.$symbol.'([a-z])/', $func, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,10 +66,10 @@ class Util
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function fromCamelCase($name)
|
||||
public static function fromCamelCase($name, $symbol = '-')
|
||||
{
|
||||
$name[0] = strtolower($name[0]);
|
||||
$func = create_function('$c', 'return "-" . strtolower($c[1]);');
|
||||
$func = create_function('$c', 'return "'.$symbol.'" . strtolower($c[1]);');
|
||||
return preg_replace_callback('/([A-Z])/', $func, $name);
|
||||
}
|
||||
|
||||
@@ -186,6 +186,58 @@ class Util
|
||||
return is_array($object) ? array_map("static::objectToArray", $object) : $object;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get Naming according to prefix or postfix type
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $prePostFix
|
||||
* @param string $type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getNaming($name, $prePostFix, $type = 'prefix', $symbol = '-')
|
||||
{
|
||||
if ($type == 'prefix') {
|
||||
return static::toCamelCase($prePostFix.$symbol.$name, false, $symbol);
|
||||
} else if ($type == 'postfix') {
|
||||
return static::toCamelCase($name.$symbol.$prePostFix, false, $symbol);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace $search in array recursively
|
||||
*
|
||||
* @param string $search
|
||||
* @param string $replace
|
||||
* @param string $array
|
||||
* @param string $isKeys
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function replaceInArray($search = '', $replace = '', $array = false, $isKeys = true)
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return str_replace($search, $replace, $array);
|
||||
}
|
||||
|
||||
$newArr = array();
|
||||
foreach ($array as $key => $value) {
|
||||
$addKey = $key;
|
||||
if ($isKeys) { //Replace keys
|
||||
$addKey = str_replace($search, $replace, $key);
|
||||
}
|
||||
|
||||
// Recurse
|
||||
$newArr[$addKey] = static::replaceInArray($search, $replace, $value, $isKeys);
|
||||
}
|
||||
|
||||
return $newArr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,5 +17,8 @@
|
||||
"search":{
|
||||
"basic":false,
|
||||
"advanced":false
|
||||
},
|
||||
"database":{
|
||||
"type":"json_array"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"database":{
|
||||
"type":"integer"
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -11,7 +11,7 @@ class Auth extends \Slim\Middleware
|
||||
|
||||
private $container;
|
||||
|
||||
public function __construct(\Doctrine\ORM\EntityManager $entityManager, \Espo\Core\Container $container)
|
||||
public function __construct(\Espo\Core\EntityManager $entityManager, \Espo\Core\Container $container)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->container = $container;
|
||||
@@ -49,7 +49,7 @@ class Auth extends \Slim\Middleware
|
||||
$username = $authKey;
|
||||
$password = $authSec;
|
||||
|
||||
$user = $this->entityManager->getRepository('\Espo\Entities\User')->findOneBy(array('username' => $username));
|
||||
$user = $this->entityManager->getRepository('User')->findOneBy(array('username' => $username));
|
||||
if ($user) {
|
||||
if ($password == $user->getPassword()) {
|
||||
$this->container->setUser($user);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -180,6 +180,38 @@ class UtilTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($testResult, Util::objectToArray($testObj));
|
||||
}
|
||||
|
||||
function testGetNaming()
|
||||
{
|
||||
$this->assertEquals('myPrefixMyName', Util::getNaming('myName', 'myPrefix', 'prefix'));
|
||||
|
||||
$this->assertEquals('myNameMyPostfix', Util::getNaming('myName', 'myPostfix', 'postfix'));
|
||||
$this->assertEquals('myNameMyPostfix', Util::getNaming('my_name', 'myPostfix', 'postfix', '_'));
|
||||
$this->assertEquals('myNameMyPostfix', Util::getNaming('my_name', 'my_postfix', 'postfix', '_'));
|
||||
}
|
||||
|
||||
function testReplaceInArray()
|
||||
{
|
||||
$testArray = array(
|
||||
'option' => array(
|
||||
'default' => '{0}',
|
||||
'testKey' => array(
|
||||
'{0}' => 'testVal',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$testResult = array(
|
||||
'option' => array(
|
||||
'default' => 'DONE',
|
||||
'testKey' => array(
|
||||
'DONE' => 'testVal',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals($testResult, Util::replaceInArray('{0}', 'DONE', $testArray, true));
|
||||
}
|
||||
|
||||
|
||||
/*function testGetScopeModuleName()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user