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; 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 => $alias) { if (is_numeric($column)) { $orm = $orm->select($alias); continue; } $orm = $orm->select($column, $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 = []; } $this->conditions = array_merge($this->conditions, $conditions); return $this; } protected function parseWhere(ORM $orm): ORM { if ($this->conditions == null or count($this->conditions) == 0) { return $orm; } foreach ($this->conditions as $condition) { $method = 'where'; $op = '='; if (isset($condition[2])) { $op = strtolower($condition[2]); } if (isset($condition['operator'])) { $op = strtolower($condition['operator']); } $mod = ['=' => '', '>' => 'Gt', '>=' => 'Gte', '<' => 'Lt', '<=', 'Lte']; if (isset($mod[$op])) { $method .= $mod[$op]; } else { switch ($op) { case 'raw': $method = 'rawWhere'; break; } } $column = $condition[0]; if (isset($condition['column'])) { $column = $condition['column']; } $value = $condition[1]; if (isset($condition['value'])) { $value = $condition['value']; } $orm = $orm->{$method}($column, $value); } 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; } }