247 lines
7.2 KiB
PHP
247 lines
7.2 KiB
PHP
<?php
|
|
namespace ProVM\Alias\Model;
|
|
|
|
use ProVM\Concept\Database\Connection;
|
|
use ProVM\Concept\Database\QueryBuilder;
|
|
use ProVM\Concept\Model;
|
|
use ProVM\Concept\Model\Factory;
|
|
use ProVM\Concept\Model\Repository as RepositoryInterface;
|
|
|
|
abstract class Repository implements RepositoryInterface
|
|
{
|
|
public function __construct(Connection $connection, QueryBuilder $builder, Factory $factory)
|
|
{
|
|
$this->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 $model;
|
|
public function setModel(string $model_class): RepositoryInterface
|
|
{
|
|
$this->model = $model_class;
|
|
return $this;
|
|
}
|
|
public function getModel(): string
|
|
{
|
|
return $this->model;
|
|
}
|
|
public function getNewModel(): Model
|
|
{
|
|
$class = $this->getModel();
|
|
return (new $class())
|
|
->setRepository($this);
|
|
}
|
|
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;
|
|
}
|
|
protected array $required;
|
|
public function setRequired(array $columns): RepositoryInterface
|
|
{
|
|
foreach ($columns as $item) {
|
|
$this->addRequired($item);
|
|
}
|
|
return $this;
|
|
}
|
|
public function addRequired(string $column): RepositoryInterface
|
|
{
|
|
$this->required []= $column;
|
|
return $this;
|
|
}
|
|
public function getRequired(): array
|
|
{
|
|
if (isset($this->optional) and !isset($this->required)) {
|
|
return array_diff($this->getColumns(), $this->getOptional());
|
|
}
|
|
return $this->required ?? $this->getColumns();
|
|
}
|
|
protected array $optional;
|
|
public function setOptional(array $columns): RepositoryInterface
|
|
{
|
|
foreach ($columns as $item) {
|
|
$this->addColumn($item);
|
|
}
|
|
return $this;
|
|
}
|
|
public function addOptional(string $column): RepositoryInterface
|
|
{
|
|
$this->optional []= $column;
|
|
return $this;
|
|
}
|
|
public function getOptional(): array
|
|
{
|
|
if (isset($this->required) and !isset($this->optional)) {
|
|
return array_diff($this->getColumns(), $this->getRequired());
|
|
}
|
|
return $this->optional ?? [];
|
|
}
|
|
|
|
public function getMethod(string $column, bool $get = true): string
|
|
{
|
|
$m = str_replace(' ', '', ucwords(str_replace('_', ' ', $column)));
|
|
if ($get) {
|
|
return "get{$m}";
|
|
}
|
|
return "set{$m}";
|
|
}
|
|
public function getProperty(string $method): string
|
|
{
|
|
$parts = preg_split('/(?=[A-Z])/', $method);
|
|
if (in_array(strtolower($parts[0]), ['get', 'set'])) {
|
|
array_shift($parts);
|
|
}
|
|
return strtolower(implode('_', $parts));
|
|
}
|
|
public function fillData(Model $model, array $data): Model
|
|
{
|
|
foreach ($this->getRequired() as $column) {
|
|
$m = 'set' . ucwords($column);
|
|
$model->{$m}($data[$column]);
|
|
}
|
|
foreach ($this->getOptional() as $column) {
|
|
if (isset($data[$column])) {
|
|
$m = 'set' . ucwords($column);
|
|
$model->{$m}($data[$column]);
|
|
}
|
|
}
|
|
return $model;
|
|
}
|
|
public function mapArray(Model $model, array $data): array
|
|
{
|
|
foreach ($this->getColumns() as $column) {
|
|
$m = $this->getMethod($column);
|
|
$val = $model->{$m}();
|
|
if (isset($data[$column])) {
|
|
continue;
|
|
}
|
|
$data[$column] = $val;
|
|
}
|
|
return $data;
|
|
}
|
|
public function load(array $data): Model
|
|
{
|
|
return $this->fillData($this->getNewModel()
|
|
->setId($data['id']), $data);
|
|
}
|
|
public function save(Model $model): void
|
|
{
|
|
if (!$model->isDirty() and !$model->isNew()) {
|
|
return;
|
|
}
|
|
if (!$model->isNew()) {
|
|
$this->update($model);
|
|
return;
|
|
}
|
|
$values = $this->mapArray($model, []);
|
|
$cols = array_fill(0, count($values), '?');
|
|
$query = $this->getQueryBuilder()->insert($this->getTable())->columns($this->getColumns())->values($cols);
|
|
$this->getConnection()->execute($query, $values);
|
|
}
|
|
public function update(Model $model): void
|
|
{
|
|
if (!$model->isDirty() and !$model->isNew()) {
|
|
return;
|
|
}
|
|
$values = $this->mapArray($model, []);
|
|
$cols = array_map(function($column) {
|
|
return "{$column} = ?";
|
|
}, $values);
|
|
$values = array_values($values);
|
|
$values []= $model->getId();
|
|
$query = $this->getQueryBuilder()->update($this->getTable())->set($cols)->where(['id = ?']);
|
|
$this->getConnection()->execute($query, $values);
|
|
}
|
|
public function create(array $data): Model
|
|
{
|
|
return $this->fillData($this->getNewModel()
|
|
->setNew(), $data);
|
|
}
|
|
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 delete(Model $model): void
|
|
{
|
|
$query = $this->getQueryBuilder()->delete($this->getTable())->where(['id = ?']);
|
|
$this->getConnection()->execute($query, [$model->getId()]);
|
|
}
|
|
|
|
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());
|
|
}
|
|
}
|