<?php
namespace Cms\CoreBundle\Util\Doctrine;
use App\Util\Querying;
use Cms\ContainerBundle\Entity\Container;
use Cms\CoreBundle\Doctrine\Hydrators\SingleColumnHydrator;
use Cms\CoreBundle\Model\Interfaces\Identifiable\IdentifiableInterface;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\EntityRepository as DoctrineEntityRepository;
/**
* Class EntityRepository
* @package Cms\CoreBundle\Util\Doctrine
*
* @method EntityManager getEntityManager()
*/
abstract class EntityRepository extends DoctrineEntityRepository
{
/**
* @param array $ids
* @return array|object[]
* @throws \Exception
*/
public function findExacts(array $ids)
{
$qb = $this->createQueryBuilder('things')
->andWhere('things.id IN (:ids)')
->setParameter('ids', $ids);
/** @var array|IdentifiableInterface[] $results */
$results = $this->queryMany($qb);
if (count($results) !== count($ids)) {
throw new \Exception();
}
$fixed = [];
foreach ($results as $result) {
$fixed[$result->getId()] = $result;
}
return $results;
}
/**
* @param mixed $id
* @return object
* @throws \Exception
*/
public function findExact($id)
{
if ($id === null) {
throw new \Exception(sprintf(
'No ID was given tying to find one of type "%s".',
$this->_class->name
));
}
$entity = $this->find($id);
if ($entity === null) {
throw new \Exception(sprintf(
'Entity with ID #%s of type "%s" was not found.',
$id,
$this->_class->name
));
}
return $entity;
}
/**
* @param mixed $query
* @param int $limit
* @param int $page
* @return array
*/
public function queryMany($query, $limit = 0, $page = 0)
{
// enforce proper query type
$query = Querying::query($query);
// handle paging
$this->applyPaging($query, $limit, $page);
// get results
return $query->getResult();
}
/**
* @param Query $query
* @param int $limit
* @param int $page
* @return Query
*/
private function applyPaging(Query $query, $limit = 0, $page = 0)
{
// determine if we need to do paging
if ($limit > 0) {
// calculate paging
$first = ($page * $limit);
$max = $limit;
// apply paging
$query->setFirstResult($first);
$query->setMaxResults($max);
}
// chain
return $query;
}
/**
* @param mixed $query
* @return mixed
*/
public function queryOne($query)
{
// enforce proper query type
$query = Querying::query($query);
// force settings
$query->setFirstResult(0);
$query->setMaxResults(1);
// run it
return $query->getOneOrNullResult();
}
/**
* @param mixed $query
* @return array|mixed[]
* @throws \Exception
*/
public function querySingleScalar($query)
{
return $this->queryHydrator($query, SingleColumnHydrator::HYDRATOR);
}
/**
* @param mixed $query
* @param int $limit
* @param int $page
* @return array|mixed[]
* @throws \Exception
*/
public function queryManySingleScalar($query, $limit = 0, $page = 0)
{
return $this->queryManyHydrator($query, SingleColumnHydrator::HYDRATOR, $limit, $page);
}
/**
* @param mixed $query
* @param int $hydrator
* @param int $limit
* @param int $page
* @return array|mixed[]
* @throws \Exception
*/
public function queryManyHydrator($query, $hydrator, $limit = 0, $page = 0)
{
// check for no hydrator
if (empty($hydrator)) {
$hydrator = AbstractQuery::HYDRATE_OBJECT;
}
// enforce proper query type
$query = Querying::query($query);
// do paging
$this->applyPaging($query, $limit, $page);
// run it
return $query->getResult($hydrator);
}
/**
* @param mixed $query
* @param int $hydrator
* @return array|mixed[]
* @throws \Exception
*/
public function queryHydrator($query, $hydrator)
{
// check for no hydrator
if (empty($hydrator)) {
$hydrator = AbstractQuery::HYDRATE_OBJECT;
}
// enforce proper query type
$query = Querying::query($query);
// run it
return $query->getResult($hydrator);
}
/**
* @param mixed $query
* @return int
*/
protected function doUpdate($query)
{
return Querying::query($query)->execute();
}
/**
* @param mixed $query
* @return int
*/
protected function doDelete($query)
{
return Querying::query($query)->execute();
}
/**
* Checks if criteria contains unique values.
*
* @param int $id Skip record with this id
* @param array $criteria
* @return bool
*/
public function isUnique($id, $criteria)
{
$builder = $this->createQueryBuilder('entities');
if ($id) {
$builder
->andWhere('entities.id != :id')
->setParameter('id', $id)
;
}
foreach ((array)$criteria as $field => $value) {
if ($value) {
$builder
->andWhere('entities.'.$field.' = :'.$field)
->setParameter($field, $value)
;
}
}
return is_null($this->queryOne($builder));
}
/**
* @param int|null $limit
* @param int $page
* @param Container|null $container
* @return array
*/
public function findPaginationAll(?int $limit = null, int $page = 0, ?Container $container = null): array
{
$offset = $page > 0 ? $limit * $page : null;
$params = [];
if ($container !== null) {
$params['container'] = $container;
}
return $this->findBy($params, null, $limit, $offset);
}
}