Commit 313c10ba authored by Markus Kalkbrenner's avatar Markus Kalkbrenner Committed by Markus Kalkbrenner
Browse files

Issue #3291943 by mkalkbrenner, abhaisasidharan: When rendering facets on non...

Issue #3291943 by mkalkbrenner, abhaisasidharan: When rendering facets on non search page, it throws error instead of 404 on 404 pages
parent 1ada16f8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
name: 'Facets'
type: module
description: 'Faceted search interfaces that can be used on Search API searchers.'
core_version_requirement: ^9.2 || ^10.0
core_version_requirement: ^9.3 || ^10.0
package: Search
configure: entity.facets_facet.collection
test_dependencies:
+17 −38
Original line number Diff line number Diff line
@@ -5,16 +5,15 @@ namespace Drupal\facets\Plugin\facets\url_processor;
use Drupal\Core\Cache\UnchangingCacheableDependencyTrait;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Url;
use Drupal\facets\Event\ActiveFiltersParsed;
use Drupal\facets\Event\QueryStringCreated;
use Drupal\facets\Event\UrlCreated;
use Drupal\facets\FacetInterface;
use Drupal\facets\UrlProcessor\UrlProcessorPluginBase;
use Drupal\facets\Utility\FacetsUrlGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;

/**
 * Query string URL processor.
@@ -43,12 +42,20 @@ class QueryString extends UrlProcessorPluginBase {
   */
  protected $eventDispatcher;

  /**
   * The URL generator.
   *
   * @var \Drupal\facets\Utility\FacetsUrlGenerator
   */
  protected $urlGenerator;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, Request $request, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $eventDispatcher) {
  public function __construct(array $configuration, $plugin_id, $plugin_definition, Request $request, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $eventDispatcher, FacetsUrlGenerator $urlGenerator) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $request, $entity_type_manager);
    $this->eventDispatcher = $eventDispatcher;
    $this->urlGenerator = $urlGenerator;
    $this->initializeActiveFilters();
  }

@@ -62,7 +69,8 @@ class QueryString extends UrlProcessorPluginBase {
      $plugin_definition,
      $container->get('request_stack')->getCurrentRequest(),
      $container->get('entity_type.manager'),
      $container->get('event_dispatcher')
      $container->get('event_dispatcher'),
      $container->get('facets.utility.url_generator')
    );
  }

