Skip to content

Commit

Permalink
simplify countBy
Browse files Browse the repository at this point in the history
  • Loading branch information
juliangut committed Apr 5, 2017
1 parent 9cf27eb commit 6b66820
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 100 deletions.
98 changes: 37 additions & 61 deletions src/RelationalRepository.php
Expand Up @@ -77,28 +77,54 @@ protected function getManager(): EntityManager
/**
* {@inheritdoc}
*
* @param array|QueryBuilder $criteria
* @param array|null $orderBy
* @param int $itemsPerPage
*
* @throws \InvalidArgumentException
* @param array $criteria
* @param array|null $orderBy
* @param int $itemsPerPage
*
* @return \Zend\Paginator\Paginator
*/
public function findPaginatedBy($criteria, array $orderBy = [], int $itemsPerPage = 10): Paginator
{
$queryBuilder = $this->createQueryBuilderFromCriteria($criteria);
$entityAlias = count($queryBuilder->getRootAliases())
? $queryBuilder->getRootAliases()[0]
: $this->getClassAlias();
$queryBuilder = $this->getQueryBuilderFromCriteria($criteria, $orderBy);

return $this->paginate($queryBuilder->getQuery(), $itemsPerPage);
}

/**
* Get query builder from criteria array.
*
* @param array $criteria
* @param array $orderBy
*
* @return QueryBuilder
*/
protected function getQueryBuilderFromCriteria(array $criteria, array $orderBy = []): QueryBuilder
{
$entityAlias = $this->getClassAlias();
$queryBuilder = $this->createQueryBuilder($entityAlias);

foreach ($criteria as $field => $value) {
if (is_null($value)) {
$queryBuilder->andWhere(sprintf('%s.%s IS NULL', $entityAlias, $field));
} else {
$parameter = sprintf('%s_%s', $field, substr(sha1($field), 0, 4));

$queryBuilder->andWhere(sprintf('%s.%s = :%s', $entityAlias, $field, $parameter));
$queryBuilder->setParameter($parameter, $value);
}
}

if (is_array($orderBy)) {
$entityAlias = count($queryBuilder->getRootAliases())
? $queryBuilder->getRootAliases()[0]
: $this->getClassAlias();

foreach ($orderBy as $field => $order) {
$queryBuilder->addOrderBy($entityAlias . '.' . $field, $order);
}
}

return $this->paginate($queryBuilder->getQuery(), $itemsPerPage);
return $queryBuilder;
}

/**
Expand All @@ -119,60 +145,10 @@ protected function paginate(Query $query, int $itemsPerPage = 10): Paginator
*
* @param array|QueryBuilder $criteria
*
* @throws \InvalidArgumentException
*
* @return int
*/
public function countBy($criteria): int
{
$queryBuilder = $this->createQueryBuilderFromCriteria($criteria);
$entityAlias = count($queryBuilder->getRootAliases())
? $queryBuilder->getRootAliases()[0]
: $this->getClassAlias();

return (int) $queryBuilder
->select('COUNT(' . $entityAlias . ')')
->getQuery()
->getSingleScalarResult();
}

/**
* Create query builder based on provided simple criteria.
*
* @param array|QueryBuilder $criteria
*
* @throws \InvalidArgumentException
*
* @return QueryBuilder
*/
protected function createQueryBuilderFromCriteria($criteria): QueryBuilder
{
if ($criteria instanceof QueryBuilder) {
return $criteria;
}

if (!is_array($criteria)) {
throw new \InvalidArgumentException(sprintf(
'Criteria must be an array of query fields or a %s',
QueryBuilder::class
));
}

$entityAlias = $this->getClassAlias();
$queryBuilder = $this->createQueryBuilder($entityAlias);

/* @var array $criteria */
foreach ($criteria as $field => $value) {
if (is_null($value)) {
$queryBuilder->andWhere(sprintf('%s.%s IS NULL', $entityAlias, $field));
} else {
$parameter = sprintf('%s_%s', $field, substr(sha1($field), 0, 4));

$queryBuilder->andWhere(sprintf('%s.%s = :%s', $entityAlias, $field, $parameter));
$queryBuilder->setParameter($parameter, $value);
}
}

return $queryBuilder;
return $this->getEntityManager()->getUnitOfWork()->getEntityPersister($this->getEntityName())->count($criteria);
}
}
55 changes: 16 additions & 39 deletions tests/ORM/RelationalRepositoryTest.php
Expand Up @@ -13,10 +13,10 @@

namespace Jgut\Doctrine\Repository\ORM\Tests;

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister;
use Doctrine\ORM\UnitOfWork;
use Jgut\Doctrine\Repository\ORM\RelationalRepository;
use Jgut\Doctrine\Repository\ORM\Tests\Stubs\EntityStub;
use Jgut\Doctrine\Repository\ORM\Tests\Stubs\RepositoryStub;
Expand Down Expand Up @@ -51,57 +51,34 @@ public function testEntityManager()
static::assertSame($manager, $repository->getManager());
}

/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Criteria must be an array of query fields or a Doctrine\ORM\QueryBuilder
*/
public function testInvalidCriteria()
{
$manager = $this->getMockBuilder(EntityManager::class)
->disableOriginalConstructor()
->getMock();
/* @var EntityManager $manager */

$repository = new RelationalRepository($manager, new ClassMetadata(EntityStub::class));

$repository->findPaginatedBy('');
}

public function testCount()
{
$query = $this->getMockBuilder(AbstractQuery::class)
$persister = $this->getMockBuilder(BasicEntityPersister::class)
->disableOriginalConstructor()
->getMock();
$query->expects(static::exactly(2))
->method('getSingleScalarResult')
$persister->expects(static::once())
->method('count')
->will(static::returnValue(10));
/* @var BasicEntityPersister $persister */

$manager = $this->getMockBuilder(EntityManager::class)
$uow = $this->getMockBuilder(UnitOfWork::class)
->disableOriginalConstructor()
->getMock();
$uow->expects(static::once())
->method('getEntityPersister')
->will(static::returnValue($persister));
/* @var UnitOfWork $uow */

$queryBuilder = $this->getMockBuilder(QueryBuilder::class)
->setConstructorArgs([$manager])
->setMethodsExcept(['select', 'from', 'andWhere', 'setParameter', 'add'])
$manager = $this->getMockBuilder(EntityManager::class)
->disableOriginalConstructor()
->getMock();
$queryBuilder->expects(static::exactly(2))
->method('getQuery')
->will(static::returnValue($query));
/* @var QueryBuilder $queryBuilder */

$manager->expects(static::once())
->method('createQueryBuilder')
->will(static::returnValue($queryBuilder));
->method('getUnitOfWork')
->will(static::returnValue($uow));
/* @var EntityManager $manager */

$repository = new RelationalRepository($manager, new ClassMetadata(EntityStub::class));

static::assertEquals(10, $repository->countBy($queryBuilder));

$queryBuilder->expects(static::exactly(2))
->method('getRootAliases')
->will(static::returnValue(['a']));

static::assertEquals(10, $repository->countBy(['fakeField' => 'fakeValue', 'nullFakeField' => null]));
static::assertEquals(10, $repository->countBy([]));
}
}

0 comments on commit 6b66820

Please sign in to comment.