252 lines
6.6 KiB
PHP
252 lines
6.6 KiB
PHP
<?php
|
|
namespace Aldarien\Common\Factory;
|
|
|
|
use Psr\Container\ContainerInterface as Container;
|
|
use \ORM as ORM;
|
|
use \Model as BaseFactory;
|
|
|
|
class Model {
|
|
protected $container;
|
|
public function __construct(Container $container) {
|
|
$this->container = $container;
|
|
}
|
|
|
|
public function reset() {
|
|
foreach ($this as $property => $value) {
|
|
if ($property == 'container') {
|
|
continue;
|
|
}
|
|
$this->$property = null;
|
|
}
|
|
}
|
|
protected $class;
|
|
public function find(string $model_class): Model {
|
|
$this->reset();
|
|
if (!class_exists($model_class)) {
|
|
throw new \InvalidArgumentException($model_class . ' not found.');
|
|
}
|
|
$this->class = $model_class;
|
|
return $this;
|
|
}
|
|
protected $columns;
|
|
/**
|
|
* <column>, [<column1>, <column2>, ...]
|
|
* string | array(array)
|
|
* <column>: [<name>, *<alias>, *<type>]
|
|
*/
|
|
public function select($columns): Model {
|
|
if ($this->columns == null) {
|
|
$this->columns = [];
|
|
}
|
|
if (!is_array($columns)) {
|
|
$columns = [[$columns]];
|
|
}
|
|
$this->columns = array_merge($this->columns, $columns);
|
|
return $this;
|
|
}
|
|
protected function parseSelect(ORM $orm): ORM {
|
|
if ($this->columns == null or count($this->columns) == 0) {
|
|
return $orm;
|
|
}
|
|
foreach ($this->columns as $column) {
|
|
if (is_string($column)) {
|
|
$column = [$column];
|
|
}
|
|
$value = $column[0];
|
|
$alias = $column['alias'] ?? $column[1] ?? '';
|
|
$method = 'select';
|
|
if (count($column) > 2 or isset($column['type'])) {
|
|
$type = $column['type'] ?? $column[2] ?? '';
|
|
switch ($type) {
|
|
case 'expr':
|
|
$method .= 'Expr';
|
|
break;
|
|
}
|
|
}
|
|
if ($alias == '') {
|
|
$orm = $orm->{$method}($value);
|
|
continue;
|
|
}
|
|
$orm = $orm->{$method}($value, $alias);
|
|
}
|
|
return $orm;
|
|
}
|
|
protected $joins;
|
|
public function join(array $joins): Model {
|
|
if ($this->joins == null) {
|
|
$this->joins = [];
|
|
}
|
|
$this->joins = array_merge($this->joins, $joins);
|
|
return $this;
|
|
}
|
|
public function parseJoin(ORM $orm): ORM {
|
|
if ($this->joins == null or count($this->joins) == 0) {
|
|
return $orm;
|
|
}
|
|
foreach ($this->joins as $join) {
|
|
$method = 'join';
|
|
if (isset($join['type'])) {
|
|
switch (strtolower($join['type'])) {
|
|
case 'left':
|
|
$method = 'leftOuterJoin';
|
|
break;
|
|
case 'right':
|
|
$method = 'rightOuterJoin';
|
|
break;
|
|
case 'raw':
|
|
$method = 'rawJoin';
|
|
break;
|
|
}
|
|
}
|
|
$table = $join[0];
|
|
if (isset($join['table'])) {
|
|
$table = $join['table'];
|
|
}
|
|
$field1 = $join[1];
|
|
if (isset($join['field1'])) {
|
|
$field1 = $join['field1'];
|
|
}
|
|
$op = '=';
|
|
if (isset($join['operator'])) {
|
|
$op = $join['operator'];
|
|
}
|
|
$field2 = $join[2];
|
|
if (isset($join['field2'])) {
|
|
$field2 = $join['field2'];
|
|
}
|
|
$alias = null;
|
|
if (isset($join['alias'])) {
|
|
$alias = $join['alias'];
|
|
}
|
|
$orm = $orm->{$method}($table, [$field1, $op, $field2], $alias);
|
|
}
|
|
return $orm;
|
|
}
|
|
protected $conditions;
|
|
public function where(array $conditions): Model {
|
|
if ($this->conditions == null) {
|
|
$this->conditions = [];
|
|
}
|
|
foreach ($conditions as $condition) {
|
|
$this->addCondition($condition);
|
|
}
|
|
return $this;
|
|
}
|
|
protected function addCondition(Condition $condition) {
|
|
$this->conditions []= $condition;
|
|
}
|
|
protected function parseWhere(ORM $orm): ORM {
|
|
if ($this->conditions == null or count($this->conditions) == 0) {
|
|
return $orm;
|
|
}
|
|
foreach ($this->conditions as $condition) {
|
|
$orm = $condition->build($orm);
|
|
}
|
|
return $orm;
|
|
}
|
|
protected $ordering;
|
|
public function order($orders): Model {
|
|
if ($this->ordering == null) {
|
|
$this->ordering = [];
|
|
}
|
|
if (!is_array($orders)) {
|
|
$orders = [$orders];
|
|
}
|
|
$this->ordering = array_merge($this->ordering, $orders);
|
|
return $this;
|
|
}
|
|
protected function parseOrder(ORM $orm): ORM {
|
|
if ($this->ordering == null or count($this->ordering) == 0) {
|
|
return $orm;
|
|
}
|
|
foreach ($this->ordering as $order => $dir) {
|
|
if (is_numeric($order)) {
|
|
$order = $dir;
|
|
$dir = 'asc';
|
|
}
|
|
$method = 'orderBy' . ucfirst(strtolower($dir));
|
|
$orm = $orm->{$method}($order);
|
|
}
|
|
return $orm;
|
|
}
|
|
protected $grouping;
|
|
public function group($groups): Model {
|
|
if ($this->grouping == null) {
|
|
$this->grouping = [];
|
|
}
|
|
if (!is_array($groups)) {
|
|
$groups = [$groups];
|
|
}
|
|
$this->grouping = array_merge($this->grouping, $groups);
|
|
return $this;
|
|
}
|
|
protected function parseGroup(ORM $orm): ORM {
|
|
if ($this->grouping == null or count($this->grouping) == 0) {
|
|
return $orm;
|
|
}
|
|
foreach ($this->grouping as $group) {
|
|
$orm = $orm->groupBy($group);
|
|
}
|
|
return $orm;
|
|
}
|
|
protected $limits;
|
|
public function limit(int $limit, int $offset = 0): Model {
|
|
$this->limits = (object) ['limit' => $limit, 'offset' => $offset];
|
|
return $this;
|
|
}
|
|
protected function parseLimit(ORM $orm): ORM {
|
|
if ($this->limits == null) {
|
|
return $orm;
|
|
}
|
|
$orm = $orm->limit($this->limits->limit);
|
|
if ($this->limits->offset > 0) {
|
|
$orm = $orm->offset($this->limits->offset);
|
|
}
|
|
return $orm;
|
|
}
|
|
public function build(): ORM {
|
|
$orm = BaseFactory::factory($this->class);
|
|
$methods = ['select', 'join', 'where', 'order', 'group', 'limit'];
|
|
foreach ($methods as $m) {
|
|
$method = 'parse' . ucfirst($m);
|
|
$orm = $this->{$method}($orm);
|
|
}
|
|
return $orm;
|
|
}
|
|
public function one($key = null) {
|
|
$model = $this->build()->findOne($key);
|
|
if ($model === false) {
|
|
return false;
|
|
}
|
|
$model->setContainer($this->container);
|
|
return $model;
|
|
}
|
|
public function many(): array {
|
|
$models = $this->build()->findMany();
|
|
array_walk($models, function(&$item, $key, $container) {
|
|
$item->setContainer($container);
|
|
}, $this->container);
|
|
return $models;
|
|
}
|
|
public function array(): array {
|
|
$models = $this->many();
|
|
return array_map(function($item) {
|
|
return $item->toArray();
|
|
}, $models);
|
|
}
|
|
public function create(string $model_class, array $data) {
|
|
$factory = new Model($this->container);
|
|
$where = [];
|
|
foreach ($data as $column => $condition) {
|
|
$where []= [$column, $condition];
|
|
}
|
|
$obj = $factory->find($model_class)->where($where)->one();
|
|
if ($obj === false) {
|
|
$obj = BaseFactory::factory($model_class)->create($data);
|
|
$obj->save();
|
|
$obj->setContainer($this->container);
|
|
}
|
|
return $obj;
|
|
}
|
|
}
|