Build metadata from all entity classes.

@param array $classes
@param boolean $namespaceTablenames
@param boolean $morphClassAbbreviations
@return array
545211
public function scan($classes, $namespaceTablenames=true, $morphClassAbbreviations=true)
    {
        $this->namespaceTablenames = $namespaceTablenames;
        $this->morphClassAbbreviations = $morphClassAbbreviations;

        $metadata = [];

        foreach ($classes as $class) {
            $entityMetadata = $this->parseClass($class);

            if ($entityMetadata) {
                $metadata[$class] = $entityMetadata;
            }
        }

        // validate pivot tables
        $this->validator->validatePivotTables($metadata);

        // generate morphable classes
        $this->generateMorphableClasses($metadata);

        return $metadata;
    }
992125
def build_collections_and_classes
    @classes = Hash.new
    @class_metadata = Hash.new # This is used to store property information about a class

    # Build complex types first, these will be used for entities
    complex_types = @edmx.xpath("//edm:ComplexType", @ds_namespaces) || []
    complex_types.each do |c|
      name = qualify_class_name(c['Name'])
      props = c.xpath(".//edm:Property", @ds_namespaces)
      methods = props.collect { |p| p['Name'] } # Standard Properties
      @classes[name] = ClassBuilder.new(name, methods, [], self, @namespace).build unless @classes.keys.include?(name)
    end

    entity_types = @edmx.xpath("//edm:EntityType", @ds_namespaces)
    entity_types.each do |e|
      next if e['Abstract'] == "true"
      klass_name = qualify_class_name(e['Name'])
      methods = collect_properties(klass_name, e, @edmx)
      nav_props = collect_navigation_properties(klass_name, e, @edmx)
      @classes[klass_name] = ClassBuilder.new(klass_name, methods, nav_props, self, @namespace).build unless @classes.keys.include?(klass_name)
    end

    # Fill in the collections instance variable
    collections = @edmx.xpath("//edm:EntityContainer/edm:EntitySet", @ds_namespaces)
    collections.each do |c|
      entity_type = c["EntityType"]
      @collections[c["Name"]] = { :edmx_type => entity_type, :type => convert_to_local_type(entity_type) }
    end

    build_function_imports
  end
985802
public synchronized Morphia map(final Set<Class> entityClasses) {
        if (entityClasses != null && !entityClasses.isEmpty()) {
            for (final Class entityClass : entityClasses) {
                if (!mapper.isMapped(entityClass)) {
                    mapper.addMappedClass(entityClass);
                }
            }
        }
        return this;
    }
234771
protected function listPackageClasses(array $namespaces)
    {
        return array_filter(get_declared_classes(), function ($class) use ($namespaces) {
            $valid = false;
            foreach ($namespaces as $ns) {
                $valid = (strpos($class, $ns) === 0) ? true : $valid;
            }
            return $valid;
        });
    }
485335
private static function buildClassList($matches)
    {
        if (array() === $matches) {
            return array();
        }

        $classes   = array();
        $namespace = '';

        for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
            if (!empty($matches['ns'][$i])) {
                $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
            } else {
                $name = $matches['name'][$i];
                // skip anon classes extending/implementing
                if ($name === 'extends' || $name === 'implements') {
                    continue;
                }
                if ($name[0] === ':') {
                    // This is an XHP class, https://github.com/facebook/xhp
                    $name = 'xhp' . substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
                } elseif ($matches['type'][$i] === 'enum') {
                    // In Hack, something like:
                    // enum Foo: int { HERP = '123'; }
                    // The regex above captures the colon, which isn't part of
                    // the class name.
                    $name = rtrim($name, ':');
                }
                $classes[] = ltrim($namespace . $name, '\\');
            }
        }

        return $classes;
    }
885808
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $classMetadata = $eventArgs->getClassMetadata();
        $classMetadata->setTableName($this->prefix . $classMetadata->getTableName());

        //if we use sequences, also prefix the sequence name
        if($classMetadata->isIdGeneratorSequence()) {
        
            $sequenceDefinition = $classMetadata->sequenceGeneratorDefinition;
            $sequenceDefinition['sequenceName'] = $this->prefix . $sequenceDefinition['sequenceName'];

            $classMetadata->setSequenceGeneratorDefinition($sequenceDefinition);
        }

        foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
            if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) {
                $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
                $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
            }
        }
    }
548712
private function getNewObjectFlagMeta($entityClass)
    {
        $meta = $this->extendedMetadataFactory->getExtendedMetadata($entityClass);

        return isset($meta['newObjectFlag']) ? $meta['newObjectFlag'] : [];
    }
609252
public function getSchemaFromMetadata(array $classes)
    {
        // Reminder for processed classes, used for hierarchies
        $processedClasses       = array();
        $eventManager           = $this->em->getEventManager();
        $schemaManager          = $this->em->getConnection()->getSchemaManager();
        $metadataSchemaConfig   = $schemaManager->createSchemaConfig();

        $metadataSchemaConfig->setExplicitForeignKeyIndexes(false);
        $schema = new Schema(array(), array(), $metadataSchemaConfig);

        $addedFks = array();
        $blacklistedFks = array();

        foreach ($classes as $class) {
            /** @var \Doctrine\ORM\Mapping\ClassMetadata $class */
            if ($this->processingNotRequired($class, $processedClasses)) {
                continue;
            }

            $table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform));

            if ($class->isInheritanceTypeSingleTable()) {
                $this->gatherColumns($class, $table);
                $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);

                // Add the discriminator column
                $this->addDiscriminatorColumnDefinition($class, $table);

                // Aggregate all the information from all classes in the hierarchy
                foreach ($class->parentClasses as $parentClassName) {
                    // Parent class information is already contained in this class
                    $processedClasses[$parentClassName] = true;
                }

                foreach ($class->subClasses as $subClassName) {
                    $subClass = $this->em->getClassMetadata($subClassName);
                    $this->gatherColumns($subClass, $table);
                    $this->gatherRelationsSql($subClass, $table, $schema, $addedFks, $blacklistedFks);
                    $processedClasses[$subClassName] = true;
                }
            } elseif ($class->isInheritanceTypeJoined()) {
                // Add all non-inherited fields as columns
                $pkColumns = array();
                foreach ($class->fieldMappings as $fieldName => $mapping) {
                    if ( ! isset($mapping['inherited'])) {
                        $columnName = $this->quoteStrategy->getColumnName(
                            $mapping['fieldName'],
                            $class,
                            $this->platform
                        );
                        $this->gatherColumn($class, $mapping, $table);

                        if ($class->isIdentifier($fieldName)) {
                            $pkColumns[] = $columnName;
                        }
                    }
                }

                $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);

                // Add the discriminator column only to the root table
                if ($class->name == $class->rootEntityName) {
                    $this->addDiscriminatorColumnDefinition($class, $table);
                } else {
                    // Add an ID FK column to child tables
                    $inheritedKeyColumns = array();
                    foreach ($class->identifier as $identifierField) {
                        $idMapping = $class->fieldMappings[$identifierField];
                        if (isset($idMapping['inherited'])) {
                            $this->gatherColumn($class, $idMapping, $table);
                            $columnName = $this->quoteStrategy->getColumnName(
                                $identifierField,
                                $class,
                                $this->platform
                            );
                            // TODO: This seems rather hackish, can we optimize it?
                            $table->getColumn($columnName)->setAutoincrement(false);

                            $pkColumns[] = $columnName;
                            $inheritedKeyColumns[] = $columnName;
                        }
                    }
                    if (!empty($inheritedKeyColumns)) {
                        // Add a FK constraint on the ID column
                        $table->addForeignKeyConstraint(
                            $this->quoteStrategy->getTableName(
                                $this->em->getClassMetadata($class->rootEntityName),
                                $this->platform
                            ),
                            $inheritedKeyColumns,
                            $inheritedKeyColumns,
                            array('onDelete' => 'CASCADE')
                        );
                    }

                }

                $table->setPrimaryKey($pkColumns);

            } elseif ($class->isInheritanceTypeTablePerClass()) {
                throw ORMException::notSupported();
            } else {
                $this->gatherColumns($class, $table);
                $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);
            }

            $pkColumns = array();
            foreach ($class->identifier as $identifierField) {
                if (isset($class->fieldMappings[$identifierField])) {
                    $pkColumns[] = $this->quoteStrategy->getColumnName($identifierField, $class, $this->platform);
                } elseif (isset($class->associationMappings[$identifierField])) {
                    /* @var $assoc \Doctrine\ORM\Mapping\OneToOne */
                    $assoc = $class->associationMappings[$identifierField];
                    foreach ($assoc['joinColumns'] as $joinColumn) {
                        $pkColumns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
                    }
                }
            }

            if ( ! $table->hasIndex('primary')) {
                $table->setPrimaryKey($pkColumns);
            }

            if (isset($class->table['indexes'])) {
                foreach ($class->table['indexes'] as $indexName => $indexData) {
                    if( ! isset($indexData['flags'])) {
                        $indexData['flags'] = array();
                    }

                    $table->addIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, (array)$indexData['flags'], isset($indexData['options']) ? $indexData['options'] : array());
                }
            }

            if (isset($class->table['uniqueConstraints'])) {
                foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) {
                    $table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, isset($indexData['options']) ? $indexData['options'] : array());
                }
            }

            if (isset($class->table['options'])) {
                foreach ($class->table['options'] as $key => $val) {
                    $table->addOption($key, $val);
                }
            }

            $processedClasses[$class->name] = true;

            if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) {
                $seqDef     = $class->sequenceGeneratorDefinition;
                $quotedName = $this->quoteStrategy->getSequenceName($seqDef, $class, $this->platform);
                if ( ! $schema->hasSequence($quotedName)) {
                    $schema->createSequence(
                        $quotedName,
                        $seqDef['allocationSize'],
                        $seqDef['initialValue']
                    );
                }
            }

            if ($eventManager->hasListeners(ToolEvents::postGenerateSchemaTable)) {
                $eventManager->dispatchEvent(
                    ToolEvents::postGenerateSchemaTable,
                    new GenerateSchemaTableEventArgs($class, $schema, $table)
                );
            }
        }

        if ( ! $this->platform->supportsSchemas() && ! $this->platform->canEmulateSchemas() ) {
            $schema->visit(new RemoveNamespacedAssets());
        }

        if ($eventManager->hasListeners(ToolEvents::postGenerateSchema)) {
            $eventManager->dispatchEvent(
                ToolEvents::postGenerateSchema,
                new GenerateSchemaEventArgs($this->em, $schema)
            );
        }

        return $schema;
    }
658219
public function parseEntity($class)
    {
        $reflectionClass = new ReflectionClass($class);

        // scan class annotations
        $classAnnotations = $this->reader->getClassAnnotations($reflectionClass);

        // init class metadata
        $entityMetadata = new EntityDefinition([
            'class' => $class,
            'morphClass' => $this->generateMorphClass($class),
            'table' => new TableDefinition([
                'name' => $this->generateTableName($class),
                'columns' => [],
            ]),
            'versionTable' => false,
        
            'softDeletes' => false,
            'timestamps' => false,
            
            'touches' => [],
            'with' => [],

            'columns' => [],
            'attributes' => [],
            'embeddeds' => [],
            'relations' => [],
        ]);

        // find entity parameters and plugins
        foreach ($classAnnotations as $annotation) {
            // entity parameters
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Entity) {
                if (! empty($annotation->morphClass)) {
                    $entityMetadata['morphClass'] = $annotation->morphClass;
                }
                if (! empty($annotation->touches)) {
                    $entityMetadata['touches'] = $annotation->touches;
                }
                if (! empty($annotation->with)) {
                    $entityMetadata['with'] = $annotation->with;
                }
            }

            // softdeletes
            if ($annotation instanceof \ProAI\Datamapper\Annotations\SoftDeletes) {
                $entityMetadata['softDeletes'] = true;
            }

            // table name
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Table) {
                $entityMetadata['table']['name'] = $annotation->name;
            }

            // timestamps
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Timestamps) {
                $entityMetadata['timestamps'] = true;
            }
        }

        // find versionable annotation (2nd loop, because table name is required)
        foreach ($classAnnotations as $annotation) {
            if ($annotation instanceof \ProAI\Datamapper\Annotations\Versionable) {
                $entityMetadata['versionTable'] = new TableDefinition([
                    'name' => $entityMetadata['table']['name'] . '_version',
                    'columns' => [],
                ]);
            }
        }

        // find columns and embedded classes
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            $name = $this->getSanitizedName($reflectionProperty->getName(), $entityMetadata['class']);
            $propertyAnnotations = $this->reader->getPropertyAnnotations($reflectionProperty);

            foreach ($propertyAnnotations as $annotation) {
                // column
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Column) {
                    $this->setAdditionalColumnProperties($name, $annotation, $propertyAnnotations);

                    $this->parseColumn($name, $annotation, $entityMetadata, false, true);
                }

                // embedded class
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Embedded) {
                    $this->parseEmbeddedClass($name, $annotation, $entityMetadata, true);
                }
            }
        }

        // check primary key
        $this->validator->validatePrimaryKey($entityMetadata);

        // find relationships (2nd loop, because primary key column is required for foreign keys)
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            $name = $this->getSanitizedName($reflectionProperty->getName(), $entityMetadata['class']);
            $propertyAnnotations = $this->reader->getPropertyAnnotations($reflectionProperty);

            foreach ($propertyAnnotations as $annotation) {
                // column
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Column) {
                    $this->setAdditionalColumnProperties($name, $annotation, $propertyAnnotations);

                    $entityMetadata['attributes'][] = $this->parseColumn($name, $annotation, $entityMetadata);
                }

                // embedded class
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Embedded) {
                    $entityMetadata['embeddeds'][] = $this->parseEmbeddedClass($name, $annotation, $entityMetadata);
                }

                // relation
                if ($annotation instanceof \ProAI\Datamapper\Annotations\Relation) {
                    $entityMetadata['relations'][] = $this->parseRelation($name, $annotation, $entityMetadata);
                }
            }
        }

        // check timestamps extension
        if (! empty($entityMetadata['timestamps'])) {
            $this->validator->validateTimestamps($entityMetadata);
        }

        // check softDeletes extension
        if (! empty($entityMetadata['softDeletes'])) {
            $this->validator->validateSoftDeletes($entityMetadata);
        }

        // check version extension
        if (! empty($entityMetadata['versionTable'])) {
            $this->validator->validateVersionTable($entityMetadata);
        }

        return $entityMetadata;
    }
885730
protected function getNestedMetadata(string $resourceClass, array $associations): ClassMetadata
    {
        $metadata = $this->getClassMetadata($resourceClass);

        foreach ($associations as $association) {
            if ($metadata->hasAssociation($association)) {
                $associationClass = $metadata->getAssociationTargetClass($association);

                $metadata = $this->getClassMetadata($associationClass);
            }
        }

        return $metadata;
    }
79442
private function getClasses(array $entrypointProperties, array $classes): array
    {
        $classes[] = [
            '@id' => '#Entrypoint',
            '@type' => 'hydra:Class',
            'hydra:title' => 'The API entrypoint',
            'hydra:supportedProperty' => $entrypointProperties,
            'hydra:supportedOperation' => [
                '@type' => 'hydra:Operation',
                'hydra:method' => 'GET',
                'rdfs:label' => 'The API entrypoint.',
                'returns' => '#EntryPoint',
            ],
        ];

        // Constraint violation
        $classes[] = [
            '@id' => '#ConstraintViolation',
            '@type' => 'hydra:Class',
            'hydra:title' => 'A constraint violation',
            'hydra:supportedProperty' => [
                [
                    '@type' => 'hydra:SupportedProperty',
                    'hydra:property' => [
                        '@id' => '#ConstraintViolation/propertyPath',
                        '@type' => 'rdf:Property',
                        'rdfs:label' => 'propertyPath',
                        'domain' => '#ConstraintViolation',
                        'range' => 'xmls:string',
                    ],
                    'hydra:title' => 'propertyPath',
                    'hydra:description' => 'The property path of the violation',
                    'hydra:readable' => true,
                    'hydra:writable' => false,
                ],
                [
                    '@type' => 'hydra:SupportedProperty',
                    'hydra:property' => [
                        '@id' => '#ConstraintViolation/message',
                        '@type' => 'rdf:Property',
                        'rdfs:label' => 'message',
                        'domain' => '#ConstraintViolation',
                        'range' => 'xmls:string',
                    ],
                    'hydra:title' => 'message',
                    'hydra:description' => 'The message associated with the violation',
                    'hydra:readable' => true,
                    'hydra:writable' => false,
                ],
            ],
        ];

        // Constraint violation list
        $classes[] = [
            '@id' => '#ConstraintViolationList',
            '@type' => 'hydra:Class',
            'subClassOf' => 'hydra:Error',
            'hydra:title' => 'A constraint violation list',
            'hydra:supportedProperty' => [
                [
                    '@type' => 'hydra:SupportedProperty',
                    'hydra:property' => [
                        '@id' => '#ConstraintViolationList/violations',
                        '@type' => 'rdf:Property',
                        'rdfs:label' => 'violations',
                        'domain' => '#ConstraintViolationList',
                        'range' => '#ConstraintViolation',
                    ],
                    'hydra:title' => 'violations',
                    'hydra:description' => 'The violations',
                    'hydra:readable' => true,
                    'hydra:writable' => false,
                ],
            ],
        ];

        return $classes;
    }
511693
protected function _morphTable($tableName, $definition, $foreignKeys, $dbAdapter)
    {
        $ignoreDropForeignKeys = array();
        /** @var \Phalcon\Db\Adapter $connection */
        $connection = $this->getDI()->get($dbAdapter);
        if ($dbAdapter === 'dbCassandra') {
            $schema = $connection->getDescriptor()['keyspace'];
        } elseif ($dbAdapter === 'dbPostgresql') {
            $schema = $connection->getDescriptor()['schema'];
        } else {
            $schema = $connection->getDescriptor()['dbname'];
        }

        $sql = array();
        $tableExists = $connection->tableExists($tableName, $schema);
        if (isset($definition['columns'])) {

            if (count($definition['columns']) == 0) {
                throw new Exception('Table must have at least one column');
            }

            $fields = array();
            foreach ($definition['columns'] as $tableColumn) {
                if (!is_object($tableColumn)) {
                    throw new Exception('Table must have at least one column');
                }
                $fields[$tableColumn->getName()] = $tableColumn;
            }

            if ($tableExists) {

                $localFields = array();
                $description = $connection->describeColumns($tableName, $schema);
                foreach ($description as $field) {
                    $localFields[$field->getName()] = $field;
                }

                foreach ($fields as $fieldName => $tableColumn) {
                    if ($dbAdapter === 'dbPostgresql') {
                        $schema = $connection->getDescriptor()['schema'];
                    }


                    if (!isset($localFields[$fieldName])) {
                        /**
                         * ADD COLUMN
                         */
                        $rawSql = $connection->getDialect()->addColumn($tableName, $tableColumn->getSchemaName(), $tableColumn);
                        $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                    } else {

                        /**
                         * ALTER TABLE
                         */
                        $changed = false;

                        if ($localFields[$fieldName]->getType() != $tableColumn->getType()) {
                            // If we are on MySQL DB, and the current column in DB is INT(1)
                            // and current annotation is "boolean", we don't notify change
                            // because when we save a boolean column in MySQL it's converted to INT(1)
                            // It prevents executing useless DB updates on each run
                            if ($dbAdapter !== 'dbMysql' || $localFields[$fieldName]->getType() !== \Phalcon\Db\Column::TYPE_INTEGER
                                || $localFields[$fieldName]->getSize() !== 1 || $tableColumn->getType() !== \Phalcon\Db\Column::TYPE_BOOLEAN
                            ) {
                                $changed = true;
                            }
                        }

                        if ($tableColumn->isNotNull() != $localFields[$fieldName]->isNotNull()) {
                            $changed = true;
                        }

                        if ($tableColumn->getSize() && $tableColumn->getSize() != $localFields[$fieldName]->getSize()) {
                            $changed = true;
                        }

                        if ($changed == true) {
                            $existingForeignKeys = [];

                            // We check if there is a foreign key constraint
                            if ($dbAdapter === 'dbMysql') {
                                $results = $connection->query("SELECT TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_SCHEMA,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = '" . $connection->getDescriptor()['dbname'] . "' AND REFERENCED_TABLE_NAME = '" . $tableName . "' AND REFERENCED_COLUMN_NAME = '" . $tableColumn->getName() . "'");
                                foreach ($results->fetchAll() as $r) {
                                    $rules = $connection->query('SELECT UPDATE_RULE, DELETE_RULE FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME="' . $r['CONSTRAINT_NAME'] . '" AND CONSTRAINT_SCHEMA ="' . $r['TABLE_SCHEMA'] . '"');
                                    $rules = $rules->fetch();
                                    $r['UPDATE_RULE'] = $rules['UPDATE_RULE'];
                                    $r['DELETE_RULE'] = $rules['DELETE_RULE'];

                                    /**
                                     * DROP FOREIGN KEY BECAUSE WE CHANGE THE CURRENT COLUMN
                                     */
                                    $rawSql = $connection->getDialect()->dropForeignKey($r['TABLE_NAME'], $r['TABLE_SCHEMA'], $r['CONSTRAINT_NAME']);
                                    $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                                    $existingForeignKeys[] = $r;
                                }
                            } elseif ($dbAdapter === 'dbPostgresql') {
                                $sqlconstraint = $this->getPGSQLConstraint($tableName, $tableColumn->getName());
                                $results = $connection->query($sqlconstraint);
                                foreach ($results->fetchAll() as $r) {

                                    $r['UPDATE_RULE'] = $r['on_update'];
                                    $r['DELETE_RULE'] = $r['on_delete'];
                                    $r['TABLE_NAME'] = $r['table_name'];
                                    $r['TABLE_SCHEMA'] = $r['constraint_schema'];
                                    $r['CONSTRAINT_NAME'] = $r['constraint_name'];
                                    $r['REFERENCED_TABLE_SCHEMA'] = $r['constraint_schema'];
                                    $r['REFERENCED_TABLE_NAME'] = $r['references_table'];
                                    $r['REFERENCED_COLUMN_NAME'] = $r['references_field'];
                                    $r['COLUMN_NAME'] = $r['column_name'];

                                    /**
                                     * DROP FOREIGN KEY BECAUSE WE CHANGE THE CURRENT COLUMN
                                     */
                                    $rawSql = $connection->getDialect()->dropForeignKey($r['TABLE_NAME'], $r['TABLE_SCHEMA'], $r['CONSTRAINT_NAME']);
                                    $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                                    $existingForeignKeys[] = $r;
                                }
                            }

                            /**
                             * ALTER TABLE
                             */
                            if ($dbAdapter === 'dbPostgresql') {
                                $rawSql = $connection->getDialect()->modifyColumn($tableName, $tableColumn->getSchemaName(), $tableColumn, $localFields[$fieldName]);
                            } else {
                                $rawSql = $connection->getDialect()->modifyColumn($tableName, $tableColumn->getSchemaName(), $tableColumn);
                            }
                            $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';

                            if ($existingForeignKeys) {
                                foreach ($existingForeignKeys as $r) {
                                    /**
                                     * ADD FOREIGN KEY AFTER DROP ONE (TO CHANGE IT)
                                     */
                                    $rawSql = $connection->getDialect()->addForeignKey(
                                        $r['TABLE_NAME'],
                                        $r['TABLE_SCHEMA'],
                                        new Reference(
                                            $r['CONSTRAINT_NAME'],
                                            array(
                                                "referencedSchema" => $r['REFERENCED_TABLE_SCHEMA'],
                                                "referencedTable" => $r['REFERENCED_TABLE_NAME'],
                                                "columns" => array($r['COLUMN_NAME']),
                                                "referencedColumns" => array($r['REFERENCED_COLUMN_NAME']),
                                                'onUpdate' => $r['UPDATE_RULE'],
                                                'onDelete' => $r['DELETE_RULE']
                                            )
                                        ));
                                    $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                                }
                            }
                        }
                    }
                }

                /**
                 * DROP COLUMN (and foreign key)
                 */
                foreach ($localFields as $fieldName => $localField) {
                    if (!isset($fields[$fieldName])) {
                        if ($dbAdapter === 'dbMysql') {
                            // We check if there is a foreign key constraint
                            $results = $connection->query("SELECT TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_SCHEMA,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = '" . $schema . "' AND TABLE_NAME = '" . $tableName . "' AND COLUMN_NAME = '" . $fieldName . "'");
                            foreach ($results->fetchAll() as $r) {
                                $ignoreDropForeignKeys[] = $r['CONSTRAINT_NAME'];
                                $rawSql = $connection->getDialect()->dropForeignKey($r['TABLE_NAME'], $r['TABLE_SCHEMA'], $r['CONSTRAINT_NAME']);
                                $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                            }
                        } elseif ($dbAdapter === 'dbPostgresql') {
                            $sqlconstraint = $this->getPGSQLConstraint($tableName, $fieldName);
                            $results = $connection->query($sqlconstraint);
                            foreach ($results->fetchAll() as $r) {
                                $ignoreDropForeignKeys[] = $r['CONSTRAINT_NAME'];
                                $rawSql = $connection->getDialect()->dropForeignKey($r['table_name'], $r['constraint_schema'], $r['constraint_name']);
                                $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                            }
                        }
                        $rawSql = $connection->getDialect()->dropColumn($tableName, $schema, $fieldName);
                        $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                    }
                }
            } else {
                /**
                 * CREATE TABLE IF NOT EXISTS
                 */
                $rawSql = $connection->getDialect()->createTable($tableName, $schema, $definition);
                if ($dbAdapter === 'dbPostgresql') {
                    $sqlInstructions = explode(';', $rawSql);
                    foreach ($sqlInstructions as $instruction) {
                        if ($instruction !== "" && strpos($instruction, '_pkey" ON') === false) {
                            $sql[] = '$this->' . $dbAdapter . '->query(\'' . $instruction . '\');';
                        }
                    }
                } else {
                    $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                }

            }
        }

        /**
         * DROP FOREIGN KEY
         */
        if ($tableExists === true && ($dbAdapter === 'dbMysql' || $dbAdapter === 'dbPostgresql')) {
            $actualReferences = $connection->describeReferences($tableName, $schema);
            /* @var $actualReference \Phalcon\Db\Reference */
            foreach ($actualReferences as $actualReference) {
                $foreignKeyExists = false;

                for ($i = count($foreignKeys) - 1; $i >= 0; --$i) {
                    if ($dbAdapter === 'dbMysql') {
                        $rules = $connection->query('SELECT UPDATE_RULE, DELETE_RULE FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME="' . $actualReference->getName() . '" AND CONSTRAINT_SCHEMA ="' . $actualReference->getReferencedSchema() . '"');
                        $rules = $rules->fetch();

                        if ($tableName === $foreignKeys[$i]['table']
                            && $actualReference->getReferencedTable() === $foreignKeys[$i]['referencedTable']
                            && count(array_diff($actualReference->getColumns(), $foreignKeys[$i]['fields'])) === 0
                            && count(array_diff($actualReference->getReferencedColumns(), $foreignKeys[$i]['referencedFields'])) === 0
                            // TODO : réactiver cette ligne si Phalcon prend en compte la méthode : && $actualReference->getOnUpdate() === $foreignKeys[$i]['action']
                            && $rules['UPDATE_RULE'] === $foreignKeys[$i]['action']
                            // TODO : réactiver cette ligne si Phalcon prend en compte la méthode : && $actualReference->getOnDelete() === $foreignKeys[$i]['action']) {
                            && $rules['DELETE_RULE'] === $foreignKeys[$i]['action']
                        ) {
                            $foreignKeyExists = true;
                            array_splice($foreignKeys, $i, 1);
                            break;
                        }
                    } else {
                        if ($tableName === $foreignKeys[$i]['table']
                            && $actualReference->getReferencedTable() === $foreignKeys[$i]['referencedTable']
                            && count(array_diff($actualReference->getColumns(), $foreignKeys[$i]['fields'])) === 0
                            && count(array_diff($actualReference->getReferencedColumns(), $foreignKeys[$i]['referencedFields'])) === 0
                        ) {
                            $foreignKeyExists = true;
                            array_splice($foreignKeys, $i, 1);
                            break;
                        }
                    }
                }

                if (!$foreignKeyExists && !in_array($actualReference->getName(), $ignoreDropForeignKeys)) {
                    $rawSql = $connection->getDialect()->dropForeignKey(
                        $tableName,
                        $actualReference->getReferencedSchema(),
                        $actualReference->getName()
                    );
                    $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                }
            }
        }

        /**
         * ADD FOREIGN KEY
         */
        if ($foreignKeys) {
            foreach ($foreignKeys as $foreignKey) {
                $rawSql = $connection->getDialect()->addForeignKey(
                    $tableName,
                    $connection->getDescriptor()['dbname'],
                    new Reference(
                        $foreignKey['name'],
                        array(
                            "referencedSchema" => $connection->getDescriptor()['dbname'],
                            "referencedTable" => $foreignKey['referencedTable'],
                            "columns" => $foreignKey['fields'],
                            "referencedColumns" => $foreignKey['referencedFields'],
                            'onUpdate' => $foreignKey['action'],
                            'onDelete' => $foreignKey['action']
                        )
                    ));
                $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
            }
        }

        /**
         * INDEXES
         */
        if (isset($definition['indexes'])) {
            if ($tableExists == true) {

                $indexes = array();
                foreach ($definition['indexes'] as $tableIndex) {
                    $indexes[$tableIndex->getName()] = $tableIndex;
                }

                if ($dbAdapter === 'dbPostgresql') {
                    $rawSql = $connection->getDialect()->modifyColumn($tableName, $tableColumn->getSchemaName(), $tableColumn, $localFields[$fieldName]);
                }

                $localIndexes = array();
                $actualIndexes = $connection->describeIndexes($tableName, $schema);
                foreach ($actualIndexes as $actualIndex) {
                    $deleted = true;

                    foreach ($definition['indexes'] as $tableIndex) {
                        // hack for encoging problem
                        $tableIndexName = $tableIndex->getName();
                        $actualIndexName = $actualIndex->getName();
                        if ($tableIndexName === $actualIndexName) {
                            $deleted = false;
                            $localIndexes[$actualIndex->getName()] = $actualIndex->getColumns();
                            break;
                        } elseif (substr($actualIndex->getName(), 0, 3) !== 'IDX' && ($dbAdapter !== 'dbCassandra') && ($dbAdapter !== 'dbPostgresql')) {
                            $deleted = false;
                            break;
                        }
                    }


                    if ($deleted) {
                        $rawSql = $connection->getDialect()->dropIndex($tableName, $tableColumn->getSchemaName(), $actualIndexName);
                        $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                    }
                }

                foreach ($definition['indexes'] as $tableIndex) {
                    $tableIndexName = $tableIndex->getName();
                    if (!isset($localIndexes[$tableIndexName])) {
                        if ($tableIndexName == 'PRIMARY') {
                            $rawSql = $connection->getDialect()->addPrimaryKey($tableName, $tableColumn->getSchemaName(), $tableIndex);
                            $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                        } else {
                            $rawSql = $connection->getDialect()->addIndex($tableName, $tableColumn->getSchemaName(), $tableIndex);
                            $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                        }
                    } else {
                        $changed = false;
                        if (count($tableIndex->getColumns()) != count($localIndexes[$tableIndexName])) {
                            $changed = true;
                        } else {
                            foreach ($tableIndex->getColumns() as $columnName) {
                                if (!in_array($columnName, $localIndexes[$tableIndexName])) {
                                    $changed = true;
                                    break;
                                }
                            }
                        }
                        if ($changed == true) {
                            if ($tableIndex->getName() == 'PRIMARY') {
                                $rawSql = $connection->getDialect()->dropPrimaryKey($tableName, $tableColumn->getSchemaName());
                                $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';

                                $rawSql = $connection->getDialect()->addPrimaryKey($tableName, $tableColumn->getSchemaName(), $tableIndex);
                                $sql[] = '$this->' . $dbAdapter . '->query(\'' . $rawSql . '\');';
                            }
                        }
                    }
                }
            }

        }

        return $sql;

    }
