Updated: Comment #N
Problem/Motivation
Datetimelist element only works when all the fields has been filled. Otherwise, you obtains unexpected behaviors and errors.
Steps to reproduce:
- Add a datetime field to any entity
- Choose Select List as the widget for the field in Manage Form Display
- Go to Entity creation form and fill only part of the elements
- You will get an error like this:
Proposed resolution
Update validation to ensure all sub-elements are filled in.
Remaining tasks
Finalize error reporting.
User interface changes
None.
API changes
None.
Related Issues
None
Data model changes
None
Beta phase evaluation
| Issue category | Bug because a form element behaves in an improper manner when it is partially completed. |
|---|---|
| Issue priority | Though it may only occur for a small percentage of users, this is a major because it triggers an unrecoverable error (a 500), and user input may be lost. |
| Prioritized changes | The main goal of this issue is fixing a bug, wich is a allowed during beta. |
| Disruption | None. |
| Comment | File | Size | Author |
|---|---|---|---|
| #30 | datetimelist_filled-2115695-30.patch | 8.88 KB | justachris |
| #30 | 2115695-interdiff-23-30.txt | 5.96 KB | justachris |
| #30 | 2115695-30-test-only.patch | 3.87 KB | justachris |
| #30 | 2115695-interdiff-test-only-23-30.txt | 3.53 KB | justachris |
| #29 | 2115695-date_validation_selection_removed.jpg | 108.77 KB | justachris |
Comments
Comment #1
plopescFirst approach patch.
This patch Returns NULL as date when not all the fields are filled. However, another unexpected behavior appears:

It comes from
DateTimeComputed::getValue(), where there is a @todo in line 58.IMHO The form element bug is coverred with this patch, but more work is necessary to get it working with field API workflow.
Any idea?
Comment #2
vijaycs85Comment #3
plopescCollateral bugs described in #1 currently do not appear.
Re-rolling patch and adding placeholder for
%filein the error message.Regards
Comment #4
mgiffordNo longer applies.
Comment #7
mpdonadioComment #8
sharique commentedException shown in issue description no longer appear, so I think this issues no longer relevant.
Comment #9
mpdonadioConfirmed the bug. Edited IS to clarify; you need to use the Select List widget.
Depending on how you have your system configured, the actual error display may be different. I just got a generic
but my PHP error log had
.
Comment #10
rpayanmComment #12
justachris commentedResolved above test fails by replacing date_increment_round with correct method.
Added simpletest checking for response to not filling out all fields; test only patch should fail, combined patch should pass.
Added a phpunit test for the DateTimePlus::checkArray() method. Although this method is not affected by the patch or involved in causing the above issue, additional phpunit test coverage is always helpful. We can remove it if not needed.
Comment #14
sharique commentedAfter applying patch #12, exception no longer appears. With some more testing it is good to make RTBC.
Comment #15
mpdonadioOK, spent some time with this.
We need to figure out a way to get a better error message in here for a partially filled in form. I think that just saying the field is invalid doesn't help the user with why the field is invalid. Maybe move the filled keys logic to a protected static the gets called from both the value and validate callbacks?
Comment #16
justachris commentedSeparated out filled key logic into protected static as suggested in comment #15, updated to provide key of non-filled value. Updated message that is below the field to indicate which part of the element is invalid (not selected). Only the first empty part is reported in this iteration.
Comment #17
mpdonadioThis looks good, except the message at the top of the form doesn't match the error under the form element. See the attached image. If we can fix that, I think this is good to go.
Comment #18
mpdonadioRaising this to Critical per the "Cause PHP fatal errors" and "Cause loss of data" clauses in the issue priorities. The data loss would be user input not being saved. I wouldn't object to this going back down to Major if the core committers don't think this warrants being Critical.
Comment #19
xjmThanks @mpdonadio!
I think this is major: when the user uses this one particular kind of field and forgets to fill out part of it, they get an exception (or, with error reporting off, an unhelpful error) instead of the expected validation error. There is no data loss because (as far as I can tell), the form submission just doesn't work at all, and the user does receive an error.
This kind of bug used to fit https://www.drupal.org/core/issue-priority#major-bug but catch added "non-fatal" there recently in https://www.drupal.org/node/45111/revisions/view/8664850/8729606 -- so I'll leave this critical for now until we discuss that (we'll triage it later this week). "Race condition or database deadlock" doesn't seem to apply to this sort of fatal during form validation, but I could be mistaken.Edit: see next comment. :)But, in general, I don't think lost input with a big flaming error is data loss, because the user will know the submission failed. :) It'd be data loss if the bug also deleted existing data, or perhaps if it failed silently but seemed to work, saving data different from what the user submitted.
Comment #20
xjmWait. If it's a cleanly thrown exception, it's not a "PHP fatal". Just checked the code and confirmed this. So downgrading. Thanks!
Comment #21
mpdonadioWas just reading this again.
These may be flagged as out of scope changes since they are unrelated to empty fields.
The @param and @return should have descriptions, and the @return should be string|null.
I'm also wondering if we can rework checkEmptyInputs() to return the empty keys. Then the is_null() in valueCallback() could become empty(), and we could use all of the empty keys in the error message in validateDatelist()?
Comment #22
justachris commentedWill remove the unrelated tests and update the docblock. We can return all of the empty keys as an array or such and adjust the setError to have the message at the top match the empty fields, I agree it is a better user experience if we do that. However, this requires that we update the element processing:
The format of the resulting error notifications is a little messy though:

