Skip to content

Commit 700f6e4

Browse files
authored
Merge pull request #7823 from kenjis/fix-filter-except
fix: filter except empty
2 parents 0665d5f + e510da9 commit 700f6e4

File tree

3 files changed

+142
-41
lines changed

3 files changed

+142
-41
lines changed

system/Filters/Filters.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ public function setResponse(ResponseInterface $response)
156156
* Runs through all of the filters for the specified
157157
* uri and position.
158158
*
159-
* @return mixed|RequestInterface|ResponseInterface
159+
* @param string $uri URI path relative to baseURL
160+
*
161+
* @return RequestInterface|ResponseInterface|string|null
160162
*
161163
* @throws FilterException
162164
*/
@@ -221,6 +223,8 @@ public function run(string $uri, string $position = 'before')
221223
* run through both a before and after and don't want to double
222224
* process the rows.
223225
*
226+
* @param string|null $uri URI path relative to baseURL (all lowercase)
227+
*
224228
* @return Filters
225229
*/
226230
public function initialize(?string $uri = null)
@@ -391,7 +395,7 @@ public function getArguments(?string $key = null)
391395
/**
392396
* Add any applicable (not excluded) global filter settings to the mix.
393397
*
394-
* @param string $uri
398+
* @param string|null $uri URI path relative to baseURL (all lowercase)
395399
*
396400
* @return void
397401
*/
@@ -416,7 +420,7 @@ protected function processGlobals(?string $uri = null)
416420
if (isset($rules['except'])) {
417421
// grab the exclusion rules
418422
$check = $rules['except'];
419-
if ($this->pathApplies($uri, $check)) {
423+
if ($this->checkExcept($uri, $check)) {
420424
$keep = false;
421425
}
422426
}
@@ -454,7 +458,7 @@ protected function processMethods()
454458
/**
455459
* Add any applicable configured filters to the mix.
456460
*
457-
* @param string $uri
461+
* @param string|null $uri URI path relative to baseURL (all lowercase)
458462
*
459463
* @return void
460464
*/
@@ -536,12 +540,47 @@ private function pathApplies(string $uri, $paths)
536540
$paths = [$paths];
537541
}
538542

539-
// treat each paths as pseudo-regex
543+
return $this->checkPseudoRegex($uri, $paths);
544+
}
545+
546+
/**
547+
* Check except paths
548+
*
549+
* @param string $uri URI path relative to baseURL (all lowercase)
550+
* @param array|string $paths The except path patterns
551+
*
552+
* @return bool True if the URI matches except paths.
553+
*/
554+
private function checkExcept(string $uri, $paths): bool
555+
{
556+
// empty array does not match anything
557+
if ($paths === []) {
558+
return false;
559+
}
560+
561+
// make sure the paths are iterable
562+
if (is_string($paths)) {
563+
$paths = [$paths];
564+
}
565+
566+
return $this->checkPseudoRegex($uri, $paths);
567+
}
568+
569+
/**
570+
* Check the URI path as pseudo-regex
571+
*
572+
* @param string $uri URI path relative to baseURL (all lowercase)
573+
* @param array $paths The except path patterns
574+
*/
575+
private function checkPseudoRegex(string $uri, array $paths): bool
576+
{
577+
// treat each path as pseudo-regex
540578
foreach ($paths as $path) {
541579
// need to escape path separators
542580
$path = str_replace('/', '\/', trim($path, '/ '));
543581
// need to make pseudo wildcard real
544582
$path = strtolower(str_replace('*', '.*', $path));
583+
545584
// Does this rule apply here?
546585
if (preg_match('#^' . $path . '$#', $uri, $match) === 1) {
547586
return true;

tests/system/Filters/FiltersTest.php

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,23 @@ public static function provideProcessMethodProcessGlobalsWithExcept(): iterable
215215
['admin/*'],
216216
],
217217
[
218-
[],
218+
['admin/*', 'foo/*'],
219+
],
220+
[
221+
['*'],
222+
],
223+
[
224+
'admin/*',
219225
],
220226
];
221227
}
222228

223229
/**
224230
* @dataProvider provideProcessMethodProcessGlobalsWithExcept
231+
*
232+
* @param array|string $except
225233
*/
226-
public function testProcessMethodProcessGlobalsWithExcept(array $except): void
234+
public function testProcessMethodProcessGlobalsWithExcept($except): void
227235
{
228236
$_SERVER['REQUEST_METHOD'] = 'GET';
229237

@@ -572,7 +580,12 @@ public function testOtherResult(): void
572580
$this->assertSame('This is curious', $response);
573581
}
574582

