Problem/Motivation

In #2767857: Add destination to edit, delete, enable, disable links in entity list builders we added destination query parameters to config entity lists and operations in Views. This unearthed the fact that some of our forms are not destination query compatible - we broke the image style user interface unexpectedly. See #2940165: [regression] Cannot add effects to image style via the UI.

The problem is that the destination param is set to win regardless of what a user does in the form. This means that any Drupal form can be redirected to somewhere using it.

As discussed in #2950759: Revert 2767857, right now, it is necessary to alter the global request object to disable a destination query arg based redirect override. That's complicated to understand and we shouldn't be doing something like that.

Older related issues are:
#579366: How many ways are there to redirect after form submission?
#1627654: drupal_redirect_form() should state that it is overridden by a destination in the request
#2325463: Destination URL breaks preview

Proposed resolution

We need a way to set a higher priority redirect on a form. So the developer can say actually regardless of the destination parameter go here because obeying the redirect makes no sense. The fix however shouldn't be tied to the forms system so the patch at the moment adds a new IgnoreDestinationRedirectReponse and the RedirectResponseSubscriber checks and doesn't apply the ?destination override if it is.

However since 90% of the redirects we are interested are from Forms the patch also adds helpers to FormState to make redirects behave like this.
FormStateInterface::getIgnoreDestination()
FormStateInterface::ignoreDestination($status)

Remaining tasks

Add more tests. One is currently provided by core/modules/image/src/Tests/ImageAdminStylesTest.php which proves this fixes #2940165: [regression] Cannot add effects to image style via the UI whilst bringing back the nice consistent UI behaviour of #2767857: Add destination to edit, delete, enable, disable links in entity list builders for Image Styles.

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#80 interdiff-2950883-75-80.txt1.23 KBacbramley
#80 2950883-80.patch15.32 KBacbramley
#75 interdiff-2950883-68-75.txt1.78 KBacbramley
#75 2950883-75.patch15.29 KBacbramley
#69 interdiff-2950883-63-68.txt2 KBacbramley
#69 2950883-68.patch16.15 KBacbramley
#69 2950883-68--failing-test.patch15.63 KBacbramley
#63 2950883-63.patch15.61 KBsmustgrave
#63 interdiff-62-63.txt1.48 KBsmustgrave
#62 2950883-62.patch15.87 KBsmustgrave
#62 interdiff-61-62.txt2.18 KBsmustgrave
#59 2950883-59.patch15.51 KBsmustgrave
#59 interdiff-58-59.txt703 bytessmustgrave
#58 2950883-58.patch15.17 KBsmustgrave
#58 interdiff-56-58.txt4.65 KBsmustgrave
#56 2950883-56.patch15.47 KBsmustgrave
#56 interdiff-55-56.txt1.34 KBsmustgrave
#55 2950883-55.patch14.75 KBsmustgrave
#55 diff-MR2678-55.txt7.04 KBsmustgrave
#43 2950883-43.patch14.34 KBsuresh prabhu parkala
#40 2950883-40.patch14.37 KBidebr
#39 2950883-39.patch14.43 KBidebr
#38 interdiff-2950883-37-38.txt1.43 KBacbramley
#38 2950883-38.patch14.46 KBacbramley
#37 interdiff-2950883-35-37.txt4.31 KBacbramley
#37 2950883-37.patch14.08 KBacbramley
#35 interdiff-2950883-34-35.txt1.52 KBacbramley
#35 2950883-35.patch10.63 KBacbramley
#34 2950883-34.patch10.42 KBacbramley
#32 interdiff_31-32.txt800 bytesraman.b
#32 2950883-32.patch44.1 KBraman.b
#31 2950883-30-PASS.patch44.15 KBdouggreen
#26 2950883-26-PASS.patch10.08 KBphenaproxima
#26 2950883-26-FAIL.patch8.81 KBphenaproxima
#20 stack-2.png103.57 KBextexan
#20 stack-1.png108.83 KBextexan
#19 2950883-19.patch7.73 KBbsztreha
#3 2950883-2.patch7.74 KBalexpott

Issue fork drupal-2950883

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

alexpott created an issue. See original summary.

berdir’s picture

Ah, I created #2950885: Add an API to disable to automatic destination-based redirect override, didn't see this.

I don't think it is or should be restricted to the form system, if anything, it could provide an accessor that would make it easier to use but that will also result in more dependencies in FormState.

alexpott’s picture

Status: Active » Needs review
StatusFileSize
new7.74 KB

The patch attached reverts the fix from #2940165: [regression] Cannot add effects to image style via the UI and implements the ability for forms to say ignore the destination and trust my redirect using a IgnoreDestinationRedirectResponse class.

alexpott’s picture

@Berdir it's not tied to the forms system it's just in other cases you return the IgnoreDestinationRedirectResponse directly.

alexpott’s picture

Component: forms system » request processing system
Issue summary: View changes
alexpott’s picture

Title: Allow form redirects to override ?destination query parameter » Allow redirects repsonses to override ?destination query parameter
andypost’s picture

There's another issue which using different way to override destination #2640672: Make redirect.destination service update request

alexpott’s picture

@andypost yes but that issue is expressly to change the current behaviour ie. destination winning to redirect winning - whereas this issue is about let destination win most of the time apart from where it doesn't make sense.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mlncn’s picture

Workaround:

       \Drupal::request()->query->remove('destination');
       return new TrustedRedirectResponse('https://example.org', 302);
trevorbradley’s picture

Re: @mlncn's workaround:

What if you want the page you're redirecting to to have the destination intact in the query?

I came at this issue from #2932050: The "Save & Edit" button redirects to admin/content using destination query. There, you want the destination to be temporarily overridden, but for the form submission to take you back to a form where the old destination is intact.

kristen pol’s picture

Thanks for the patch. Although there was discussion about the patch, it didn't look like the code was actually reviewed, so I did that below. This still needs testing.

  1. +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
    @@ -50,17 +51,19 @@ public function checkRedirectUrl(FilterResponseEvent $event) {
    +          }
    +          catch (\InvalidArgumentException $e) {
    +          }
    

    Nitpick: I know this is the same as the original code but I find empty catch clauses confusing. Consider adding a comment here.

  2. +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php
    @@ -158,6 +158,26 @@ public function setRedirectUrl(Url $url);
    +   * Determines whether the redirect respects the destination query parameter.
    +   *
    +   * @param bool $status
    

    Nitpick: "Determines" makes me think of a getter, not a setter. Consider changing the wording. Sets? Defines?

  3. +++ b/core/lib/Drupal/Core/Routing/IgnoreDestinationRedirectResponse.php
    @@ -0,0 +1,11 @@
    + * Provides a redirect response which will override the destination query parameter.
    

    Nitpick: Comment is over 80 chars.

  4. +++ b/core/lib/Drupal/Core/Routing/IgnoreDestinationRedirectResponse.php
    @@ -0,0 +1,11 @@
    +class IgnoreDestinationRedirectResponse extends RedirectResponse {
    +}
    

    Nitpick: Might be good to explain that the class is empty intentionally and why.

  5. +++ b/core/modules/image/src/Form/ImageStyleEditForm.php
    @@ -220,6 +220,7 @@ public function effectSave($form, FormStateInterface $form_state) {
    +      $form_state->ignoreDestination();
    

    It would be good to explain why this is being set for this form.

kristen pol’s picture

Status: Needs review » Needs work

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

m.lebedev’s picture

pancho’s picture

I'm coming from contrib issue #3046178: Temporarily override the original 'destination' query parameter and am wondering whether the IgnoreDestinationRedirectReponse would help with our case (and similar ones, such as Core's node entity) or if that's a separate issue.

In the node case, the user coming from admin/content goes to node/1/edit (by hitting the edit button). Now on node/1/edit, the user clicks 'Delete' but then decides to 'Cancel'.

Now the user is sent all the way back to admin/content instead of just going one step back to node/1/edit.

This is because the overview page appended itself as ?destination, while the node edit page preserved the ?destination rather than overriding it.

While using a IgnoreDestinationRedirectReponse in the confirm form to always send the user to the edit form would cover this particular case, it doesn't seem the right thing to do. Finally, we do rely on ?destination being properly set, as otherwise we don't know where the user comes from. They might have used the 'Delete' button on the overview form, so shouldn't always be sent to the edit form.

Instead I would expect node/1/edit:

  • either to override the ?destination it inherited from admin/content
  • or: to prepend its own path (if ?destination could be an array).
tim.plunkett’s picture

Issue tags: +Needs tests

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

bsztreha’s picture

StatusFileSize
new7.73 KB

Just did an update with 2950883-2.patch file to able to apply 8.8.x branch (also tested on 8.9.x too), attached new patch file

extexan’s picture

StatusFileSize
new108.83 KB
new103.57 KB

Just wanted to add this case where the patch didn't work...

I have a views bulk action that includes what is essentially a confirm form on steroids. The action has evolved into a rather complicated process, so it is now a 3-page multi-step form. At various stages, it needs to take the user either back to the original page from where they initiated the action, or redirect them to a node created in the submit for form step 1 (of 3). The views bulk action process automatically puts the "destination" arg in the URL, which I want to ignore in favor of what I am returning in the response.

It's failing to redirect the user to the newly created node, returning them, instead, to the original page (which is specified in the "destination=/path/to/original/page").

Via debug, I've tried to narrow it down to where it's failing. In the dispatch() method of ContainerAwareEventDispatcher, it goes through a foreach loop several times. The value of $event->response->response is correct (/sales/releases/release-12345) for several iterations through the loop. But at some point, that gets changed to the original page (/shipping/shipment-3456). I believe it is happening here:

call_user_func($definition['callable'], $event, $event_name, $this);

...which is at line 111 in my Drupal 8.8.5 version, with the #19 patch above applied.

The value of the $definition array is as follows (this may be a partial rendering, and I may not have gotten the indentation right):

$definition = {array} [2]
service = {array} [2]
0 = "redirect_response_subscriber"
1 = "checkRedirectUrl"
callable = {array} [2]
0 = {Drupal\Core\EventSubscriber\RedirectResponseSubscriber} [3]
unroutedUrlAssembler = {Drupal\Core\Utility\UnroutedUrlAssembler} [3]
requestContext = {Drupal\Core\Routing\RequestContext} [11]
completeBaseUrl = "http://localhost"
*Symfony\Component\Routing\RequestContext*baseUrl = ""
*Symfony\Component\Routing\RequestContext*pathInfo = "/actions/release-containers"
*Symfony\Component\Routing\RequestContext*method = "POST"
*Symfony\Component\Routing\RequestContext*host = "localhost"
*Symfony\Component\Routing\RequestContext*scheme = "http"
*Symfony\Component\Routing\RequestContext*httpPort = {int} 80
*Symfony\Component\Routing\RequestContext*httpsPort = {int} 443
*Symfony\Component\Routing\RequestContext*queryString = "destination=/shipping/shipment-9194"
*Symfony\Component\Routing\RequestContext*parameters = {array} [0]
_serviceId = "router.request_context"

The important part of that is the queryString entry. That's the wrong destination.

I wasn't able to copy/paste the stack from my debugger, so I've attached a couple of screenshots instead.

