0

I have been trying to intercept a page request from /node/nid which is of type the_content_type and then appending some facet query parameters to it which is something like this

?f[0]=city%3A160&f[1]=country%3A48.

The purpose is to preselect the facet options from that page.

Here is the subscriber class I have written so far

<?php

namespace Drupal\custom_module\EventSubscriber;

use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Drupal\Core\Routing\TrustedRedirectResponse;

class RedirectWithFilterSubscriber implements EventSubscriberInterface {
  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    // This announces which events you want to subscribe to.
    // We only need the request event for this example.  Pass
    // this an array of method names
    return([
      KernelEvents::REQUEST => [
        ['redirectWithFilter'],
      ]
    ]);
  }

  /**
   * Redirect requests for my_content_type node detail pages to node/123.
   *
   * @param GetResponseEvent $event
   * @return void
   */
  public function redirectWithFilter(GetResponseEvent $event) {
    $request = $event->getRequest();

    // This is necessary because this also gets called on
    // node sub-tabs such as "edit", "revisions", etc.  This
    // prevents those pages from redirected.
    if ($request->attributes->get('_route') !== 'entity.node.canonical') {
      return;
    }

    // Only redirect a certain content type.
    if ($request->attributes->get('node')->getType() !== 'the_content_type') {
      return;
    }

    $node = $request->attributes->get('node');
    $node_id = $node->id();
    $node_url = $node->url();
    $country = $node->field_country->getValue();
    $city = $node->field_city->getValue();
    $country_target_id = $country[0]['target_id'];
    $city_target_id = $city[0]['target_id'];

    if (empty($country) && empty($city)) {
      return;
    }

    // This is where you set the destination.
    $option = [
      "query" => [
        "f" => [
          "city:$city_target_id",
          "country:$country_target_id"
        ]
      ],
    ];

    $redirect_url = Url::fromUri("entity:node/$node_id", $option);
    $response = new RedirectResponse($redirect_url->toString(), 301);
    $event->setResponse($response);
  }
}

The resulting url looks fine though

http://project.dev/some-custom-page?f%5B0%5D=city%3A160&f%5B1%5D=country%3A48

But the problem is, the page always shows

The page isn’t redirecting properly

on my browser. I've been figuring this out for almost 3 days now and I can't seem to find a way through it. I've been wanting someone to have a fresh look into it. Maybe I am doing something wrong. Is there somebody can lend me a help please? Or maybe, a different way other than this? Thank you in advance.

1

Could be a redirect loop. You have to check whether the query string is already present and then stop redirecting again:

  public function redirectWithFilter(GetResponseEvent $event) {
    $request = $event->getRequest();
    if ($request->query->has('city')) {
      return;
    }
    ...
  }
  • Thank you for feedback 4k4. It really helps me to figure out the problem and allow me to fix the issue. I have modified a bit your answer to suit my needs. – Teody C. Seguin Jan 26 at 11:08
  • This is how I did it. $query = $request->query->all(); if ($query['f'][0] == "city:$city_target_id") { return; } if ($query['f'][0] == "country:$country_target_id") { return; } – Teody C. Seguin Jan 26 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.