You are here

class BreadcrumbManagerBuilder in Breadcrumb Manager 8

Class BreadcrumbManagerBuilder.

@package Drupal\breadcrumb_manager\Breadcrumb

Hierarchy

Expanded class hierarchy of BreadcrumbManagerBuilder

1 string reference to 'BreadcrumbManagerBuilder'
breadcrumb_manager.services.yml in ./breadcrumb_manager.services.yml
breadcrumb_manager.services.yml
1 service uses BreadcrumbManagerBuilder
breadcrumb_manager.breadcrumb in ./breadcrumb_manager.services.yml
Drupal\breadcrumb_manager\Breadcrumb\BreadcrumbManagerBuilder

File

src/Breadcrumb/BreadcrumbManagerBuilder.php, line 35

Namespace

Drupal\breadcrumb_manager\Breadcrumb
View source
class BreadcrumbManagerBuilder extends PathBasedBreadcrumbBuilder {
  use StringTranslationTrait;

  /**
   * The Breadcrumb Title Resolver Manager.
   *
   * @var \Drupal\breadcrumb_manager\Plugin\BreadcrumbTitleResolverManager
   */
  protected $titleResolverManager;

  /**
   * An array of Breadcrumb Title resolver plugins.
   *
   * @var \Drupal\breadcrumb_manager\Plugin\BreadcrumbTitleResolverInterface[]
   */
  protected $titleResolvers;

  /**
   * Breadcrumb Manager configurations.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $breadcrumbConfig;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * An array of excluded paths.
   *
   * @var array
   */
  protected $excludedPaths;

