class PathBasedBreadcrumbBuilder

Same name in other branches
  1. 9 core/modules/system/src/PathBasedBreadcrumbBuilder.php \Drupal\system\PathBasedBreadcrumbBuilder
  2. 8.9.x core/modules/system/src/PathBasedBreadcrumbBuilder.php \Drupal\system\PathBasedBreadcrumbBuilder
  3. 10 core/modules/system/src/PathBasedBreadcrumbBuilder.php \Drupal\system\PathBasedBreadcrumbBuilder

Defines a class to build path-based breadcrumbs.

Hierarchy

Expanded class hierarchy of PathBasedBreadcrumbBuilder

See also

\Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface

1 file declares its use of PathBasedBreadcrumbBuilder
PathBasedBreadcrumbBuilderTest.php in core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php
1 string reference to 'PathBasedBreadcrumbBuilder'
system.services.yml in core/modules/system/system.services.yml
core/modules/system/system.services.yml
1 service uses PathBasedBreadcrumbBuilder
system.breadcrumb.default in core/modules/system/system.services.yml
Drupal\system\PathBasedBreadcrumbBuilder

File

core/modules/system/src/PathBasedBreadcrumbBuilder.php, line 35

Namespace

Drupal\system
View source
class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface {
    use StringTranslationTrait;
    
    /**
     * The router request context.
     *
     * @var \Drupal\Core\Routing\RequestContext
     */
    protected $context;
    
    /**
     * The access check service.
     *
     * @var \Drupal\Core\Access\AccessManagerInterface
     */
    protected $accessManager;
    
    /**
     * The dynamic router service.
     *
     * @var \Symfony\Component\Routing\Matcher\RequestMatcherInterface
     */
    protected $router;
    
    /**
     * The inbound path processor.
     *
     * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface
     */
    protected $pathProcessor;
    
    /**
     * Site config object.
     *
     * @var \Drupal\Core\Config\Config
     */
    protected $config;
    
    /**
     * The title resolver.
     *
     * @var \Drupal\Core\Controller\TitleResolverInterface
     */
    protected $titleResolver;
    
    /**
     * The current user object.
     *
     * @var \Drupal\Core\Session\AccountInterface
     */
    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.
     *
     * @param \Drupal\Core\Routing\RequestContext $context
     *   The router request context.
     * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
     *   The access check service.
     * @param \Symfony\Component\Routing\Matcher\RequestMatcherInterface $router
     *   The dynamic router service.
     * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $path_processor
     *   The inbound path processor.
     * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
     *   The config factory service.
     * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
     *   The title resolver service.
     * @param \Drupal\Core\Session\AccountInterface $current_user
     *   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, ?PathMatcherInterface $path_matcher = NULL) {
        $this->context = $context;
        $this->accessManager = $access_manager;
        $this->router = $router;
        $this->pathProcessor = $path_processor;
        $this->config = $config_factory->get('system.site');
        $this->titleResolver = $title_resolver;
        $this->currentUser = $current_user;
        $this->currentPath = $current_path;
        $this->pathMatcher = $path_matcher ?: \Drupal::service('path.matcher');
    }
    
    /**
     * {@inheritdoc}
     */
    public function applies(RouteMatchInterface $route_match, ?CacheableMetadata $cacheable_metadata = NULL) {
        return TRUE;
    }
    
    /**
     * {@inheritdoc}
     */
    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',
            'url.path.is_front',
        ]);
        // 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.
        $path = trim($this->context
            ->getPathInfo(), '/');
        $path_elements = explode('/', $path);
        $exclude = [];
        // Don't show a link to the front-page path.
        $front = $this->config
            ->get('page.front');
        $exclude[$front] = TRUE;
        // /user is just a redirect, so skip it.
        // @todo Find a better way to deal with /user.
        $exclude['/user'] = TRUE;
        while (count($path_elements) > 1) {
            array_pop($path_elements);
            // Copy the path elements for up-casting.
            $route_request = $this->getRequestForPath('/' . implode('/', $path_elements), $exclude);
            if ($route_request) {
                $route_match = RouteMatch::createFromRequest($route_request);
                $access = $this->accessManager
                    ->check($route_match, $this->currentUser, NULL, TRUE);
                // The set of breadcrumb links depends on the access result, so merge
                // the access result's cacheability metadata.
                $breadcrumb = $breadcrumb->addCacheableDependency($access);
                if ($access->isAllowed()) {
                    $title = $this->titleResolver
                        ->getTitle($route_request, $route_match->getRouteObject());
                    if (!isset($title)) {
                        // Fallback to using the raw path component as the title if the
                        // route is missing a _title or _title_callback attribute.
                        $title = str_replace([
                            '-',
                            '_',
                        ], ' ', Unicode::ucfirst(end($path_elements)));
                    }
                    $url = Url::fromRouteMatch($route_match);
                    $links[] = new Link($title, $url);
                }
            }
        }
        // Add the Home link.
        $links[] = Link::createFromRoute($this->t('Home'), '<front>');
        return $breadcrumb->setLinks(array_reverse($links));
    }
    
    /**
     * Matches a path in the router.
     *
     * @param string $path
     *   The request path with a leading slash.
     * @param array $exclude
     *   An array of paths or system paths to skip.
     *
     * @return \Symfony\Component\HttpFoundation\Request
     *   A populated request object or NULL if the path couldn't be matched.
     */
    protected function getRequestForPath($path, array $exclude) {
        if (!empty($exclude[$path])) {
            return NULL;
        }
        $request = Request::create($path);
        // Performance optimization: set a short accept header to reduce overhead in
        // AcceptHeaderMatcher when matching the request.
        $request->headers
            ->set('Accept', 'text/html');
        // Find the system path by resolving aliases, language prefix, etc.
        $processed = $this->pathProcessor
            ->processInbound($path, $request);
        if (empty($processed) || !empty($exclude[$processed])) {
            // This resolves to the front page, which we already add.
            return NULL;
        }
        $this->currentPath
            ->setPath($processed, $request);
        // Attempt to match this path to provide a fully built request.
        try {
            $request->attributes
                ->add($this->router
                ->matchRequest($request));
            return $request;
        } catch (ParamNotConvertedException|ResourceNotFoundException|MethodNotAllowedException|AccessDeniedHttpException|NotFoundHttpException) {
            return NULL;
        }
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
PathBasedBreadcrumbBuilder::$accessManager protected property The access check service.
PathBasedBreadcrumbBuilder::$config protected property Site config object.
PathBasedBreadcrumbBuilder::$context protected property The router request context.
PathBasedBreadcrumbBuilder::$currentPath protected property The current path service.
PathBasedBreadcrumbBuilder::$currentUser protected property The current user object.
PathBasedBreadcrumbBuilder::$pathMatcher protected property The patch matcher service.
PathBasedBreadcrumbBuilder::$pathProcessor protected property The inbound path processor.
PathBasedBreadcrumbBuilder::$router protected property The dynamic router service.
PathBasedBreadcrumbBuilder::$titleResolver protected property The title resolver.
PathBasedBreadcrumbBuilder::applies public function Whether this breadcrumb builder should be used to build the breadcrumb. Overrides BreadcrumbBuilderInterface::applies
PathBasedBreadcrumbBuilder::build public function Builds the breadcrumb. Overrides BreadcrumbBuilderInterface::build
PathBasedBreadcrumbBuilder::getRequestForPath protected function Matches a path in the router.
PathBasedBreadcrumbBuilder::__construct public function Constructs the PathBasedBreadcrumbBuilder.
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.