@@ -88,6 +96,8 @@ class QueryString extends UrlProcessorPluginBase {
    // Set the url alias from the facet object.
    $this->urlAlias = $facet->getUrlAlias();

    // In case of a view page display, the facet source has a path, If the
    // source is a block, the path is null.
    $facet_source_path = $facet->getFacetSource()->getPath();
    $request = $this->getRequestByFacetSourcePath($facet_source_path);
    $requestUrl = $this->getUrlForRequest($facet_source_path, $request);
@@ -274,9 +284,8 @@ class QueryString extends UrlProcessorPluginBase {
  /**
   * Gets the URL object for a request.
   *
   * This method statically caches the URL object for a request based on the
   * facet source path. This reduces subsequent calls to the processor from
   * having to regenerate the URL object.
   * This method delegates to the URL generator service. But we keep it for
   * backward compatibility for custom implementations that extend this class.
   *
   * @param string $facet_source_path
   *   The facet source path.
@@ -287,37 +296,7 @@ class QueryString extends UrlProcessorPluginBase {
   *   The URL.
   */
  protected function getUrlForRequest($facet_source_path, Request $request) {
    /** @var \Drupal\Core\Url[] $requestUrlsByPath */
    $requestUrlsByPath = &drupal_static(__CLASS__ . __FUNCTION__, []);

    if (array_key_exists($facet_source_path, $requestUrlsByPath)) {
      return $requestUrlsByPath[$facet_source_path];
    }

    // Try to grab any route params from the original request.
    // In case of request path not having a matching route, Url generator will
    // fail with.
    try {
      $requestUrl = Url::createFromRequest($request);
    }
    catch (ResourceNotFoundException $e) {
      // Bypass exception if no path available.
      // Should be unreachable in default FacetSource implementations,
      // but you never know.
      if (!$facet_source_path) {
        throw $e;
      }

      $requestUrl = Url::fromUserInput($facet_source_path, [
        'query' => [
          '_format' => $this->request->get('_format'),
        ],
      ]);
    }

    $requestUrl->setOption('attributes', ['rel' => 'nofollow']);
    $requestUrlsByPath[$facet_source_path] = $requestUrl;
    return $requestUrl;
    return $this->urlGenerator->getUrlForRequest($request, $facet_source_path);
  }

  /**
+4 −4
Original line number Diff line number Diff line
@@ -67,14 +67,14 @@ class LinksWidget extends WidgetPluginBase {

      unset($active_filters[$facet->id()]);

      // Only if there are still active filters, use url generator.
      $urlGenerator = \Drupal::service('facets.utility.url_generator');
      if ($active_filters) {
        $url = \Drupal::service('facets.utility.url_generator')
          ->getUrl($active_filters, FALSE);
        $url = $urlGenerator->getUrl($active_filters, FALSE);
      }
      else {
        $request = \Drupal::request();
        $url = Url::createFromRequest($request);
        $facet_source = $facet->getFacetSource();
        $url = $urlGenerator->getUrlForRequest($request, $facet_source ? $facet_source->getPath() : NULL);
        $params = $request->query->all();
        unset($params[$url_processor->getFilterKey()]);
        if (\array_key_exists('page', $params)) {
+1 −3
Original line number Diff line number Diff line
@@ -127,9 +127,7 @@ abstract class UrlProcessorPluginBase extends ProcessorPluginBase implements Url
      $configuration,
      $plugin_id,
      $plugin_definition,
      // Support 9.3+.
      // @todo remove switch after 9.3 or greater is required.
      version_compare(\Drupal::VERSION, '9.3', '>=') ? $request_stack->getMainRequest() : $request_stack->getMasterRequest(),
      $request_stack->getMainRequest(),
      $container->get('entity_type.manager')
    );
  }
+68 −0
Original line number Diff line number Diff line
@@ -3,8 +3,11 @@
namespace Drupal\facets\Utility;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Url;
use Drupal\facets\Result\Result;
use Drupal\facets\UrlProcessor\UrlProcessorPluginManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;

/**
 * Facets Url Generator service.
@@ -109,4 +112,69 @@ class FacetsUrlGenerator {
    return NULL;
  }

  /**
   * Gets the URL object for a request.
   *
   * This method statically caches the URL object for a request based on the
   * facet source path. This reduces subsequent calls to the processor from
   * having to regenerate the URL object.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   * @param string $facet_source_path
   *   The facet source path.
   *
   * @return \Drupal\Core\Url
   *   The URL.
   */
  public function getUrlForRequest(Request $request, $facet_source_path = NULL): Url {
    /** @var \Drupal\Core\Url[] $requestUrlsByPath */
    $requestUrlsByPath = &drupal_static(__CLASS__ . __FUNCTION__, []);
    $request_uri = $request->getRequestUri();

    if (array_key_exists($request_uri, $requestUrlsByPath)) {
      return $requestUrlsByPath[$request_uri];
    }

    // Try to grab any route params from the original request.
    // In case of request path not having a matching route, Url generator will
    // fail with.
    try {
      $requestUrl = Url::createFromRequest($request);
    }
    catch (ResourceNotFoundException $e) {
      // Bypass exception if no path available.
      // Should be unreachable in default FacetSource implementations,
      // but you never know.
      if ($facet_source_path) {
        $requestUrl = Url::fromUserInput($facet_source_path, [
          'query' => [
            '_format' => \Drupal::request()->get('_format'),
          ],
        ]);
      }
      else {
        if ('system.404' === $request->attributes->get('_route')) {
          // It seems that a facet that is configured to be rendered without its
          // facet source is currently rendered on a dedicated "page not found"
          // page. If the facet source has a valid path we would not land here
          // but in the condition above. So the facet source must be view block
          // display or something similar. In this case we could assume that
          // such a facet takes care about its link target itself and doesn't
          // depend on the current path or the facet source path. Let's provide
          // the front page as valid fallback to let the facet do its job.
          $requestUrl = Url::fromRoute('<front>');
        }
        else {
          throw $e;
        }
      }
    }

    $requestUrl->setOption('attributes', ['rel' => 'nofollow']);
    $requestUrlsByPath[$request_uri] = $requestUrl;

    return $requestUrl;
  }

}
Loading