Attach errors to owner relational attributes
@param BaseActiveRecord $relationModel
@param BaseActiveRecord $owner
@param string $relationName
@param string $prettyRelationName
196094
private function _addError($relationModel, $owner, $relationName, $prettyRelationName)
    {
        foreach ($relationModel->errors as $attribute => $attributeErrors) {
            foreach ($attributeErrors as $error) {
                $owner->addError($relationName, "{$prettyRelationName}: {$error}");
            }
        }
    }
1184169
protected function buildRelationsFromModels(string $relationName, Closure $relationConstraints): Collection
    {
        return $this->models->toBase()->map(
            function (Model $model) use ($relationName, $relationConstraints) {
                $relation = $this->getRelationInstance($relationName);

                $relation->addEagerConstraints([$model]);

                // Call the constraints
                $relationConstraints($relation, $model);

                if (method_exists($relation, 'shouldSelect')) {
                    $shouldSelect = new ReflectionMethod(get_class($relation), 'shouldSelect');
                    $shouldSelect->setAccessible(true);
                    $select = $shouldSelect->invoke($relation, ['*']);

                    $relation->addSelect($select);
                } elseif (method_exists($relation, 'getSelectColumns')) {
                    $getSelectColumns = new ReflectionMethod(get_class($relation), 'getSelectColumns');
                    $getSelectColumns->setAccessible(true);
                    $select = $getSelectColumns->invoke($relation, ['*']);

                    $relation->addSelect($select);
                }

                $relation->initRelation([$model], $relationName);

                return $relation;
            }
        );
    }
1221271
protected function addPolymorphicRelations(Model $model, $morphName, array $relatedTables)
    {
        foreach ($relatedTables as $relatedTable) {
            $relatedModel = $this->models[$relatedTable];

            if ($this->isOneToOneRelation($relatedModel, $model, $morphName)) {
                $relatedModel->morphOne($model, $morphName);
            } else {
                $relatedModel->morphMany($model, $morphName);
            }
        }

        $model->morphTo($morphName);
    }
1084922
protected function setSingleRelation($relationName, $value)
    {
        /** @var BaseActiveRecord $owner */
        $owner = $this->owner;
        /** @var ActiveQuery $relation */
        $relation = $owner->getRelation($relationName);
        if (!($value instanceof $relation->modelClass)) {
            $value = $this->processModelAsArray($value, $relation, $relationName);
        }
        $this->_newRelationValue[$relationName] = $value;
        $owner->populateRelation($relationName, $value);
    }
260151
public function performStoreAfter(Model $model, $source, $value)
    {
        $relation = $this->resolveModelSource($model, $source);

        if ( ! ($relation instanceof Relation)) {
            throw new UnexpectedValueException("{$source} did not resolve to relation");
        }

        // Belongs to are handled before the model is saved
        if ($relation instanceof BelongsTo) return;

        // Should not be used, since this is for singular relations..
        if ($relation instanceof BelongsToMany) {
            $relation->sync([ $value ]);
            return;
        }

        // For *One and *Many relations, we need to handle detachment for currently related models.
        if (    $relation instanceof HasOne
            ||  $relation instanceof HasMany
            ||  $relation instanceof MorphOne
            ||  $relation instanceof MorphMany
        ) {
            // Detach only the models that shouldn't stay attached (ie. don't match the new value)

            /** @var Collection|Model[] $currentlyRelated */
            $currentlyRelated = $relation->get();
            if ($value) {
                $currentlyRelated = $currentlyRelated->filter(function (Model $model) use ($value) {
                    return ! $model->getKey() == $value;
                });
            }

            $this->detachRelatedModelsForOneOrMany($currentlyRelated, $relation);
        }

        if ( ! $value) return;

        // For HasOne (and HasMany), the related model must be found,
        // and then it should be saved on the relation.
        $relatedModel = $this->getModelByKey($relation->getRelated(), $value);

        if ( ! $relatedModel) return;

        if (    $relation instanceof HasOne
            ||  $relation instanceof HasMany
            ||  $relation instanceof MorphOne
            ||  $relation instanceof MorphMany
        ) {
            $relation->save($relatedModel);
            return;
        }

        throw new UnexpectedValueException(
            'Unexpected relation class ' . get_class($relation) . " for {$source}"
        );
    }
