diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php index eeae1a1ff1b..8f8e97e8668 100644 --- a/core/lib/Drupal/Core/Cache/Cache.php +++ b/core/lib/Drupal/Core/Cache/Cache.php @@ -20,16 +20,14 @@ class Cache { /** * Merges arrays of cache contexts and removes duplicates. * - * @param array $a - * Cache contexts array to merge. - * @param array $b - * Cache contexts array to merge. + * @param string[] ... + * Cache contexts arrays to merge. * * @return string[] * The merged array of cache contexts. */ - public static function mergeContexts(array $a = [], array $b = []) { - $cache_contexts = array_unique(array_merge($a, $b)); + public static function mergeContexts(array ...$cache_contexts) { + $cache_contexts = array_unique(array_merge(...$cache_contexts)); assert(\Drupal::service('cache_contexts_manager')->assertValidTokens($cache_contexts)); sort($cache_contexts); return $cache_contexts; @@ -46,18 +44,15 @@ class Cache { * allows items to be invalidated based on all tags attached to the content * they're constituted from. * - * @param array $a - * Cache tags array to merge. - * @param array $b - * Cache tags array to merge. + * @param string[] ... + * Cache tags arrays to merge. * * @return string[] * The merged array of cache tags. */ - public static function mergeTags(array $a = [], array $b = []) { - assert(Inspector::assertAllStrings($a) && Inspector::assertAllStrings($b), 'Cache tags must be valid strings'); - - $cache_tags = array_unique(array_merge($a, $b)); + public static function mergeTags(array ...$cache_tags) { + $cache_tags = array_unique(array_merge(...$cache_tags)); + assert(Inspector::assertAllStrings($cache_tags), 'Cache tags must be valid strings'); sort($cache_tags); return $cache_tags; } @@ -67,25 +62,21 @@ class Cache { * * Ensures infinite max-age (Cache::PERMANENT) is taken into account. * - * @param int $a - * Max age value to merge. - * @param int $b - * Max age value to merge. + * @param int ... + * Max age values to merge. * * @return int * The minimum max-age value. */ - public static function mergeMaxAges($a = Cache::PERMANENT, $b = Cache::PERMANENT) { - // If one of the values is Cache::PERMANENT, return the other value. - if ($a === Cache::PERMANENT) { - return $b; - } - if ($b === Cache::PERMANENT) { - return $a; - } + public static function mergeMaxAges(...$max_ages) { + // Remove Cache::PERMANENT values to return the correct minimum value. + $max_ages = array_filter($max_ages, function ($max_age) { + return $max_age !== Cache::PERMANENT; + }); - // If none or the values are Cache::PERMANENT, return the minimum value. - return min($a, $b); + // If there are no max ages left return Cache::PERMANENT, otherwise return + // the minimum value. + return empty($max_ages) ? Cache::PERMANENT : min($max_ages); } /** diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php index e211db418b4..12dc9bb5399 100644 --- a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php @@ -4,6 +4,9 @@ namespace Drupal\Tests\Core\Cache; use Drupal\Core\Cache\Cache; use Drupal\Tests\UnitTestCase; +use Prophecy\Argument; +use Drupal\Core\Cache\Context\CacheContextsManager; +use Drupal\Core\DependencyInjection\Container; /** * @coversDefaultClass \Drupal\Core\Cache\Cache @@ -48,12 +51,13 @@ class CacheTest extends UnitTestCase { public function mergeTagsProvider() { return [ [[], [], []], - [['bar'], ['foo'], ['bar', 'foo']], - [['foo'], ['bar'], ['bar', 'foo']], - [['foo'], ['bar', 'foo'], ['bar', 'foo']], - [['foo'], ['foo', 'bar'], ['bar', 'foo']], - [['bar', 'foo'], ['foo', 'bar'], ['bar', 'foo']], - [['foo', 'bar'], ['foo', 'bar'], ['bar', 'foo']], + [['bar', 'foo'], ['bar'], ['foo']], + [['bar', 'foo'], ['foo'], ['bar']], + [['bar', 'foo'], ['foo'], ['bar', 'foo']], + [['bar', 'foo'], ['foo'], ['foo', 'bar']], + [['bar', 'foo'], ['bar', 'foo'], ['foo', 'bar']], + [['bar', 'foo'], ['foo', 'bar'], ['foo', 'bar']], + [['bar', 'foo', 'llama'], ['bar', 'foo'], ['foo', 'bar'], ['llama', 'foo']], ]; } @@ -62,8 +66,8 @@ class CacheTest extends UnitTestCase { * * @dataProvider mergeTagsProvider */ - public function testMergeTags(array $a, array $b, array $expected) { - $this->assertEquals($expected, Cache::mergeTags($a, $b)); + public function testMergeTags(array $expected, ...$cache_tags) { + $this->assertEquals($expected, Cache::mergeTags(...$cache_tags)); } /** @@ -77,14 +81,22 @@ class CacheTest extends UnitTestCase { [60, 60, 60], [0, 0, 0], - [60, 0, 0], [0, 60, 0], + [0, 0, 60], - [Cache::PERMANENT, 0, 0], [0, Cache::PERMANENT, 0], + [0, 0, Cache::PERMANENT], - [Cache::PERMANENT, 60, 60], [60, Cache::PERMANENT, 60], + [60, 60, Cache::PERMANENT], + + [Cache::PERMANENT, Cache::PERMANENT, Cache::PERMANENT, Cache::PERMANENT], + [30, 60, 60, 30], + [0, 0, 0, 0], + + [60, Cache::PERMANENT, 60, Cache::PERMANENT], + [60, 60, Cache::PERMANENT, Cache::PERMANENT], + [60, Cache::PERMANENT, Cache::PERMANENT, 60], ]; } @@ -93,8 +105,47 @@ class CacheTest extends UnitTestCase { * * @dataProvider mergeMaxAgesProvider */ - public function testMergeMaxAges($a, $b, $expected) { - $this->assertSame($expected, Cache::mergeMaxAges($a, $b)); + public function testMergeMaxAges($expected, ...$max_ages) { + $this->assertSame($expected, Cache::mergeMaxAges(...$max_ages)); + } + + /** + * Provides a list of pairs of cache contexts arrays to be merged. + * + * @return array + */ + public function mergeCacheContextsProvide() { + return [ + [[], [], []], + [['foo'], [], ['foo']], + [['foo'], ['foo'], []], + + [['bar', 'foo'], ['foo'], ['bar']], + [['bar', 'foo'], ['bar'], ['foo']], + + [['foo.bar', 'foo.foo'], ['foo.foo'], ['foo.bar']], + [['foo.bar', 'foo.foo'], ['foo.bar'], ['foo.foo']], + + [['bar', 'foo', 'llama'], [], ['foo', 'bar', 'llama']], + [['bar', 'foo', 'llama'], ['foo', 'bar', 'llama'], []], + + [['bar', 'foo', 'llama'], ['foo'], ['foo', 'bar', 'llama']], + [['bar', 'foo', 'llama'], ['foo', 'bar', 'llama'], ['foo']], + ]; + } + + /** + * @covers ::mergeContexts + * + * @dataProvider mergeCacheContextsProvide + */ + public function testMergeCacheContexts(array $expected, ...$contexts) { + $cache_contexts_manager = $this->prophesize(CacheContextsManager::class); + $cache_contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE); + $container = $this->prophesize(Container::class); + $container->get('cache_contexts_manager')->willReturn($cache_contexts_manager->reveal()); + \Drupal::setContainer($container->reveal()); + $this->assertSame($expected, Cache::mergeContexts(...$contexts)); } /**