862028
private function convertClassAnnotationsToEntityClassMetadata(
        array $classAnnotations,
        ReflectionClass $reflectionClass,
        Mapping\ClassMetadata $parent
    ) {
        /** @var Annotation\Entity $entityAnnot */
        $entityAnnot   = $classAnnotations[Annotation\Entity::class];
        $classMetadata = new Mapping\ClassMetadata($reflectionClass->getName(), $parent);

        if ($entityAnnot->repositoryClass !== null) {
            $classMetadata->setCustomRepositoryClassName($entityAnnot->repositoryClass);
        }

        if ($entityAnnot->readOnly) {
            $classMetadata->asReadOnly();
        }

        // Evaluate @Table annotation
        if (isset($classAnnotations[Annotation\Table::class])) {
            /** @var Annotation\Table $tableAnnot */
            $tableAnnot = $classAnnotations[Annotation\Table::class];
            $table      = $this->convertTableAnnotationToTableMetadata($tableAnnot);

            $classMetadata->setTable($table);
        }

        // Evaluate @ChangeTrackingPolicy annotation
        if (isset($classAnnotations[Annotation\ChangeTrackingPolicy::class])) {
            /** @var Annotation\ChangeTrackingPolicy $changeTrackingAnnot */
            $changeTrackingAnnot = $classAnnotations[Annotation\ChangeTrackingPolicy::class];

            $classMetadata->setChangeTrackingPolicy(
                constant(sprintf('%s::%s', Mapping\ChangeTrackingPolicy::class, $changeTrackingAnnot->value))
            );
        }

        // Evaluate @EntityListeners annotation
        if (isset($classAnnotations[Annotation\EntityListeners::class])) {
            /** @var Annotation\EntityListeners $entityListenersAnnot */
            $entityListenersAnnot = $classAnnotations[Annotation\EntityListeners::class];

            foreach ($entityListenersAnnot->value as $listenerClassName) {
                if (! class_exists($listenerClassName)) {
                    throw Mapping\MappingException::entityListenerClassNotFound(
                        $listenerClassName,
                        $reflectionClass->getName()
                    );
                }

                $listenerClass = new ReflectionClass($listenerClassName);

                /** @var ReflectionMethod $method */
                foreach ($listenerClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
                    foreach ($this->getMethodCallbacks($method) as $callback) {
                        $classMetadata->addEntityListener($callback, $listenerClassName, $method->getName());
                    }
                }
            }
        }

        // Evaluate @HasLifecycleCallbacks annotation
        if (isset($classAnnotations[Annotation\HasLifecycleCallbacks::class])) {
            /** @var ReflectionMethod $method */
            foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
                foreach ($this->getMethodCallbacks($method) as $callback) {
                    $classMetadata->addLifecycleCallback($method->getName(), $callback);
                }
            }
        }

        // Evaluate @InheritanceType annotation
        if (isset($classAnnotations[Annotation\InheritanceType::class])) {
            /** @var Annotation\InheritanceType $inheritanceTypeAnnot */
            $inheritanceTypeAnnot = $classAnnotations[Annotation\InheritanceType::class];

            $classMetadata->setInheritanceType(
                constant(sprintf('%s::%s', Mapping\InheritanceType::class, $inheritanceTypeAnnot->value))
            );

            if ($classMetadata->inheritanceType !== Mapping\InheritanceType::NONE) {
                $discriminatorColumn = new Mapping\DiscriminatorColumnMetadata();

                // Evaluate @DiscriminatorColumn annotation
                if (isset($classAnnotations[Annotation\DiscriminatorColumn::class])) {
                    /** @var Annotation\DiscriminatorColumn $discriminatorColumnAnnot */
                    $discriminatorColumnAnnot = $classAnnotations[Annotation\DiscriminatorColumn::class];

                    $discriminatorColumn->setColumnName($discriminatorColumnAnnot->name);

                    if (! empty($discriminatorColumnAnnot->columnDefinition)) {
                        $discriminatorColumn->setColumnDefinition($discriminatorColumnAnnot->columnDefinition);
                    }

                    if (! empty($discriminatorColumnAnnot->type)) {
                        $discriminatorColumn->setType(Type::getType($discriminatorColumnAnnot->type));
                    }

                    if (! empty($discriminatorColumnAnnot->length)) {
                        $discriminatorColumn->setLength($discriminatorColumnAnnot->length);
                    }
                }

                if (empty($discriminatorColumn->getColumnName())) {
                    throw Mapping\MappingException::nameIsMandatoryForDiscriminatorColumns($reflectionClass->getName());
                }

                $classMetadata->setDiscriminatorColumn($discriminatorColumn);

                // Evaluate @DiscriminatorMap annotation
                if (isset($classAnnotations[Annotation\DiscriminatorMap::class])) {
                    /** @var Annotation\DiscriminatorMap $discriminatorMapAnnotation */
                    $discriminatorMapAnnotation = $classAnnotations[Annotation\DiscriminatorMap::class];
                    $discriminatorMap           = $discriminatorMapAnnotation->value;

                    $classMetadata->setDiscriminatorMap($discriminatorMap);
                }
            }
        }

        return $classMetadata;
    }
