diff --git a/src/Filters/GlobalFilters/GlobalFilters.php b/src/Filters/GlobalFilters/GlobalFilters.php index ca38f1ca6..ecc3a01a1 100644 --- a/src/Filters/GlobalFilters/GlobalFilters.php +++ b/src/Filters/GlobalFilters/GlobalFilters.php @@ -52,6 +52,20 @@ public function toArray(): array ]; } + public function isDeclared(string $key): bool + { + return collect(sharp()->config()->get('global_filters')) + ->contains(function (GlobalRequiredFilter $filter) use ($key) { + $filter->buildFilterConfig(); + + if (class_exists($key)) { + return $filter instanceof $key; + } + + return $filter->getKey() === $key; + }); + } + public function findFilter(string $key): ?Filter { return $this->filterContainer()->findFilterHandler($key); diff --git a/src/Http/Context/SharpContext.php b/src/Http/Context/SharpContext.php index 02f6e872c..a72442cc0 100644 --- a/src/Http/Context/SharpContext.php +++ b/src/Http/Context/SharpContext.php @@ -19,10 +19,13 @@ public function globalFilterValue(string $handlerClassOrKey): array|string|null { $handler = $this->globalFiltersHandler->findFilter($handlerClassOrKey); - throw_if( - ! $handler instanceof GlobalRequiredFilter, - new SharpInvalidGlobalFilterKeyException('Filter ['.$handlerClassOrKey.'] is not a global required filter.') - ); + if (! $handler instanceof GlobalRequiredFilter) { + if ($this->globalFiltersHandler->isDeclared($handlerClassOrKey)) { + return null; + } else { + throw new SharpInvalidGlobalFilterKeyException('Filter ['.$handlerClassOrKey.'] is not a global required filter.'); + } + } return $handler->currentValue(); } diff --git a/tests/Http/GlobalFilterControllerTest.php b/tests/Http/GlobalFilterControllerTest.php index c01281e46..b575d055a 100644 --- a/tests/Http/GlobalFilterControllerTest.php +++ b/tests/Http/GlobalFilterControllerTest.php @@ -93,80 +93,3 @@ public function defaultValue(): mixed ); }); }); - -it('does not sends filters of none configured', function () { - sharp()->config()->declareEntity(PersonEntity::class); - - $this - ->followingRedirects() - ->get('/sharp/s-list/person') - ->assertInertia(fn (Assert $page) => $page - ->where('globalFilters', null) - ); -}); - -it('does not sends filters of there have no values', function () { - sharp()->config()->declareEntity(PersonEntity::class); - - sharp()->config()->addGlobalFilter( - new class() extends GlobalRequiredFilter - { - public function buildFilterConfig(): void - { - $this->configureKey('test-no-values'); - } - - public function values(): array - { - return []; - } - - public function defaultValue(): mixed - { - return null; - } - } - ); - - $this - ->followingRedirects() - ->get('/sharp/s-list/person') - ->assertInertia(fn (Assert $page) => $page - ->where('globalFilters', null) - ); - - sharp()->config()->addGlobalFilter( - new class() extends GlobalRequiredFilter - { - public function buildFilterConfig(): void - { - $this->configureKey('test'); - } - - public function values(): array - { - return [ - 1 => 'One', - 2 => 'Two', - 3 => 'Three', - ]; - } - - public function defaultValue(): mixed - { - return 2; - } - } - ); - - $this - ->followingRedirects() - ->get('/sharp/3/s-list/person') - ->assertInertia(fn (Assert $page) => $page - ->has('globalFilters.config.filters._root', 1) - ->has('globalFilters.config.filters._root.0', fn (Assert $filter) => $filter - ->where('key', 'test') - ->etc() - ) - ); -}); diff --git a/tests/Http/GlobalFilterDataTest.php b/tests/Http/GlobalFilterDataTest.php new file mode 100644 index 000000000..18844d2dc --- /dev/null +++ b/tests/Http/GlobalFilterDataTest.php @@ -0,0 +1,153 @@ +config()->declareEntity(PersonEntity::class); +}); + +it('does not sends filters of none configured', function () { + $this + ->followingRedirects() + ->get('/sharp/s-list/person') + ->assertInertia(fn (Assert $page) => $page + ->where('globalFilters', null) + ); +}); + +it('does not sends filters of there have no values', function () { + sharp()->config()->addGlobalFilter( + new class() extends GlobalRequiredFilter + { + public function buildFilterConfig(): void + { + $this->configureKey('test-no-values'); + } + + public function values(): array + { + return []; + } + + public function defaultValue(): mixed + { + return null; + } + } + ); + + $this + ->followingRedirects() + ->get('/sharp/s-list/person') + ->assertInertia(fn (Assert $page) => $page + ->where('globalFilters', null) + ); + + sharp()->config()->addGlobalFilter( + new class() extends GlobalRequiredFilter + { + public function buildFilterConfig(): void + { + $this->configureKey('test'); + } + + public function values(): array + { + return [ + 1 => 'One', + 2 => 'Two', + 3 => 'Three', + ]; + } + + public function defaultValue(): mixed + { + return 2; + } + } + ); + + $this + ->followingRedirects() + ->get('/sharp/3/s-list/person') + ->assertInertia(fn (Assert $page) => $page + ->has('globalFilters.config.filters._root', 1) + ->has('globalFilters.config.filters._root.0', fn (Assert $filter) => $filter + ->where('key', 'test') + ->etc() + ) + ); +}); + +it('globalFilterValue() throws if global filter is not declared', function () { + $this + ->followingRedirects() + ->get('/sharp/s-list/person'); + + expect(fn () => sharp()->context()->globalFilterValue('test'))->toThrow(SharpInvalidGlobalFilterKeyException::class); +}); + +it('globalFilterValue() returns null if global filter is not authorized', function () { + sharp()->config()->addGlobalFilter( + new class() extends GlobalRequiredFilter + { + public function buildFilterConfig(): void + { + $this->configureKey('test'); + } + + public function values(): array + { + return [ + 1 => 'One', + 2 => 'Two', + 3 => 'Three', + ]; + } + + public function defaultValue(): mixed + { + return 2; + } + + public function authorize(): bool + { + return false; + } + } + ); + + $this->get(route('code16.sharp.list', ['globalFilter' => 'root', 'entityKey' => 'person'])); + + expect(sharp()->context()->globalFilterValue('test'))->toBeNull(); +}); + +it('globalFilterValue() returns null if global filter has no values', function () { + sharp()->config()->addGlobalFilter( + new class() extends GlobalRequiredFilter + { + public function buildFilterConfig(): void + { + $this->configureKey('test'); + } + + public function values(): array + { + return []; + } + + public function defaultValue(): mixed + { + return 2; + } + } + ); + + $this->get(route('code16.sharp.list', ['globalFilter' => 'root', 'entityKey' => 'person'])); + + expect(sharp()->context()->globalFilterValue('test'))->toBeNull(); +});