szurubooru/src/Dao/AbstractDao.php

251 lines
6.5 KiB
PHP
Raw Normal View History

<?php
namespace Szurubooru\Dao;
abstract class AbstractDao implements ICrudDao
{
2014-09-14 16:16:15 +02:00
protected $pdo;
protected $fpdo;
protected $tableName;
2014-08-30 17:10:45 +02:00
protected $entityConverter;
2014-08-30 17:10:45 +02:00
public function __construct(
\Szurubooru\DatabaseConnection $databaseConnection,
2014-09-14 16:16:15 +02:00
$tableName,
\Szurubooru\Dao\EntityConverters\IEntityConverter $entityConverter)
{
2014-09-21 09:35:43 +02:00
$this->setDatabaseConnection($databaseConnection);
$this->tableName = $tableName;
$this->entityConverter = $entityConverter;
$this->entityConverter->setEntityDecorator(function($entity)
{
$this->afterLoad($entity);
});
}
2014-09-14 16:16:15 +02:00
public function getTableName()
{
2014-09-14 16:16:15 +02:00
return $this->tableName;
}
public function getEntityConverter()
{
return $this->entityConverter;
}
public function save(&$entity)
{
if ($entity->getId())
{
2014-09-15 11:38:24 +02:00
$entity = $this->update($entity);
}
else
{
2014-09-15 11:38:24 +02:00
$entity = $this->create($entity);
}
2014-09-15 11:38:24 +02:00
$this->afterSave($entity);
return $entity;
}
public function findAll()
{
2014-09-14 16:16:15 +02:00
$query = $this->fpdo->from($this->tableName);
2014-09-23 20:45:59 +02:00
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
}
public function findById($entityId)
{
2014-09-21 09:35:43 +02:00
return $this->findOneBy($this->getIdColumn(), $entityId);
}
public function findByIds($entityIds)
{
return $this->findBy($this->getIdColumn(), $entityIds);
}
2014-09-26 19:14:34 +02:00
public function findFiltered(\Szurubooru\SearchServices\Filters\IFilter $searchFilter)
2014-09-23 20:45:59 +02:00
{
2014-09-27 10:59:37 +02:00
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
2014-09-23 20:45:59 +02:00
2014-09-26 19:14:34 +02:00
$orderByString = self::compileOrderBy($searchFilter->getOrder());
if ($orderByString)
$query->orderBy($orderByString);
$this->decorateQueryFromFilter($query, $searchFilter);
if ($searchFilter->getPageSize() > 0)
{
$query->limit($searchFilter->getPageSize());
$query->offset($searchFilter->getPageSize() * ($searchFilter->getPageNumber() - 1));
}
2014-09-23 20:45:59 +02:00
$entities = $this->arrayToEntities(iterator_to_array($query));
2014-09-24 20:13:16 +02:00
2014-09-27 10:59:37 +02:00
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
2014-09-26 19:14:34 +02:00
$this->decorateQueryFromFilter($query, $searchFilter);
2014-09-24 20:13:16 +02:00
$totalRecords = count($query);
2014-09-23 20:45:59 +02:00
2014-09-26 19:14:34 +02:00
$searchResult = new \Szurubooru\SearchServices\Result();
$searchResult->setSearchFilter($searchFilter);
$searchResult->setEntities($entities);
$searchResult->setTotalRecords($totalRecords);
$searchResult->setPageNumber($searchFilter->getPageNumber());
$searchResult->setPageSize($searchFilter->getPageSize());
return $searchResult;
2014-09-23 20:45:59 +02:00
}
public function deleteAll()
{
foreach ($this->findAll() as $entity)
{
$this->beforeDelete($entity);
}
2014-09-14 16:16:15 +02:00
$this->fpdo->deleteFrom($this->tableName)->execute();
}
public function deleteById($entityId)
{
2014-09-21 09:35:43 +02:00
return $this->deleteBy($this->getIdColumn(), $entityId);
2014-09-14 16:16:15 +02:00
}
2014-09-15 11:38:24 +02:00
protected function update(\Szurubooru\Entities\Entity $entity)
{
$arrayEntity = $this->entityConverter->toArray($entity);
2014-09-21 09:35:43 +02:00
$this->fpdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
2014-09-15 11:38:24 +02:00
return $entity;
}
protected function create(\Szurubooru\Entities\Entity $entity)
{
$arrayEntity = $this->entityConverter->toArray($entity);
$this->fpdo->insertInto($this->tableName)->values($arrayEntity)->execute();
$entity->setId(intval($this->pdo->lastInsertId()));
return $entity;
}
2014-09-21 09:35:43 +02:00
protected function getIdColumn()
{
return 'id';
}
2014-09-14 16:16:15 +02:00
protected function hasAnyRecords()
{
return count(iterator_to_array($this->fpdo->from($this->tableName)->limit(1))) > 0;
}
protected function findBy($columnName, $value)
{
2014-09-28 16:26:44 +02:00
if (is_array($value) and empty($value))
return [];
$query = $this->fpdo->from($this->tableName)->where($columnName, $value);
2014-09-27 21:33:31 +02:00
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
}
2014-09-14 16:16:15 +02:00
protected function findOneBy($columnName, $value)
{
$arrayEntities = $this->findBy($columnName, $value);
if (!$arrayEntities)
2014-09-15 11:38:24 +02:00
return null;
return array_shift($arrayEntities);
2014-09-14 16:16:15 +02:00
}
protected function deleteBy($columnName, $value)
{
foreach ($this->findBy($columnName, $value) as $entity)
{
$this->beforeDelete($entity);
}
2014-09-14 16:16:15 +02:00
$this->fpdo->deleteFrom($this->tableName)->where($columnName, $value)->execute();
}
2014-09-15 11:38:24 +02:00
protected function afterLoad(\Szurubooru\Entities\Entity $entity)
{
}
protected function afterSave(\Szurubooru\Entities\Entity $entity)
{
}
protected function beforeDelete(\Szurubooru\Entities\Entity $entity)
{
}
2014-09-23 20:45:59 +02:00
2014-09-27 10:59:37 +02:00
protected function decorateQueryFromRequirement($query, \Szurubooru\SearchServices\Requirements\Requirement $requirement)
{
$value = $requirement->getValue();
$sqlColumn = $requirement->getType();
if ($value instanceof \Szurubooru\SearchServices\Requirements\RequirementCompositeValue)
{
$sql = $sqlColumn;
$bindings = [$value->getValues()];
}
else if ($value instanceof \Szurubooru\SearchServices\Requirements\RequirementRangedValue)
{
if ($value->getMinValue() and $value->getMaxValue())
{
$sql = $sqlColumn . ' >= ? AND ' . $sqlColumn . ' <= ?';
$bindings = [$value->getMinValue(), $value->getMaxValue()];
}
elseif ($value->getMinValue())
{
$sql = $sqlColumn . ' >= ?';
$bindings = [$value->getMinValue()];
}
elseif ($value->getMaxValue())
{
$sql = $sqlColumn . ' <= ?';
$bindings = [$value->getMaxValue()];
}
else
throw new \RuntimeException('Neither min or max value was supplied');
}
else if ($value instanceof \Szurubooru\SearchServices\Requirements\RequirementSingleValue)
{
$sql = $sqlColumn;
$bindings = [$value->getValue()];
}
else
throw new \Exception('Bad value: ' . get_class($value));
if ($requirement->isNegated())
$sql = 'NOT (' . $sql . ')';
call_user_func_array([$query, 'where'], array_merge([$sql], $bindings));
}
2014-09-23 20:45:59 +02:00
protected function arrayToEntities(array $arrayEntities)
{
$entities = [];
foreach ($arrayEntities as $arrayEntity)
{
$entity = $this->entityConverter->toEntity($arrayEntity);
$entities[$entity->getId()] = $entity;
}
return $entities;
}
private function setDatabaseConnection(\Szurubooru\DatabaseConnection $databaseConnection)
{
$this->pdo = $databaseConnection->getPDO();
$this->fpdo = new \FluentPDO($this->pdo);
}
2014-09-26 19:14:34 +02:00
private function decorateQueryFromFilter($query, \Szurubooru\SearchServices\Filters\IFilter $filter)
2014-09-24 20:13:16 +02:00
{
2014-09-26 19:14:34 +02:00
foreach ($filter->getRequirements() as $requirement)
{
2014-09-27 10:59:37 +02:00
$this->decorateQueryFromRequirement($query, $requirement);
2014-09-26 19:14:34 +02:00
}
2014-09-24 20:13:16 +02:00
}
private static function compileOrderBy($order)
2014-09-23 20:45:59 +02:00
{
$orderByString = '';
foreach ($order as $orderColumn => $orderDir)
2014-09-26 19:14:34 +02:00
$orderByString .= $orderColumn . ' ' . ($orderDir === \Szurubooru\SearchServices\Filters\IFilter::ORDER_DESC ? 'DESC' : 'ASC') . ', ';
2014-09-23 20:45:59 +02:00
return substr($orderByString, 0, -2);
}
}