894635
protected function fixInputRelations(eZContentObject $object, $versionNo)
    {
        $validRelationTypes = array(1, 2, 4, 8, 16, 32, 64, 128);

        $db = eZDB::instance();
        $rows = $db->arrayQuery(
            "SELECT * FROM ezcontentobject_link
            WHERE from_contentobject_id={$object->attribute('id')}
            AND from_contentobject_version={$versionNo}"
        );

        foreach ($rows as $row) {
            $relationType = (int)$row['relation_type'];

            if (!in_array($relationType, $validRelationTypes)) {
                foreach ($validRelationTypes as $validRelationType) {
                    if ($relationType & $validRelationType) {
                        $db->query(
                            "INSERT INTO ezcontentobject_link (
                                from_contentobject_id,
                                from_contentobject_version,
                                to_contentobject_id,
                                contentclassattribute_id,
                                relation_type
                            ) VALUES (
                                {$row['from_contentobject_id']},
                                {$row['from_contentobject_version']},
                                {$row['to_contentobject_id']},
                                {$row['contentclassattribute_id']},
                                {$validRelationType}
                            )
                        ");
                    }
                }

                $db->query("DELETE FROM ezcontentobject_link WHERE id = {$row['id']}");
            }
        }
    }
1301234
public function assignChildren ($relationIdentifier, $id, $childIds, $subtractive = true)
		{
			$relation = $this->getRelation($relationIdentifier);
			$childIds = (array)$childIds;

			if (! $relation) {
				throw new RelationException('Invalid relation `' . $relationIdentifier);
			}

			if ($relation instanceof OneToMany) {
				$this->database->createQuery()
					->update()
					->table($relation->getRelatedTable())
					->set(
						array(
							$relation->getRelatedKey() => $id,
						)
					)
					->whereIn($this->database->primaryKey($relation->getRelatedTable()), $childIds)
					->execute();

				if ($subtractive) {
					$this->database->createQuery()
						->update()
						->table($relation->getRelatedTable())
						->set(
							array(
								$relation->getRelatedKey() => null,
							)
						)
						->whereEqual($relation->getRelatedKey(), $id)
						->whereNotIn($this->database->primaryKey($relation->getRelatedTable()), $childIds)
						->execute();
				}
			} else if ($relation instanceof ManyToMany) {
				if ($subtractive) {
					$this->database->createQuery()
						->delete()
						->from($relation->getRelationalTable())
						->whereEqual($relation->getKey(), $id)
						->whereNotIn($relation->getRelatedKey(), $childIds)
						->execute();
				}

				$query = $this->database->createQuery();

				$assignedIds =
					$query->select($relation->getRelatedKey())
						->from($relation->getRelationalTable())
						->whereEqual($relation->getKey(), $id)
						->execute()
						->fetchColumn();

				$newIds = array_diff($childIds, $assignedIds);

				foreach ($newIds as $newId) {
					$this->database->createQuery()
						->insert()
						->into($relation->getRelationalTable())
						->set(
							array(
								$relation->getKey()        => $id,
								$relation->getRelatedKey() => $newId,
							)
						)
						->execute();
				}
			} else {
				throw new RelationException('Invalid relation type `' . gettype($relation) . '`');
			}
		}
261243
protected function joinRelation(Relation $relationClass)
    {
        switch (get_class($relationClass)) {
            case BelongsToMany::class:
                /* @var BelongsToMany $relationClass */
                $this->joinBelongsToMany($relationClass);
                break;
            case BelongsTo::class:
                /* @var BelongsTo $relationClass */
                $this->joinBelongsTo($relationClass);
                break;
            case HasOne::class:
            case HasMany::class:
                /* @var HasOneOrMany $relationClass */
                $this->joinHasOneOrMany($relationClass);
                break;
        }
    }
102818
protected function updateRelations($eloquentModel, $action)
    {
        $mapping = $eloquentModel->getMapping();
        $eloquentRelations = $eloquentModel->getRelations();

        foreach($mapping['relations'] as $name => $relationMapping) {
            if (isset($eloquentRelations[$name])) {
                $this->updateRelation($eloquentModel, $name, $relationMapping, $action);
            }
        }
    }
1057476
public function findRelation($entity, $relationName, $orderColumn = null, $orderType = null) {
        $this->load();
        $mapper = MapperBuilder::buildFromClassName($this->mapping, get_class($entity));
        $relation = $mapper->getRelation($relationName);
        $relationMapper = MapperBuilder::buildFromName($this->mapping, $relation->getEntity());

        $selectQuery = "SELECT tmain.* FROM `" . $relationMapper->getTable() . "` tmain ";
        $joinQuery = QueryBuilder::buildJoinRelationQuery($relation, "tmain", "j1");
        $whereQuery = "WHERE j1." . $relation->getLocalColumn() . " = '" . $entity->getId() . "'";

        $orderQuery = "";
        if (!is_null($orderColumn)) {
            $orderQuery .= "ORDER BY $orderColumn ";
            if (!is_null($orderType)) {
                $orderQuery .= "$orderType";
            } else {
                $orderQuery .= "ASC";
            }
        }

        $query = $selectQuery . $joinQuery . $whereQuery . $orderQuery;
        $queryResult = $this->getDataSource()->query($query);
        if ($queryResult) {
            $collection = new Collection($relationMapper->getClass(), $queryResult, $relationMapper);
        } else {
            $collection = new Collection($relationMapper->getClass(), array(), $relationMapper);
        }

        return $collection;
    }
