diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index 994c6f37c7e2..d93de522f6fa 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -154,7 +154,18 @@ private function discoverFilters(): void $files = $locator->search('Config/Filters.php'); + // Our main Filter configs are never included again, see below. Skip them + // by path, as reading and tokenizing them to find that out is wasted work. + $mainFiles = [ + APPPATH . 'Config' . DIRECTORY_SEPARATOR . 'Filters.php', + SYSTEMPATH . 'Config' . DIRECTORY_SEPARATOR . 'Filters.php', + ]; + foreach ($files as $file) { + if (in_array($file, $mainFiles, true)) { + continue; + } + // The $file may not be a class file. $className = $locator->getClassname($file); diff --git a/tests/system/Filters/FiltersTest.php b/tests/system/Filters/FiltersTest.php index d696498efaa2..cb91393358ed 100644 --- a/tests/system/Filters/FiltersTest.php +++ b/tests/system/Filters/FiltersTest.php @@ -13,6 +13,7 @@ namespace CodeIgniter\Filters; +use CodeIgniter\Autoloader\FileLocator; use CodeIgniter\Config\Services; use CodeIgniter\Filters\Exceptions\FilterException; use CodeIgniter\Filters\fixtures\GoogleCurious; @@ -488,6 +489,52 @@ public function testAllCustomFiltersAreDiscoveredInConstructor(): void $this->assertContains('test-customfilter', array_keys($configFilters->aliases)); } + public function testDiscoveryDoesNotTokenizeTheDefaultFiltersConfigs(): void + { + service('superglobals')->setServer('REQUEST_METHOD', 'GET'); + + $locator = new class (service('autoloader')) extends FileLocator { + /** + * @var list + */ + public array $tokenized = []; + + public function getClassname(string $file): string + { + $this->tokenized[] = $file; + + return parent::getClassname($file); + } + }; + Services::injectMock('locator', $locator); + + $appConfig = APPPATH . 'Config' . DIRECTORY_SEPARATOR . 'Filters.php'; + $systemConfig = SYSTEMPATH . 'Config' . DIRECTORY_SEPARATOR . 'Filters.php'; + $testConfig = realpath(TESTPATH . '_support/Config/Filters.php'); + + // Discovery does find them all, so the checks below are not vacuous. + $found = $locator->search('Config/Filters.php'); + $this->assertContains($appConfig, $found); + $this->assertContains($systemConfig, $found); + $this->assertContains($testConfig, $found); + + $config = [ + 'aliases' => [], + 'globals' => [], + ]; + $filtersConfig = $this->createConfigFromArray(FiltersConfig::class, $config); + $filters = $this->createFilters($filtersConfig); + + $this->assertNotContains($appConfig, $locator->tokenized); + $this->assertNotContains($systemConfig, $locator->tokenized); + + // Any other file is still checked and included. + $this->assertContains($testConfig, $locator->tokenized); + + $configFilters = $this->getPrivateProperty($filters, 'config'); + $this->assertContains('test-customfilter', array_keys($configFilters->aliases)); + } + public function testRunThrowsWithInvalidClassType(): void { service('superglobals')->setServer('REQUEST_METHOD', 'GET');