Updated: Comment #17
Problem/Motivation
Date field widgets can behave incorrectly when set to a disabled state.
When specific date types are disabled when the related form array #disabled element is set to TRUE, there
are PDO exceptions which occur. These specific date types are: datestamp (UNIX Timestamp)and datetime (Date). The date type (ISO format) behaves normally.
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '' for column '[FIELD NAME]_value2' at row 1: INSERT INTO {field_data_[FIELD NAME]} (entity_type, entity_id, revision_id, bundle, delta, language, [FIELD NAME]_value, [FIELD NAME]_value2) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7); Array ( [:db_insert_placeholder_0] => node [:db_insert_placeholder_1] => 1 [:db_insert_placeholder_2] => 1 [:db_insert_placeholder_3] => date_field_disable [:db_insert_placeholder_4] => 0 [:db_insert_placeholder_5] => und [:db_insert_placeholder_6] => 2014-02-28 20:27:46 [:db_insert_placeholder_7] => )
When disabled using a JavaScript approach, validation errors occur.
Remaining tasks
Write some tests that set #disabled to true.- Some root cause analysis so we can drill down and fix the underlying issues in either the $form_state that this module generates or where the validation hook(s) are looking.
Original report by ZeiP
I'm getting these errors when I save a node type that has a date field that is disabled via Javascript:
warning: trim() expects parameter 1 to be string, array given in /var/www/drupal6-shared/sites/all/modules/date/date/date_token.inc on line 40.
warning: mysqli_real_escape_string() expects parameter 2 to be string, array given in /var/www/drupal6-shared/includes/database.mysqli.inc on line 329.
warning: trim() expects parameter 1 to be string, array given in /var/www/drupal6-shared/sites/all/modules/date/date/date_token.inc on line 40.
The reason for these seem to be that while the code assumes it's getting a string value, it's actually getting an array. I didn't find out why it does this, but I found a way around it, attached as a patch. It's pretty simple (and ugly), it just makes date interpret a date value empty if it's actually empty (according to empty()) AND also if it's an array. I'm not sure if this is the correct way (ie. if the date value is sometimes array on the check function on purpose), but it seemed to work for me.
Comment | File | Size | Author |
---|---|---|---|
#58 | date-1190830-58.patch | 548 bytes | nicola85 |
#55 | date-1190830-55.patch | 548 bytes | MustangGB |
| |||
#52 | date-n1190830-52.patch | 9.25 KB | DamienMcKenna |
#14 | date-input_disabled-1190830-14.patch | 490 bytes | sandipmkhairnar |
#8 | date-input_disabled-1190830-7.patch | 518 bytes | zany |
Comments
Comment #1
KarenS CreditAttribution: KarenS commentedCritical item is that this is for a disabled field. Disabling form elements has known issues that I'll have to dig into later.
Comment #2
pjsz CreditAttribution: pjsz commentedSame problem in 6.x.2.7. Thanks for the patch. It seems to work good. Thanks KarenS for your great modules. We really appreciate them.
Comment #3
KarenS CreditAttribution: KarenS commentedI need more information about how to reproduce this. There are lots of ways to attempt to disable a field. I have no idea what was being done.
Comment #4
KarenS CreditAttribution: KarenS commentedNo response and I cannot reproduce the issue.
Comment #5
aleksey.tk CreditAttribution: aleksey.tk commentedExist in D6 version too (6.x-2.7 version). Didn't check latest, but almost 80% sure that it exist there too.
Comment #7
zany CreditAttribution: zany commentedThe bug is still there. Steps to reproduce:
(actually that code is conditional on access schemes.)
date_popup_validate()
will error as the input is a string and not an array.Patch to handle this is attached! Thanks!
Comment #8
zany CreditAttribution: zany commentedpatch with
array_key_exists()
safeguardComment #9
vijaycs858: date-input_disabled-1190830-7.patch queued for re-testing.
Comment #10
MustangGB CreditAttribution: MustangGB commentedWhy not do it this way instead, it's more readable and I think a more standard way of achieving the same thing:
Comment #11
zany CreditAttribution: zany commentedyou are right the php manual on empty() states that "empty() does not generate a warning if the variable does not exist."
Comment #12
zany CreditAttribution: zany commentedComment #13
vijaycs85Lets move comment to it's own line as per https://drupal.org/coding-standards#comment
Comment #14
sandipmkhairnar CreditAttribution: sandipmkhairnar commentedThanks Zany for patch. Vijay Updated code as per coding standard.
Comment #15
wwedding CreditAttribution: wwedding commentedHas anyone tested this with Javascript? The original report specifies that is how they came across the problem, which would not be solved via checking for the #disabled FAPI attribute.
If not, I'll check it out within the next day and see if I can reproduce it that way.
Comment #16
vijaycs85Thanks @stickywes. We can RTBC, once it pass manual testing.
Comment #17
zany CreditAttribution: zany commentedPlease note that this patch does not need manual regression testing. Testing would be need to figure out how to invoke this bug from JS. (The OP doesn't seem to be around anymore though.)
My patch does in fact addresses a bug which hopefully has a similar code path.
I'll open a separate issue if that is better suited?
Comment #18
wwedding CreditAttribution: wwedding commentedI have verified that JavaScript does cause problems, and am typing up code snippets and a summary.
The bug that seems to be "fixed" by the patch could be better addressed by additional root cause analysis since JavaScript methods of setting form elements to disabled also cause problems. I would argue that it should not be considered a separate issue.
Comment #19
wwedding CreditAttribution: wwedding commentedUpdating the title and description so that the issue more accurately reflects the current state of things. Note that my hand testing couldn't find problems with respect to #disabled. We could still use some functional tests, though, in case I missed something.
This module has a pretty significant history of issues with trying to validate disabled or hidden field widgets, and this seems like another one. I'd like to advocate that we find the root cause of the problem, and not just deal with what are essentially side effects of a larger issue. If we fix the root cause, the side effects should go away. Maybe... hopefully!
Comment #20
wwedding CreditAttribution: wwedding commentedComment #21
wwedding CreditAttribution: wwedding commentedThis patch will add tests that will identify issues with elements that have had "#disabled" set to true on the base form element for field widgets.
The patch also refactors DateFieldBasic slightly so that it accepts arguments. I needed to be able to enable a helper module.
The added module creates a node type and has a form alter hook that targets the node form for this node type, to ease creating disabled form elements.
This doesn't catch the JavaScript issues, obviously. However, it does confirm that #disabled is still an issue. My hand testing didn't catch it earlier because I did not test the "datetime" or "datestamp" types. Both (I think) of those actually generate PDO exceptions, regardless of widget types.
PDOException: SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '' for column 'field_datetime_text_disabled_value2' at row 1: INSERT INTO ...
The test needs a little more work because it doesn't verify that the correct values have been saved yet, merely that validation and submit errors are not occuring.
Comment #22
sandipmkhairnar CreditAttribution: sandipmkhairnar commentedComment #24
MustangGB CreditAttribution: MustangGB commented@stickywes: If #14 is only treating the symptoms rather than the cause, have you any insight into what the cause is?
Comment #25
wwedding CreditAttribution: wwedding commentedAh, sorry, meant to follow up on this by now.
The root cause of the JavaScript issue is probably the same issue that causes #1419286: Using hide() on Date field form elements causes validation errors and caused other problems when #access = FALSE was set on the widget. The commit by Karen S to fix #1387890: Using form_alter to set a date field to #disabled removes the field from the form (http://drupalcode.org/project/date.git/commit/8450ad5)fixed the symptom with #access but didn't address what seems to be the underlying problem.
Which is: date_combo_validate relies on $form_state['input']. When an input is disabled or absent (either because hide() was called on the element or
#access = FALSE
), there is no $form_state['input'] because that part for the form state array represents user input.It might be worth separating the JavaScript portion of this specific issue out, since that would be addressed if/when I fix #1419286: Using hide() on Date field form elements causes validation errors, and addressing whatever is causing a PDO error when
#disabled = TRUE
as a completely separate issue; I haven't really encountered the PDO exception before so I haven't explored the causes there yet.Comment #26
wwedding CreditAttribution: wwedding commentedI'll be working on dealing with the combo validation callback and its assumptions about user input this weekend (US time), but the quick fixes I've tried so far have just lead to additional issues. If I recall correctly, after "fixing" that assumption the field then began to handle timezone offsets incorrectly and every time a node form was saved the time would be shifted several hours forward/backwards.
Another thing that complicates fixing the issue I reported back in the day with hide() is that it means carefully peeling back some code in an old commit while trying to not cause regression (which means writing more tests).
Comment #27
MustangGB CreditAttribution: MustangGB commentedSo (my main interest) hook_form_alter() + #disabled also results in this PDO error?
And fixing what you're talking about (sorry I don't really follow what exactly this is) would also fix this?
i.e. Why can't we keep the scope of this issue to fixing this specific error as a nice quick fix, and if you can come up with a super amazing improvement to the entire module that touches hide()/PDO/combo/timezones/etc as a separate follow-up.
Comment #28
wwedding CreditAttribution: wwedding commentedYeah, this issue got pretty muddy, didn't it! Let's just rehash what we've gone over so far, in hope that it gets made clearer.
If we move forward and let this specific issue only be the PDO exception, which I'm fine with:
We know that #disabled will cause a PDO error. Do we know why there are inappropriate values being saved to the database? Checking for #disabled will make this bug report go away but doesn't actually address the defect.
If that's good enough for everyone else, sure, let's move forward and mark this fixed after the tests start passing. I realize that root cause analysis can require a significant time investment and this is an open source project that people are contributing their limited free time to. Just understand what the potential costs are when you pick quick fixes: messy code that gets hard to maintain (I feel like this module is already there) while also making other potential related bugs more challenging to fix.
Comment #29
wwedding CreditAttribution: wwedding commentedIn an effort to provide clarity I'm trimming out a bunch of irrelevant things I included in my last issue description update.
Comment #30
wwedding CreditAttribution: wwedding commentedComment #31
wwedding CreditAttribution: wwedding commentedCompleted my test and rolled #14 into a single patch.
Comment #33
rakun CreditAttribution: rakun commentedIs patch date-arrayisempty.patch #21 will be applied to next release?
Comment #34
wwedding CreditAttribution: wwedding commentedDid you test it manually to see if it fixed your/the issue? Did it work?
Comment #35
MustangGB CreditAttribution: MustangGB commentedWell #14 works for me, clearly the tested in #31 are having some problems.
Comment #36
wwedding CreditAttribution: wwedding commentedDid you test without #14?
I just did a quick manual test this with a Standard install profile, enabling date and date_popup.
I added 6 fields to the basic page (ISO and Unix types with 3 different widgets), and disabled them all with a custom module.
No validation errors happened. Even without #14.
This issue might have been fixed as a side-effect of other issue fixes.
Comment #39
wwedding CreditAttribution: wwedding commentedOkay, maybe not...
Comment #40
MustangGB CreditAttribution: MustangGB commented@stickywes
So any idea what's wrong with the test?
Are you still working on this?
Comment #41
wwedding CreditAttribution: wwedding commentedI haven't looked into it yet, no. But I have time to tonight (US time).
The test itself is pretty straightforward, so I think I need to look into the differences between my field configuration when I hand-tested things and the configuration of the fields done during the test setup.
Comment #42
wwedding CreditAttribution: wwedding commentedLooks like it wasn't as simple as I thought. Somehow the values are getting through validation with the "value2" column winding up blank even when I seem to have replicated the field configuration exactly, which was the behavior that used to occur during manual testing.
Comment #43
wwedding CreditAttribution: wwedding commentedI finally figured out how to make this happen outside of automated testing again.
I'm creating a Feature to capture the specific field configuration so it is easier to confirm and will post config specifics when I do.
Comment #44
wwedding CreditAttribution: wwedding commentedMade a sandbox: https://www.drupal.org/sandbox/stickywes/2531848
If you grab the code and enable the Feature, you'll have a node with a few fields configured that will cause the SQL error when you submit them.
If you don't want to deal with the Feature, then add some date fields to a node; a unix date field with a text widget, a date field with a text widget, and a ISO date field with a text widget.
The setting that sets it off is checking "Collect an end date", and then making sure the default end date is set to "No default value." See the attached pic to see.
Disable these fields you've added in a custom module (or grab the sandbox):
Comment #45
wwedding CreditAttribution: wwedding commentedComment #46
wwedding CreditAttribution: wwedding commentedComment #47
MustangGB CreditAttribution: MustangGB commentedOkay so it's been quite a while without update, stickywes said he was fine with keeping this issue in-scope, presumably the extra stuff he found will make it into a follow-up issue at some point, but for now I'm going to try marking #14 as RTBC on the basis that it passes manual testing.
Comment #48
wwedding CreditAttribution: wwedding as a volunteer commentedIf we keep the issue scope narrowed it can be described as the following: using Javascript to disable date field inputs generates a PDO Exception...
It seems like the JavaScript problem got fixed in some other patch somewhere, so this issue can be closed, I guess? I kinda feel like I stole a patch credit from zany by slowing down this issue...
Here is some manual testing without patch #14 applied by disabling the fields via my browser's debugger/inspector since I don't have time to write the JavaScript.
Popup widget tests
Text field tests (with "collect end date" checked and "no default value" selected for default value):
I skipped select list because that has less of a troubled past (and I'm outta time!)
I need to find a new home for the non-JavaScript trigger. Leaving my notes here for copying to whatever issue turns out more appropriate by me or someone else (but probably me).
**********************************
Here are the manual steps to make it happen without JavaScript.
At this point, you will experience the PDO Exception.
Comment #49
MustangGB CreditAttribution: MustangGB commentedComment #50
vijaycs85I can't see what tests are failing for #31 but we just committed some fixes for test fails in 7.x HEAD (@see #2646646: Tests are broken on current 7.x-2.x branch). Can we re-roll the patch to test again?
Comment #51
MustangGB CreditAttribution: MustangGB commentedvijaycs85: The patch that was RTBC is #14, stickywes went off on a tangent to try and rewrite the entire system, but by his own admission doesn't have the time to finish it, hope that helps.
Comment #52
DamienMcKennaRerolled the patch.
Comment #54
DamienMcKennaSix test failures, so this needs some work.
Comment #55
MustangGB CreditAttribution: MustangGB commentedRe-roll without tests.
Comment #56
wwedding CreditAttribution: wwedding as a volunteer commentedEdit: Nevermind.
Comment #57
jdleonardI realize there's still work to be done, but 55 is working for me, thanks!
Comment #58
nicola85 CreditAttribution: nicola85 commentedComment #59
DamienMcKennaComment #61
steinmb CreditAttribution: steinmb as a volunteer commentedThe patch is missing all the tests from #52