Account created on 30 December 2024, 4 months ago
#

Recent comments

Reposted the solution, thanks for all the help!

Hi thanks for the reply, and happy new year!

The reason I renamed web to docroot was because I was following an acquia tutorial and they require you change the directory name, you can find the guide here.

Adding the debug_print_backtrace() I was able top pinpoint the issue in the docroot/modules/contrib/opigno_module/src/EventSubscriber/QueryPathEventSubscriber.php

Root Cause

The issue lies in the `checkRedirection` method in the `QueryPathEventSubscriber` class.  

1. Session Data Conflict:  
   - The session stores `ajax_page_state`, which is not relevant for redirection but gets checked during subsequent requests.  
   - The presence of `ajax_page_state` causes a mismatch between current query parameters and the session state, triggering the redirection repeatedly.

2. Recursive Redirection:  
   - The `RedirectResponse` is continuously generated because the comparison between the current request and the session-stored state does not account for `ajax_page_state`.

here is the revised code.

php
public function checkRedirection(ResponseEvent $event): void {
  $available_routes = [
    'entity.opigno_activity.collection',
    'entity.opigno_module.collection',
    'entity.group.collection',
  ];
  $current_route = $this->routeMatch->getRouteName();
  if (!in_array($current_route, $available_routes)) {
    return;
  }

  $request = $this->requestStack->getCurrentRequest();
  $session = $request->getSession();
  $param = $request->query->all();

  // Exclude ajax_page_state from query parameters.
  unset($param['ajax_page_state']);

  if (!empty($param)) {
    $session->set($current_route, $param);
    return;
  }

  $order_values = $session->get($current_route);

  // Exclude ajax_page_state from session state.
  if (!empty($order_values)) {
    unset($order_values['ajax_page_state']);
  }

  if (!empty($order_values)) {
    // Prevent recursive redirection.
    if ($param == $order_values) {
      return;
    }

    $url = Url::fromRoute($current_route);
    $url->setOption('query', $order_values);
    $response = new RedirectResponse($url->toString());
    $event->setResponse($response);
  }
}

Hi thanks for replying and happy new year!

The reason for the change of the web directory file name change to docroot is because I was following Acquia's documentation, see here for the guide. 

I added the debug_print_backtrace to my RedirectResponse.php file which is located in vendor/symfony/http-foundation. I was then able to pin point the problem to the checkRedirection function located in QueryPathEventSubscriber.php which is located under docroot/modules/contrib/opigno_module/src/EventSubscribe.

The issue lies in the checkRedirection method in the QueryPathEventSubscriber class.

  1. Session Data Conflict:

    • The session stores ajax_page_state, which is not relevant for redirection but gets checked during subsequent requests.
    • The presence of ajax_page_state causes a mismatch between current query parameters and the session state, triggering the redirection repeatedly.
  2. Recursive Redirection:

    • The RedirectResponse is continuously generated because the comparison between the current request and the session-stored state does not account for ajax_page_state.

logging the session param revealed the following.

{
  "ajax_page_state": {
    "libraries": "calendar/calendar.theme,contextual/drupal.contextual-links,opigno_learning_path/global,...",
    "theme": "gin",
    "theme_token": "78ARd8lu8dfMc0oBO743lTwQ1Lj05KWa2pHZaYrYVRk"
  }
}

Solution 
The checkRedirection method was updated to ignore ajax_page_state in both session storage and query parameter comparison.

from this (original)

  public function checkRedirection(ResponseEvent $event): void {
    // Remember the query only for activities, modules and groups listings.
    $available_routes = [
      'entity.opigno_activity.collection',
      'entity.opigno_module.collection',
      'entity.group.collection',
    ];
    $current_route = $this->routeMatch->getRouteName();
    
    if (!in_array($current_route, $available_routes)) {
      return;
    }

    $request = $this->requestStack->getCurrentRequest();
    $session = $request->getSession();
    $param = $request->query->all();

    // If we have an empty page (without the new query params), we need to
    // load the previous one.
    if (!empty($param)) {
      $session->set($current_route, $param);
      return;
    }

    $order_values = $session->get($current_route);
    if (!empty($order_values)) {
      \Drupal::logger('opigno_module')->debug('Session values: @values', ['@values' => json_encode($order_values)]);
      unset($order_values['ajax_page_state']);
      $url = Url::fromRoute($current_route);
      $url->setOption('query', $order_values);
      $response = new RedirectResponse($url->toString());
      $event->setResponse($response);
    }
  }

new (modified)

<?php

namespace Drupal\opigno_module\EventSubscriber;

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Defines the event subscriber service.
 *
 * @package Drupal\opigno_module\EventSubscriber
 */
class QueryPathEventSubscriber implements EventSubscriberInterface {

  /**
   * The route match service.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected RouteMatchInterface $routeMatch;

  /**
   * The request stack service.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected RequestStack $requestStack;

  /**
   * QueryPathEventSubscriber constructor.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request
   *   The request stack service.
   */
  public function __construct(RouteMatchInterface $route_match, RequestStack $request) {
    $this->routeMatch = $route_match;
    $this->requestStack = $request;
  }

  /**
   * Remember the query string (with the table sort) as a session variable.
   *
   * @param \Symfony\Component\HttpKernel\Event\ResponseEvent $event
   *   The response event.
   */
  public function checkRedirection(ResponseEvent $event): void {
    $available_routes = [
      'entity.opigno_activity.collection',
      'entity.opigno_module.collection',
      'entity.group.collection',
    ];
    $current_route = $this->routeMatch->getRouteName();
    if (!in_array($current_route, $available_routes)) {
      return;
    }
  
    $request = $this->requestStack->getCurrentRequest();
    $session = $request->getSession();
    $param = $request->query->all();
  
    // Exclude ajax_page_state from query parameters.
    unset($param['ajax_page_state']);
  
    if (!empty($param)) {
      $session->set($current_route, $param);
      return;
    }
  
    $order_values = $session->get($current_route);
  
    // Exclude ajax_page_state from session state.
    if (!empty($order_values)) {
      unset($order_values['ajax_page_state']);
    }
  
    if (!empty($order_values)) {
      // Prevent recursive redirection.
      if ($param == $order_values) {
        return;
      }
  
      $url = Url::fromRoute($current_route);
      $url->setOption('query', $order_values);
      $response = new RedirectResponse($url->toString());
      $event->setResponse($response);
    }
  }
  

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['checkRedirection'];
    return $events;
  }

}

Thank you for all the help!

Production build 0.71.5 2024