container = $container; return $this; } public function save() { $pdo = ORM::getDb(); $pdo->beginTransaction(); try { $result = parent::save(); $pdo->commit(); return $result; } catch (\Exception $e) { $pdo->rollBack(); throw $e; } } const KEY_EXCEPTION = 'Exception'; protected function parseKeys(string $called_function, array $definitions, array $defaults) { foreach ($defaults as $key => $value) { if (!isset($definitions[$key])) { if ($value == self::KEY_EXCEPTION) { throw new \InvalidArgumentException("Missing '" . $key . "' in '" . $called_function . "' for " . get_called_class()); } $definitions[$key] = $value; } } return (object) $definitions; } protected function validateVar(string $var) { if (!isset($this->$var)) { throw new \Exception("'" . $var . "' not found in '" . get_called_class() . "'."); } } public function childOf(string $parent_class, array $id_definitions, $var = '') { $id_definitions = $this->parseKeys('childOf', $id_definitions, [self::SELF_KEY => self::KEY_EXCEPTION, self::PARENT_KEY => 'id']); if ($var == '') { return $this->container->model->find($parent_class) ->where([[$id_definitions->parent_key, $this->{$id_definitions->self_key}]]) ->one(); } $this->validateVar($var); if ($this->$var == null) { $this->$var = $this->container->model->find($parent_class) ->where([[$id_definitions->parent_key, $this->{$id_definitions->self_key}]]) ->one(); } return $this->$var; } public function parentOf(string $child_class, array $id_definitions, $var = ''): ModelFactory { $id_definitions = $this->parseKeys('parentOf', $id_definitions, [self::SELF_KEY => 'id', self::CHILD_KEY => self::KEY_EXCEPTION]); if ($var == '') { return $this->container->model->find($child_class) ->where([[$id_definitions->child_key, $this->{$id_definitions->self_key}]]); } $this->validateVar($var); if ($this->$var == null) { $this->$var = $this->container->model->find($child_class) ->where([[$id_definitions->child_key, $this->{$id_definitions->self_key}]]); } return $this->$var; } public function parentOfOne(string $child_class, array $id_definitions, $var = '') { $factory = $this->parentOf($child_class, $id_definitions, $var); return $factory->one(); } public function parentOfMany(string $child_class, array $id_definitions, $var = '') { $factory = $this->parentOf($child_class, $id_definitions, $var); return $factory->many(); } public function siblingOf(string $sibling_class, string $table_through, array $id_definitions, $var = ''): ModelFactory { $id_definitions = $this->parseKeys('siblingOf', $id_definitions, [ self::SIBLING_THROUGH_KEY => self::KEY_EXCEPTION, self::SIBLING_KEY => 'id', self::SELF_THROUGH_KEY => self::KEY_EXCEPTION, self::SELF_KEY => 'id' ]); $sibling_table = self::getTable($sibling_class); if ($var == '') { return $this->container->model->find($sibling_class) ->select($sibling_table . '.*') ->join([ [$table_through, $table_through . '.' . $id_definitions->sibling_through_key, $sibling_table . '.' . $id_definitions->sibling_key] ]) ->where([[$table_through . '.' . $id_definitions->self_through_key, $this->{$id_definitions->self_key}]]); } $this->validateVar($var); if ($this->$var == null) { $this->$var = $this->container->model->find($sibling_class) ->select($sibling_table . '.*') ->join([ [$table_through, $table_through . '.' . $id_definitions->sibling_through_key, $sibling_table . '.' . $id_definitions->sibling_key] ]) ->where([[$table_through . '.' . $id_definitions->self_through_key, $this->{$id_definitions->self_key}]]); } return $this->$var; } public function siblingOfOne(string $sibling_class, string $table_through, array $id_definitions, $var = '') { $factory = $this->siblingOf($sibling_class, $table_through, $id_definitions, $var); if ($var == '') { return $factory->one(); } $this->validateVar($var); if (!is_a($this->$var, $sibling_class)) { $this->$var = $factory->one(); } return $this->$var; } public function siblingOfMany(string $sibling_class, string $table_through, array $id_definitions, $var = '') { $factory = $this->siblingOf($sibling_class, $table_through, $id_definitions, $var); if ($var == '') { return $factory->many(); } $this->validateVar($var); if (!is_a($this->$var, $sibling_class)) { $this->$var = $factory->many(); } return $this->$var; } public function toArray(): array { return $this->asArray(); } public function jsonSerialize() { return $this->toArray(); } public function setRelationship(string $class_name, string $relation_key, string $self_key): Relationship { return (new Relationship) ->setFactory($this->container->get('model')) ->setStart($class_name) ->with($class_name, $relation_key, get_called_class(), $self_key) ->setCondition(get_called_class(), $self_key, $this->$self_key); } }