I'm going to try @mincn's work-around (post #10), but hopefully this will help point someone toward a fix.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

phenaproxima’s picture

phenaproxima’s picture

Regarding additional test coverage, we can easily adapt some of the coverage from #3033960-52: After adding media, return the user to the media listing they started from. It proves that EntityController::addPage() is also broken by the destination parameter when there is only one bundle of the entity being added.

phenaproxima’s picture

Title: Allow redirects repsonses to override ?destination query parameter » Allow redirects responses to override ?destination query parameter

Fixing a typo in the issue title.

phenaproxima’s picture

Title: Allow redirects responses to override ?destination query parameter » Allow form redirects to ignore ?destination query parameter

Fixing the title again to clarify the actual scope of this patch.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new8.81 KB
new10.08 KB

Here's a very basic test of this functionality, with a fail patch to prove the test is effective.

alexpott’s picture

One thing I'm wondering is what happens when we want the same functionality for any of the other sub classes of RedirectResponse. There are quite a few in core and probably more in contrib. I'm wondering if instead of implementing a class to do this we implement a switch on redirect_response_subscriber to disable destination overriding. And then inject this service in the form_submitter service. It's a little less elegant but we already have a tonne of state going on with FormState and it makes this fix generalisable to all redirect responses.

The last submitted patch, 26: 2950883-26-FAIL.patch, failed testing. View results

phenaproxima’s picture

I'm wondering if instead of implementing a class to do this we implement a switch on redirect_response_subscriber to disable destination overriding. And then inject this service in the form_submitter service.

IMHO it makes sense to do this, but I think we should expose the switch on the redirect.destination service. My reasoning is that RedirectDestinationTrait is already widely used, so consuming classes wouldn't need to adjust their dependencies to inject an obscure event subscriber.

I wonder if something like this might make sense: $this->getRedirectDestination()->set(FALSE), as an explicit way of saying "completely disable the redirect destination". Internally, the RedirectDestination service would then call a ignoreQueryParameter() method on RedirectResponseSubscriber. This approach has two main benefits I can see -- very little code needs to be adjusted to benefit from this, and backwards compatibility is maintained.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

douggreen’s picture

StatusFileSize
new44.15 KB

reroll of #26

raman.b’s picture

StatusFileSize
new44.1 KB
new800 bytes

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

acbramley’s picture

Issue tags: -Needs tests
StatusFileSize
new10.42 KB

I've taken #26 and implemented #27 - no interdiff since it's a different approach and needed a re-roll.

I kind of agree with #29 although if RedirectDestination is calling something in RedirectResponseSubscriber anyway then we're really just putting an intermediate step inbetween for semantics because it feels weird to inject an event subscriber (fwiw I agree it feels kinda weird). That would then mean consumers could inject either service, making another "more than 1 ways to do the same thing" XD

Hiding patch #32 as it includes .orig files.

acbramley’s picture

StatusFileSize
new10.63 KB
new1.52 KB

Fixed phpcs issues.

Status: Needs review » Needs work

The last submitted patch, 35: 2950883-35.patch, failed testing. View results

acbramley’s picture

Status: Needs work » Needs review
StatusFileSize
new14.08 KB
new4.31 KB

Fixed FormSubmitterTest and FormBuilderTest

acbramley’s picture

StatusFileSize
new14.46 KB
new1.43 KB

Also adding a BC layer for the constructor changes, will wait for confirmation on this approach before creating the CR and updating the link.

idebr’s picture

StatusFileSize
new14.43 KB
idebr’s picture

StatusFileSize
new14.37 KB
joachim’s picture

Status: Needs review » Needs work

This needs documentation.

This creates a 3-level hierarchy, AFAICT, from low to high priority

- the form's redirect
- the URL destination query parameter
- the form's redirect if the form really means it

At the very least, FormSubmitterInterface::redirectForm() needs a rewrite to explain this. It would be nice to see some overview docs about this too, say on RedirectDestination?

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

suresh prabhu parkala’s picture

StatusFileSize
new14.34 KB

Just a re-roll against the latest 9.4.x. Please review.

bceyssens’s picture

Ignore destination will remove the destination completely, in some cases it would be better if it is passed on to the next page.

This could be useful in flows, like password reset. The user would complete all steps of the password reset flow and then be redirect to the destination he/she had on the login page.

jonathanshaw’s picture

+1 for #11 / #44

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

akalam made their first commit to this issue’s fork.

akalam’s picture

Created a new MR to reroll the patch #43 to the 9.5 branch

akalam’s picture

Added a new commit trying to move the redirection to the target url, as suggested on #11 and #44.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

emircanerkul’s picture

#10 works well. But we can use this in EntityForm while waiting for a real solution accepted

$this->requestStack->getCurrentRequest()->query->remove('destination');

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: +Bug Smash Initiative, +Needs change record
StatusFileSize
new7.04 KB
new14.75 KB

Tried starting a 11.x branch but no luck so patch it is

I started from MR 2678

Updated the RedirectTest to check the path not destination (since it was ignored)
Updated typehinting for D10
Updated trigger_error message, still needs a change record

I undid the change for core/modules/image/src/ImageStyleListBuilder.php as I wasn't sure it was needed? If it is then the solution needs to be looked at because currently when adding an image style
1. The url is messed up with the destination parameter now appearing.
2. When saving an image style instead of going back to the individual style you get redirected to the whole styles page.

Had issues with the interdiff so just made a diff.

smustgrave’s picture

StatusFileSize
new1.34 KB
new15.47 KB

Or this approach where I add the changes back to ImageStyleListBuilder but in RedirectResponseSubscriber I don't add the destination paramter for item 55.1

Which also solved 55.2

lauriii’s picture

Status: Needs review » Needs work
  1. +++ b/core/core.services.yml
    --- a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
    +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
    
    +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
    @@ -59,12 +66,21 @@ public function checkRedirectUrl(ResponseEvent $event) {
    +        else {
    +          $target_url = $response->getTargetUrl();
    +          $query_string = parse_url($target_url, PHP_URL_QUERY) ?: '';
    +          parse_str($query_string, $query);
    +          $target_url = substr($target_url, 0, strpos($target_url, '?')) . '?' . http_build_query($query);
    +          $response->setTargetUrl($target_url);
    

    Why do we need this 🤔

  2. +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
    @@ -25,6 +25,13 @@ class RedirectResponseSubscriber implements EventSubscriberInterface {
    +  protected $ignoreDestination = FALSE;
    

    We can use property type declaration 😇

  3. +++ b/core/lib/Drupal/Core/Form/FormState.php
    @@ -136,6 +136,13 @@ class FormState implements FormStateInterface {
    +  protected $ignoreDestination = FALSE;
    

    We could use property type declaration here too 😇

  4. +++ b/core/lib/Drupal/Core/Form/FormStateDecoratorBase.php
    --- a/core/lib/Drupal/Core/Form/FormStateInterface.php
    +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php
    
    +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php
    @@ -158,6 +158,26 @@ public function setRedirectUrl(Url $url);
    +  public function ignoreDestination(bool $status = TRUE);
    

    Wondering if this should be setIgnoreDestination given that this can be used for disabling this behavior too?

smustgrave’s picture

StatusFileSize
new4.65 KB
new15.17 KB

#57.1 = I'm trying to remember but lets see what happens without it.
#57.2 = added type
#57.3 = added type
#57.4 = changed all function calls to setIgnoreDestination

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record
StatusFileSize
new703 bytes
new15.51 KB

Added back that snippet from 57.1

Seems to grab the URL minus the destination.

Also started the CR https://www.drupal.org/node/3375113

larowlan’s picture

Status: Needs review » Needs work

Updated issue credits

  1. +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
    @@ -59,12 +66,21 @@ public function checkRedirectUrl(ResponseEvent $event) {
    +          $target_url = $response->getTargetUrl();
    +          $query_string = parse_url($target_url, PHP_URL_QUERY) ?: '';
    +          parse_str($query_string, $query);
    +          $target_url = substr($target_url, 0, strpos($target_url, '?')) . '?' . http_build_query($query);
    +          $response->setTargetUrl($target_url);
    

    Can we get a comment explaining what this is doing? It seems to parse the query, and then un-parse it and re-set it on the same url?

  2. +++ b/core/lib/Drupal/Core/Form/FormSubmitter.php
    @@ -34,10 +42,17 @@ class FormSubmitter implements FormSubmitterInterface {
    +  public function __construct(RequestStack $request_stack, UrlGeneratorInterface $url_generator, RedirectResponseSubscriber $redirect_response_subscriber = NULL) {
    

    shouldn't this be ?RedirectResponseSubscriber

smustgrave’s picture

Assigned: Unassigned » smustgrave

Will work on this tomorrow. If I don’t get to in 2 days anyone can have at it.

Assigning to myself as a submaintainer

smustgrave’s picture

StatusFileSize
new2.18 KB
new15.87 KB

Lets try this.

smustgrave’s picture

Status: Needs work » Needs review
StatusFileSize
new1.48 KB
new15.61 KB

Address #60

acbramley’s picture

Updated our patch for this issue during a 10.1 upgrade and something has broken with a mix of $form_state->setRedirect() and setIgnoreDestination() - now the form doesn't redirect at all, instead the page refreshes with an empty query string.

acbramley’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Debugging through it, somehow $target_url is becoming literally a ? after this line:

$target_url = substr($target_url, 0, strpos($target_url, '?')) . '?' . http_build_query($query);

Where before the line, target_url is http://127.0.0.1:8080/admin/content/service-status-messages/560/scheduled-transitions

and $query is empty.

I guess we need test coverage for this and only do this if $target_url contains a ?

acbramley’s picture

Weird cause this test case should be testing exactly that

    // Test basic redirection, ignoring the 'destination' query parameter.
    $options['query']['destination'] = $this->randomMachineName();
    $edit = [
      'redirection' => TRUE,
      'destination' => $this->randomMachineName(),
      'ignore_destination' => TRUE,
    ];
    $this->drupalGet($path, $options);
    $this->submitForm($edit, 'Submit');
    $this->assertSession()->addressEquals($path);

Actually no that's incorrect, it should be $this->assertSession()->addressEquals($edit['destination']);

EDIT 2: Just so it's clear (because calling something "destination" when it's actually the redirect URL in the context of this test is extremely confusing), we do this in the test form:

$form_state->setRedirectUrl(Url::fromUserInput('/' . $form_state->getValue('destination')));

acbramley’s picture

Assigned: smustgrave » acbramley

Addressing this bug, looks like it was first introduced in #55

smustgrave’s picture

The snippet was added in the MR to retain the destination in the url

acbramley’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new15.63 KB
new16.15 KB
new2 KB

Fixed, also added coverage for when the redirect url itself contains a query param.

acbramley’s picture

@smustgrave no, the MR still had the correct check in the test https://git.drupalcode.org/project/drupal/-/merge_requests/2678/diffs#62...

The last submitted patch, 69: 2950883-68--failing-test.patch, failed testing. View results

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Was referring to $target_url = substr($target_url, 0, strpos($target_url, '?')) . '?' . http_build_query($query);

But #69 is all green and still working.

Would be nice to get this in as it's a blocker for a block_content redirect.

The last submitted patch, 69: 2950883-68--failing-test.patch, failed testing. View results

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
@@ -59,12 +66,25 @@ public function checkRedirectUrl(ResponseEvent $event) {
+          // The 'destination' parameter should remain in the query but be
+          // unused by the target_url.
+          $target_url = $response->getTargetUrl();
+          if (str_contains($target_url, '?')) {
+            $query_string = parse_url($target_url, PHP_URL_QUERY) ?: '';
+            parse_str($query_string, $query);
+            $target_url = substr($target_url, 0, strpos($target_url, '?')) . '?' . http_build_query($query);
+          }
+          $response->setTargetUrl($target_url);

Sorry if I'm being daft here, but I don't understand what this code is doing.

It seems to
a) get the query
b) if it contains a ? parse the query
c) recreate the same query

https://3v4l.org/XYAX5 - the body of queryManip is copy pasted from here

acbramley’s picture

StatusFileSize
new15.29 KB
new1.78 KB

Confirming #57, #60 and #74 - this code is redundant.

What it looks to be trying to achieve is what's described in #11 and #44 which while it might be nice, is IMO out of scope of this issue. If people want this functionality (retaining the destination query param on the redirected URL) then please file a follow up. That way we can discuss specific use cases and have a more targeted discussion.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Awesome!

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/lib/Drupal/Core/Form/FormSubmitter.php
    @@ -27,6 +28,13 @@ class FormSubmitter implements FormSubmitterInterface {
    +  protected $redirectResponseSubscriber;
    

    We can typehint this

  2. +++ b/core/lib/Drupal/Core/Form/FormSubmitter.php
    @@ -34,10 +42,17 @@ class FormSubmitter implements FormSubmitterInterface {
    +      @trigger_error('Calling ' . __CLASS__ . '::__construct() without the $redirect_response_subscriber argument is deprecated in drupal:10.2.0 and is required in drupal:11.0.0. See https://www.drupal.org/node/XXXX', E_USER_DEPRECATED);
    

    This needs an actual change record URL

acbramley’s picture

Status: Needs work » Needs review
StatusFileSize
new15.32 KB
new1.23 KB

CR added https://www.drupal.org/node/3377297

Type and comment updated.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Feedback addressed

  • larowlan committed 92abbb59 on 11.x
    Issue #2950883 by acbramley, smustgrave, akalam, phenaproxima, idebr,...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed 92abbb5 and pushed to 11.x. Thanks!

Thanks all, we got there in the end.

Publishing both change records.

lauriii’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.