Get the keys from relation in order to join the table.

@param  \Illuminate\Database\Eloquent\Relations\Relation $relation
@return array

@throws \LogicException
8284
protected function getJoinKeys(Relation $relation)
    {
        if ($relation instanceof HasOne || $relation instanceof MorphOne) {
            return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedParentKeyName()];
        }

        if ($relation instanceof BelongsTo && !$relation instanceof MorphTo) {
            return [$relation->getQualifiedForeignKey(), $relation->getQualifiedOwnerKeyName()];
        }

        $class = get_class($relation);

        throw new LogicException(
            "Only HasOne, MorphOne and BelongsTo mappings can be queried. {$class} given."
        );
    }
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;
    }
1350877
protected function getForeignKeyAttributesFromNonLoadedRelation(string $relation): array
    {
        $keys = $this->entityMap->getLocalKeys($relation);

        // We'll treat single and composite keys (polymorphic) the same way.
        if (!is_array($keys)) {
            $keys = [$keys];
        }

        $foreignKey = [];

        foreach ($keys as $key) {
            $foreignKey[$key] = $this->getEntityAttribute($key);
        }

        return $foreignKey;
    }
522531
public function getLink($relation)
    {
        $links = $this->getAllLinks();
        foreach ($links as $link) {
            if ($link->getRelation() === $relation) {
                return $link;
            }
        }

        return null;
    }
541504
private function getRelations(Repository $repository, array $relations = [])
    {
        // if we have relation array passed, ignore request input
        if (count($relations) === 0) {
            $relations = Input::get('with');

            if (!is_array($relations)) {
                $relations = $this->inputService->decode('with');
            }
        }

        $result = [];
        $repo_relations = $repository->relations();
        foreach ($relations as $key => $value) {
            if (in_array($key, $repo_relations)) {
                $result[] = $key;
            } elseif (in_array($value, $repo_relations)) {
                $result[] = $value;
            }
        }

        return $result;
    }
789311
public function getRelation($relation)
    {
        $query = Relation::noConstraints(function() use ($relation)
        {
            return $this->getModel()->$relation();
        });

        $nested = $this->nestedRelations($relation);

        if (count($nested) > 0) {
            $query->getQuery()->with($nested);
        }

        return $query;
    }
1042681
public function relation($relation)
    {
        list($name, $furtherRelations) = $this->factory->splitRelationName($relation);

        if (!isset($this->relations[$name])) {
            throw new QueryException(sprintf('Unable to retrieve relation "%s" query, relation does not exists in query "%s"', $name, $this->model()->entity()));
        }

        if ($furtherRelations) {
            return $this->relations[$name]->relation($furtherRelations);
        }

        return $this->relations[$name];
    }
207642
protected function fetchRelation(array $relation)
    {
        /* a relation is of the form
         * [$type, $foreign_class, $foreign_column, $column]
         */
        list($type, $foreign_class, $foreign_column, $column) = $relation;

        switch ($type) {
        case 'has_one':
            return $this->fetchOneToOne($foreign_class, $foreign_column, $column);
        case 'belongs_to':
            return $this->fetchOneToOne($foreign_class, $foreign_column, $column);
        case 'has_many':
            return $this->fetchOneToMany($foreign_class, $foreign_column, $column);
        default:
        }
    }
947230
public function getResults($relation)
    {
        $results = $this->query->get();

        $this->cacheRelation($results, $relation);

        return $results;
    }
761040
public static function where($column, $relation, $value)
    {
        $self = self::instance();
        $key = $self->_keyName;
        $data = \Query::from($self->_table)->select($key)->where($column, $relation, $value)->get();
        $rows = [];

        if (!is_null($data)) {
            foreach ($data as $item) {
                $rows[] = self::instance($item->$key);
            }
        }

        return $rows;
    }
1225802
protected function buildBelongsToManyInfo($key, BelongsToMany $relation)
    {
        $other = $relation->getRelated();
        return [
            'type'         => 'sequence|itemType:[object|class:'.get_class($other).']',
            'foreign_keys' => [$this->getForeignKey($relation)]
        ];
    }
110911
public function getMissingEntities(string $relation): array
    {
        $cachedRelations = $this->getCachedAttribute($relation);

        if (is_null($cachedRelations)) {
            return [];
        }

        $missing = [];

        foreach ($cachedRelations as $hash) {
            if (!$this->getRelatedAggregateFromHash($hash, $relation)) {
                $missing[] = $hash;
            }
        }

        return $missing;
    }
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;
    }
1091179
public static function related_class($relation)
	{
		$class = get_called_class();

		foreach (static::$_valid_relations as $rel_name => $rel_class)
		{
			if (property_exists($class, '_'.$rel_name))
			{
				if (isset(static::${'_'.$rel_name}[$relation]))
				{
					return static::${'_'.$rel_name}[$relation]['model_to'];
				}
			}
		}

		return null;
	}
515693
public function getLocalKeys($relation)
    {
        return isset($this->localForeignKeys[$relation]) ? $this->localForeignKeys[$relation] : null;
    }
701682
protected function getNonExistingFromRelation(string $relation): array
    {
        $nonExisting = [];

        foreach ($this->relationships[$relation] as $aggregate) {
            if (!$aggregate->exists()) {
                $nonExisting[] = $aggregate;
            }
        }

        return $nonExisting;
    }
1065622
protected function getRelationshipFromMethod($key, $camelKey)
    {
        $relation = call_user_func(array($this, $camelKey));

        if (! $relation instanceof Relation) {
            throw new LogicException('Relationship method must return an object of type [Nova\Database\ORM\Relations\Relation]');
        }

        return $this->relations[$key] = $relation->getResults();
    }