Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
base system
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
16 Sep 2009 at 18:20 UTC
Updated:
22 Jul 2010 at 15:47 UTC
Jump to comment: Most recent file
Comments
Comment #1
chx commentedyou forgot hook_drupal_goto_alter. wth is $form['destination'] thats new to me and what are the rules for form_state[no_redirect]? Where this got added? Someone should dig around in cvs annotate and ask the original writer.
Comment #2
mattyoung commentedsub
Comment #3
sunKilling $form['#redirect'].
Is almost entirely replaced by $form_state['redirect'] already. Patch makes additionally use of $form_state['no_redirect'] in ajax.inc.
Which leaves us with $form['destination'], which is potentially just cruft we carried over from old days. I'll investigate.
Comment #4
sunIndeed. $form['destination'] is crap we carried over from D5 without notice. Since those had no effect since D6, let's just remove 'em.
Comment #5
chx commentedOH JOY. $form gone from drupal_redirect_form and there was much much rejoicing. For those who do not remember that's an ancient remnant in FAPI.
Comment #6
chx commentedSorry. I just realized what is form['destination'] -- it sets REQUEST['destination'] for drupal_goto and that REQUEST really should be GET and wherever we used the form destination so that if an action is set (do we have ANY place in core where that is set??) then after the form submission Drupal finds its way back to the page but then we can put the destination in the query string.
REQUEST is broken however because it's contents is PHP.INI dependent. So. Change please REQUEST to GET in drupal_goto and let's see what breaks.
Comment #7
sunhah, that was fun... :) Both chx and me had no clue about WTF $form['destination'] could be... puzzled in CVS history, and, yes, we should just try to break that. :)
btw, that would go hand in hand with #582456: Make confirm_form() respect query string destination 8)
But for now, I realized that we can just replace $form['destination'] with $form_state['redirect'] ;)
Next one will try to break.
Comment #8
sunLet's break $_POST['destination']. :)
Comment #10
sunComment #11
litwol commentedThis is with patch from #8, but notice small adition inside drupal_access_denied
Comment #13
litwol commentedAnd here the patch that i forgot to attach.
Comment #14
litwol commentedComment #15
sunFixing that weird test after a lengthy, awesome debugging session with litwol in IRC. :)
Lessons learned: $_REQUEST['foo'] = 'bar'; is NOT like $_GET['foo'] = 'bar'; -- Which of both ends up in $_GET?
Comment #16
sunOne hack less?
Comment #17
chx commentedThis is very promising, there is a "user is redirect to" which comes from the original comments but since we are touching it anyways, let's fix it.
Comment #18
sun*redirected
Comment #19
chx commentedI truly love this. REQUEST bites the dust, that's exquisite.
Comment #20
dries commentedCan't
$form_state['no_redirect'] = TRUE;be replaced by$form_state['redirect'] = FALSE;? Would that allow us to get rid of$form_state['no_redirect']too? The reason I'm asking is because the snippet below is somewhat counter-intuitive and confusing:Comment #21
sun$form_state['redirect'] can be set by the form builder itself and can be altered by any form submit handler during processing.
$form_state['no_redirect'] is supposed to be defined in the initial $form_state only (like in ajax.inc) to explicitly prevent/disallow redirection of the form, regardless of what's in $form_state['redirect']. Form builders/handlers are not supposed to alter $form_state['no_redirect'], only $form_state['redirect'] - but there is nothing that would prevent them from doing it.
I agree that this construct is a bit fragile, but it's not invented here. Instead, we just clean up other stuff in this API that was not removed when these two were introduced.
I'll try to incorporate this info into the code comments.
Comment #22
dries commentedIncorporating that information in the code comments would be great, then we can revisit it later. Thanks for the clarification, and thanks for rerolling!
Comment #23
sunThanks! That additional clarification allowed for another re-thinking and further clean-up:
We now just pass $form_state to drupal_redirect_form() and keep all the redirection logic along with the documentation about the behavior in one place.
Less magic, less grepping for invocations of drupal_redirect_form(), less mess to understand it.
I've tried to be very verbose in the PHPDoc about the relevant options. And I also didn't squeeze all conditions into one giant if statement, but instead made the code as readable and understandable as possible, so developers can read the PHPDoc, but can also quickly scan the actual code to grok it.
The order of conditions in PHPDoc doesn't match the code, since I wanted to keep the original order in the code, but move the most important properties for developers to the beginning in the PHPDoc.
I love this one. :)
Comment #24
sunUpdated two comments in batch.inc and batch_process().
Comment #26
sunSorry, silly mistake. Tests should pass now.
Comment #27
dries commentedTogether with the phpDoc, I can actually understand the form APIs redirection handling now, instead of having to study the code for 2 hours straight. That is a good success metric. ;-)
Truly great code clean-up, sun and chx. Committed to CVS HEAD. Great job.
Comment #28
moshe weitzman commentedSo, I have D6 code that changes the redirect destination after a comment. Thats done with by setting $form['#redirect'] in hook_form_alter(). It looks like in D7, one has to add a submit handler after comment modules handler since that is what sets $form_state['redirect']. IMO, thats not an improvement. Not worht re-opening this issue I guess, but #redirect was useful.
Comment #30
jhodgdonThis was not quite completed.
a) There is no documentation on http://drupal.org/update/modules/6/7 about #redirect being gone that I can see. What should we tell D6 updaters to do?
b) There are still two places in modules/locale/locale.admin.inc that are trying to use $form['#redirect']. What should they be doing?
Comment #31
rfayand
c) It needs to be updated in the Form API Reference.
I'll take these on.
@jhodgdon, for b) they use $form_state['redirect']. We'll probably want a separate issue for that.
Comment #32
jhodgdonalso
c) #redirect needs to be removed from the FAPI reference guide for Drupal 7.
Comment #33
rfayComment #34
rfayFollowup on b) (locale.admin.inc) is at #766200: Obsolete locale usage of $form['#redirect'] needs to be changed to $form_state['redirect'].
Comment #35
suna) Replace $form['#redirect'] with $form_state['redirect']. The value is identical. That said, (but different issue) $form_state['redirect'] supports the same arguments as drupal_goto() in D7.
b) most probably see a), but I'll review that patch separately.
c) Right, Form API reference needs to be updated. We badly need to put that into code. :-/
d) This patch also removed support for $_REQUEST['destination'] in favor of $_GET['destination']. All code needs to be replaced like that, too.
@moshe: Sorry for recognizing your follow-up earlier. Especially when considering multiple form actions/buttons, I think it would be wrong to force a certain, global redirect target via hook_form_alter() for all form actions. Requiring developers to override the form redirection target in a dedicated form submit handler for the intended form action therefore sounds like an improvement to me.
Comment #36
jhodgdonRE #35 c - If you'd like to comment on how to move the FAPI into code, we have an issue on that:
#100680: [meta] Make API module generate Form API documentation
Constructive suggestions on how to manage it would be welcome there.
Comment #37
rfayComment #38
jhodgdonLooks reasonable to me. Thanks rfay!
Comment #40
effulgentsia commentedAfter reading #21 and #28, I'm hoping for some clarification. Is it intended that a redirect can no longer be set by a form builder function or a hook_form_alter()? With $form['#redirect'], people were able to do this. With $form_state['redirect'], it's not clear. If the intention is that it can only be set during drupal_process_form(), we should probably document that in the module upgrade guide. If the intention is that it ought to be settable from a form builder function or hook_form_alter(), then we have a bug, because that doesn't work when the form is cached, because 'redirect' is one of the keys in form_state_keys_no_cache(), and we can't simply remove it from there, because if two submit handlers run and one sets 'redirect' and one sets 'rebuild', then we need to remove the 'redirect'.
Comment #41
effulgentsia commentedThe question in #40 is specifically about $form_state['redirect'] and whether it should remain in form_state_keys_no_cache(), but regardless of that, please see #800460: WTF coupling between $form_state['cache'] and form processing.
Comment #42
rfayComment #43
rfayNote: Documenting $form_state (including $form_state['redirect']) in #802746: Document $form_state and form builder function in form_api group. Comments and participation welcome.
Comment #44
sunNot sure what's left here? #40 re-opened, but moved to a new issue, which seems to fix #40 and #41. #43 referenced an already fixed issue only.
Therefore, reverting status. Feel free to re-revert. ;)
Comment #45
barrapontowhat about #action? how does it work? it got me all confused up when trying to redirect after submitting comments...
Comment #46
rfaybarraponto, you probably know this, but #action is for *submitting* to a different location, which is a very uncommon situation. If you want to redirect after submission, use the standard technique of $form_state['redirect'] = 'some/path';