.../Drupal/Core/Cache/Context/PathCacheContext.php | 3 - .../Breadcrumb/ForumListingBreadcrumbBuilder.php | 1 - .../src/Breadcrumb/ForumNodeBreadcrumbBuilder.php | 1 + .../Breadcrumb/ForumBreadcrumbBuilderBaseTest.php | 27 +++---- .../ForumListingBreadcrumbBuilderTest.php | 93 ++++++++++------------ .../Breadcrumb/ForumNodeBreadcrumbBuilderTest.php | 78 ++++++++---------- .../system/src/PathBasedBreadcrumbBuilder.php | 1 - .../Breadcrumbs/PathBasedBreadcrumbBuilderTest.php | 61 ++++++++++---- .../modules/taxonomy/src/TermBreadcrumbBuilder.php | 3 +- .../Core/Breadcrumb/BreadcrumbManagerTest.php | 32 ++++++-- 10 files changed, 154 insertions(+), 146 deletions(-) diff --git a/core/lib/Drupal/Core/Cache/Context/PathCacheContext.php b/core/lib/Drupal/Core/Cache/Context/PathCacheContext.php index d4c3eee..8b13c5a 100644 --- a/core/lib/Drupal/Core/Cache/Context/PathCacheContext.php +++ b/core/lib/Drupal/Core/Cache/Context/PathCacheContext.php @@ -9,7 +9,6 @@ use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\Core\Cache\Context\RequestStackCacheContextBase; /** * Defines the PathCacheContext service, for "per URL path" caching. @@ -23,8 +22,6 @@ */ class PathCacheContext extends RequestStackCacheContextBase implements CacheContextInterface { - use StringTranslationTrait; - /** * {@inheritdoc} */ diff --git a/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php b/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php index e421d5c..494af46 100644 --- a/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php +++ b/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php @@ -7,7 +7,6 @@ namespace Drupal\forum\Breadcrumb; -use Drupal\Core\Breadcrumb\Breadcrumb; use Drupal\Core\Link; use Drupal\Core\Routing\RouteMatchInterface; diff --git a/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php b/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php index 09923f3..5d6e592 100644 --- a/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php +++ b/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php @@ -35,6 +35,7 @@ public function build(RouteMatchInterface $route_match) { if ($parents) { $parents = array_reverse($parents); foreach ($parents as $parent) { + $breadcrumb->addCacheableDependency($parent); $breadcrumb->addLink(Link::createFromRoute($parent->label(), 'forum.page', array( 'taxonomy_term' => $parent->id(), diff --git a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php index e171f53..f690e03 100644 --- a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php +++ b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php @@ -92,25 +92,18 @@ public function testBuild() { ->disableOriginalConstructor() ->getMock(); - $vocab_item = $this->getMock('Drupal\taxonomy\VocabularyInterface'); - $vocab_item->expects($this->any()) - ->method('label') - ->will($this->returnValue('Fora_is_the_plural_of_forum')); - $vocab_item->expects($this->once()) - ->method('getCacheTags') - ->willReturn([]); - $vocab_item->expects($this->once()) - ->method('getCacheContexts') - ->willReturn([]); - $vocab_item->expects($this->once()) - ->method('getCacheMaxAge') - ->willReturn(Cache::PERMANENT); + $prophecy = $this->prophesize('Drupal\taxonomy\VocabularyInterface'); + $prophecy->label()->willReturn('Fora_is_the_plural_of_forum'); + $prophecy->id()->willReturn(5); + $prophecy->getCacheTags()->willReturn(['taxonomy_vocabulary:5']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); $vocab_storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface'); $vocab_storage->expects($this->any()) ->method('load') ->will($this->returnValueMap(array( - array('forums', $vocab_item), + array('forums', $prophecy->reveal()), ))); $entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManagerInterface') @@ -155,7 +148,11 @@ public function testBuild() { ); // And finally, the test. - $this->assertEquals($expected, $breadcrumb_builder->build($route_match)->getLinks()); + $breadcrumb = $breadcrumb_builder->build($route_match); + $this->assertEquals($expected, $breadcrumb->getLinks()); + $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } } diff --git a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php index 6faa797..3935916 100644 --- a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php +++ b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Link; +use Drupal\taxonomy\Entity\Term; use Drupal\Tests\UnitTestCase; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\DependencyInjection\Container; @@ -123,27 +124,21 @@ public function providerTestApplies() { */ public function testBuild() { // Build all our dependencies, backwards. - $term1 = $this->getMockBuilder('Drupal\taxonomy\Entity\Term') - ->disableOriginalConstructor() - ->getMock(); - $term1->expects($this->any()) - ->method('label') - ->will($this->returnValue('Something')); - $term1->expects($this->any()) - ->method('id') - ->will($this->returnValue(1)); - $this->setCacheabilityExpectations($term1); - - $term2 = $this->getMockBuilder('Drupal\taxonomy\Entity\Term') - ->disableOriginalConstructor() - ->getMock(); - $term2->expects($this->any()) - ->method('label') - ->will($this->returnValue('Something else')); - $term2->expects($this->any()) - ->method('id') - ->will($this->returnValue(2)); - $this->setCacheabilityExpectations($term2); + $prophecy = $this->prophesize('Drupal\taxonomy\Entity\Term'); + $prophecy->label()->willReturn('Something'); + $prophecy->id()->willReturn(1); + $prophecy->getCacheTags()->willReturn(['taxonomy_term:1']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $term1 = $prophecy->reveal(); + + $prophecy = $this->prophesize('Drupal\taxonomy\Entity\Term'); + $prophecy->label()->willReturn('Something else'); + $prophecy->id()->willReturn(2); + $prophecy->getCacheTags()->willReturn(['taxonomy_term:2']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $term2 = $prophecy->reveal(); $forum_manager = $this->getMock('Drupal\forum\ForumManagerInterface'); $forum_manager->expects($this->at(0)) @@ -154,16 +149,17 @@ public function testBuild() { ->will($this->returnValue(array($term1, $term2))); // The root forum. - $vocab_item = $this->getMock('Drupal\taxonomy\VocabularyInterface'); - $vocab_item->expects($this->any()) - ->method('label') - ->will($this->returnValue('Fora_is_the_plural_of_forum')); - $this->setCacheabilityExpectations($vocab_item); + $prophecy = $this->prophesize('Drupal\taxonomy\VocabularyInterface'); + $prophecy->label()->willReturn('Fora_is_the_plural_of_forum'); + $prophecy->id()->willReturn(5); + $prophecy->getCacheTags()->willReturn(['taxonomy_vocabulary:5']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); $vocab_storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface'); $vocab_storage->expects($this->any()) ->method('load') ->will($this->returnValueMap(array( - array('forums', $vocab_item), + array('forums', $prophecy->reveal()), ))); $entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManagerInterface') @@ -197,14 +193,13 @@ public function testBuild() { $breadcrumb_builder->setStringTranslation($translation_manager); // The forum listing we need a breadcrumb back from. - $forum_listing = $this->getMockBuilder('Drupal\taxonomy\Entity\Term') - ->disableOriginalConstructor() - ->getMock(); - $forum_listing->tid = 23; - $forum_listing->expects($this->any()) - ->method('label') - ->will($this->returnValue('You_should_not_see_this')); - $this->setCacheabilityExpectations($forum_listing); + $prophecy = $this->prophesize('Drupal\taxonomy\Entity\Term'); + $prophecy->label()->willReturn('You_should_not_see_this'); + $prophecy->id()->willReturn(23); + $prophecy->getCacheTags()->willReturn(['taxonomy_term:23']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $forum_listing = $prophecy->reveal(); // Our data set. $route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface'); @@ -219,7 +214,11 @@ public function testBuild() { Link::createFromRoute('Fora_is_the_plural_of_forum', 'forum.index'), Link::createFromRoute('Something', 'forum.page', array('taxonomy_term' => 1)), ); - $this->assertEquals($expected1, $breadcrumb_builder->build($route_match)->getLinks()); + $breadcrumb = $breadcrumb_builder->build($route_match); + $this->assertEquals($expected1, $breadcrumb->getLinks()); + $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['taxonomy_term:1', 'taxonomy_term:23', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); // Second test. $expected2 = array( @@ -228,24 +227,12 @@ public function testBuild() { Link::createFromRoute('Something else', 'forum.page', array('taxonomy_term' => 2)), Link::createFromRoute('Something', 'forum.page', array('taxonomy_term' => 1)), ); - $this->assertEquals($expected2, $breadcrumb_builder->build($route_match)->getLinks()); - } + $breadcrumb = $breadcrumb_builder->build($route_match); + $this->assertEquals($expected2, $breadcrumb->getLinks()); + $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['taxonomy_term:1', 'taxonomy_term:2', 'taxonomy_term:23', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); - /** - * Sets cacheability expectations for an object. - * - * @param \PHPUnit_Framework_MockObject_MockObject $object - */ - protected function setCacheabilityExpectations(&$object) { - $object->expects($this->any()) - ->method('getCacheTags') - ->willReturn([]); - $object->expects($this->any()) - ->method('getCacheContexts') - ->willReturn([]); - $object->expects($this->any()) - ->method('getCacheMaxAge') - ->willReturn(Cache::PERMANENT); } } diff --git a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php index 1f4e62b..76851fd 100644 --- a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php +++ b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php @@ -129,27 +129,21 @@ public function providerTestApplies() { */ public function testBuild() { // Build all our dependencies, backwards. - $term1 = $this->getMockBuilder('Drupal\Core\Entity\EntityInterface') - ->disableOriginalConstructor() - ->getMock(); - $term1->expects($this->any()) - ->method('label') - ->will($this->returnValue('Something')); - $term1->expects($this->any()) - ->method('id') - ->will($this->returnValue(1)); - $this->setCacheabilityExpectations($term1); - - $term2 = $this->getMockBuilder('Drupal\Core\Entity\EntityInterface') - ->disableOriginalConstructor() - ->getMock(); - $term2->expects($this->any()) - ->method('label') - ->will($this->returnValue('Something else')); - $term2->expects($this->any()) - ->method('id') - ->will($this->returnValue(2)); - $this->setCacheabilityExpectations($term2); + $prophecy = $this->prophesize('Drupal\taxonomy\Entity\Term'); + $prophecy->label()->willReturn('Something'); + $prophecy->id()->willReturn(1); + $prophecy->getCacheTags()->willReturn(['taxonomy_term:1']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $term1 = $prophecy->reveal(); + + $prophecy = $this->prophesize('Drupal\taxonomy\Entity\Term'); + $prophecy->label()->willReturn('Something else'); + $prophecy->id()->willReturn(2); + $prophecy->getCacheTags()->willReturn(['taxonomy_term:2']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $term2 = $prophecy->reveal(); $forum_manager = $this->getMockBuilder('Drupal\forum\ForumManagerInterface') ->disableOriginalConstructor() @@ -161,16 +155,17 @@ public function testBuild() { ->method('getParents') ->will($this->returnValue(array($term1, $term2))); - $vocab_item = $this->getMock('Drupal\taxonomy\VocabularyInterface'); - $vocab_item->expects($this->any()) - ->method('label') - ->will($this->returnValue('Forums')); - $this->setCacheabilityExpectations($vocab_item); + $prophecy = $this->prophesize('Drupal\taxonomy\VocabularyInterface'); + $prophecy->label()->willReturn('Forums'); + $prophecy->id()->willReturn(5); + $prophecy->getCacheTags()->willReturn(['taxonomy_vocabulary:5']); + $prophecy->getCacheContexts()->willReturn([]); + $prophecy->getCacheMaxAge()->willReturn(Cache::PERMANENT); $vocab_storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface'); $vocab_storage->expects($this->any()) ->method('load') ->will($this->returnValueMap(array( - array('forums', $vocab_item), + array('forums', $prophecy->reveal()), ))); $entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManagerInterface') @@ -223,7 +218,11 @@ public function testBuild() { Link::createFromRoute('Forums', 'forum.index'), Link::createFromRoute('Something', 'forum.page', array('taxonomy_term' => 1)), ); - $this->assertEquals($expected1, $breadcrumb_builder->build($route_match)->getLinks()); + $breadcrumb = $breadcrumb_builder->build($route_match); + $this->assertEquals($expected1, $breadcrumb->getLinks()); + $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['taxonomy_term:1', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); // Second test. $expected2 = array( @@ -232,24 +231,11 @@ public function testBuild() { Link::createFromRoute('Something else', 'forum.page', array('taxonomy_term' => 2)), Link::createFromRoute('Something', 'forum.page', array('taxonomy_term' => 1)), ); - $this->assertEquals($expected2, $breadcrumb_builder->build($route_match)->getLinks()); - } - - /** - * Sets cacheability expectations for an object. - * - * @param \PHPUnit_Framework_MockObject_MockObject $object - */ - protected function setCacheabilityExpectations(&$object) { - $object->expects($this->any()) - ->method('getCacheTags') - ->willReturn([]); - $object->expects($this->any()) - ->method('getCacheContexts') - ->willReturn([]); - $object->expects($this->any()) - ->method('getCacheMaxAge') - ->willReturn(Cache::PERMANENT); + $breadcrumb = $breadcrumb_builder->build($route_match); + $this->assertEquals($expected2, $breadcrumb->getLinks()); + $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['taxonomy_term:1', 'taxonomy_term:2', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } } diff --git a/core/modules/system/src/PathBasedBreadcrumbBuilder.php b/core/modules/system/src/PathBasedBreadcrumbBuilder.php index ba3a606..4acbee2 100644 --- a/core/modules/system/src/PathBasedBreadcrumbBuilder.php +++ b/core/modules/system/src/PathBasedBreadcrumbBuilder.php @@ -11,7 +11,6 @@ use Drupal\Core\Access\AccessManagerInterface; use Drupal\Core\Breadcrumb\Breadcrumb; use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface; -use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Link; diff --git a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php index ff7534a..bf106f6 100644 --- a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php +++ b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php @@ -7,6 +7,8 @@ namespace Drupal\Tests\system\Unit\Breadcrumbs; +use Drupal\Core\Access\AccessResult; +use Drupal\Core\Cache\Cache; use Drupal\Core\Link; use Drupal\Core\Access\AccessResultAllowed; use Drupal\Core\Session\AccountInterface; @@ -139,8 +141,11 @@ public function testBuildOnFrontpage() { ->method('getPathInfo') ->will($this->returnValue('/')); - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); - $this->assertEquals([], $links->getLinks()); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $this->assertEquals([], $breadcrumb->getLinks()); + $this->assertEquals(['url.path'], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -153,8 +158,11 @@ public function testBuildWithOnePathElement() { ->method('getPathInfo') ->will($this->returnValue('/example')); - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); - $this->assertEquals([0 => new Link('Home', new Url(''))], $links->getLinks()); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); + $this->assertEquals(['url.path'], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -185,8 +193,11 @@ public function testBuildWithTwoPathElements() { $this->setupAccessManagerToAllow(); - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); - $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Example', new Url('example'))], $links->getLinks()); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Example', new Url('example'))], $breadcrumb->getLinks()); + $this->assertEquals(['url.path', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -223,14 +234,21 @@ public function testBuildWithThreePathElements() { } })); - $this->setupAccessManagerToAllow(); - - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $this->accessManager->expects($this->any()) + ->method('check') + ->willReturnOnConsecutiveCalls( + AccessResult::allowed()->cachePerPermissions(), + AccessResult::allowed()->addCacheContexts(['bar'])->addCacheTags(['example']) + ); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([ new Link('Home', new Url('')), new Link('Example', new Url('example')), new Link('Bar', new Url('example_bar')), - ], $links->getLinks()); + ], $breadcrumb->getLinks()); + $this->assertEquals(['bar', 'url.path', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['example'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -251,10 +269,13 @@ public function testBuildWithException($exception_class, $exception_argument) { ->method('matchRequest') ->will($this->throwException(new $exception_class($exception_argument))); - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); // No path matched, though at least the frontpage is displayed. - $this->assertEquals([0 => new Link('Home', new Url(''))], $links->getLinks()); + $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); + $this->assertEquals(['url.path'], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -292,10 +313,13 @@ public function testBuildWithNonProcessedPath() { ->method('matchRequest') ->will($this->returnValue(array())); - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); // No path matched, though at least the frontpage is displayed. - $this->assertEquals([0 => new Link('Home', new Url(''))], $links->getLinks()); + $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); + $this->assertEquals(['url.path'], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -339,8 +363,11 @@ public function testBuildWithUserPath() { ->with($this->anything(), $route_1) ->will($this->returnValue('Admin')); - $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); - $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Admin', new Url('user_page'))], $links->getLinks()); + $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Admin', new Url('user_page'))], $breadcrumb->getLinks()); + $this->assertEquals(['url.path', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -349,7 +376,7 @@ public function testBuildWithUserPath() { public function setupAccessManagerToAllow() { $this->accessManager->expects($this->any()) ->method('check') - ->willReturn(new AccessResultAllowed()); + ->willReturn((new AccessResultAllowed())->cachePerPermissions()); } protected function setupStubPathProcessor() { diff --git a/core/modules/taxonomy/src/TermBreadcrumbBuilder.php b/core/modules/taxonomy/src/TermBreadcrumbBuilder.php index e3b1335..c2387c4 100644 --- a/core/modules/taxonomy/src/TermBreadcrumbBuilder.php +++ b/core/modules/taxonomy/src/TermBreadcrumbBuilder.php @@ -9,7 +9,6 @@ use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface; use Drupal\Core\Breadcrumb\Breadcrumb; -use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Link; use Drupal\Core\Routing\RouteMatchInterface; @@ -31,7 +30,7 @@ class TermBreadcrumbBuilder implements BreadcrumbBuilderInterface { /** * The taxonomy storage. * - * @var \Drupal\Core\Entity\TermStorageInterface + * @var \Drupal\Taxonomy\TermStorageInterface */ protected $termStorage; diff --git a/core/tests/Drupal/Tests/Core/Breadcrumb/BreadcrumbManagerTest.php b/core/tests/Drupal/Tests/Core/Breadcrumb/BreadcrumbManagerTest.php index ade54cf..4e48755 100644 --- a/core/tests/Drupal/Tests/Core/Breadcrumb/BreadcrumbManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Breadcrumb/BreadcrumbManagerTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Breadcrumb\Breadcrumb; use Drupal\Core\Breadcrumb\BreadcrumbManager; +use Drupal\Core\Cache\Cache; use Drupal\Tests\UnitTestCase; /** @@ -51,8 +52,11 @@ protected function setUp() { * Tests the breadcrumb manager without any set breadcrumb. */ public function testBuildWithoutBuilder() { - $result = $this->breadcrumbManager->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); - $this->assertEquals(array(), $result->getLinks()); + $breadcrumb = $this->breadcrumbManager->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); + $this->assertEquals([], $breadcrumb->getLinks()); + $this->assertEquals([], $breadcrumb->getCacheContexts()); + $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -62,6 +66,7 @@ public function testBuildWithSingleBuilder() { $builder = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface'); $links = array('Test'); $this->breadcrumb->setLinks($links); + $this->breadcrumb->setCacheContexts(['foo'])->setCacheTags(['bar']); $builder->expects($this->once()) ->method('applies') @@ -78,8 +83,11 @@ public function testBuildWithSingleBuilder() { $this->breadcrumbManager->addBuilder($builder, 0); - $result = $this->breadcrumbManager->build($route_match); - $this->assertEquals($links, $result->getLinks()); + $breadcrumb = $this->breadcrumbManager->build($route_match); + $this->assertEquals($links, $breadcrumb->getLinks()); + $this->assertEquals(['foo'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['bar'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -95,6 +103,7 @@ public function testBuildWithMultipleApplyingBuilders() { $builder2 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface'); $links2 = array('Test2'); $this->breadcrumb->setLinks($links2); + $this->breadcrumb->setCacheContexts(['baz'])->setCacheTags(['qux']); $builder2->expects($this->once()) ->method('applies') ->will($this->returnValue(TRUE)); @@ -111,8 +120,11 @@ public function testBuildWithMultipleApplyingBuilders() { $this->breadcrumbManager->addBuilder($builder1, 0); $this->breadcrumbManager->addBuilder($builder2, 10); - $result = $this->breadcrumbManager->build($route_match); - $this->assertEquals($links2, $result->getLinks()); + $breadcrumb = $this->breadcrumbManager->build($route_match); + $this->assertEquals($links2, $breadcrumb->getLinks()); + $this->assertEquals(['baz'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['qux'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /** @@ -129,6 +141,7 @@ public function testBuildWithOneNotApplyingBuilders() { $builder2 = $this->getMock('Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface'); $links2 = ['Test2']; $this->breadcrumb->setLinks($links2); + $this->breadcrumb->setCacheContexts(['baz'])->setCacheTags(['qux']); $builder2->expects($this->once()) ->method('applies') ->will($this->returnValue(TRUE)); @@ -145,8 +158,11 @@ public function testBuildWithOneNotApplyingBuilders() { $this->breadcrumbManager->addBuilder($builder1, 10); $this->breadcrumbManager->addBuilder($builder2, 0); - $result = $this->breadcrumbManager->build($route_match); - $this->assertEquals($links2, $result->getLinks()); + $breadcrumb = $this->breadcrumbManager->build($route_match); + $this->assertEquals($links2, $breadcrumb->getLinks()); + $this->assertEquals(['baz'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['qux'], $breadcrumb->getCacheTags()); + $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } /**