Build join parameters for related model.

`HasOne` and `BelongsTo` relation has different join parameters.

@param Relation $relation

@throws \Exception

@return array
189191
protected function joinParameters(Relation $relation)
    {
        $relatedTable = $relation->getRelated()->getTable();

        if ($relation instanceof BelongsTo) {
            $foreignKeyMethod = (app()->version() < '5.8.0') ? 'getForeignKey' : 'getForeignKeyName';

            return [
                $relatedTable,
                $relation->{$foreignKeyMethod}(),
                '=',
                $relatedTable.'.'.$relation->getRelated()->getKeyName(),
            ];
        }

        if ($relation instanceof HasOne) {
            return [
                $relatedTable,
                $relation->getQualifiedParentKeyName(),
                '=',
                $relation->getQualifiedForeignKeyName(),
            ];
        }

        throw new \Exception('Related sortable only support `HasOne` and `BelongsTo` relation.');
    }
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;
    }
844222
protected function relationResolver($relation)
    {
        $return = ['relation' => '', 'action' => 'update'];

        try {
            list($relation, $action) = explode('@', $relation);
            $return = ['relation' => $relation, 'action' => $action];
        } catch (\Exception $e) {
            $return['relation'] = $relation;
        }

        if (!in_array($return['action'], $this->availableActions)) {
            DB::rollBack(); //Rollback the transaction before throw exception
            throw (new SoftCascadeNonExistentRelationActionException())->setRelation(implode('@', $return));
        }

        return $return;
    }
756566
protected function getForeignKeyAttributesFromRelation(string $relation): array
    {
        // Call Relationship's method
        $relationship = $this->entityMap->$relation($this->getEntityObject());

        $relatedAggregate = $this->relationships[$relation][0];

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

        return null;
    }
504859
protected function joinEagerLoadedColumn($relation, $relationColumn)
    {
        $joins = [];
        foreach ((array) $this->getQueryBuilder()->joins as $key => $join) {
            $joins[] = $join->table;
        }

        $model = $this->query->getRelation($relation);
        if ($model instanceof BelongsToMany) {
            $pivot   = $model->getTable();
            $pivotPK = $model->getForeignKey();
            $pivotFK = $model->getQualifiedParentKeyName();

            if (!in_array($pivot, $joins)) {
                $this->getQueryBuilder()->leftJoin($pivot, $pivotPK, '=', $pivotFK);
            }

            $related = $model->getRelated();
            $table   = $related->getTable();
            $tablePK = $related->getForeignKey();
            $tableFK = $related->getQualifiedKeyName();

            if (!in_array($table, $joins)) {
                $this->getQueryBuilder()->leftJoin($table, $pivot . '.' . $tablePK, '=', $tableFK);
            }
        } else {
            $table   = $model->getRelated()->getTable();
            $foreign = $model->getQualifiedForeignKey();
            $other   = $model->getQualifiedOtherKeyName();
            if (!in_array($table, $joins)) {
                $this->getQueryBuilder()->leftJoin($table, $foreign, '=', $other);
            }
        }

        $column = $table . '.' . $relationColumn;

        return $column;
    }
86577
public function with($relation)
    {
        $this->reset();

        if (func_num_args() > 1) {
            return $this->with(func_get_args());
        }

        if (is_array($relation)) {
            $this->related = array_merge($this->related, $relation);
        } else {
            $this->related[] = $relation;
        }

        $this->relatedCount = count($this->related);

        return $this;
    }
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;
	}
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;
    }
562837
public function getCmsSpecialRelationType($relation)
    {
        if (    ! array_key_exists($relation, $this->relationsConfig)
            ||  ! array_key_exists('type', $this->relationsConfig[$relation])
        ) {
            return null;
        }

        return $this->relationsConfig[ $relation ]['type'];
    }
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;
	}
1302235
public function getRelationTableName($relation) {
        $relationTable  = !empty($this->tablePrefix) ? $this->tablePrefix : '';
        $relationTable .= $this->tableName?$this->tableName:$this->name;
        $relationTable .= '_'.$relation->getModelName();
        return strtolower($relationTable);
    }
1052949
protected function getRelationshipValue(string $relation)
    {
        $value = $this->getEntityAttribute($relation);

        if (is_scalar($value)) {
            throw new MappingException("Entity's attribute $relation should be array, object, collection or null");
        }

        return $value;
    }
160794
public function initRelation(array $models, $relation)
    {
        foreach ($models as $model) {
            $model->setRelation($relation, $this->getDefaultFor($model));
        }

        return $models;
    }
421952
public function addRelation(Relation $relation) {
        $relation->setPrimaryModel($this);

        $this->_relations[$relation->getAlias()] = $relation;
        $this->_aliases[$relation->getRelatedClass()] = $relation->getAlias();
        $this->reserved[] = $relation->getAlias();

        $this->on('relation', $relation);

        return $this;
    }
1031803
protected function buildRelatedForms()
    {
        if (is_null($this->form)) {
            return [];
        }

        $model = $this->form->model();

        $relation = call_user_func([$model, $this->relationName]);

        if (!$relation instanceof Relation && !$relation instanceof MorphMany) {
            throw new \Exception('hasMany field must be a HasMany or MorphMany relation.');
        }

        $forms = [];

        /*
         * If redirect from `exception` or `validation error` page.
         *
         * Then get form data from session flash.
         *
         * Else get data from database.
         */
        if ($values = old($this->column)) {
            foreach ($values as $key => $data) {
                if ($data[NestedForm::REMOVE_FLAG_NAME] == 1) {
                    continue;
                }

                $model = $relation->getRelated()->replicate()->forceFill($data);

                $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $model)
                    ->fill($data);
            }
        } else {
            foreach ($this->value as $data) {
                $key = Arr::get($data, $relation->getRelated()->getKeyName());

                $model = $relation->getRelated()->replicate()->forceFill($data);

                $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $model)
                    ->fill($data);
            }
        }

        return $forms;
    }
289920
public static function getRelationName($relation)
    {
        // get the relationName
        list($fullName, $relationAlias) = self::getClassAndAlias($relation);
        if ($relationAlias) {
            $relationName = $relationAlias;
        } elseif (false === strpos($fullName, '.')) {
            $relationName = $fullName;
        } else {
            list(, $relationName) = explode('.', $fullName);
        }

        return $relationName;
    }