  /**
   * {@inheritdoc}
   */
  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, BreadcrumbTitleResolverManager $title_resolver_manager, ModuleHandlerInterface $module_handler) {
    parent::__construct($context, $access_manager, $router, $path_processor, $config_factory, $title_resolver, $current_user, $current_path, $path_matcher);
    $this->titleResolverManager = $title_resolver_manager;
    $this->titleResolvers = $this->titleResolverManager
      ->getInstances();
    $this->breadcrumbConfig = $config_factory
      ->get('breadcrumb_manager.config');
    $this->moduleHandler = $module_handler;
  }

  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $attributes) {
    return !$this
      ->isExcludedPath($attributes
      ->getRouteObject()
      ->getPath());
  }

  /**
   * {@inheritdoc}
   */
  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
    $breadcrumb
      ->addCacheContexts([
      'url',
    ]);
    $breadcrumb
      ->addCacheTags([
      'config:breadcrumb_manager.config',
    ]);
    $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.
    $path = trim($this->context
      ->getPathInfo(), '/');
    $path_elements = explode('/', $path);

    // Hide current page from breadcrumb if necessary.
    if (!$this->breadcrumbConfig
      ->get('show_current')) {
      array_pop($path_elements);
    }
    $is_first = TRUE;
    while (count($path_elements) > 0) {
      $current_path = '/' . implode('/', $path_elements);
      array_pop($path_elements);

      // Check if we have to show last segment as link.
      $show_as_link = $is_first ? $this->breadcrumbConfig
        ->get('show_current_as_link') : TRUE;
      $is_first = FALSE;

      // Copy the path elements for up-casting.
      $route_request = $this
        ->getRequestForPath($current_path, $this
        ->getExcludedPaths());
      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()) {
          continue;
        }
        $title = FALSE;
        foreach ($this->titleResolvers as $titleResolver) {
          if (!$titleResolver
            ->isActive()) {
            continue;
          }
          $resolved_title = $titleResolver
            ->getTitle($current_path, $route_request, $route_match);
          if (!empty($resolved_title)) {
            $title = $resolved_title;
            break;
          }
        }
        if ($title) {
          $url = $show_as_link ? Url::fromRouteMatch($route_match) : Url::fromRoute('<none>');
          $links[] = new Link($title, $url);
        }
      }
      elseif ($this->breadcrumbConfig
        ->get('show_fake_segments')) {

        // Show fake segments if this option has been selected.
        try {
          $titleResolver = $this->titleResolverManager
            ->createInstance('raw_path_component');

          // We don't really need a valid Request, so creating a simple one
          // will be more than necessary to let the plugin resolving the title.
          $current_request = Request::create($current_path);
          $title = $titleResolver
            ->getTitle($current_path, $current_request, $route_match);
          $url = Url::fromRoute('<none>');

          // Let other modules alter the fake segment.
          $this->moduleHandler
            ->alter('breadcrumb_manager_fake_segments', $current_path, $title, $url);
          $links[] = new Link($title, $url);
        } catch (PluginException $e) {

          // Nothing to do here cause 'raw_path_component' will always exist.
        }
      }
    }

    // Add the Home link if necessary.
    if ($this->breadcrumbConfig
      ->get('show_home')) {
      $home = $this->breadcrumbConfig
        ->get('home') ?: $this
        ->t('Home');
      $links[] = Link::createFromRoute($home, '<front>');
    }
    return $breadcrumb
      ->setLinks(array_reverse($links));
  }

  /**
   * Set excluded paths.
   */
  protected function setExcludedPaths() {
    $excluded_paths = $this->breadcrumbConfig
      ->get('excluded_paths');
    $this->excludedPaths = explode("\r\n", $excluded_paths);

    // Exclude Front page if not necessary.
    if (!$this->breadcrumbConfig
      ->get('show_front')) {
      $this->excludedPaths[] = $this->config
        ->get('page.front');
    }
  }

  /**
   * Get excluded paths.
   *
   * @return array
   *   An array of excluded paths.
   */
  protected function getExcludedPaths() {
    if (!isset($this->excludedPaths)) {
      $this
        ->setExcludedPaths();
    }
    return $this->excludedPaths;
  }

  /**
   * Checks if the given path is excluded.
   *
   * @param string $path
   *   The path to be checked.
   *
   * @return bool
   *   A boolean indicating if the given path is excluded.
   */
  protected function isExcludedPath($path) {
    $excluded = implode("\n", $this
      ->getExcludedPaths());
    return $this->pathMatcher
      ->matchPath($path, $excluded);
  }

  /**
   * 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 (in_array($path, $exclude)) {
      return NULL;
    }

    // @todo Use the RequestHelper once https://www.drupal.org/node/2090293 is
    //   fixed.
    $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) || $this
      ->isExcludedPath($processed)) {
      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 $e) {
      return NULL;
    } catch (ResourceNotFoundException $e) {
      return NULL;
    } catch (MethodNotAllowedException $e) {
      return NULL;
    } catch (AccessDeniedHttpException $e) {
      return NULL;
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
BreadcrumbManagerBuilder::$breadcrumbConfig protected property Breadcrumb Manager configurations.
BreadcrumbManagerBuilder::$excludedPaths protected property An array of excluded paths.
BreadcrumbManagerBuilder::$moduleHandler protected property The module handler.
BreadcrumbManagerBuilder::$titleResolverManager protected property The Breadcrumb Title Resolver Manager.
BreadcrumbManagerBuilder::$titleResolvers protected property An array of Breadcrumb Title resolver plugins.
BreadcrumbManagerBuilder::applies public function Whether this breadcrumb builder should be used to build the breadcrumb. Overrides PathBasedBreadcrumbBuilder::applies
BreadcrumbManagerBuilder::build public function Builds the breadcrumb. Overrides PathBasedBreadcrumbBuilder::build
BreadcrumbManagerBuilder::getExcludedPaths protected function Get excluded paths.
BreadcrumbManagerBuilder::getRequestForPath protected function Matches a path in the router. Overrides PathBasedBreadcrumbBuilder::getRequestForPath
BreadcrumbManagerBuilder::isExcludedPath protected function Checks if the given path is excluded.
BreadcrumbManagerBuilder::setExcludedPaths protected function Set excluded paths.
BreadcrumbManagerBuilder::__construct public function Constructs the PathBasedBreadcrumbBuilder. Overrides PathBasedBreadcrumbBuilder::__construct
PathBasedBreadcrumbBuilder::$accessManager protected property The menu link access 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.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
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.