Problem/Motivation

In #1668866: Replace drupal_goto() with RedirectResponse we introduced the following pattern...

-          drupal_goto("node/$node->nid");
+          return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));

This is issue will discuss if we can improve the pattern by removing the eminently forgetable array('absolute' => TRUE)

Proposed resolution

  1. Subclass RedirectResponse and check the passed url. if not external make it so
  2. Wrap the whole thing in a service and dont use RedirectResponse directly. Apply same logic as above
  3. Add a method to Url generator. Given that most callbacks that use redirection will be converted eventually to the new routing system, with url generator injected...instead of calling generateFromPath, call generateAbsolute
  4. Provide a Base class with a redirect() method that also takes care of the dependency on the url generator service. Something like #2018411: Figure out a nice DX when working with injected translation

Comments

catch’s picture

Priority: Normal » Major

I'd also like to see if we could remove the url() call so this ends up using the generator more or less directly - if we want to eventually be able to move routes around without updating path strings, this is a necessary step towards that.

Bumping to major because this needs to be resolved before code freeze if possible.

ParisLiakos’s picture

Issue summary: View changes

Added some potential resolutions

Crell’s picture

1) As long as we don't break any existing code I don't think it should be blocked by code freeze. Although I agree that sooner=better.

2) One issue with putting it on the generator is that there are two pathways there: By path fragment and by route name. An increasing percentage of the system is now route-name-based, which means we can/should be moving a lot of url() calls over to using route names rather than paths. Yes, using an injected generator.

3) Symfony fullstack has a ContainerAware Controller base class that has utility methods like ->redirect(), which handles that sort of thing. We don't have a base class and have made the decision to not make all controllers container aware. However, we're doing something with an optional base class for translation, most likely: #2018411: Figure out a nice DX when working with injected translation. Damnit, I want traits!

ParisLiakos’s picture

3) Symfony fullstack has a ContainerAware Controller base class that has utility methods like ->redirect(), which handles that sort of thing.

i like that...because that would also handle the url generator dependency as well, double win:)

ParisLiakos’s picture

Issue summary: View changes

turn ul to ol

Crell’s picture

Except for the next sentence in that paragraph. :-) Adding a base class now involves a not-small amount of change.

chx’s picture

Also #185 in the parent talks about firing an event before the url is constructed so that $path and $options are not lost.

ParisLiakos’s picture

To clarify: I dont talk about a response event..I talk about an event (or it can be hook_alter, i am not sure what we do for newly introduced things like that) which will fire before the url is being passed to the Url generator, before the RedirectResponse is being created...but even with this, noone can guarantee that a response can fire only by a controller.
See eg the Goto action..

agentrickard’s picture

Something related (DX/UX wise) that is worth mentioning here.

With drupal_goto(), you could pair that call with drupal_set_message() to send a message regarding the redirect. The RedirectResponse class doesn't support that. It's a new request, and the information in drupal_set_message() seems to be destroyed.

Crell’s picture

drupal_set_message() hasn't really changed (yet). I think the issue in #7 is unrelated, in that we're still calling drupal_get_messages() when we shouldn't be, which is clearing out the session-stored messages. That's a straight up bug in its own right, but separate from the issue here.

Perhaps a redirect subclass, RouteRedirectResponse('some_route_name', $array_of_placeholders)? Then a response listener that pulls that data out, runs it through the generator, and then sets the redirect target on the response before passing it along. So modules would do something like:

return new RouteRedirectResponse('node_page', array('node' => 5));

And the rest gets taken care of by the listener.

dlu’s picture

Moved to routing system per #2050763-16: Refine "base system" component (notes on refactoring of "base system" category here: https://docs.google.com/a/acquia.com/spreadsheet/ccc?key=0AusehVccVSq2dF...).

dlu’s picture

Issue summary: View changes

Add base class proposal

Crell’s picture

Component: base system » routing system

Note that the new ControllerBase class has a redirect() method, so that's at least some use cases addressed.

tim.plunkett’s picture

Priority: Major » Normal
Issue summary: View changes

I'd like to think that between ControllerBase having $this->redirect(), and $form_state['redirect']/$form_state['redirect_response'] still working, that this is no longer major.

Crell’s picture

Status: Active » Fixed

Since you shouldn't be firing a redirect from anywhere else besides a controller or a form, I would say this is done per #11.

Status: Fixed » Closed (fixed)

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