Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
forms system
Priority:
Critical
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
17 Jan 2010 at 20:49 UTC
Updated:
30 Jul 2010 at 00:37 UTC
Jump to comment: Most recent file
Comments
Comment #1
yched commentedIndeed. After a quick look, seems to be some FAPI-related mess up.
Er, critical.
Comment #2
yched commentedThat affects text fields.
That's because the 'Maximum length' input at the bottom of the form is '#disabled' (which, BTW, Seven doesn't really hint : #690980: Disabled form elements not properly rendered) - see text_field_settings_form().
When the form is submitted, $form_state['values'] contains an empty string for the element, instead of the '#default_value'.
That empty string is taken as the new setting for the 'Maximum length', and since you're not supposed to be able to change this at this point (there's already data in the field, Field API doesn't support changing the db schema), this raises an exception.
I don't know when this broke. Definitely worked at some point earlier.
This shows we lack tests on Field UI, but I'm a bit surprised that a #disabled element is handed back by FAPI as having actually changed ;-).
Need feedback from FAPI gurus here.
Comment #3
yched commentedWhen a textfield element is #disabled, _form_builder_handle_input_element() does:
comes back with NULL in $form_state['values'], then
runs form_type_textfield_value(), which puts back '' (empty string) in $element['#value'].
Last refactor in this area was #622922: User input keeping during multistep forms, crossposting over there.
Comment #4
effulgentsia commented@yched: can you confirm that this fixes the original issue reported? If it does, since this touches on security, a FAPI maintainer should review this prior to it being RTBC.
Comment #5
Shai commentedI applied the patch in #4 to an install of of D7 - alpha 1. The patch applied cleanly. I went to an existing text field, with nodes using that field in the db, and changed the label. The new field label updated without error.
Shai
Comment #6
yched commented@effulgentsia: Yup, I confirm it fixes it.
Comment #7
katriencI've also tested this and confirm that the patch on #4 solves the issue.
Comment #8
effulgentsia commentedNow we just need chx or another FAPI maintainer to approve the change (or identify why it's completely wrong).
Comment #9
effulgentsia commentedThis one adds one more hunk for the form_type_textfield_value() that's commented with why. If FAPI maintainers disagree with the change introduced by #4, then just this patch's form_type_textfield_value() hunk alone can be committed (with a modified comment) and it will fix the specific use-case this issue was started with, but I continue to think this full patch is in order. It makes no sense to me that there is no way currently to set something as not being available to user input, but still visible. There was a recent comment posted to the D6 FAPI reference to this effect as well: http://api.drupal.org/api/drupal/developer--topics--forms_api_reference..... It makes a lot more sense to me to treat #disabled as meaning not just default the browser to having it disabled, but make the server-side code treat it as disabled too. If someone doesn't want an element disabled in this sense, they can set #attributes['disabled']='disabled' instead of setting #disabled, and this would mean: only disable it client-side, and if client-side code enables the element, then user input can be accepted by the server.
Comment #10
effulgentsia commentedChanged so that even programmatically submitted forms can't bypass #disabled restrictions (note, this is how checkboxes work in HEAD, so this patch just applies the same rule to all elements), and removed the @todo from #9. I'm quite confident this is now correct and ready to fly, but it needs someone familiar enough with FAPI and security to RTBC.
Comment #11
arhak commentedwould be nice to have it documented
Comment #12
effulgentsia commentedYep, I think the most logical place, if this patch goes in, would be in http://api.drupal.org/api/drupal/developer--topics--forms_api_reference..... For better or worse, that seems to be where Form API properties are explained. Since this is also an API change from D6 (in terms of making the #disabled property mean more than it meant in D6), this will also need to be mentioned in http://drupal.org/update/modules/6/7 (again, assuming the patch gets committed).
Comment #13
David_Rothstein commentedThis seems related to (or maybe a duplicate of) #426056: Server-side enforcement of #disabled is inconsistent?
Comment #14
effulgentsia commentedOk, since there's the other issue, this one is just a patch to fix the original issue reported. This one's a no-brainer, but still needs someone to RTBC (though doesn't have to be a FAPI guru).
Comment #15
effulgentsia commentedBetter title given that this is a regression that occurred due to #622922: User input keeping during multistep forms, and all this issue does is fix that regression.
Comment #16
eric_a commentedIs this really a regression due to #622922: User input keeping during multistep forms? Or let me put it this way: I got bitten by this in D6. In simple forms I would set the #disabled property on textfields with default values and was left with empty strings after submission. At the time I decided this was just the way FAPI worked and that I either had to set the values myself in a submit handler or set #access FALSE and display a disabled copy of the original textfield.
Comment #17
effulgentsia commented@Eric_A: You're correct. It's not a regression. I looked at the D6 code and at the D7 code prior to #622922: User input keeping during multistep forms, and both have the same bug. I assumed it was a regression because of comment #2, but I guess there's some other reason FieldUI worked before and now doesn't.
I still think it's a critical bug, and the current behavior makes no sense, because, for example, #type='select' and #type='textarea' do not have this bug. It should at least be fixed for D7, and #14 can be easily rolled for D6 too if that's desired.
The best way to hack around this limitation of textfields until this issue is fixed is to set #value on the element which is the way to force a value on any element regardless of user input. In fact, until #426056: Server-side enforcement of #disabled is inconsistent is fixed, I highly recommend doing this on all #disabled elements that the form doesn't want input for, since currently, nothing prevents javascript from enabling a disabled element.
Comment #18
moshe weitzman commentedLooks proper to me. I've been bitten by this too.
Comment #19
yched commentedAw, sorry for wrongly assigning blame, effulgentsia.
Confirming that #14 fixes the bug.
Comment #20
webchickLet's get some tests for this.
Comment #21
Shai commentedWhat would the appropriate tests be?
I know that in my original example, the problem only occurred if there was data in the database for the particular field. So the test would create a content-type, and then a text field, and then add a node with data in the text field, and then try to change the label in the content type. Is that right?
What other tests should be created?
Re: writing the tests... how do we get someone to jump in. I think with the limited time I have to work on core my time would be better spent in doing things I already know how to do. However, if it is deemed that there is a big shortage of test writers... then maybe I would jump in. For me or others, can someone leave a link for the best "writing tests for core" tutorial.
Shai
Comment #22
sunsubscribing
Comment #23
effulgentsia commentedI'd like #426056: Server-side enforcement of #disabled is inconsistent to go in first. There's a dependency between that issue and proper testing of this one. If that issue weren't on the table, this one could proceed, but since that one has reached consensus, and is just awaiting bot to return and someone to RTBC it, it makes sense to get that one in first.
@Shai: once that issue goes in, I'll write the test for this one. It'll be pretty simple: it can leverage existing FAPI tests.
Comment #24
effulgentsia commented.
Comment #25
effulgentsia commentedThis got fixed as part of #335035: drupalPost() incorrectly submits input for disabled elements. The test for this already existed as part of FormsTestCase::testDisabledElements(), but the test wasn't working correctly due to that bug.
Comment #27
ledut commentedsubscribing