575-
public function testBeforeExceptString(): void
583+
/**
584+
* @dataProvider provideBeforeExcept
585+
*
586+
* @param array|string $except
587+
*/
588+
public function testBeforeExcept(string $uri, $except, array $expected): void
576589
{
577590
$_SERVER['REQUEST_METHOD'] = 'GET';
578591

@@ -584,7 +597,7 @@ public function testBeforeExceptString(): void
584597
],
585598
'globals' => [
586599
'before' => [
587-
'foo' => ['except' => 'admin/*'],
600+
'foo' => ['except' => $except],
588601
'bar',
589602
],
590603
'after' => [
@@ -595,48 +608,91 @@ public function testBeforeExceptString(): void
595608
$filtersConfig = $this->createConfigFromArray(FiltersConfig::class, $config);
596609
$filters = $this->createFilters($filtersConfig);
597610

598-
$uri = 'admin/foo/bar';
599-
$expected = [
600-
'before' => [
601-
'bar',
602-
],
603-
'after' => ['baz'],
604-
];
605611
$this->assertSame($expected, $filters->initialize($uri)->getFilters());
606612
}
607613

608-
public function testBeforeExceptInapplicable(): void
614+
public static function provideBeforeExcept(): iterable
609615
{
610-
$_SERVER['REQUEST_METHOD'] = 'GET';
611-
612-
$config = [
613-
'aliases' => [
614-
'foo' => '',
615-
'bar' => '',
616-
'baz' => '',
616+
return [
617+
'string exclude' => [
618+
'admin/foo/bar',
619+
'admin/*',
620+
[
621+
'before' => [
622+
'bar',
623+
],
624+
'after' => ['baz'],
625+
],
617626
],
618-
'globals' => [
619-
'before' => [
620-
'foo' => ['except' => 'george/*'],
621-
'bar',
627+
'string not exclude' => [
628+
'admin/foo/bar',
629+
'george/*',
630+
[
631+
'before' => [
632+
'foo',
633+
'bar',
634+
],
635+
'after' => ['baz'],
622636
],
623-
'after' => [
624-
'baz',
637+
],
638+
'empty array not exclude' => [
639+
'admin/foo/bar',
640+
[],
641+
[
642+
'before' => [
643+
'foo',
644+
'bar',
645+
],
646+
'after' => ['baz'],
625647
],
626648
],
627-
];
628-
$filtersConfig = $this->createConfigFromArray(FiltersConfig::class, $config);
629-
$filters = $this->createFilters($filtersConfig);
630-
631-
$uri = 'admin/foo/bar';
632-
$expected = [
633-
'before' => [
634-
'foo',
635-
'bar',
649+
'empty string not exclude' => [
650+
'admin/foo/bar',
651+
// The URI path '' means the baseURL.
652+
'',
653+
[
654+
'before' => [
655+
'foo',
656+
'bar',
657+
],
658+
'after' => ['baz'],
659+
],
660+
],
661+
'empty string exclude' => [
662+
// The URI path '' means the baseURL.
663+
'',
664+
// So this setting excludes `foo` filter only to the baseURL.
665+
'',
666+
[
667+
'before' => [
668+
'bar',
669+
],
670+
'after' => ['baz'],
671+
],
672+
],
673+
'slash not exclude' => [
674+
'admin/foo/bar',
675+
'/',
676+
[
677+
'before' => [
678+
'foo',
679+
'bar',
680+
],
681+
'after' => ['baz'],
682+
],
683+
],
684+
'slash exclude' => [
685+
// The URI path '' means the baseURL.
686+
'',
687+
'/',
688+
[
689+
'before' => [
690+
'bar',
691+
],
692+
'after' => ['baz'],
693+
],
636694
],
637-
'after' => ['baz'],
638695
];
639-
$this->assertSame($expected, $filters->initialize($uri)->getFilters());
640696
}
641697

642698
public function testAfterExceptString(): void

user_guide_src/source/changelogs/v4.3.8.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ Deprecations
2424
Bugs Fixed
2525
**********
2626

27+
- **Controller Filters:** In previous versions, ``['except' => []]`` or ``['except' => '']``
28+
meant "except all". The bug has been fixed, and now
29+
30+
- ``['except' => []]`` means to exclude nothing.
31+
- ``['except' => '']`` means to exclude the baseURL only.
32+
2733
See the repo's
2834
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
2935
for a complete list of bugs fixed.

0 commit comments

Comments
 (0)