Metadata conversion from Espo format into Doctrine

@param string $entityName
@param array $entityMetadata

@return array
353818
protected function convertFields($entityName, &$entityMetadata)
    {
        //List of unmerged fields with default field defenitions in $outputMeta
        $unmergedFields = array(
            'name',
        );

        $outputMeta = array(
            'id' => array(
                'type' => Entity::ID,
                'dbType' => 'varchar'
            ),
            'name' => array(
                'type' => isset($entityMetadata['fields']['name']['type']) ? $entityMetadata['fields']['name']['type'] : Entity::VARCHAR,
                'notStorable' => true
            ),
            'deleted' => array(
                'type' => Entity::BOOL,
                'default' => false
            )
        );

        foreach ($entityMetadata['fields'] as $fieldName => $fieldParams) {
            if (empty($fieldParams['type'])) continue;

            /** check if "fields" option exists in $fieldMeta */
            $fieldTypeMetadata = $this->getMetadataHelper()->getFieldDefsByType($fieldParams);

            $fieldDefs = $this->convertField($entityName, $fieldName, $fieldParams, $fieldTypeMetadata);

            if ($fieldDefs !== false) {
                //push fieldDefs to the ORM metadata array
                if (isset($outputMeta[$fieldName]) && !in_array($fieldName, $unmergedFields)) {
                    $outputMeta[$fieldName] = array_merge($outputMeta[$fieldName], $fieldDefs);
                } else {
                    $outputMeta[$fieldName] = $fieldDefs;
                }
            }

            /** check and set the linkDefs from 'fields' metadata */
            if (isset($fieldTypeMetadata['linkDefs'])) {
                $linkDefs = $this->getMetadataHelper()->getLinkDefsInFieldMeta($entityName, $fieldParams, $fieldTypeMetadata['linkDefs']);
                if (isset($linkDefs)) {
                    if (!isset($entityMetadata['links'])) {
                        $entityMetadata['links'] = array();
                    }
                    $entityMetadata['links'] = Util::merge( array($fieldName => $linkDefs), $entityMetadata['links'] );
                }
            }
        }

        return $outputMeta;
    }
75372
private function serialize(EntityMetadata $metadata)
    {
        switch ($this->serializer) {
            case self::SERIALIZER_PHP:
                return serialize($metadata);
            case self::SERIALIZER_IGBINARY:
                return igbinary_serialize($metadata);
            default:
                throw new RuntimeException('Unable to handle serialization of the metadata object');
        }
    }
753691
public function to(string $entityType, string $tableName = null) : RelationDefiner
    {
        return new RelationDefiner($this->callback, function () use ($entityType, $tableName) {
            return $this->orm->getEntityMapper($entityType, $tableName);
        });
    }
634587
public function create(array $entityData)
    {
        $this->preCreate($entityData);
        $entity = $this->doCreate($entityData);
        $this->getEntityManager()->persist($entity);
        $this->getEntityManager()->flush($entity);
        $this->postCreate($entity);
        $this->getEntityManager()->flush($entity);

        return $entity;
    }
120670
public function generateModel($entityMetadata)
    {
        $stub = $this->stubs['model'];

        // header
        $this->replaceNamespace(get_mapped_model_namespace(), $stub);
        $this->replaceClass(class_basename(get_mapped_model($entityMetadata['class'], false)), $stub);
        $this->replaceMappedClass($entityMetadata['class'], $stub);

        // traits
        $this->replaceTraits($entityMetadata, $stub);

        // table name
        $this->replaceTable($entityMetadata['table']['name'], $stub);

        // primary key
        $columnMetadata = $this->getPrimaryKeyColumn($entityMetadata);
        $this->replacePrimaryKey($columnMetadata['name'], $stub);
        $this->replaceIncrementing((! empty($columnMetadata['options']['autoIncrement'])), $stub);

        $this->replaceAutoUuids($entityMetadata, $stub);

        // timestamps
        $this->replaceTimestamps($entityMetadata['timestamps'], $stub);

        // misc
        $this->replaceTouches($entityMetadata['touches'], $stub);
        $this->replaceWith($entityMetadata['with'], $stub);
        $this->replaceVersioned($entityMetadata['versionTable'], $stub);
        $this->replaceMorphClass($entityMetadata['morphClass'], $stub);

        // mapping data
        $this->replaceMapping($entityMetadata, $stub);
        
        // relations
        $this->replaceRelations($entityMetadata['relations'], $stub);

        $this->files->put($this->path . '/' . get_mapped_model_hash($entityMetadata['class']), $stub);
    }
25896
private function convertRelationships(EntityMetadata $metadata, array $data)
    {
        foreach ($metadata->getRelationships() as $key => $relMeta) {
            if (!isset($data[$key])) {
                continue;
            }
            if (true === $relMeta->isMany() && !is_array($data[$key])) {
                throw PersisterException::badRequest(sprintf('Relationship key "%s" is a reference many. Expected record data type of array, "%s" found on model "%s" for identifier "%s"', $key, gettype($data[$key]), $type, $identifier));
            }
            $references = $relMeta->isOne() ? [$data[$key]] : $data[$key];

            $extracted = [];
            foreach ($references as $reference) {
                $extracted[] =  $this->extractRelationship($relMeta, $reference);
            }
            $data[$key] = $relMeta->isOne() ? reset($extracted) : $extracted;
        }
        return $data;
    }