Comment #23
justachris commentedUpdated patch that produces the validation notifications as displayed in #22
Additionally,
Removed the unrelated test (unit test of DateTimePlus::checkArray). Made minor update to the applicable simpletest to cover the singular and plural form of the validation message.
Updated docblock for the added method Datelist::checkEmptyInputs()
Uploading the modified test-only patch, which should fail.
Comment #25
mpdonadioMinor nit that can be fixed on commit, but per https://www.drupal.org/node/1354, the different sections in a docblock should have a blank line between them, so there should be one between the last @param and the @return.
The code looks good, and I did a fair amount of manual testing with it. The formatting on the error message is unfortunate, but I can't think of any other options (and I tried several).
I'm going to leave this at Needs Review for a few days to see if anyone has a better idea for how to handle this. If we don't get any more comments, I'll RTBC it.
Comment #26
mpdonadioComment #27
larowlanLooking good, couple of observations/questions/suggestions
Should these be using ===?
nit: should be no space after ( or before ), but should be one after )
Any reason this can't be one line?
nit:If we're re-rolling to add a newline above the @return, can we put full stops on the end of these at the same time?
I think this can be done with array_diff
Might need an array_filter if some keys are there but missing values
Isn't 0 a valid value?
Can we test what happens if 0 is submitted for hour or minute, the empty() above will report it as missing I suspect
Can we make this more specific?
Comment #28
justachris commentedThanks larowlan for these.
Setting back to needs work since #27.6 points out a failure in the existing logic (hour and minutes can be 0) and tests should be expanded to check for these as noted. Additional comments should be addressed as well since the patch will need to be updated.
Comment #29
justachris commentedWhile working on this, a related issue was found.
If the submitted date (in datelist format) fails validation, such as not selecting one of the date elements, selected values that are 0 become unselected after the validation error is displayed.
This image should describe what is happening. Note that the minute field is selected as "00" by the user and is now blank after validation.

The cause of this is a related usage of empty()
Also note that is corrected when the submitted values pass validation by the subsequent line:
I should have an update patch for the previous issues sometime today. Any input on this new issue is welcome.
Comment #30
justachris commentedUpdated patch and tests. All comments have been addressed except #27.1, I think the == is sufficient here since the input options are known.
-Modified logic in Datelist::checkEmptyInputs()
-Added tests to check the selection of 0 as hour and minutes
-Replaced empty() in processDatelist, resolving the bug noted in #29, and added test for this scenario to ensure selected value is not deselected
-Additional style updates as noted in #25 & #27
Upload modified test only patch, which should fail.
Comment #32
mpdonadioI think the comments in #27 have been addressed, as well as the additional in-scope bug in #29.
We have a good IS, a Beta Eval, a test that demonstrates the problem, and a good patch. I also manually tested the latest patch.
I think this is good to go.
Comment #33
alexpottCommitted 3843053 and pushed to 8.0.x. Thanks!
Thanks for adding the beta evaluation to the issue summary.