Skip to content

Commit

Permalink
Merge pull request #26 from modera/crub_pagination_fetch_fix
Browse files Browse the repository at this point in the history
[MPFE-1068] ModeraServerCrudBundle: proper pagination fetch for complex queries
  • Loading branch information
sergeil committed Jul 9, 2018
2 parents 84561ee + 7399b2a commit aba8477
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* [MPFE-1049][ModeraSecurityBundle] Clean non-letter characters from First & Last name, except "space" and "-"
* [CLS-1236][ModeraFileRepositoryBundle] Update version for gaufrette library
* [MPFE-984][ModeraTranslationsBundle] Collation utf8_bin is now not necessary for TranslationToken's entity
* [MPFE-1068][ModeraServerCrudBundle] Proper pagination fetch for complex queries

## 2.56.0 (05.10.2017)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Sli\ExtJsIntegrationBundle\QueryBuilder\ExtjsQueryBuilder;

/**
Expand All @@ -19,15 +20,30 @@ class DoctrinePersistenceHandler implements PersistenceHandlerInterface
{
private $em;
private $queryBuilder;
private $usePaginator;

/**
* @param EntityManager $em
* @param ExtjsQueryBuilder $queryBuilder
* @param bool $usePaginator
*/
public function __construct(EntityManager $em, ExtjsQueryBuilder $queryBuilder)
public function __construct(EntityManager $em, ExtjsQueryBuilder $queryBuilder, $usePaginator = true)
{
$this->em = $em;
$this->queryBuilder = $queryBuilder;
$this->usePaginator = $usePaginator;
}

/**
* @param string $entityClass
* @param array $query
* @return Paginator
*/
private function createPaginator($entityClass, array $query)
{
$qb = $this->queryBuilder->buildQueryBuilder($entityClass, $query);

return new Paginator($qb->getQuery());
}

private function resolveEntityId($entity)
Expand Down Expand Up @@ -116,6 +132,10 @@ public function updateBatch(array $entities)
*/
public function query($entityClass, array $query)
{
if ($this->usePaginator) {
return $this->createPaginator($entityClass, $query)->getIterator()->getArrayCopy();
}

return $this->queryBuilder->buildQuery($entityClass, $query)->getResult();
}

Expand All @@ -124,6 +144,10 @@ public function query($entityClass, array $query)
*/
public function getCount($entityClass, array $query)
{
if ($this->usePaginator) {
return $this->createPaginator($entityClass, $query)->count();
}

$qb = $this->queryBuilder->buildQueryBuilder($entityClass, $query);

return $this->queryBuilder->buildCountQueryBuilder($qb)->getQuery()->getSingleScalarResult();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Sli\ExtJsIntegrationBundle\QueryBuilder\ExtjsQueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Sli\ExtJsIntegrationBundle\QueryBuilder\ExtjsQueryBuilder;

/**
* This implementation relies of RegistryInterface so it can support many EntityManagers for entities (previous
Expand All @@ -27,14 +28,33 @@ class DoctrineRegistryPersistenceHandler implements PersistenceHandlerInterface
*/
private $queryBuilder;

/**
* @var bool
*/
private $usePaginator;

/**
* @param RegistryInterface $doctrineRegistry
* @param ExtjsQueryBuilder $queryBuilder
* @param bool $usePaginator
*/
public function __construct(RegistryInterface $doctrineRegistry, ExtjsQueryBuilder $queryBuilder)
public function __construct(RegistryInterface $doctrineRegistry, ExtjsQueryBuilder $queryBuilder, $usePaginator = true)
{
$this->doctrineRegistry = $doctrineRegistry;
$this->queryBuilder = $queryBuilder;
$this->usePaginator = $usePaginator;
}

/**
* @param string $entityClass
* @param array $query
* @return Paginator
*/
private function createPaginator($entityClass, array $query)
{
$qb = $this->queryBuilder->buildQueryBuilder($entityClass, $query);

return new Paginator($qb->getQuery());
}

/**
Expand Down Expand Up @@ -181,6 +201,10 @@ public function updateBatch(array $entities)
*/
public function query($entityClass, array $query)
{
if ($this->usePaginator) {
return $this->createPaginator($entityClass, $query)->getIterator()->getArrayCopy();
}

return $this->queryBuilder->buildQuery($entityClass, $query)->getResult();
}

Expand All @@ -189,6 +213,10 @@ public function query($entityClass, array $query)
*/
public function getCount($entityClass, array $query)
{
if ($this->usePaginator) {
return $this->createPaginator($entityClass, $query)->count();
}

$qb = $this->queryBuilder->buildQueryBuilder($entityClass, $query);

return $this->queryBuilder->buildCountQueryBuilder($qb)->getQuery()->getSingleScalarResult();
Expand Down
73 changes: 73 additions & 0 deletions src/Modera/ServerCrudBundle/Tests/Fixtures/Entity/entities.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Modera\ServerCrudBundle\Tests\Functional;

use Doctrine\ORM\Mapping as Orm;
use Doctrine\Common\Collections\ArrayCollection;

/**
* @Orm\Entity
Expand All @@ -26,6 +27,17 @@ class DummyUser
*/
public $lastname;

/**
* @var ArrayCollection
* @Orm\OneToMany(targetEntity="DummyNote", mappedBy="user")
*/
public $notes;

public function __construct()
{
$this->notes = new ArrayCollection();
}

/**
* @param mixed $id
*/
Expand All @@ -49,6 +61,67 @@ public function setLastname($lastname)
$this->lastname = $lastname;
}

public function addNote(DummyNote $note)
{
if (!$this->notes->contains($note)) {
$note->setUser($this);
$this->notes[] = $note;
}
}

public static function clazz()
{
return get_called_class();
}
}