853424
private function initFieldDescriptors($entityName, $id)
    {
        $mediaEntityName = $this->getParameter('sulu.model.media.class');

        $entityJoin = new DoctrineJoinDescriptor(
            $mediaEntityName,
            $entityName . '.medias',
            $entityName . '.id = ' . $id,
            DoctrineJoinDescriptor::JOIN_METHOD_INNER
        );

        $this->fieldDescriptors = [];

        $this->fieldDescriptors['entity'] = new DoctrineFieldDescriptor(
            'id',
            'entity',
            $entityName,
            null,
            [],
            FieldDescriptorInterface::VISIBILITY_NO,
            FieldDescriptorInterface::SEARCHABILITY_NO
        );

        $this->fieldDescriptors['id'] = new DoctrineFieldDescriptor(
            'id',
            'id',
            $mediaEntityName,
            'public.id',
            [
                $mediaEntityName => $entityJoin,
            ],
            FieldDescriptorInterface::VISIBILITY_NO,
            FieldDescriptorInterface::SEARCHABILITY_NO
        );

        $this->fieldDescriptors['thumbnails'] = new DoctrineFieldDescriptor(
            'id',
            'thumbnails',
            $mediaEntityName,
            'media.media.thumbnails',
            [
                $mediaEntityName => $entityJoin,
            ],
            FieldDescriptorInterface::VISIBILITY_YES,
            FieldDescriptorInterface::SEARCHABILITY_NEVER,
            'thumbnails',
            false
        );

        $this->fieldDescriptors['name'] = new DoctrineFieldDescriptor(
            'name',
            'name',
            self::$fileVersionEntityName,
            'public.name',
            [
                $mediaEntityName => $entityJoin,
                self::$fileEntityName => new DoctrineJoinDescriptor(
                    self::$fileEntityName,
                    $mediaEntityName . '.files'
                ),
                self::$fileVersionEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionEntityName,
                    self::$fileEntityName . '.fileVersions',
                    self::$fileVersionEntityName . '.version = ' . self::$fileEntityName . '.version'
                ),
            ]
        );
        $this->fieldDescriptors['size'] = new DoctrineFieldDescriptor(
            'size',
            'size',
            self::$fileVersionEntityName,
            'media.media.size',
            [
                $mediaEntityName => $entityJoin,
                self::$fileEntityName => new DoctrineJoinDescriptor(
                    self::$fileEntityName,
                    $mediaEntityName . '.files'
                ),
                self::$fileVersionEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionEntityName,
                    self::$fileEntityName . '.fileVersions',
                    self::$fileVersionEntityName . '.version = ' . self::$fileEntityName . '.version'
                ),
            ],
            FieldDescriptorInterface::VISIBILITY_NO,
            FieldDescriptorInterface::SEARCHABILITY_NEVER,
            'bytes'
        );

        $this->fieldDescriptors['changed'] = new DoctrineFieldDescriptor(
            'changed',
            'changed',
            self::$fileVersionEntityName,
            'public.changed',
            [
                $mediaEntityName => $entityJoin,
                self::$fileEntityName => new DoctrineJoinDescriptor(
                    self::$fileEntityName,
                    $mediaEntityName . '.files'
                ),
                self::$fileVersionEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionEntityName,
                    self::$fileEntityName . '.fileVersions',
                    self::$fileVersionEntityName . '.version = ' . self::$fileEntityName . '.version'
                ),
            ],
            FieldDescriptorInterface::VISIBILITY_NO,
            FieldDescriptorInterface::SEARCHABILITY_NEVER,
            'date'
        );

        $this->fieldDescriptors['created'] = new DoctrineFieldDescriptor(
            'created',
            'created',
            self::$fileVersionEntityName,
            'public.created',
            [
                $mediaEntityName => $entityJoin,
                self::$fileEntityName => new DoctrineJoinDescriptor(
                    self::$fileEntityName,
                    $mediaEntityName . '.files'
                ),
                self::$fileVersionEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionEntityName,
                    self::$fileEntityName . '.fileVersions',
                    self::$fileVersionEntityName . '.version = ' . self::$fileEntityName . '.version'
                ),
            ],
            FieldDescriptorInterface::VISIBILITY_NO,
            FieldDescriptorInterface::SEARCHABILITY_NEVER,
            'date'
        );

        $this->fieldDescriptors['title'] = new DoctrineFieldDescriptor(
            'title',
            'title',
            self::$fileVersionMetaEntityName,
            'public.title',
            [
                $mediaEntityName => $entityJoin,
                self::$fileEntityName => new DoctrineJoinDescriptor(
                    self::$fileEntityName,
                    $mediaEntityName . '.files'
                ),
                self::$fileVersionEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionEntityName,
                    self::$fileEntityName . '.fileVersions',
                    self::$fileVersionEntityName . '.version = ' . self::$fileEntityName . '.version'
                ),
                self::$fileVersionMetaEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionMetaEntityName,
                    self::$fileVersionEntityName . '.meta'
                ),
            ],
            FieldDescriptorInterface::VISIBILITY_NO,
            FieldDescriptorInterface::SEARCHABILITY_YES,
            'title'
        );

        $this->fieldDescriptors['description'] = new DoctrineFieldDescriptor(
            'description',
            'description',
            self::$fileVersionMetaEntityName,
            'media.media.description',
            [
                $mediaEntityName => $entityJoin,
                self::$fileEntityName => new DoctrineJoinDescriptor(
                    self::$fileEntityName,
                    $mediaEntityName . '.files'
                ),
                self::$fileVersionEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionEntityName,
                    self::$fileEntityName . '.fileVersions',
                    self::$fileVersionEntityName . '.version = ' . self::$fileEntityName . '.version'
                ),
                self::$fileVersionMetaEntityName => new DoctrineJoinDescriptor(
                    self::$fileVersionMetaEntityName,
                    self::$fileVersionEntityName . '.meta'
                ),
            ],
            FieldDescriptorInterface::VISIBILITY_YES,
            FieldDescriptorInterface::SEARCHABILITY_YES
        );
    }
