You are here

public function MenuBasedBreadcrumbBuilder::applies in Menu Breadcrumb 8

Same name and namespace in other branches
  1. 2.0.x src/MenuBasedBreadcrumbBuilder.php \Drupal\menu_breadcrumb\MenuBasedBreadcrumbBuilder::applies()

Whether this breadcrumb builder should be used to build the breadcrumb.

Parameters

\Drupal\Core\Routing\RouteMatchInterface $route_match: The current route match.

Return value

bool TRUE if this builder should be used or FALSE to let other builders decide.

Overrides BreadcrumbBuilderInterface::applies

File

src/MenuBasedBreadcrumbBuilder.php, line 171

Class

MenuBasedBreadcrumbBuilder

Namespace

Drupal\menu_breadcrumb

Code

public function applies(RouteMatchInterface $route_match) {

  // This may look heavyweight for applies() but we have to check all ways the
  // current path could be attached to the selected menus before turning over
  // breadcrumb building (and caching) to another builder.  Generally this
  // should not be a problem since it will then fall back to the system (path
  // based) breadcrumb builder which caches a breadcrumb no matter what.
  if (!$this->config
    ->get('determine_menu')) {
    return FALSE;
  }

  // Don't breadcrumb the admin pages, if disabled on config options:
  if ($this->config
    ->get('disable_admin_page') && $this->adminContext
    ->isAdminRoute($route_match
    ->getRouteObject())) {
    return FALSE;
  }

  // No route name means no active trail:
  $route_name = $route_match
    ->getRouteName();
  if (!$route_name) {
    return FALSE;
  }

  // This might be a "node" with no fields, e.g. a route to a "revision" URL,
  // so we don't check for taxonomy fields on unfieldable nodes:
  $node_object = $route_match
    ->getParameters()
    ->get('node');
  $node_is_fieldable = $node_object instanceof FieldableEntityInterface;

  // Make sure menus are selected, and breadcrumb text strings, are displayed
  // in the content rather than the (default) interface language:
  $this->contentLanguage = $this->languageManager
    ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
    ->getId();

  // Check each selected menu, in turn, until a menu or taxonomy match found:
  // then cache its state for building & caching in build() and exit.
  $menus = $this->config
    ->get('menu_breadcrumb_menus');
  uasort($menus, function ($a, $b) {
    return SortArray::sortByWeightElement($a, $b);
  });
  foreach ($menus as $menu_name => $params) {

    // Look for current path on any enabled menu.
    if (!empty($params['enabled'])) {

      // Skip over any menu that's not in the current content language,
      // if and only if the "language handling" option set for that menu.
      // NOTE this menu option is added late, so we check its existence first.
      if (array_key_exists('langhandle', $params) && $params['langhandle']) {
        $menu_objects = $this->entityTypeManager
          ->getStorage('menu')
          ->loadByProperties([
          'id' => $menu_name,
        ]);
        if ($menu_objects) {
          $menu_language = reset($menu_objects)
            ->language()
            ->getId();
          if ($menu_language != $this->contentLanguage && $menu_language !== Language::LANGCODE_NOT_SPECIFIED && $menu_language !== Language::LANGCODE_NOT_APPLICABLE) {
            continue;
          }
        }
      }
      if ($this->config
        ->get('derived_active_trail')) {

        // Do not use the global MenuActiveTrail service because we need one
        // which is aware of the given routeMatch, not of the global one.
        $menuActiveTrail = new MenuActiveTrail($this->menuLinkManager, $route_match, $this->cacheMenu, $this->lock);
        $trail_ids = $menuActiveTrail
          ->getActiveTrailIds($menu_name);
      }
      else {

        // Default, for the majority & compatibility with historical use and
        // other modules: use the global (injected) MenuActiveTrail service.
        $trail_ids = $this->menuActiveTrail
          ->getActiveTrailIds($menu_name);
      }
      $trail_ids = array_filter($trail_ids);
      if ($trail_ids) {
        $this->menuName = $menu_name;
        $this->menuTrail = $trail_ids;
        $this->taxonomyAttachment = NULL;
        return TRUE;
      }
    }

    // Look for a "taxonomy attachment" by node field, regardless of language.
    if (!empty($params['taxattach']) && $node_is_fieldable) {

      // Check all taxonomy terms applying to the current page.
      foreach ($node_object
        ->getFields() as $field) {
        if ($field
          ->getSetting('target_type') == 'taxonomy_term') {

          // In general these entity references will support multiple
          // values so we check all terms in the order they are listed.
          foreach ($field
            ->referencedEntities() as $term) {
            $url = $term
              ->toUrl();
            $route_links = $this->menuLinkManager
              ->loadLinksByRoute($url
              ->getRouteName(), $url
              ->getRouteParameters(), $menu_name);
            if (!empty($route_links)) {

              // Successfully found taxonomy attachment, so pass to build():
              // - the menu in which we have found the attachment
              // - the effective menu trail of the taxonomy-attached node
              // - the node itself (in build() we will find its title & URL)
              $taxonomy_term_link = reset($route_links);
              $taxonomy_term_id = $taxonomy_term_link
                ->getPluginId();
              $this->menuName = $menu_name;
              $this->menuTrail = $this->menuLinkManager
                ->getParentIds($taxonomy_term_id);
              $this->taxonomyAttachment = $node_object;
              return TRUE;
            }
          }
        }
      }
    }
  }

  // No more menus to check...
  return FALSE;
}