You are here

function facets_system_breadcrumb_alter in Facets 8

Implements hook_system_breadcrumb_alter().

File

./facets.module, line 215
Contains facets.module.

Code

function facets_system_breadcrumb_alter(Breadcrumb &$breadcrumb, RouteMatchInterface $route_match, array $context) {

  /** @var \Drupal\facets\FacetSource\FacetSourcePluginManager $facet_source_manager */
  $facet_source_manager = \Drupal::service('plugin.manager.facets.facet_source');

  /** @var \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager */
  $facet_manager = \Drupal::service('facets.manager');

  /** @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */
  $entity_type_manager = \Drupal::service('entity_type.manager');

  /** @var \Drupal\Core\Entity\EntityStorageInterface $facet_source_storage */
  $facet_source_storage = $entity_type_manager
    ->getStorage('facets_facet_source');
  $facet_sources_definitions = $facet_source_manager
    ->getDefinitions();
  $facets_url_generator = \Drupal::service('facets.utility.url_generator');

  // No facet sources found, so don't do anything.
  if (empty($facet_sources_definitions)) {
    return;
  }
  foreach ($facet_sources_definitions as $definition) {

    /* @var \Drupal\facets\FacetSource\FacetSourcePluginBase $facet_source_plugin */
    $facetsource_id = $definition['id'];
    $facet_source_plugin = $facet_source_manager
      ->createInstance($facetsource_id);

    // If the current facet source is not being rendered, don't do anything with
    // these facet sources.
    if (!$facet_source_plugin
      ->isRenderedInCurrentRequest()) {
      continue;
    }
    $source_id = str_replace(':', '__', $facetsource_id);

    /** @var \Drupal\facets\FacetSourceInterface $facet_source */
    $facet_source = $facet_source_storage
      ->load($source_id);

    // If the facet source is not loaded, or the facet source doesn't have
    // breadcrumbs enabled, don't do anything.
    if (!($facet_source && !empty($facet_source
      ->getBreadcrumbSettings()['active']))) {
      continue;
    }

    // Add the required cacheability metadata.
    $breadcrumb
      ->addCacheContexts([
      'url',
    ]);
    $breadcrumb
      ->addCacheableDependency($facet_source);

    // Process the facets if they are not already processed.
    $facet_manager
      ->processFacets($facetsource_id);
    $facets = $facet_manager
      ->getFacetsByFacetSourceId($facetsource_id);

    // Sort facets by weight.
    uasort($facets, function (FacetInterface $a, FacetInterface $b) {
      if ($a
        ->getWeight() == $b
        ->getWeight()) {
        return 0;
      }
      return $a
        ->getWeight() < $b
        ->getWeight() ? -1 : 1;
    });

    /** @var \Drupal\facets\UrlProcessor\UrlProcessorPluginManager $url_processor_manager */
    $url_processor_manager = \Drupal::service('plugin.manager.facets.url_processor');

    // Get active facets and results to use them at building the crumbs.
    $active_results = [];
    $active_facets = [];
    foreach ($facets as $facet) {
      if (count($facet
        ->getActiveItems()) > 0) {

        // Add the facet as a cacheable dependency.
        $breadcrumb
          ->addCacheableDependency($facet);

        /** @var \Drupal\facets\UrlProcessor\UrlProcessorInterface $url_processor */
        $url_processor = $url_processor_manager
          ->createInstance($facet_source
          ->getUrlProcessorName(), [
          'facet' => $facet,
        ]);
        $facet_manager
          ->build($facet);
        foreach ($facet
          ->getResults() as $result) {
          if ($result
            ->isActive() || $result
            ->hasActiveChildren()) {

            // Clone the result so we can mark it as inactive to be added to the
            // url parameters when calling buildUrls.
            $cloned_result = clone $result;
            $cloned_result
              ->setActiveState(FALSE);
            $active_results[$facet
              ->id()][] = $cloned_result;
          }
        }
        if (!empty($active_results[$facet
          ->getUrlAlias()])) {
          $url_processor
            ->buildUrls($facet, $active_results[$facet
            ->getUrlAlias()]);
        }
        $active_facets[$facet
          ->id()] = $facet;
      }
    }

    // TODO find a better way to construct the url for a crumb maybe url
    // processor will have a function to get params for a result
    // without all the other request parameters; with this we could implement:
    // @see https://www.drupal.org/node/2861586
    // TODO handle not grouped facets.

    /** @var \Drupal\facets\Result\ResultInterface[] $facet_results */
    foreach ($active_results as $facet_id => $facet_results) {
      $facet_used_result[$facet_id] = [];
      $facet_crumb_items = [];

      // Because we can't get the desired display value trough a url processor
      // method we iterate each result url and remove the facet params that
      // haven't been used on previous crumbs.
      foreach ($facet_results as $res) {
        $facet_used_result[$facet_id][] = $res
          ->getRawValue();
        $facet_crumb_items[] = $res
          ->getDisplayValue();
      }
      sort($facet_crumb_items);
      $facet_url = $facets_url_generator
        ->getUrl($facet_used_result, FALSE);
      if (!empty($facet_source
        ->getBreadcrumbSettings()['before'])) {
        $crumb_text = $active_facets[$facet_id]
          ->label() . ': ' . implode(', ', $facet_crumb_items);
      }
      else {
        $crumb_text = implode(', ', $facet_crumb_items);
      }
      $link = Link::fromTextAndUrl($crumb_text, $facet_url);
      $breadcrumb
        ->addLink($link);
    }
  }
}