1132619
public function setRelation($name, $related_object)
    {
        //if no related object is supplied, set it to false (an array
        //value of null will not pass an isset() check on the
        //relation_objects array).
        if (!$related_object) {
            $related_object = false;
        }

        $this->relation_objects[$name] = $related_object;
    }
628502
protected static function getModelsForRelation($model, $relationKey)
    {
        if (!method_exists($model, $relationKey)) {
            throw new Exception(
                    'Relation "' . $relationKey . '" does not exist in model',
                    static::ERROR_SCOPE | static::ERROR_UNKNOWN_ID,
                    BaseResponse::HTTP_INTERNAL_SERVER_ERROR
                );
        }
        $relationModels = $model->{$relationKey};
        if (is_null($relationModels)) {
            return null;
        }

        if (! $relationModels instanceof Collection) {
            return [ $relationModels ];
        }

        return $relationModels;
    }
573560
private function _checkFileRelationExists(Model $model, $relationName)
    {
        if ((!method_exists($model, $relationName) && !$model->{$relationName}() instanceof Relation)) {
            if (Lang::has('resource-controller.filerelationinexistent')) {
                $message = trans('resource-controller.filerelationinexistent', ['relationName' => $relationName]);
            } else {
                $message = "Request file '{$relationName}' is not named after an existent relation.";
            }
            throw new UploadException($message);
        }
    }
964095
public function addRelation(Relation $relation)
    {
        switch (get_class($relation)) {
            case BelongsTo::class:
                $this->relations['belongsTo'][] = $relation;
                break;

            case BelongsToMany::class:
                $this->relations['belongsToMany'][] = $relation;
                break;

            case HasOne::class:
                $this->relations['hasOne'][] = $relation;
                break;

            case HasMany::class:
                $this->relations['hasMany'][] = $relation;
                break;

            case HasManyThrough::class:
                $this->relations['hasManyThrough'][] = $relation;
                break;

            default:
                throw new \Exception("Unknown relation type " . get_class($relation));
        }
    }
663737
public function unassignChild ($relationIdentifier, $id, $childId)
		{
			$relation = $this->getRelation($relationIdentifier);

			if (!$relation) {
				throw new RelationException('Invalid relation `' . $relationIdentifier);
			}

			if ($relation instanceof OneToMany) {
				$this->database->createQuery()
					->update()
					->table($relation->getRelatedTable())
					->set(
						array(
							$relation->getRelatedKey() => null,
						)
					)
					->whereEqual($relation->getRelatedKey(), $id)
					->whereEqual($relation->getKey(), $childId)
					->execute();
			} else if ($relation instanceof ManyToMany) {
				$this->database->createQuery()
					->delete()
					->from($relation->getRelationalTable())
					->whereEqual($relation->getKey(), $id)
					->whereEqual($relation->getRelatedKey(), $childId)
					->execute();
			} else {
				throw new RelationException('Invalid relation type `' . gettype($relation) . '`');
			}
		}
1005083
protected function relationsMap($relations, $callback)
    {
        try {
            if (is_callable($callback)) {
                array_map($callback, $relations);
            }
        } catch (\Exception $e) {
            Yii::$app->getDb()->getTransaction()->rollBack();
            throw new RelationException('Owner-model not saved due to unknown error');
        }
    }
608495
protected function saveHasManyData($relatedModel, HasMany $hasMany, $data, $relationName)
    {
        if ($this->exists) {
            $models = [];
            $pk = $hasMany->getRelated()->primaryKey;
            $fk = $hasMany->getForeignKeyName();

            foreach ((array)$data as $d) {
                /** @var Model $model */
                if (empty($pkValue = array_get($d, $pk))) {
                    $model = $relatedModel::findCompositeForeignKeyModel($this->{$this->primaryKey}, $d);
                } else {
                    $model = $relatedModel::find($pkValue);
                }
                if (!empty($model)) {
                    /** @var Model $parent */
                    $fkId = array_get($d, $fk);
                    if (array_key_exists($fk, $d) && is_null($fkId)) {
                        //Foreign key field is set to null therefore delete the child record.
                        $model->delete();
                        continue;
                    } elseif (!empty($fkId) &&
                        $fkId !== $this->{$this->primaryKey} &&
                        (null !== $parent = static::find($fkId))
                    ) {
                        //Foreign key field is set but the id belongs to a different parent than this parent.
                        //There the child is adopted by the supplied parent id (foreign key).
                        $relatedData = [$relationName => [$d]];
                        $parent->update($relatedData);
                        continue;
                    } else {
                        $model->fill($d);
                    }
                } else {
                    // not found, create a new one
                    $model = new $relatedModel($d);
                }
                $models[] = $model;
            }

            $hasMany->saveMany($models);
        }
    }