From b3a02c77e74bb7686ec860a91728af8347e3b26f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 16 Mar 2021 14:55:29 +0100 Subject: [PATCH 1/2] Introduce interface `ipl\Stdlib\Contract\Filterable` --- src/Contract/Filterable.php | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/Contract/Filterable.php diff --git a/src/Contract/Filterable.php b/src/Contract/Filterable.php new file mode 100644 index 0000000..2a6316a --- /dev/null +++ b/src/Contract/Filterable.php @@ -0,0 +1,63 @@ + Date: Fri, 19 Mar 2021 12:05:37 +0100 Subject: [PATCH 2/2] Introduce trait `ipl\Stdlib\Filters` --- src/Filters.php | 58 ++++++++++++++ tests/FiltersTest.php | 125 ++++++++++++++++++++++++++++++ tests/FiltersTest/FiltersUser.php | 11 +++ 3 files changed, 194 insertions(+) create mode 100644 src/Filters.php create mode 100644 tests/FiltersTest.php create mode 100644 tests/FiltersTest/FiltersUser.php diff --git a/src/Filters.php b/src/Filters.php new file mode 100644 index 0000000..defff43 --- /dev/null +++ b/src/Filters.php @@ -0,0 +1,58 @@ +filter ?: Filter::all(); + } + + public function filter(Filter\Rule $filter) + { + $currentFilter = $this->getFilter(); + if ($currentFilter instanceof Filter\All) { + $this->filter = $currentFilter->add($filter); + } else { + $this->filter = Filter::all($filter); + if (! $currentFilter->isEmpty()) { + $this->filter->insertBefore($currentFilter, $filter); + } + } + + return $this; + } + + public function orFilter(Filter\Rule $filter) + { + $currentFilter = $this->getFilter(); + if ($currentFilter instanceof Filter\Any) { + $this->filter = $currentFilter->add($filter); + } else { + $this->filter = Filter::any($filter); + if (! $currentFilter->isEmpty()) { + $this->filter->insertBefore($currentFilter, $filter); + } + } + + return $this; + } + + public function notFilter(Filter\Rule $filter) + { + $this->filter(Filter::none($filter)); + + return $this; + } + + public function orNotFilter(Filter\Rule $filter) + { + $this->orFilter(Filter::none($filter)); + + return $this; + } +} diff --git a/tests/FiltersTest.php b/tests/FiltersTest.php new file mode 100644 index 0000000..7ad642d --- /dev/null +++ b/tests/FiltersTest.php @@ -0,0 +1,125 @@ +filterable = new FiltersUser(); + } + + public function testFilterKeepsCurrentHierarchy() + { + $this->filterable->filter(Filter::equal('', '')); + $this->filterable->filter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::all( + Filter::equal('', ''), + Filter::unequal('', '') + )); + } + + public function testFilterWrapsCurrentHierarchy() + { + $this->filterable->orFilter(Filter::equal('', '')); + $this->filterable->filter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::all( + Filter::any(Filter::equal('', '')), + Filter::unequal('', '') + )); + } + + public function testOrFilterKeepsCurrentHierarchy() + { + $this->filterable->orFilter(Filter::equal('', '')); + $this->filterable->orFilter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::any( + Filter::equal('', ''), + Filter::unequal('', '') + )); + } + + public function testOrFilterWrapsCurrentHierarchy() + { + $this->filterable->filter(Filter::equal('', '')); + $this->filterable->orFilter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::any( + Filter::all(Filter::equal('', '')), + Filter::unequal('', '') + )); + } + + public function testNotFilterKeepsCurrentHierarchy() + { + $this->filterable->notFilter(Filter::equal('', '')); + $this->filterable->notFilter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::all( + Filter::none(Filter::equal('', '')), + Filter::none(Filter::unequal('', '')) + )); + } + + public function testNotFilterWrapsCurrentHierarchy() + { + $this->filterable->orFilter(Filter::equal('', '')); + $this->filterable->notFilter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::all( + Filter::any(Filter::equal('', '')), + Filter::none(Filter::unequal('', '')) + )); + } + + public function testOrNotFilterKeepsCurrentHierarchy() + { + $this->filterable->orNotFilter(Filter::equal('', '')); + $this->filterable->orNotFilter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::any( + Filter::none(Filter::equal('', '')), + Filter::none(Filter::unequal('', '')) + )); + } + + public function testOrNotFilterWrapsCurrentHierarchy() + { + $this->filterable->filter(Filter::equal('', '')); + $this->filterable->orNotFilter(Filter::unequal('', '')); + + $this->assertSameFilterHierarchy(Filter::any( + Filter::all(Filter::equal('', '')), + Filter::none(Filter::unequal('', '')) + )); + } + + protected function assertSameFilterHierarchy(Filter\Chain $expected) + { + $actual = $this->filterable->getFilter(); + + $checkHierarchy = function ($expected, $actual) use (&$checkHierarchy) { + $expectedArray = iterator_to_array($expected); + $actualArray = iterator_to_array($actual); + foreach ($expectedArray as $key => $rule) { + $this->assertTrue(isset($actualArray[$key])); + $this->assertInstanceOf(get_class($rule), $actualArray[$key]); + if ($rule instanceof Filter\Chain) { + $checkHierarchy($rule, $actualArray[$key]); + } + } + }; + + $checkHierarchy($expected, $actual); + } +} diff --git a/tests/FiltersTest/FiltersUser.php b/tests/FiltersTest/FiltersUser.php new file mode 100644 index 0000000..7342cf9 --- /dev/null +++ b/tests/FiltersTest/FiltersUser.php @@ -0,0 +1,11 @@ +