Unverified Commit 2d691d50 authored by larowlan's avatar larowlan
Browse files

Issue #2891075 by Berdir, dawehner, larowlan: PathBasedBreadcrumbBuilder...

Issue #2891075 by Berdir, dawehner, larowlan: PathBasedBreadcrumbBuilder always displays Home in Breadcrumb when using path language prefixes
parent 1ab1078b
<?php
namespace Drupal\Tests\language\Functional;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\BrowserTestBase;
/**
* Tests breadcrumbs functionality.
*
* @group Menu
*/
class LanguageBreadcrumbTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language', 'block', 'filter'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('system_breadcrumb_block');
ConfigurableLanguage::createFromLangcode('de')->save();
ConfigurableLanguage::createFromLangcode('gsw-berne')->save();
}
/**
* Tests breadcrumbs with URL prefixes.
*/
public function testBreadCrumbs() {
// Prepare common base breadcrumb elements.
$home = ['' => 'Home'];
$admin = $home + ['admin' => t('Administration')];
$page = $this->getSession()->getPage();
// /user/login is the default frontpage which only works for an anonymous
// user. Access the frontpage in different languages, ensure that no
// breadcrumb is displayed.
$this->drupalGet('user/login');
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertNull($breadcrumbs);
$this->drupalGet('de/user/login');
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertNull($breadcrumbs);
$this->drupalGet('gsw-berne/user/login');
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertNull($breadcrumbs);
$admin_user = $this->drupalCreateUser(['access administration pages']);
$this->drupalLogin($admin_user);
// Use administration routes to assert that breadcrumb is displayed
// correctly on pages other than the frontpage.
$this->drupalGet('admin');
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertEquals(1, substr_count($breadcrumbs->getText(), 'Home'));
$this->assertEquals(0, substr_count($breadcrumbs->getText(), 'Administration'));
$this->drupalGet('de/admin');
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertEquals(1, substr_count($breadcrumbs->getText(), 'Home'));
$this->assertEquals(0, substr_count($breadcrumbs->getText(), 'Administration'));
$this->drupalGet('admin/structure', $admin);
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertEquals(1, substr_count($breadcrumbs->getText(), 'Home'));
$this->assertEquals(1, substr_count($breadcrumbs->getText(), 'Administration'));
$this->drupalGet('de/admin/structure', $admin);
$breadcrumbs = $page->find('css', '.block-system-breadcrumb-block');
$this->assertEquals(1, substr_count($breadcrumbs->getText(), 'Home'));
$this->assertEquals(1, substr_count($breadcrumbs->getText(), 'Administration'));
}
}
......@@ -11,6 +11,7 @@
use Drupal\Core\Link;
use Drupal\Core\ParamConverter\ParamNotConvertedException;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Path\PathMatcherInterface;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\Routing\RequestContext;
use Drupal\Core\Routing\RouteMatch;
......@@ -79,6 +80,20 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface {
*/
protected $currentUser;
/**
* The current path service.
*
* @var \Drupal\Core\Path\CurrentPathStack
*/
protected $currentPath;
/**
* The patch matcher service.
*
* @var \Drupal\Core\Path\PathMatcherInterface
*/
protected $pathMatcher;
/**
* Constructs the PathBasedBreadcrumbBuilder.
*
......@@ -98,8 +113,10 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface {
* The current user object.
* @param \Drupal\Core\Path\CurrentPathStack $current_path
* The current path.
* @param \Drupal\Core\Path\PathMatcherInterface $path_matcher
* The path matcher service.
*/
public function __construct(RequestContext $context, AccessManagerInterface $access_manager, RequestMatcherInterface $router, InboundPathProcessorInterface $path_processor, ConfigFactoryInterface $config_factory, TitleResolverInterface $title_resolver, AccountInterface $current_user, CurrentPathStack $current_path) {
public function __construct(RequestContext $context, AccessManagerInterface $access_manager, RequestMatcherInterface $router, InboundPathProcessorInterface $path_processor, ConfigFactoryInterface $config_factory, TitleResolverInterface $title_resolver, AccountInterface $current_user, CurrentPathStack $current_path, PathMatcherInterface $path_matcher = NULL) {
$this->context = $context;
$this->accessManager = $access_manager;
$this->router = $router;
......@@ -108,6 +125,7 @@ public function __construct(RequestContext $context, AccessManagerInterface $acc
$this->titleResolver = $title_resolver;
$this->currentUser = $current_user;
$this->currentPath = $current_path;
$this->pathMatcher = $path_matcher ?: \Drupal::service('path.matcher');
}
/**
......@@ -124,6 +142,15 @@ public function build(RouteMatchInterface $route_match) {
$breadcrumb = new Breadcrumb();
$links = [];
// Add the url.path.parent cache context. This code ignores the last path
// part so the result only depends on the path parents.
$breadcrumb->addCacheContexts(['url.path.parent']);
// Do not display a breadcrumb on the frontpage.
if ($this->pathMatcher->isFrontPage()) {
return $breadcrumb;
}
// General path-based breadcrumbs. Use the actual request path, prior to
// resolving path aliases, so the breadcrumb can be defined by simply
// creating a hierarchy of path aliases.
......@@ -136,9 +163,6 @@ public function build(RouteMatchInterface $route_match) {
// /user is just a redirect, so skip it.
// @todo Find a better way to deal with /user.
$exclude['/user'] = TRUE;
// Add the url.path.parent cache context. This code ignores the last path
// part so the result only depends on the path parents.
$breadcrumb->addCacheContexts(['url.path.parent']);
while (count($path_elements) > 1) {
array_pop($path_elements);
// Copy the path elements for up-casting.
......@@ -160,13 +184,11 @@ public function build(RouteMatchInterface $route_match) {
$links[] = new Link($title, $url);
}
}
}
if ($path && '/' . $path != $front) {
// Add the Home link, except for the front page.
$links[] = Link::createFromRoute($this->t('Home'), '<front>');
}
// Add the Home link.
$links[] = Link::createFromRoute($this->t('Home'), '<front>');
return $breadcrumb->setLinks(array_reverse($links));
}
......
......@@ -12,7 +12,7 @@ services:
arguments: ['@module_handler', '@entity.manager', '@request_stack', '@menu.link_tree', '@menu.active_trail']
system.breadcrumb.default:
class: Drupal\system\PathBasedBreadcrumbBuilder
arguments: ['@router.request_context', '@access_manager', '@router', '@path_processor_manager', '@config.factory', '@title_resolver', '@current_user', '@path.current']
arguments: ['@router.request_context', '@access_manager', '@router', '@path_processor_manager', '@config.factory', '@title_resolver', '@current_user', '@path.current', '@path.matcher']
tags:
- { name: breadcrumb_builder, priority: 0 }
path_processor.files:
......
......@@ -11,6 +11,7 @@
use Drupal\Core\Cache\Cache;
use Drupal\Core\Link;
use Drupal\Core\Access\AccessResultAllowed;
use Drupal\Core\Path\PathMatcherInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Url;
use Drupal\Core\Utility\LinkGeneratorInterface;
......@@ -84,6 +85,13 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
*/
protected $currentPath;
/**
* The mocked path matcher service.
*
* @var \Drupal\Core\Path\PathMatcherInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $pathMatcher;
/**
* {@inheritdoc}
*
......@@ -106,6 +114,8 @@ protected function setUp() {
->disableOriginalConstructor()
->getMock();
$this->pathMatcher = $this->getMock(PathMatcherInterface::class);
$this->builder = new TestPathBasedBreadcrumbBuilder(
$this->context,
$this->accessManager,
......@@ -114,7 +124,8 @@ protected function setUp() {
$config_factory,
$this->titleResolver,
$this->currentUser,
$this->currentPath
$this->currentPath,
$this->pathMatcher
);
$this->builder->setStringTranslation($this->getStringTranslationStub());
......@@ -136,9 +147,9 @@ protected function setUp() {
* @covers ::build
*/
public function testBuildOnFrontpage() {
$this->context->expects($this->once())
->method('getPathInfo')
->will($this->returnValue('/'));
$this->pathMatcher->expects($this->once())
->method('isFrontPage')
->willReturn(TRUE);
$breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
$this->assertEquals([], $breadcrumb->getLinks());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment