Match Eagerly loaded relation to result.

@param array  $results
@param string $relation

@return array
184656
public function match(array $results, $relation)
    {
        $entities = $this->getEager();

        // TODO; optimize this operation
        $dictionary = $this->buildDictionary($entities);

        $keyName = $this->parentMap->getKeyName();

        $cache = $this->parentMapper->getEntityCache();

        $host = $this;

        // Once we have an array dictionary of child objects we can easily match the
        // children back to their parent using the dictionary and the keys on the
        // the parent models. Then we will return the hydrated models back out.
        return array_map(function ($result) use ($dictionary, $keyName, $cache, $relation, $host) {
            $key = $result[$keyName];

            if (isset($dictionary[$key])) {
                $collection = $host->relatedMap->newCollection($dictionary[$key]);

                $result[$relation] = $collection;

                // TODO Refactor this
                $cache->cacheLoadedRelationResult($key, $relation, $collection, $this);
            } else {
                $result[$relation] = $host->relatedMap->newCollection();
            }

            return $result;
        }, $results);
    }
894762
protected function nestedRelations( $relation )
	{
		$nested = [];

		// We are basically looking for any relationships that are nested deeper than
		// the given top-level relationship. We will just check for any relations
		// that start with the given top relations and adds them to our arrays.
		foreach ( $this->eagerLoad as $name => $constraints )
		{
			if ( $this->isNested( $name, $relation ) )
			{
				$nested[substr( $name, strlen( $relation . '.' ) )] = $constraints;
			}
		}

		return $nested;
	}
804301
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
    {
        $localKey = $this->localKey;
        $range    = [];

        foreach ($resultSet as $result) {
            // 获取关联外键列表
            if (isset($result->$localKey)) {
                $range[] = $result->$localKey;
            }
        }

        if (!empty($range)) {
            $where = [
                [$this->foreignKey, 'in', $range],
            ];
            $data = $this->eagerlyOneToMany($where, $relation, $subRelation, $closure);

            // 关联属性名
            $attr = Db::parseName($relation);

            // 关联数据封装
            foreach ($resultSet as $result) {
                $pk = $result->$localKey;
                if (!isset($data[$pk])) {
                    $data[$pk] = [];
                }

                foreach ($data[$pk] as &$relationModel) {
                    $relationModel->setParent(clone $result);
                }

                $result->setRelation($attr, $this->resultSetBuild($data[$pk]));
            }
        }
    }
660223
protected function parseManyRelationship(string $relation): bool
    {
        if (!$value = $this->parseForCommonValues($relation)) {
            return true;
        }

        if (is_array($value) || (!$value instanceof CollectionProxy && $value instanceof Collection)) {
            $this->needSync[] = $relation;
        }

        // If the relation is a proxy, we test is the relation
        // has been lazy loaded, otherwise we'll just treat
        // the subset of newly added items.
        if ($value instanceof CollectionProxy && $value->isProxyInitialized()) {
            $this->needSync[] = $relation;
            //$value = $value->getUnderlyingCollection();
        }

        if ($value instanceof CollectionProxy && !$value->isProxyInitialized()) {
            $value = $value->getAddedItems();
        }

        // At this point $value should be either an array or an instance
        // of a collection class.
        if (!is_array($value) && !$value instanceof Collection) {
            throw new MappingException("'$relation' attribute should be array() or Collection");
        }

        $this->relationships[$relation] = $this->createSubAggregates($value, $relation);

        return true;
    }
1107086
protected function parseWithRelations(array $relations)
    {
        $results = [];

        foreach ($relations as $name => $constraints) {
            // If the "relation" value is actually a numeric key, we can assume that no
            // constraints have been specified for the eager load and we'll just put
            // an empty Closure with the loader so that we can treat all the same.
            if (is_numeric($name)) {
                $name = $constraints;

                list($name, $constraints) = Str::contains($name, ':')
                    ? $this->createSelectWithConstraint($name)
                    : [$name, function () {
                        //
                    }];
            }

            // We need to separate out any nested includes. Which allows the developers
            // to load deep relationships using "dots" without stating each level of
            // the relationship with its own key in the array of eager load names.
            $results = $this->addNestedWiths($name, $results);

            $results[$name] = $constraints;
        }

        return $results;
    }
1372426
public function match(array $models, Collection $results, $relation)
    {
        // We will need the parent node placeholder so that we use it to extract related results.
        $parent = $this->query->getQuery()->modelAsNode($this->parent->getTable());

        /**
         * Looping into all the parents to match back onto their children using
         * the primary key to map them onto the correct instances, every single
         * result will be having both instances at each Collection item, held by their
         * node placeholder.
         */
        foreach ($models as $model)
        {
            $matched = $results->filter(function($result) use($parent, $model)
            {
                if ($result[$parent] instanceof Model)
                {
                    // In the case of fetching nested relations, we will get an array
                    // with the first key being the model we need, and the other being
                    // the related model so we'll just take the first model out of the array.
                    if (is_array($model)) $model = reset($model);

                    return $model->getKey() == $result[$parent]->getKey();
                }
            });

            // Now that we have the matched parents we know where to add the relations.
            // Sometimes we have more than a match so we gotta catch them all!
            foreach ($matched as $match)
            {
                // In the case of fetching nested relations, we will get an array
                // with the first key being the model we need, and the other being
                // the related model so we'll just take the first model out of the array.
                if (is_array($model)) $model = reset($model);

                $model->setRelation($relation, $match[$relation]);
            }
        }

        return $models;
    }
93291
public function with($relations)
    {
        if (is_array($relations)) {
            if (Arr::isAssoc($relations)) {
                $relations = array_keys($relations);
            }

            $this->eagerLoads = array_merge($this->eagerLoads, $relations);
        }

        if (is_string($relations)) {
            if (Str::contains($relations, '.')) {
                $relations = explode('.', $relations)[0];
            }

            if (Str::contains($relations, ':')) {
                $relations = explode(':', $relations)[0];
            }

            if (in_array($relations, $this->eagerLoads)) {
                return $this;
            }

            $this->eagerLoads[] = $relations;
        }

        return $this->__call('with', (array) $relations);
    }
579967
protected function parseRelations(array $relations)
	{
		$results = array();

		foreach ($relations as $name => $constraints)
		{
			// If the "relation" value is actually a numeric key, we can assume that no
			// constraints have been specified for the eager load and we'll just put
			// an empty Closure with the loader so that we can treat all the same.
			if (is_numeric($name))
			{
				$f = function() {};

				list($name, $constraints) = array($constraints, $f);
			}

			// We need to separate out any nested includes. Which allows the developers
			// to load deep relationships using "dots" without stating each level of
			// the relationship with its own key in the array of eager load names.
			$results = $this->parseNested($name, $results);

			$results[$name] = $constraints;
		}

		return $results;
	}
368064
protected function processResult(array $results)
    {
        foreach ($results as $key => $entity) {

            if (!empty($entity['data'])) {

                $entity['data'] = $this->decorator->denormalizeValue($entity['data']);
                $results[$key] = $entity;
            }
        }

        return $results;
    }
1214419
public function getAll($relations = true)
    {
        $results = array_merge($this->data, [
            'active' => $this->getActiveFieldName(),
            'created' => $this->getCreatedFieldName(),
            'filterable' => $this->getFilterableFieldNames(),
            'fields' => $this->getFields(),
            'files' => $this->getFileFieldNames(),
            'json' => $this->getJsonFieldNames(),
            'ipaddress' => $this->getIPAddressFieldName(),
            'listable' => $this->getListableFieldNames(),
            'detailable' => $this->getDetailableFieldNames(),
            'primary' => $this->getPrimaryFieldName(),
            'required' => $this->getRequiredFieldNames(),
            'searchable' => $this->getSearchableFieldNames(),
            'slugable' => $this->getSlugableFieldNames(),
            'sortable' => $this->getSortableFieldNames(),
            'uuids' => $this->getUuidFieldNames(),
            'unique' => $this->getUniqueFieldNames(),
            'updated' => $this->getUpdatedFieldName()
        ]);

        if ($relations) {
            $results['relations'] = $this->getRelations();
        }

        return $results;
    }
375233
protected function getLinkedIds($relation)
    {
        $models = (array)$this->owner->{$relation};
        $ids = ArrayHelper::getColumn($models, 'primaryKey', false);
        $ids = array_filter($ids);

        return $ids;
    }
407756
protected function buildEmbeddedRelationships(array $results) : array
    {
        $entityMap = $this->entityMap;
        $instance = $this->mapper->newInstance();
        $embeddeds = $entityMap->getEmbeddedRelationships();

        foreach ($embeddeds as $embedded) {
            $results = $entityMap->$embedded($instance)->match($results, $embedded);
        }

        return $results;
    }
106795
public function initRelation(array $models, $relation)
    {
        foreach ($models as $model)
        {
            // In the case of fetching nested relations, we will get an array
            // with the first key being the model we need, and the other being
            // the related model so we'll just take the first model out of the array.
            if (is_array($model)) $model = reset($model);

            $model->setRelation($relation, $this->related->newCollection());
        }

        return $models;
    }
645976
protected function getRelations($relations)
    {
        $existingNames = [];
        $finalRelations = [];
        foreach ($relations as $relation) {
            $newRelation = ForeignRelationship::fromString($relation);
            if (is_null($newRelation)) {
                continue;
            }

            if (!empty($newRelation->name) && in_array($newRelation->name, $existingNames)) {
                continue;
            }

            $finalRelations[] = $newRelation;
            $existingNames[] = $newRelation->name;
        }

        return $finalRelations;
    }
310195
private function getDependencies(array $results)
    {
        $dependencies = [];
        $doubles = [];

        foreach ($results as $name => $result) {
            $type = $this->recursive ? Dependency::PROHIBITS : Dependency::DEPENDS;
            $dependency = Dependency::create($name, $type, $result);
            $unique = (string) $dependency->getLink();
            if (isset($doubles[$unique])) {
                continue;
            }
            $doubles[$unique] = true;
            $dependencies[] = $dependency;
        }

        return $dependencies;
    }
326661
public function match(array $models, Collection $results, $relation)
    {
        return $this->matchOne($models, $results, $relation);
    }
231195
public function build(array $results, array $eagerLoads)
    {
        // First, we'll cache the raw result set
        $this->cacheResults($results);

        // Parse embedded relations and build corresponding entities using the default
        // mapper.
        $results = $this->buildEmbeddedRelationships($results);

        // Launch the queries related to eager loads, and match the
        // current result set to these loaded relationships.
        $results = $this->queryEagerLoadedRelationships($results, $eagerLoads);

        return $this->buildResultSet($results);
    }