183 lines
5.6 KiB
PHP
183 lines
5.6 KiB
PHP
<?php
|
|
namespace Incoviba\Common\Ideal;
|
|
|
|
use PDO;
|
|
use ReflectionProperty;
|
|
use Incoviba\Common\Define;
|
|
use Incoviba\Common\Implement;
|
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
|
|
|
abstract class Repository implements Define\Repository
|
|
{
|
|
public function __construct(protected Define\Connection $connection) {}
|
|
|
|
protected string $table;
|
|
public function getTable(): string
|
|
{
|
|
return $this->table;
|
|
}
|
|
public function setTable(string $table): Repository
|
|
{
|
|
$this->table = $table;
|
|
return $this;
|
|
}
|
|
|
|
public function load(array $data_row): Define\Model
|
|
{
|
|
$model = $this->create($data_row);
|
|
$model->{$this->getKey()} = $data_row[$this->getKey()];
|
|
return $model;
|
|
}
|
|
|
|
public function remove(Define\Model $model): void
|
|
{
|
|
$query = $this->connection->getQueryBuilder()
|
|
->delete()->from($this->getTable())
|
|
->where("{$this->getKey()} = ?");
|
|
$this->connection->execute($query, [$model->{$this->getKey()}]);
|
|
}
|
|
|
|
/**
|
|
* @throws EmptyResult
|
|
*/
|
|
public function fetchById(int $id): Define\Model
|
|
{
|
|
$query = $this->connection->getQueryBuilder()
|
|
->select()
|
|
->from($this->getTable())
|
|
->where("{$this->getKey()} = ?");
|
|
return $this->fetchOne($query, [$id]);
|
|
}
|
|
|
|
/**
|
|
* @throws EmptyResult
|
|
*/
|
|
public function fetchAll(null|string|array $ordering = null): array
|
|
{
|
|
$query = $this->connection->getQueryBuilder()
|
|
->select()
|
|
->from($this->getTable());
|
|
if ($ordering !== null) {
|
|
$query->order($ordering);
|
|
}
|
|
return $this->fetchMany($query);
|
|
}
|
|
|
|
protected string $key = 'id';
|
|
public function setKey(string $key): Repository
|
|
{
|
|
$this->key = $key;
|
|
return $this;
|
|
}
|
|
protected function getKey(): string
|
|
{
|
|
return $this->key;
|
|
}
|
|
protected function parseData(Define\Model $model, ?array $data, Implement\Repository\MapperParser $data_map): Define\Model
|
|
{
|
|
if ($data === null) {
|
|
return $model;
|
|
}
|
|
foreach ($data_map->getColumns() as $column) {
|
|
if (!$data_map->hasMapper($column)) {
|
|
$this->parsePlainColumn($model, $column, $data);
|
|
continue;
|
|
}
|
|
|
|
$settings = $data_map->getMapper($column);
|
|
if ($settings->parse($model, $column, $data)) {
|
|
continue;
|
|
}
|
|
$property = $column;
|
|
if ($settings->hasProperty()) {
|
|
$property = $settings->property;
|
|
}
|
|
$this->setDefault($model, $property);
|
|
}
|
|
return $model;
|
|
}
|
|
protected function parsePlainColumn(Define\Model &$model, string $column, ?array $data): void
|
|
{
|
|
$property = $column;
|
|
if (isset($data[$column])) {
|
|
$model->{$property} = $data[$column];
|
|
return;
|
|
}
|
|
$this->setDefault($model, $property);
|
|
}
|
|
protected function setDefault(Define\Model &$model, string $property): void
|
|
{
|
|
$prop = new ReflectionProperty($model, $property);
|
|
$type = $prop->getType()->getName();
|
|
$value = match ($type) {
|
|
'int' => 0,
|
|
'float' => 0.0,
|
|
'string' => '',
|
|
default => null,
|
|
};
|
|
$model->{$property} = $value;
|
|
}
|
|
protected function saveNew(array $columns, array $values): int
|
|
{
|
|
$query = $this->connection->getQueryBuilder()
|
|
->insert()
|
|
->into($this->getTable())
|
|
->columns($columns)
|
|
->values(array_fill(0, count($columns), '?'));
|
|
$this->connection->execute($query, $values);
|
|
return $this->connection->getPDO()->lastInsertId();
|
|
}
|
|
protected function update(Define\Model $model, array $columns, array $data): Define\Model
|
|
{
|
|
$changes = [];
|
|
$values = [];
|
|
foreach ($columns as $column) {
|
|
if (in_array($column, array_keys($data))) {
|
|
$changes []= $column;
|
|
$values []= $data[$column];
|
|
}
|
|
}
|
|
|
|
if (count($changes) === 0) {
|
|
return $model;
|
|
}
|
|
$columns_string = implode(', ', array_map(function($property) {return "`{$property}` = ?";}, $changes));
|
|
$query = $this->connection->getQueryBuilder()
|
|
->update($this->getTable())
|
|
->set($columns_string)
|
|
->where("{$this->getKey()} = ?");
|
|
$values []= $model->{$this->getKey()};
|
|
$this->connection->execute($query, $values);
|
|
return $this->fetchById($model->{$this->getKey()});
|
|
}
|
|
protected function fetchOne(string $query, ?array $data = null): Define\Model
|
|
{
|
|
$result = $this->connection->execute($query, $data)->fetch(PDO::FETCH_ASSOC);
|
|
if ($result === false) {
|
|
throw new EmptyResult($query);
|
|
}
|
|
return $this->load($result);
|
|
}
|
|
protected function fetchMany(string $query, ?array $data = null): array
|
|
{
|
|
$results = $this->connection->execute($query, $data)->fetchAll(PDO::FETCH_ASSOC);
|
|
if ($results === false) {
|
|
throw new EmptyResult($query);
|
|
}
|
|
return array_map([$this, 'load'], $results);
|
|
}
|
|
protected function fetchAsArray(string $query, ?array $data = null): array
|
|
{
|
|
$results = $this->connection->execute($query, $data)->fetchAll(PDO::FETCH_ASSOC);
|
|
if ($results === false) {
|
|
throw new EmptyResult($query);
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
public function filterData(array $data): array
|
|
{
|
|
return $data;
|
|
}
|
|
}
|