Get array of morphable classes for a morphTo or morphToMany relation.

@param string $relatedEntity
@param string $morphName
@param array $metadata
@param boolean $many
@return void
501454
protected function getMorphableClasses($relatedEntity, $morphName, array $metadata, $many=false)
    {
        $morphableClasses = [];

        foreach ($metadata as $entityMetadata) {
            foreach ($entityMetadata['relations'] as $relationMetadata) {
                // check relation type
                if (! ((! $many && $relationMetadata['type'] == 'morphOne')
                    || (! $many && $relationMetadata['type'] == 'morphMany')
                    || ($many && $relationMetadata['type'] == 'morphToMany' && $relationMetadata['options']['inverse']))) {
                    continue;
                }

                // check foreign entity and morph name
                if ($relationMetadata['relatedEntity'] == $relatedEntity
                    && $relationMetadata['options']['morphName'] == $morphName) {
                    $morphableClasses[$entityMetadata['morphClass']] = $entityMetadata['class'];
                }
            }
        }

        return $morphableClasses;
    }
1352273
public function morphTo($name = null, $type = null, $id = null)
    {
        $args = func_get_args();
        $args['type'] = 'morphTo';
        return $this->setRelationship(json_encode($args));
    }
623616
private function getFieldFilter(ClassMetadata $metadata, array $fields)
    {
        /* @var \Doctrine\ORM\Mapping\ClassMetadata $metadata */
        $filters = array();
        foreach ($fields as $field) {
            $fieldName = $this->getFieldName($metadata, $field);
            try {
                $filters[] = $metadata->getFieldMapping($fieldName);
            } catch (\Exception $ex) {
                $mapping = $metadata->getAssociationMapping($fieldName);
                $associationMatadata = $this->entityManager->getClassMetadata($mapping['targetEntity']);
                $associationFields = $associationMatadata->getFieldNames();
                $associationIdentifier = $associationMatadata->getIdentifierFieldNames();
                $associationFields = array_values(array_filter(
                    $associationFields,
                    function ($value) use ($associationIdentifier) {
                        return !in_array($value, $associationIdentifier);
                    }
                ));
                if ($associationFields) {
                    $filters[] = array_merge(array(
                        'join' => true,
                        'join_field' => $fieldName,
                        'join_alias' => $this->getAlias(),
                    ), $associationMatadata->getFieldMapping($associationFields[0]));
                }
            }
        }

        return $filters;
    }
1069887
@Override
    protected List<Object> recursivelyPopulateEntities(EntityMetadata m, Client client)
    {
        List result = populateEntities(m, client);
        return setRelationEntities(result, client, m);
    }
217092
protected function doSetSkillId(Lineage $model, $relatedId) {
		if ($model->getSkillId() !== $relatedId) {
			$model->setSkillId($relatedId);

			return true;
		}

		return false;
	}
671426
protected function generateMorphToColumns($name, Annotation $annotation, EntityDefinition &$entityMetadata)
    {
        $morphName = (! empty($annotation->morphName))
            ? $annotation->morphName
            : $name;

        $morphId = (! empty($annotation->morphId))
            ? $annotation->morphId
            : $morphName.'_id';

        $morphType = (! empty($annotation->morphType))
            ? $annotation->morphType
            : $morphName.'_type';

        $entityMetadata['table']['columns'][] = $this->getModifiedPrimaryKeyColumn($entityMetadata['table'], [
            'name' => $morphId,
            'primary' => false,
            'options' => [
                'autoIncrement' => false
            ]
        ]);

        $entityMetadata['table']['columns'][] = new ColumnDefinition([
            'name' => $morphType,
            'type' => 'string',
            'nullable' => false,
            'default' => false,
            'primary' => false,
            'unique' => false,
            'index' => false,
            'options' => []
        ]);
    }
1221308
protected function fromArrayRelationEntity($v, $p, $pn, $getter, $setter,
                                                $association, $policy,
                                                Reader $ar,
                                                PolicyResolver $pr,
                                                EntityManagerInterface $em,
                                                \ReflectionClass $refClass,
                                                $idField, $class, $subPolicy) {
        $jc = $ar->getPropertyAnnotation($p, 'Doctrine\ORM\Mapping\JoinColumn'); // find target id field name
        if($jc) { $idField = $jc->referencedColumnName; }
        $idGetter = 'get'.ucfirst($idField);  
                        
        $subEntity = null;
        
         // non-existent
        if(empty($v[$idField])) {
            if($policy instanceof Policy\Interfaces\DenyNewFrom) { return; }
            $subEntity = new $class();
            $subEntity->fromArray($v, $em, $subPolicy, $ar, $pr);
            $this->$setter($subEntity);
            
        // existent
        } else {
            $current = $this->$getter();
            
            // existent internal
            if($current && ($current->$idGetter() === $v[$idField])) { 
                $subEntity = $current;
                
            // RETRIEVING existent external
            } else if(!($policy instanceof Policy\Interfaces\DenyUpdateFrom) || $policy->allowExternal) { 
                $subEntity = $em->getReference($class, $v[$idField]);
            }
            
            // UPDATING internal or external
            if($subEntity) {
                if(!($policy instanceof Policy\Interfaces\DenyUpdateFrom) || $policy->allowExistent) {
                    $subEntity->fromArray($v, $em, $subPolicy, $ar, $pr);
                }
                $this->$setter($subEntity);
            }
            
        }
    }
1343834
private function convertRelations($className, array $model, ClassMetadataInfo $metadata)
    {
        if (empty($model['relations'])) {
            return;
        }

        foreach ($model['relations'] as $name => $relation) {
            if ( ! isset($relation['alias'])) {
                $relation['alias'] = $name;
            }
            if ( ! isset($relation['class'])) {
                $relation['class'] = $name;
            }
            if ( ! isset($relation['local'])) {
                $relation['local'] = Inflector::tableize($relation['class']);
            }
            if ( ! isset($relation['foreign'])) {
                $relation['foreign'] = 'id';
            }
            if ( ! isset($relation['foreignAlias'])) {
                $relation['foreignAlias'] = $className;
            }

            if (isset($relation['refClass'])) {
                $type = 'many';
                $foreignType = 'many';
                $joinColumns = array();
            } else {
                $type = isset($relation['type']) ? $relation['type'] : 'one';
                $foreignType = isset($relation['foreignType']) ? $relation['foreignType'] : 'many';
                $joinColumns = array(
                    array(
                        'name' => $relation['local'],
                        'referencedColumnName' => $relation['foreign'],
                        'onDelete' => isset($relation['onDelete']) ? $relation['onDelete'] : null,
                    )
                );
            }

            if ($type == 'one' && $foreignType == 'one') {
                $method = 'mapOneToOne';
            } elseif ($type == 'many' && $foreignType == 'many') {
                $method = 'mapManyToMany';
            } else {
                $method = 'mapOneToMany';
            }

            $associationMapping = array();
            $associationMapping['fieldName'] = $relation['alias'];
            $associationMapping['targetEntity'] = $relation['class'];
            $associationMapping['mappedBy'] = $relation['foreignAlias'];
            $associationMapping['joinColumns'] = $joinColumns;

            $metadata->$method($associationMapping);
        }
    }
1228934
private function resolveAssociations(Entity $config, ClassMetadata $metadata)
    {
        $associations = [];
        foreach ($metadata->getAssociationMappings() as $associationMapping) {
            $fieldName = $associationMapping['fieldName'];
            $fieldClass = array_filter($config->listFields(), function (ListField $field) use ($fieldName) {
                if (!isset($field->options()['field'])) {
                    return;
                }

                return $fieldName === explode('.', $field->options()['field'])[0];
            });

            if (count($fieldClass) > 0) {
                $associations[] = $fieldName;
            }
        }

        return $associations;
    }
711479
public function morphMany(Model $relatedModel, $morphName)
    {
        if ($relatedModel->isIgnored()) {
            return;
        }

        $this->relations->add(
            new Relations\MorphMany($this, $relatedModel, $morphName)
        );
    }
1057046
public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
    {
        // To escape the error:
        // Strict standards: Declaration of Sgpatil\Orientdb\Eloquent\Model::morphMany() should be
        //          compatible with Illuminate\Database\Eloquent\Model::morphMany()
        // We'll just map them in with the variables we want.
        $relationType = $name;
        $key          = $type;
        $relation     = $id;

        // If no relation name was given, we will use this debug backtrace to extract
        // the calling method's name and use that as the relationship name as most
        // of the time this will be what we desire to use for the relationships.
        if (is_null($relation))
        {
            list(, $caller) = debug_backtrace(false);

            $relation = $caller['function'];
        }

        // If no $key was provided we will consider it the key name of this model.
        $key = $key ?: $this->getKeyName();

        // If no relationship type was provided, we can use the previously traced back
        // $relation being the function name that called this method and using it in its
        // all uppercase form.
        if (is_null($relationType))
        {
            $relationType = mb_strtoupper($relation);
        }

        $instance = new $related;

        // Now we're ready to create a new query builder for the related model and
        // the relationship instances for the relation. The relations will set
        // appropriate query constraint and entirely manages the hydrations.
        $query = $instance->newQuery();

        return new MorphMany($query, $this, $relationType, $key, $relation);
    }