1299093
public function getRepository($entityName)
    {
        $entityName = ltrim($entityName, '\\');
        if (isset($this->repositories[$entityName])) {
            return $this->repositories[$entityName];
        }

        $metadata = $this->getClassMetadata($entityName);
        $customRepositoryClassName = $metadata->customRepositoryClassName;

        if ($customRepositoryClassName !== null) {
            $repository = new $customRepositoryClassName($this, $metadata);
        } else {
            $repository = new XmlEntityRepository($this, $metadata);
        }

        $this->repositories[$entityName] = $repository;

        return $repository;
    }
1188238
public static function fromEntity(FieldMetadata $meta, $entity) {
        $instance = new static($meta, $entity->getAttribute($meta->name));

        return $instance;
    }
762705
private Map<String, EntityMetadata> getEntityMetadataCol(ApplicationMetadata appMetadata, String persistenceUnit)
    {
        Metamodel metaModel = appMetadata.getMetamodel(persistenceUnit);
        Map<String, EntityMetadata> entityMetadataMap = ((MetamodelImpl) metaModel).getEntityMetadataMap();
        return entityMetadataMap;
    }
780799
private function validateDatabase(EntityMetadata $metadata)
    {
        $persistence = $metadata->persistence;
        if (false === $metadata->isChildEntity() && (empty($persistence->db) || empty($persistence->collection))) {
            throw MetadataException::invalidMetadata($metadata->type, 'The persistence database and collection names cannot be empty.');
        }
    }
1092193
public static function getAllEntityClassNames(EntityManager $entityManager)
    {
        $classes = [];

        foreach ($entityManager->getMetadataFactory()->getAllMetadata() as $meta) {
            $classes[] = $meta->getName();
        }

        return $classes;
    }
616987
public function getEntityBuilder($className = null, ClassMetadata $classMetadata = null)
    {
        $builder = new Entity\Builder($this->getMapper(), $this->getFieldManager());

        if ($className !== null) {
            $builder->setClass($className);
        }

        if ($classMetadata !== null) {
            $builder->setClassMetadata($classMetadata);
        }

        return $builder;
    }
1014028
protected function createAndReturnNewFirstEntity($data, $entityName)
    {
        if (is_array($data)) {
            $entity = $this->getFirstEntityByName($entityName);
            return $this->mapAttributesFromSecondEntityToFirstEntityAndReturnEntity($data, $entity);
        }

        return null;
    }
820053
protected function getForeignField($name, $entityName)
    {
        $foreignField = $this->getMetadata()->get('entityDefs.'.$entityName.'.fields.'.$name);

        if ($foreignField['type'] != 'varchar') {
            if ($foreignField['type'] == 'personName') {
                return array('first' . ucfirst($name), ' ', 'last' . ucfirst($name));
            }
        }

        return $name;
    }
552018
protected function getFieldsFromMetadata($metadata)
    {
        $fields = $metadata->fieldMappings;

        // Remove the primary key field if it's not managed manually
        if (!$metadata->isIdentifierNatural()) {
            foreach ($metadata->identifier as $oneId) {
                unset($fields[$oneId]);
            }
        }

        foreach ($metadata->associationMappings as $fieldName => $relation) {
            if (in_array($relation['type'], [ClassMetadataInfo::MANY_TO_ONE, ClassMetadataInfo::ONE_TO_MANY])) {
                $fields[$fieldName] = $relation;
            } elseif ($relation['type'] == ClassMetadataInfo::MANY_TO_MANY && (empty($relation['mappedBy']) == false  || empty($relation['inversedBy'])  == false)) {
                /*|| $relation['targetEntity'] == $relation['sourceEntity']*/
                $fields[$fieldName] = $relation;
            }
        }

        return $fields;
    }
190742
public function create($entityName)
    {
        return new DoctrineListBuilder($this->em, $entityName, $this->eventDispatcher, $this->permissions);
    }