1106218
public function loadClassMetadata(LoadClassMetadataEventArgs $args)
    {
        /** @var ClassMetadata $metadata */
        $metadata = $args->getClassMetadata();
        // entity class name
        $className = $metadata->getName();

        // we load repository once per class
        if (in_array($className, $this->classesLoaded)) {
            return;
        }
        $this->classesLoaded[] = $className;

        // a custom repository class must be set and it must be in the repository pool
        if ($metadata->customRepositoryClassName and $this
                ->repositoryPool
                ->has($metadata->customRepositoryClassName)
        ) {
            // load repository from pool (hydrated by the repository compiler pass)
            $repository = $this
                ->repositoryPool
                ->get($metadata->customRepositoryClassName);

            // create entity doctrine repository
            $entityManager = $args->getEntityManager();
            $doctrineRepository = new EntityRepository($entityManager, $entityManager->getClassMetadata($className));

            // hydrate repository with doctrine data
            $repository
                ->setEntityClassName($className)
                ->setObjectManager($entityManager)
                ->setRepository($doctrineRepository)
            ;
        }
    }
187987
private function buildCustomEntitiesMap(array $entities)
    {
        $map = [];

        foreach ($entities as $entity) {
            $entityClass = ClassUtils::getClass($entity);
            $objectHash = spl_object_hash($entity);

            foreach ($this->getCustomObjectMeta($entityClass) as $targetProperty => $params) {
                $initPropertyValue = $this->getPropertyValue($entity, $params['initPropertyValuePath']);

                if (empty($initPropertyValue)) {
                    continue;
                }
                if (!isset($map[$entityClass])) {
                    $map[$entityClass] = [];
                }
                if (!isset($map[$entityClass][$objectHash])) {
                    $map[$entityClass][$objectHash] = [];
                }

                $map[$entityClass][$objectHash][$targetProperty] = [
                    'class' => !empty($params['class'])
                        ? $params['class']
                        : $this->getPropertyValue($entity, $params['classPropertyPath'])
                    ,
                    'initProperty' => !empty($params['initProperty'])
                        ? $params['initProperty']
                        : $this->extendedMetadataFactory->getIdentifier($entityClass)
                    ,
                    'initPropertyValue' => $initPropertyValue,
                ];
            }
        }

        return $map;
    }
