Files
intranet/app/Service/Factory.php
2020-12-01 17:23:13 -03:00

205 lines
4.6 KiB
PHP

<?php
namespace App\Service;
use Stringy\Stringy;
class Factory
{
protected $class;
protected $is_aggregator;
public function __construct($class)
{
$this->class = $class;
$this->is_aggregator = true;
if (is_subclass_of($class, 'Model')) {
$this->is_aggregator = false;
}
}
public function new()
{
$class = $this->class;
if ($this->is_aggregator) {
return new $class();
}
return model($class)->create();
}
public function create($data)
{
$class = $this->class;
if ($this->is_aggregator) {
$obj = new $class();
$obj->create($data);
return $obj;
}
return model($class)->create($data);
}
/**
* [column => value, column => [value, operator]]
* @var array
*/
protected $conditions;
public function where(array $data)
{
if ($this->conditions == null) {
$this->conditions = $data;
return $this;
}
$this->conditions = array_merge($this->conditions, $data);
return $this;
}
/**
* [column, column => order]
* @var array
*/
protected $order;
public function order(array $data)
{
if ($this->order == null) {
$this->order = $data;
return $this;
}
$this->order = array_merge($this->order, $data);
return $this;
}
protected $limit;
public function limit(array $data)
{
if (!isset($data['limit'])) {
$data['limit'] = $data[0];
}
if (!isset($data['offset'])) {
$data['offset'] = 0;
if (isset($data[1])) {
$data['offset'] = $data[1];
}
}
$this->limit = (object) ['limit' => $data['limit'], 'offset' => $data['offset']];
return $this;
}
protected $many;
public function find($many = false)
{
$this->many = $many;
if ($this->is_aggregator) {
return $this->findAggregator();
}
return $this->findModel();
}
protected function findModel()
{
$objs = model($this->class);
$objs = $this->parseLimit($this->parseOrder($this->parseConditions($objs)));
if ($this->many) {
return $objs->findMany();
}
return $objs->findOne();
}
protected function parseConditions($orm)
{
if ($this->conditions == null) {
return $orm;
}
foreach ($this->conditions as $column => $value) {
if (is_array($value)) {
list($value, $op) = $value;
switch ($op) {
case '>':
case 'gt':
$orm = $orm->whereGt($column, $value);
break;
}
} else {
$orm = $orm->where($column, $value);
}
}
return $orm;
}
protected function parseOrder($orm)
{
if ($this->order == null) {
return $orm;
}
foreach ($this->order as $column => $order) {
if (is_numeric($column)) {
$column = $order;
$order = 'asc';
}
switch (strtolower($order)) {
case 'asc':
default:
$orm = $orm->orderByAsc($column);
break;
case 'desc':
$orm = $orm->orderByDesc($column);
break;
case 'expr':
$orm = $orm->orderByExpr($column);
break;
}
}
return $orm;
}
protected function parseLimit($orm)
{
if ($this->limit == null) {
return $orm;
}
$orm = $orm->limit($this->limit->limit);
if (isset($this->limit->offset)) {
$orm = $orm->offset($this->limit->offset);
}
return $orm;
}
protected function findAggregator()
{
$model = $this->modelName($this->class);
$ids = $this->getIds($model);
$class = $this->class;
if (count($ids) == 0) {
return false;
}
if ($this->many) {
$objs = [];
foreach ($ids as $id) {
$objs []= new $class($id);
}
} else {
$objs = new $class($ids[0]);
}
return $objs;
}
protected function getIds($model)
{
$id = $this->getModelId($model);
$table = $this->getTable($model);
$st = \ORM::forTable($table)->select($id);
$st = $this->parseConditions($st);
$results = $st->findArray();
$output = array_map(function($a) use($id) {
return $a[$id];
}, $results);
return $output;
}
protected function modelName($class)
{
$arr = explode("\\", $class);
\array_push($arr, end($arr));
return implode("\\", $arr);
}
protected function getModelId($model)
{
$table = $this->getTable($model);
$query = "SHOW KEYS FROM {$table} WHERE Key_name = 'PRIMARY'";
$st = \ORM::getDb()->query($query);
$results = $st->fetchAll(\PDO::FETCH_OBJ);
return $results[0]->Column_name;
}
protected function getTable($model)
{
$arr = explode("\\", $model);
return Stringy::create(end($arr))->toLowerCase() . '';
}
}