/**
* @Orm\Entity
*/
class DummyNote
{
/**
* @Orm\Column(type="integer")
* @Orm\Id
* @Orm\GeneratedValue(strategy="AUTO")
*/
public $id;

/**
* @Orm\Column(type="string")
*/
public $text;

/**
* @var DummyUser
* @Orm\ManyToOne(targetEntity="DummyUser", inversedBy="notes")
* @Orm\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;

/**
* @param mixed $id
*/
public function setId($id)
{
$this->id = $id;
}

public function getId()
{
return $this->id;
}

public function setText($text)
{
$this->text = $text;
}

public function setUser(DummyUser $user)
{
$this->user = $user;
}

public static function clazz()
{
return get_called_class();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Modera\ServerCrudBundle\Persistence\OperationResult;
use Sli\AuxBundle\Util\Toolkit;
use Modera\ServerCrudBundle\Tests\Functional\DummyUser;
use Modera\ServerCrudBundle\Tests\Functional\DummyNote;

/**
* @deprecated In favor of DoctrineRegistryPersistenceHandlerTest
Expand All @@ -21,10 +22,12 @@ class DoctrinePersistenceHandlerTest extends FunctionalTestCase
public static function doSetUpBeforeClass()
{
Toolkit::createTableFoEntity(self::$em, DummyUser::clazz());
Toolkit::createTableFoEntity(self::$em, DummyNote::clazz());
}

public static function doTearDownAfterClass()
{
Toolkit::dropTableForEntity(self::$em, DummyNote::clazz());
Toolkit::dropTableForEntity(self::$em, DummyUser::clazz());
}

Expand Down Expand Up @@ -110,16 +113,61 @@ private function loadSomeData()
return $users;
}

public function testQuery()


/**
* @return DummyUser[]
*/
private function loadSomeNotes(DummyUser $user)
{
$this->loadSomeData();
$notes = array();

/* @var DummyUser[] $result */
$result = $this->getHandler()->query(DummyUser::clazz(), array(
'limit' => 5,
for ($i = 0; $i < 3; ++$i) {
$note = new DummyNote();
$note->text = 'Note_'.$i;
$user->addNote($note);

self::$em->persist($note);

$notes[] = $note;
}
self::$em->flush();

return $notes;
}

public function testQuery()
{
$query = array(
'page' => 2,
'start' => 0,
));
'limit' => 5,
);

$users = $this->loadSomeData();

/* @var DummyUser[] $result */
$result = $this->getHandler()->query(DummyUser::clazz(), $query);

$this->assertTrue(is_array($result));
$this->assertEquals(5, count($result));
$this->assertEquals(8, $result[0]->id);

foreach ($users as $user) {
$this->loadSomeNotes($user);
}

$query['filter'] = array(
array(
array(
'property' => 'notes.text',
'value' => 'like:%Note%',
),
)
);

/* @var DummyUser[] $result */
$result = $this->getHandler()->query(DummyUser::clazz(), $query);

$this->assertTrue(is_array($result));
$this->assertEquals(5, count($result));
Expand All @@ -129,14 +177,29 @@ public function testQuery()
public function testGetCount()
{
$query = array(
'limit' => 5,
'page' => 2,
'start' => 0,
'limit' => 5,
);

$this->assertEquals(0, $this->getHandler()->getCount(DummyUser::clazz(), $query));

$this->loadSomeData();
$users = $this->loadSomeData();

$this->assertEquals(10, $this->getHandler()->getCount(DummyUser::clazz(), $query));

foreach ($users as $user) {
$this->loadSomeNotes($user);
}

$query['filter'] = array(
array(
array(
'property' => 'notes.text',
'value' => 'like:%Note%',
),
)
);

$this->assertEquals(10, $this->getHandler()->getCount(DummyUser::clazz(), $query));
}
Expand Down

0 comments on commit aba8477

Please sign in to comment.