2

I am trying to alter the existing 'Log In' URL so that it points to a certain location and also includes the REQUEST_URI as a query string that is not encoded. How do I do this?

Based on this article, Altering existing routes and adding new routes based on dynamic ones and this SE answer I can change the 'Log In' URL so it points to a different location (/login). What I can't seem to figure out is how to add a query string that isn't encoded.

This code:

$route->setPath('/login?destination=' . \Drupal::request()->server->get('REQUEST_URI'));

Gives me:

/login%3Fdestination%3Dpage2

What I want is:

/login?destination=page2

I have looked into RequestContext::setQueryString and Route::addOptions but can't seem to get anything to work.

Full code:

<?php
namespace Drupal\myModule\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
* Listens to the dynamic route events.
*/
class RouteSubscriber extends RouteSubscriberBase {

    /**
    * {@inheritdoc}
    */

    protected function alterRoutes(RouteCollection $collection) {
        // Change path '/user/login' to '/login'.
        if ($route = $collection->get('user.login')) {
            //$route->setPath('/login');
            $route->setPath('/login?destination=' . \Drupal::request()->server->get('REQUEST_URI'));

        }
        
        // Always deny access to '/user/logout'.
        // Note that the second parameter of setRequirement() is a string.
        if ($route = $collection->get('user.logout')) {
            $route->setRequirement('_access', 'FALSE');
        }
    }
}
3
  • Note: There is also a cache issue when you do it in a route subscriber, as the path value stays the same.
    – No Sssweat
    Oct 16, 2020 at 2:20
  • The easy solution would be to append the param part to the login link's href via JS
    – No Sssweat
    Oct 16, 2020 at 2:40
  • 1
    @NoSssweat, I was hoping you would chime in since I used your answer from long-ago. Using JS is a heck of a lot easier and seems to work like a charm. Thank you.
    – jbreslow
    Oct 16, 2020 at 18:58

1 Answer 1

0

I think you'll need to have a look to PathProcessors, you might do something like that:

mymodule/mymodule.services.yml

mymodule.path_processor:
  class: Drupal\mymodule\PathProcessor\MymodulePathProcessor
  tags:
    - { name: path_processor_inbound, priority: 250 }

mymodule/src/PathProcessor/MymodulePathProcessor

<?php

namespace Drupal\mymodule\PathProcessor;

use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class MymodulePathProcessor.
 *
 * @package Drupal\mymodule\PathProcessor
 */
class MymodulePathProcessor implements InboundPathProcessorInterface {
  
  /**
   * {@inheritdoc}
   */
  public function processInbound($path, Request $request) {
    if ($path == '/user/login') {
      $request_uri = $request->server->get('REQUEST_URI');
      return "/login?destination={$request_uri}";
    }
  }
}

Don't forget to clear the cache before to try it.

You might need the processOutbound function too in which case you'll need one more line in your service

mymodule/mymodule.services.yml

mymodule.path_processor:
  class: Drupal\mymodule\PathProcessor\MymodulePathProcessor
  tags:
    - { name: path_processor_inbound, priority: 250 }
    - { name: path_processor_outbound, priority: 250 }
4
  • Doesn't work, Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route found for "GET /node/14" in Symfony\Component\HttpKernel\EventListener\RouterListener->onKernelRequest() (line 137 of vendor/symfony/http-kernel/EventListener/RouterListener.php).
    – No Sssweat
    Oct 16, 2020 at 6:05
  • Is the node published and can anonymous user access this content type in your permissions (asking but I am pretty sure it's not the problem since you would get a 403 exception not a 404) ? /node/14 route is entity.node.canonical. That error is weird unless the content doesn't exist
    – MacSim
    Oct 16, 2020 at 6:31
  • It's published and accessible to anyone. I tried different pages like the homepage and same result. It even occurs when logged in as admin (user 1).
    – No Sssweat
    Oct 16, 2020 at 6:38
  • 1
    "You might need the processOutbound function too" ... yes but only proccessOutbound(), where you can add the query parameter to $options and also the context url.pathto the bubbleable metadata to get caching right. The inbound path processor is not necessary and doesn't work BTW because paths are handled in path processing without query parameters. Those are stored in the request if you need to change them inbound.
    – 4uk4
    Oct 17, 2020 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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