1300901
public static function updateMorphMap($classNames = null)
    {
        if (is_null($classNames)) {
            $classNames = [
                static::classname(Role::class),
                static::classname(Ability::class),
            ];
        }

        Relation::morphMap($classNames);
    }
1326943
static public function findClass($name, $type=null, $namespaces=null)
	{
	    $name = StringHelper::toClassName($name);
	    if (!$namespaces && strpos($name, '\\') !== false && class_exists($name)) {
	        return $name;
	    }
	    
	    $class_names = [];
	    if (!empty($type)) {
	        $type = StringHelper::toCamelCase($type);
	        if ($pos = strpos($name, '\\')) {
	            $class_names[] = $type . '\\' . $name . $type;
	            $class_names[] = $type . '\\' . $name;
	            
	            $name = substr($name, 0, $pos) . '\\' . $type . '\\' . substr($name, $pos+1);
	        } else {
	            $name = $type . '\\' . $name;
	        }
	        $class_names[] = $name;
	        $class_names[] = $name . $type;
		} else {
		    $class_names[] = $name;
		}
		
		if ($namespaces) {
            $namespaces = (array)static::formatNamespace($namespaces);
		} else {
            //$namespaces = array_unique(array_merge((array)$namespaces, static::getNamespaces()));
		    $namespaces = static::getNamespaces();
		}
		
		foreach ($namespaces as $nss) {
		    foreach ($class_names as $class) { 
		        if (class_exists($nss . $class)) {
		            return $nss . $class;
		        }
		    }
		}
		
		return null;
	}