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.