I am hesitating between qualifying this as a minor bug or as a feature request...
Problem/Motivation
The site we're migrating from Drupal 7 used Polls + Advanced Polls. In Drupal 7, polls are nodes with a specific type, but in Drupal 8+, polls have their own entity type, so the poll which was available at path /node/123
will be avaliable at /poll/123
.
We don't want to migrate a "placeholder" node for these changed routes - our intent is migrating a redirect entity which redirects any request made to /node/123
to /poll/123
.
The problem is that this is not possible right now on certain conditions. We are able to properly save a new redirect entity, our issue is with admin language negotiator and how Drupal's kernel handles these routes:
-
If we have a multilingual instance, \Drupal\language\EventSubscriber\LanguageRequestSubscriber
is registered.
-
This will call \Drupal\language\ConfigurableLanguageManager::getCurrentLanguage
to get the interface language with admin language negotiation.
-
When LanguageNegotiationUserAdmin
tries to determine if the current route is an admin route in ::isAdminPath()
, it tries to match the URL to the route collection, which then invokes e.g. parameter converters.
-
Since the source path we're using does match to an entity route pattern (/node/{node}
), Drupal tries to apply parameter converters.
-
This will result in a ParamNotConvertedException
(obviously, because we don't have a node with ID 123
).
-
So in Symfony\Component\HttpKernel::handle()
, we will end at handleThrowable()
,
-
Which will then invoke Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber::on404()
(core service: exception.default_html
)
- When
DefaultExceptionHtmlSubscriber
instantiates the 404 sub-request in makeSubrequest
, the place where it calls
$parameters->add($this->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code]);
,it will also add a destination
query to the subrequest.
-
This subrequest is the thing that reaches RedirectRequestSubscriber::onKernelRequestCheckRedirect
, but since this request contains a destination
query (of course we won't see it because this is not the master request), RedirectChecker::canRedirect()
will return FALSE
, so the redirect we have won't be applied.
Steps to reproduce
- Install Drupal with at least two configurable language, with
node
and redirect
modules.
- Enable Account administration pages language negotiator, and make it the first evaluated plugin.
- Add a Redirect which redirects from
node/123
to e.g. /filter/tips
.
- Create a user with
access administration pages
and access content
permissions, and set and explicit admin language on the user profile's edit form. (The "default" root user also works.)
- Try to open the patch
/node/123
with this user being logged in.
Expected result: User is redirected to /filter/tips
.
Actual result: User gets a 404 response.
Proposed resolution
Subscribe to KernelEvents::EXCEPTION
too with RedirectRequestSubscriber
, and apply the same logic as it has right now for KernelEvents::REQUEST
if the exception in the event is a NotFoundHttpException
.
Remaining tasks
TDB.
User interface changes
Nothing.
API changes
RedirectRequestSubscriber
also subscribes to KernelEvents::EXCEPTION
and tries to apply redirects.
Data model changes
Nothing.