diff --git a/.gitignore b/.gitignore index 9aa7c69..eed7ff6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ # Composer -/vendor/ -composer.lock +**/vendor/ +**/*.lock + +# PHPStorm +**/.idea/ diff --git a/common/Alias/Model.php b/common/Alias/Model.php deleted file mode 100644 index cf63238..0000000 --- a/common/Alias/Model.php +++ /dev/null @@ -1,156 +0,0 @@ -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(); - } - - protected static function parseInput($input): array { - return array_intersect_key((array) $input, array_combine(static::$fields, static::$fields)); - } - public static function add(ModelFactory $factory, $input): ?ModelInterface { - $data = static::parseInput($input); - $class = get_called_class(); - if (method_exists($class, 'find')) { - $obj = static::find($factory, $input); - } else { - $where = $data; - array_walk($where, function(&$item, $key) { - $item = [$key, $item]; - }); - $where = array_values($where); - $obj = $factory->find($class)->where($where)->one(); - } - if ($obj === null) { - $obj = $factory->create($class, $data); - } - return $obj; - } - public function edit($input): bool { - $data = static::parseInput($input); - foreach (static::$fields as $field) { - if ($this->{$field} != $data[$field]) { - $this->{$field} = $data[$field]; - } - } - return $this->save(); - } -} diff --git a/common/Define/Model.php b/common/Define/Model.php deleted file mode 100644 index 5e220c6..0000000 --- a/common/Define/Model.php +++ /dev/null @@ -1,17 +0,0 @@ -date); - } - $this->date = $data->format('Y-m-d'); - } -} diff --git a/common/Define/Model/DateTime.php b/common/Define/Model/DateTime.php deleted file mode 100644 index 0471f1b..0000000 --- a/common/Define/Model/DateTime.php +++ /dev/null @@ -1,13 +0,0 @@ -date_time); - } - $this->date_time = $date_time->format('c'); - } -} diff --git a/common/Define/Model/Time.php b/common/Define/Model/Time.php deleted file mode 100644 index cabc719..0000000 --- a/common/Define/Model/Time.php +++ /dev/null @@ -1,13 +0,0 @@ -time); - } - $this->time = $time->format('H:i:s e'); - } -} diff --git a/common/Factory/Model.php b/common/Factory/Model.php deleted file mode 100644 index bda8562..0000000 --- a/common/Factory/Model.php +++ /dev/null @@ -1,393 +0,0 @@ -{$p} = null; - } - return $this; - } - public function create(string $model_class, array $data = null): ModelInterface { - if ($data !== null) { - $model = $this->find($model_class); - foreach ($data as $f => $v) { - $model = $model->where([[$f, $v]]); - } - $model = $model->one(); - if ($model !== null) { - return $model; - } - } - $model = BaseModel::factory($model_class)->create($data); - $model->setFactory($this); - return $model; - } - protected $class; - public function find(string $model_class): Model { - if (!class_exists($model_class)) { - throw new \InvalidArgumentException('El modelo ' . $model_class . ' no existe.'); - } - $this->reset(); - $this->class = $model_class; - return $this; - } - protected $columns; - public function select($columns): Model { - if ($this->columns === null) { - $this->columns = []; - } - if (!is_array($columns)) { - $columns = [$columns]; - } - foreach ($columns as $c) { - $col = (object) [ - 'table' => '', - 'column' => $c - ]; - if (is_array($c)) { - $col = (object) [ - 'table' => $c['table'] ?? $c[0], - 'column' => $c['column'] ?? $c[1] - ]; - } - $this->columns []= $col; - } - return $this; - } - protected $joins; - public function join(array $joins): Model { - if ($this->joins === null) { - $this->joins = []; - } - foreach ($joins as $j) { - $join = (object) [ - 'table' => $j['table'] ?? $j[0], - 'from' => $j['from'] ?? $j[1], - 'to' => $j['to'] ?? $j[2], - 'symb' => $j['symb'] ?? ($j[3] ?? '='), - 'alias' => $j['alias'] ?? '', - 'type' => strtolower($j['type'] ?? ''), - 'params' => $j['params'] ?? '' - ]; - $this->joins []= $join; - } - return $this; - } - protected $conditions; - public function where(array $conditions): Model { - if ($this->conditions === null) { - $this->conditions = []; - } - foreach ($conditions as $c) { - $cond = (object) [ - 'column' => $c['column'] ?? $c[0], - 'value' => $c['value'] ?? $c[1], - 'symb' => strtolower($c['symb'] ?? ($c[2] ?? '=')), - 'type' => strtolower($c['type'] ?? '') - ]; - $this->conditions []= $cond; - } - return $this; - } - protected $grouping; - public function group($groups): Model { - if ($this->grouping === null) { - $this->grouping = []; - } - if (!is_array($groups)) { - $groups = [$groups]; - } - foreach ($groups as $g) { - $this->grouping []= $g; - } - return $this; - } - protected $ordering; - public function order($orders): Model { - if ($this->ordering === null) { - $this->ordering = []; - } - if (!is_array($orders)) { - $orders = [$orders]; - } - foreach ($orders as $o) { - $order = (object) [ - 'column' => $o, - 'direction' => 'asc' - ]; - if (is_array($o)) { - $order = (object) [ - 'column' => $o['column'] ?? $o[0], - 'direction' => strtolower($o['direction']) ?? $o[1] - ]; - } - $this->ordering []= $order; - } - return $this; - } - protected $limit; - public function limit(int $limit): Model { - $this->limit = $limit; - } - protected $offset; - public function offset(int $offset): Model { - $this->offset = $offset; - } - - protected function parseSelect(ORM $orm): ORM { - if ($this->columns === null) { - return $orm; - } - foreach ($this->columns as $col) { - $orm = $orm->select(trim(implode('.', (array) $col), '.')); - } - return $orm; - } - protected function parseJoin(ORM $orm): ORM { - if ($this->joins === null) { - return $orm; - } - foreach ($this->joins as $join) { - $method = 'join'; - switch ($join->type) { - case 'raw': - $method = 'rawJoin'; - break; - case 'inner': - $method = 'innerJoin'; - break; - case 'left': - case 'left outer': - case 'left_outer': - case 'leftouter': - $method = 'leftOuterJoin'; - break; - case 'right': - case 'right outer': - case 'right_outer': - case 'rightouter': - $method = 'rightOuterJoin'; - break; - case 'full': - case 'full outer': - case 'full_outer': - case 'fullouter': - $method = 'fullOuterJoin'; - break; - } - if ($join->type == 'raw') { - $orm = $orm->{$method}($join->table, [$join->from, $join->symb, $join->to], $join->alias, $join->params); - } elseif ($join->alias !== '') { - $orm = $orm->{$method}($join->table, [$join->from, $join->symb, $join->to], $join->alias); - } else { - $orm = $orm->{$method}($join->table, [$join->from, $join->symb, $join->to]); - } - } - return $orm; - } - protected function parseWhere(ORM $orm): ORM { - if ($this->conditions === null) { - return $orm; - } - foreach ($this->conditions as $cond) { - $method = 'where'; - switch ($cond->symb) { - case '<': - $method = 'whereLt'; - break; - case '<=': - $method = 'whereLte'; - break; - case '>': - $method = 'whereGt'; - break; - case '>=': - $method = 'whereGte'; - break; - case '!=': - $method = 'whereNotEqual'; - break; - case 'like': - $method = 'whereLike'; - break; - case 'not like': - case 'not_like': - case 'notlike': - $method = 'whereNotLike'; - break; - } - switch ($cond->type) { - case 'equal': - $method = 'whereEqual'; - break; - case 'not equal': - case 'not_equal': - case 'notequal': - $method = 'whereNotEqual'; - break; - case 'less': - case 'less than': - case 'less_than': - case 'lessthan': - case 'lt': - $method = 'whereLt'; - break; - case 'less equal': - case 'less_equal': - case 'lessequal': - case 'less than equal': - case 'less_than_equal': - case 'lessthanequal': - case 'lte': - $method = 'whereLte'; - break; - case 'greater': - case 'greater than': - case 'greater_than': - case 'greaterthan': - case 'gt': - $method = 'whereGt'; - break; - case 'greater equal': - case 'greater_equal': - case 'greaterequal': - case 'greater than equal': - case 'greater_than_equal': - case 'greaterthanequal': - case 'gte': - $method = 'whereGte'; - break; - case 'like': - $method = 'whereLike'; - break; - case 'not like': - case 'not_like': - case 'notlike': - $method = 'whereNotLike'; - break; - case 'in': - $method = 'whereIn'; - break; - case 'not in': - case 'not_in': - case 'notin': - $method = 'whereNotIn'; - break; - case 'raw': - $method = 'rawWhere'; - break; - } - $orm = $orm->{$method}($cond->column, $cond->value); - } - return $orm; - } - protected function parseGroup(ORM $orm): ORM { - if ($this->grouping === null) { - return $orm; - } - foreach ($this->grouping as $group) { - if (strpos($group, '(') !== false) { - $orm = $orm->groupByExpr($group); - } else { - $orm = $orm->groupBy($group); - } - } - return $orm; - } - protected function parseOrder(ORM $orm): ORM { - if ($this->ordering === null) { - return $orm; - } - foreach ($this->ordering as $order) { - if (strpos($order->column, '(') !== false) { - $orm = $orm->orderByExpr($order->column); - continue; - } - switch ($order->direction) { - case 'asc': - case 'ascending': - $orm = $orm->orderByAsc($order->column); - break; - case 'desc': - case 'descending': - $orm = $orm->orderByDesc($order->column); - break; - } - } - return $orm; - } - protected function parseLimit(ORM $orm): ORM { - if ($this->limit === null) { - return $orm; - } - return $orm->limit($this->limit); - } - protected function parseOffset(ORM $orm): ORM { - if ($this->offset === null) { - return $orm; - } - return $orm->offset($this->offset); - } - - public function one($id = null): ?ModelInterface { - $result = $this->build()->findOne($id); - if (!$result) { - return null; - } - $result->setFactory($this); - return $result; - } - public function many(): ?array { - $results = $this->build()->findMany(); - if (!$results) { - return null; - } - foreach ($results as &$r) { - $r->setFactory($this); - } - return $results; - } - public function array(): ?array { - $results = $this->many(); - if (!$results or $results === null) { - return null; - } - array_walk($results, function(&$item) { - $item = $item->toArray(); - }); - return $results; - } - - protected function build(): ORM { - $orm = BaseModel::factory($this->class); - $methods = [ - 'select', - 'join', - 'where', - 'group', - 'order', - 'limit', - 'offset' - ]; - foreach ($methods as $m) { - $method = 'parse' . ucfirst($m); - $orm = $this->{$method}($orm); - } - return $orm; - } -} diff --git a/common/Form/Model.php b/common/Form/Model.php deleted file mode 100644 index 591186d..0000000 --- a/common/Form/Model.php +++ /dev/null @@ -1,6 +0,0 @@ -factory = $factory; + return $this; + } + public function getFactory(): Factory + { + return $this->factory; + } + protected int $id; + public function setId(int $id): ModelInterface + { + $this->id = $id; + return $this; + } + public function getId(): int + { + return $this->id; + } + protected bool $new; + public function setNew(): ModelInterface + { + $this->new = true; + return $this; + } + public function isNew(): bool + { + return $this->new ?? false; + } + protected bool $dirty; + public function setDirty(): ModelInterface + { + $this->dirty = true; + return $this; + } + public function isDirty(): bool + { + return $this->dirty ?? $this->isNew(); + } + + public function save(): void + { + if ($this->isDirty()) { + $this->getFactory()->get(get_class($this))->save($this); + } + } + public function edit(array $data): void + { + foreach ($data as $key => $val) { + $m = 'set' . ucwords($key); + $this->{$m}($val); + } + $this->isDirty(); + } +} diff --git a/src/Alias/Model/Repository.php b/src/Alias/Model/Repository.php new file mode 100644 index 0000000..69767b3 --- /dev/null +++ b/src/Alias/Model/Repository.php @@ -0,0 +1,119 @@ +setConnection($connection) + ->setQueryBuilder($builder) + ->setFactory($factory) + ->setup(); + } + + protected Connection $connection; + public function setConnection(Connection $connection): Repository + { + $this->connection = $connection; + return $this; + } + public function getConnection(): Connection + { + return $this->connection; + } + protected QueryBuilder $builder; + public function setQueryBuilder(QueryBuilder $builder): RepositoryInterface + { + $this->builder = $builder; + return $this; + } + public function getQueryBuilder(): QueryBuilder + { + return $this->builder; + } + protected Factory $factory; + public function setFactory(Factory $factory): RepositoryInterface + { + $this->factory = $factory; + return $this; + } + public function getFactory(): Factory + { + return $this->factory; + } + protected string $table; + public function setTable(string $table): RepositoryInterface + { + $this->table = $table; + return $this; + } + public function getTable(): string + { + return $this->table; + } + protected array $columns; + public function setColumns(array $columns): RepositoryInterface + { + foreach ($columns as $column) { + $this->addColumn($column); + } + return $this; + } + public function addColumn(string $column): RepositoryInterface + { + $this->columns []= $column; + return $this; + } + public function getColumns(): array + { + return $this->columns; + } + + public function save(Model $model): void + { + if (!$model->isDirty() and !$model->isNew()) { + return; + } + $cols = []; + $values = []; + foreach ($this->getColumns() as $column) { + $m = 'get' . ucwords($column); + $cols []= '?'; + $values []= $model->{$m}(); + } + $query = $this->getQueryBuilder()->insert($this->getTable())->columns($this->getColumns())->values($cols); + $this->getConnection()->execute($query, $values); + } + public function edit(Model $model, array $data): Model + { + foreach ($this->getColumns() as $col) { + if (isset($data[$col])) { + $m = 'set' . ucwords($col); + $model->{$m}($data[$col]); + } + } + return $model; + } + public function fetchById(int $id): Model + { + $query = $this->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where([['id', '?']]) + ->limit(1); + return $this->load($this->getConnection()->execute($query, [$id])->getAsArray()[0]); + } + public function fetchAll(): array + { + $query = $this->getQueryBuilder() + ->select() + ->from($this->getTable()); + return array_map([$this, 'load'], $this->getConnection()->query($query)->getAsArray()); + } +} diff --git a/src/Concept/Model.php b/src/Concept/Model.php new file mode 100644 index 0000000..d6f836d --- /dev/null +++ b/src/Concept/Model.php @@ -0,0 +1,18 @@ +