Skip to content

Commit a8072a5

Browse files
authored
Merge pull request #6475 from JavaDeveloperKiev/cachingBugFix
Fix broken caching system when array of allowed parameters used
2 parents 51e67a7 + 2b5dae8 commit a8072a5

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

system/CodeIgniter.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -730,9 +730,12 @@ protected function generateCacheName(Cache $config): string
730730
}
731731

732732
$uri = $this->request->getUri();
733-
734733
if ($config->cacheQueryString) {
735-
$name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery());
734+
if (is_array($config->cacheQueryString)) {
735+
$name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(['only' => $config->cacheQueryString]));
736+
} else {
737+
$name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery());
738+
}
736739
} else {
737740
$name = URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath());
738741
}

tests/system/CodeIgniterTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use CodeIgniter\Test\Filters\CITestStreamFilter;
1919
use CodeIgniter\Test\Mock\MockCodeIgniter;
2020
use Config\App;
21+
use Config\Cache;
2122
use Config\Filters;
2223
use Config\Modules;
2324
use Tests\Support\Filters\Customfilter;
@@ -622,4 +623,81 @@ public function testPageCacheSendSecureHeaders()
622623
stream_filter_remove($outputStreamFilter);
623624
stream_filter_remove($errorStreamFilter);
624625
}
626+
627+
/**
628+
* @param array|bool $cacheQueryStringValue
629+
* @dataProvider cacheQueryStringProvider
630+
*
631+
* @see https://github.com/codeigniter4/CodeIgniter4/pull/6410
632+
*/
633+
public function testPageCacheWithCacheQueryString($cacheQueryStringValue, int $expectedPagesInCache, array $testingUrls)
634+
{
635+
// Suppress command() output
636+
CITestStreamFilter::$buffer = '';
637+
$outputStreamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter');
638+
$errorStreamFilter = stream_filter_append(STDERR, 'CITestStreamFilter');
639+
640+
// Create cache config with cacheQueryString value from the dataProvider
641+
$cacheConfig = new Cache();
642+
$cacheConfig->cacheQueryString = $cacheQueryStringValue;
643+
644+
// Clear cache before starting the test
645+
command('cache:clear');
646+
647+
// Calculate amount of items in the cache before the test
648+
$cache = \Config\Services::cache();
649+
$cacheStartCounter = count($cache->getCacheInfo());
650+
651+
// Generate request to each URL from the testing array
652+
foreach ($testingUrls as $testingUrl) {
653+
$_SERVER['REQUEST_URI'] = '/' . $testingUrl;
654+
$routes = Services::routes(true);
655+
$routes->add($testingUrl, static function () {
656+
CodeIgniter::cache(0); // Dont cache the page in the run() function because CodeIgniter class will create default $cacheConfig and overwrite settings from the dataProvider
657+
$response = Services::response();
658+
$string = 'This is a test page, to check cache configuration';
659+
660+
return $response->setBody($string);
661+
});
662+
663+
// Inject router
664+
$router = Services::router($routes, Services::request(null, false));
665+
Services::injectMock('router', $router);
666+
667+
// Cache the page output using default caching function and $cacheConfig with value from the data provider
668+
$this->codeigniter->useSafeOutput(true)->run();
669+
$this->codeigniter->cachePage($cacheConfig); // Cache the page using our own $cacheConfig confugration
670+
}
671+
672+
// Calculate how much cached items exist in the cache after the test requests
673+
$cacheEndCounter = count($cache->getCacheInfo());
674+
$newPagesCached = $cacheEndCounter - $cacheStartCounter;
675+
676+
// Clear cache after the test
677+
command('cache:clear');
678+
679+
// Check that amount of new items created in the cache matching expected value from the data provider
680+
$this->assertSame($expectedPagesInCache, $newPagesCached);
681+
682+
// Remove stream filters
683+
stream_filter_remove($outputStreamFilter);
684+
stream_filter_remove($errorStreamFilter);
685+
}
686+
687+
public function cacheQueryStringProvider(): array
688+
{
689+
$testingUrls = [
690+
'test', // URL #1
691+
'test?important_parameter=1', // URL #2
692+
'test?important_parameter=2', // URL #3
693+
'test?important_parameter=1&not_important_parameter=2', // URL #4
694+
'test?important_parameter=1&not_important_parameter=2&another_not_important_parameter=3', // URL #5
695+
];
696+
697+
return [
698+
'$cacheQueryString=false' => [false, 1, $testingUrls], // We expect only 1 page in the cache, because when cacheQueryString is set to false, all GET parameter should be ignored, and page URI will be absolutely same "/test" string for all 5 requests
699+
'$cacheQueryString=true' => [true, 5, $testingUrls], // We expect all 5 pages in the cache, because when cacheQueryString is set to true, all GET parameter should be processed as unique requests
700+
'$cacheQueryString=array' => [['important_parameter'], 3, $testingUrls], // We expect only 3 pages in the cache, because when cacheQueryString is set to array with important parameters, we should ignore all parameters thats not in the array. Only URL #1, URL #2 and URL #3 should be cached. URL #4 and URL #5 is duplication of URL #2 (with value ?important_parameter=1), so they should not be processed as new unique requests and application should return already cached page for URL #2
701+
];
702+
}
625703
}

0 commit comments

Comments
 (0)