From e78b40daffd1c232028e072f922f9dc8e5b57674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Guti=C3=A9rrez?= Date: Sat, 7 Oct 2017 18:08:03 +0200 Subject: [PATCH] manage filters --- README.md | 40 ++++++++- src/FiltersTrait.php | 98 +++++++++++++++++++++++ src/Repository.php | 24 ++++++ tests/Repository/FiltersTraitTest.php | 68 ++++++++++++++++ tests/Repository/Stubs/FilterStub.php | 36 +++++++++ tests/Repository/Stubs/RepositoryStub.php | 10 +++ 6 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 src/FiltersTrait.php create mode 100644 tests/Repository/FiltersTraitTest.php create mode 100644 tests/Repository/Stubs/FilterStub.php diff --git a/README.md b/README.md index 389311d..363a230 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Create your custom repository implementing Repository interface ```php use Doctrine\ORM\EntityRepository; use Jgut\Doctrine\Repository\EventsTrait; +use Jgut\Doctrine\Repository\FiltersTrait; use Jgut\Doctrine\Repository\PaginatorTrait; use Jgut\Doctrine\Repository\Repository; use Jgut\Doctrine\Repository\RepositoryTrait; @@ -37,8 +38,14 @@ class customRepository extends EntityRepository implements Repository { use RepositoryTrait; use EventsTrait; + use FiltersTrait; use PaginatorTrait; + protected function getFilterCollection() + { + // Custom implementation + } + public function countBy($criteria) { // Custom implementation @@ -53,7 +60,7 @@ class customRepository extends EntityRepository implements Repository { // Custom implementation } - + // Custom methods } ``` @@ -198,6 +205,37 @@ $repository->restoreEventListener('onFlush'); // $repository->restoreAllEventListener(); ``` +## Filters managing + +Filters managing is provided by `FiltersTrait` + +### Disabling filters + +You might want to temporarily disable all filters. + +```php +$repository = $manager->getRepository(ObjectClass::class); + +$repository->disableFilters(); +$repository->save(new EntityClass()); +$repository->restoreFilters(); +``` + +### Disabling a single filter + +You might want to disable a single filter. + +```php +$repository = $manager->getRepository(ObjectClass::class); + +$repository->disableFilter('locale'); +$repository->save(new EntityClass()); +$repository->restoreFilter('locale'); +// $repository->restoreFilters(); +``` + +_requires the implementation of getFilterCollection method on custom repository_ + ## Paginating Returns the same results that `findBy` would return but within a `\Zend\Paginator\Paginator` object with pagination information. Provided by `PaginatorTrait` diff --git a/src/FiltersTrait.php b/src/FiltersTrait.php new file mode 100644 index 0000000..0d335fc --- /dev/null +++ b/src/FiltersTrait.php @@ -0,0 +1,98 @@ + + */ + +declare(strict_types=1); + +namespace Jgut\Doctrine\Repository; + +/** + * Filters trait. + */ +trait FiltersTrait +{ + /** + * List of disabled filters. + * + * @var object[] + */ + protected $disabledFilters = []; + + /** + * Disable all filters. + */ + public function disableFilters() + { + foreach (array_keys($this->getFilterCollection()->getEnabledFilters()) as $filter) { + $this->disableFilter($filter); + } + } + + /** + * Disable filter. + * + * @param string $filter + */ + public function disableFilter(string $filter) + { + if (in_array($filter, $this->disabledFilters, true)) { + return; + } + + $this->getFilterCollection()->disable($filter); + + $this->disabledFilters[] = $filter; + } + + /** + * Restore all disabled filters. + */ + public function restoreFilters() + { + $filterCollection = $this->getFilterCollection(); + + foreach ($this->disabledFilters as $filter) { + $filterCollection->enable($filter); + } + + $this->disabledFilters = []; + } + + /** + * Restore disabled filter. + * + * @param string $filter + */ + public function restoreFilter(string $filter) + { + $position = array_search($filter, $this->disabledFilters, true); + if ($position === false) { + return; + } + + $this->getFilterCollection()->enable($filter); + + array_splice($this->disabledFilters, $position, 1); + } + + /** + * Get filter collection. + * + * @return object + */ + abstract protected function getFilterCollection(); + + /** + * Get object manager. + * + * @return \Doctrine\Common\Persistence\ObjectManager + */ + abstract protected function getManager(); +} diff --git a/src/Repository.php b/src/Repository.php index cd35298..7bafd90 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -100,6 +100,30 @@ public function restoreEventListeners(string $event); */ public function getRegisteredEvents(): array; + /** + * Disable all filters. + */ + public function disableFilters(); + + /** + * Disable filter. + * + * @param string $filter + */ + public function disableFilter(string $filter); + + /** + * Restore all disabled filters. + */ + public function restoreFilters(); + + /** + * Restore disabled filter. + * + * @param string $filter + */ + public function restoreFilter(string $filter); + /** * Return paginated elements filtered by criteria. * diff --git a/tests/Repository/FiltersTraitTest.php b/tests/Repository/FiltersTraitTest.php new file mode 100644 index 0000000..a7f6076 --- /dev/null +++ b/tests/Repository/FiltersTraitTest.php @@ -0,0 +1,68 @@ + + */ + +declare(strict_types=1); + +namespace Jgut\Doctrine\Repository\Tests; + +use Doctrine\ORM\Configuration; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Query\FilterCollection; +use Jgut\Doctrine\Repository\Tests\Stubs\FilterStub; +use Jgut\Doctrine\Repository\Tests\Stubs\RepositoryStub; + +/** + * Filters trait tests. + */ +class FiltersTraitTest extends \PHPUnit_Framework_TestCase +{ + public function testFiltersManagement() + { + $manager = $this->getMockBuilder(EntityManager::class) + ->disableOriginalConstructor() + ->getMock(); + /* @var EntityManager $manager */ + + $config = new Configuration(); + $config->addFilter('anything', new FilterStub($manager)); + + $manager->expects(self::any()) + ->method('getConfiguration') + ->will(static::returnValue($config)); + + $filterCollection = new FilterCollection($manager); + $filterCollection->enable('anything'); + + $manager->expects(self::any()) + ->method('getFilters') + ->will(static::returnValue($filterCollection)); + + $repository = new RepositoryStub($manager); + + $repository->disableFilter('anything'); + static::assertCount(0, $filterCollection->getEnabledFilters()); + + $repository->disableFilter('anything'); + static::assertCount(0, $filterCollection->getEnabledFilters()); + + $repository->restoreFilter('unknown'); + static::assertCount(0, $filterCollection->getEnabledFilters()); + + $repository->restoreFilter('anything'); + static::assertCount(1, $filterCollection->getEnabledFilters()); + + $repository->disableFilters(); + static::assertCount(0, $filterCollection->getEnabledFilters()); + + $repository->restoreFilters(); + static::assertCount(1, $filterCollection->getEnabledFilters()); + } +} diff --git a/tests/Repository/Stubs/FilterStub.php b/tests/Repository/Stubs/FilterStub.php new file mode 100644 index 0000000..82aa27b --- /dev/null +++ b/tests/Repository/Stubs/FilterStub.php @@ -0,0 +1,36 @@ + + */ + +declare(strict_types=1); + +namespace Jgut\Doctrine\Repository\Tests\Stubs; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query\Filter\SQLFilter; + +/** + * Filter stub. + */ +class FilterStub extends SQLFilter +{ + /** + * {@inheritdoc} + */ + public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) + { + // Check if the entity implements the LocalAware interface + if (!$targetEntity->reflClass->implementsInterface('anything')) { + return ''; + } + + return $targetTableAlias . '.anything = ' . $this->getParameter('anything'); + } +} diff --git a/tests/Repository/Stubs/RepositoryStub.php b/tests/Repository/Stubs/RepositoryStub.php index 9ba3fe9..3cbf8ac 100644 --- a/tests/Repository/Stubs/RepositoryStub.php +++ b/tests/Repository/Stubs/RepositoryStub.php @@ -16,6 +16,7 @@ use Doctrine\Common\Persistence\Mapping\ClassMetadata; use Doctrine\ORM\EntityManager; use Jgut\Doctrine\Repository\EventsTrait; +use Jgut\Doctrine\Repository\FiltersTrait; use Jgut\Doctrine\Repository\Repository; use Jgut\Doctrine\Repository\RepositoryTrait; use Zend\Paginator\Paginator; @@ -27,6 +28,7 @@ class RepositoryStub implements Repository { use RepositoryTrait; use EventsTrait; + use FiltersTrait; /** * @var EntityManager @@ -127,4 +129,12 @@ protected function getClassMetadata(): ClassMetadata { return new \Doctrine\ORM\Mapping\ClassMetadataInfo(self::class); } + + /** + * {@inheritdoc} + */ + protected function getFilterCollection() + { + return $this->entityManager->getFilters(); + } }