factory = $factory; return $this; } protected function checkDefinitions(array $definitions, array $required, array $default) { foreach ($default as $key => $value) { if (!isset($definitions[$key])) { $definitions[$key] = $value; } } foreach ($required as $definition) { if (!isset($definitions[$definition])) { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); throw new \InvalidArgumentException($definition . ' is required for ' . $trace[1]['function'] . ' in ' . get_called_class()); } } return $definitions; } public function parentOf(string $child_model_class, array $relation_definitions): ?array { $relation_definitions = $this->checkDefinitions($relation_definitions, [ Model::SELF_KEY, Model::CHILD_KEY ], [ Model::SELF_KEY => 'id' ]); return $this->factory ->find($child_model_class) ->where([ [ $relation_definitions[Model::CHILD_KEY], $this->{$relation_definitions[Model::SELF_KEY]} ] ]) ->many(); } public function childOf(string $parent_model_class, array $relation_definitions): ?ModelInterface { $relation_definitions = $this->checkDefinitions($relation_definitions, [ Model::SELF_KEY, Model::PARENT_KEY ], [ Model::PARENT_KEY => 'id' ]); $parent_table = (new $parent_model_class())->getTable(); return $this->factory ->find($parent_model_class) ->where([ [ $relation_definitions[Model::PARENT_KEY], $this->{$relation_definitions[Model::SELF_KEY]} ] ]) ->one(); } public function siblingOf(string $sibling_model_class, string $connecting_table, array $relation_definitions): ?array { $relation_definitions = $this->checkDefinitions($relation_definitions, [ Model::SELF_KEY, Model::SIBLING_KEY, Model::SELF_CONNECT_KEY, Model::SIBLING_CONNECT_KEY ], [ Model::SELF_KEY => 'id', Model::SIBLING_KEY => 'id' ]); $sibling_table = (new $sibling_model_class())->getTable(); return $this->find($sibling_model_class) ->select([ [ $sibling_table, '*' ], [ $connecting_table, '*' ] ]) ->join([ [ $connecting_table, implode('.', [ $connecting_table, $relation_definitions[Model::SIBLING_CONNECT_KEY] ]), implode('.', [ $sibling_table, $relation_definitions[Model::SIBLING_KEY] ]) ] ]) ->where([ [ implode('.', [ $connecting_table, $relation_definitions[Model::SELF_CONNECT_KEY] ]), $this->{$relation_definitions[Model::SELF_KEY]} ] ]) ->many(); } public function toArray(): array { return $this->asArray(); } }