1235588
public function getVariation(string $variation): ManyToManyRelation
    {
        if (isset($this->nested[$variation])) {
            return $this->nested[$variation];
        }

        if (!isset($this->schema[Record::MORPHED_ALIASES][$variation])) {
            throw new RelationException("Undefined morphed variation '{$variation}'");
        }

        $class = $this->schema[Record::MORPHED_ALIASES][$variation];

        $relation = new ManyToManyRelation(
            $class,
            $this->makeSchema($class),
            $this->orm,
            $this->orm->define($class, ORMInterface::R_ROLE_NAME)
        );

        return $this->nested[$variation] = $relation->withContext($this->parent, false);
    }
245777
public function call_related(\Asgard\Entity\Entity $entity, $relation) {
		return $this->getDataMapper()->related($entity, $relation);
	}
1117458
void buildIntermediateManyToManyManyToMany(Relation middleToLeft, Entity middleEntity, Relation middleToRight) {
        // MANY TO MANY
        // Note: if the manyToManyConfig is null, by convention, we create the m2m relation

        Namer toNamer = relationUtil.getManyToManyNamer(middleToLeft.getTo(), middleToRight.getFromAttribute().getColumnConfig(), middleToRight.getTo());
        Namer fromNamer = relationUtil.getManyToManyNamer(middleToRight.getTo(), middleToLeft.getFromAttribute().getColumnConfig(), middleToLeft.getTo());

        ManyToMany m2m = new ManyToMany(fromNamer, toNamer, middleEntity, middleToLeft, middleToRight);
        ManyToManyConfig m2mConfig = middleToRight.getFromAttribute().getColumnConfig().getManyToManyConfig();
        m2m.setCascadeGetter(m2mConfig);
        m2m.setFetchTypeGetter(m2mConfig);
        m2m.setOrderByGetter(m2mConfig);

        setLabelPlural(m2mConfig, m2m);
        initDisplayOrderAsString(m2mConfig, m2m);
        configureActions(m2m, cfg().getDefaultManyToManyConfig(), m2mConfig);
        middleToLeft.getToEntity().addRelation(m2m);

        if (shouldCreateInverse(m2m)) {
            // MANY TO MANY inverse
            ManyToMany inverseM2m = (ManyToMany) m2m.createInverse(); // TODO: fix cast ?
            ManyToManyConfig inverseM2mConfig = middleToLeft.getFromAttribute().getColumnConfig().getManyToManyConfig();
            inverseM2m.setCascadeGetter(inverseM2mConfig);
            inverseM2m.setFetchTypeGetter(inverseM2mConfig);
            inverseM2m.setOrderByGetter(inverseM2mConfig);
            setLabelPlural(inverseM2mConfig, inverseM2m);
            initDisplayOrderAsString(inverseM2mConfig, inverseM2m);
            configureActions(inverseM2m, cfg().getDefaultInverseManyToManyConfig(), inverseM2mConfig);
            middleToRight.getToEntity().addRelation(inverseM2m);
        }
    }
660232
protected function getFieldsFromMetadata(ClassMetadataInfo $metadata)
    {
        $fields = (array) $metadata->fieldNames;

        // Remove the primary key field if it's not managed manually
        if (!$metadata->isIdentifierNatural()) {
            $fields = array_diff($fields, $metadata->identifier);
        }

        foreach ($metadata->associationMappings as $fieldName => $relation) {
            if ($relation['type'] !== ClassMetadataInfo::ONE_TO_MANY) {
                $fields[] = $fieldName;
            }
        }

        return $fields;
    }
1155723
@Override
    protected List recursivelyPopulateEntities(EntityMetadata m, Client client)
    {
        List<EnhanceEntity> ls = populateEntities(m, client);
        return setRelationEntities(ls, client, m);
    }
962435
protected function generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata)
    {
        $lines = array();

        foreach ($metadata->associationMappings as $associationMapping) {
            if ($this->hasProperty($associationMapping['fieldName'], $metadata)) {
                continue;
            }

            $lines[] = $this->generateAssociationMappingPropertyDocBlock($associationMapping, $metadata);
            $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $associationMapping['fieldName']
                     . ($associationMapping['type'] == 'manyToMany' ? ' = array()' : null) . ";\n";
        }

        return implode("\n", $lines);
    }