Problem/Motivation
When using #date_year_range on date form element, it adds min and max HTML attributes that prevents the browser from accepting a date outside this range.
However, if the browser does not support these attributes, the range is never validated server-side.
Steps to reproduce
Create a form with a date element then alter it:
/**
* Implements hook_field_widget_WIDGET_TYPE_form_alter().
*/
function foo_field_widget_datetime_default_form_alter(array &$element) {
$element['value']['#date_year_range'] = '1850:3000';
}
Then try to submit a date before 1850 with a browser that does not support the min attribute on date inputs (or with curl).
Proposed resolution
DateTime::validateDatetime() should validate, using the Entity validation API server-side, if the date is in the range.
Issue fork drupal-3269890
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3269890-dateyearrange-is-not
changes, plain diff MR !1976
Comments
Comment #3
prudloff commentedComment #5
pieterdcThanks for sharing, @prudloff!
As far as I've tested it, it works.
Looking at the code, the logic may be located better in a place where it makes $date->hasErrors() (the line above the code changes) fail, but I'm not familiar enough with how these kinds of PHP classes should be coded to claim your code changes need to be reworked, so I'm leaving the issue state as is.
Comment #7
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
The MR will need to be updated to 9.5.x or 10.1.x
also will require a test case to show the issue.
Comment #9
prudloff commentedI rebased and added a test.
DateTimePlus::hasErrors() checks if the date is a valid date but it has no notion of allowed values.
Comment #10
smustgrave commentedShows test coverage so removing the tag for tests, also the coverage being added looks great and in depth.
Believe all feedback for this one has been addressed.
Comment #11
catchLooks good but has merge conflicts.
Comment #13
shalini_jha commentedI have rebased this MR and resolved the merge conflicts. During the rebase, I noticed that some new behavior was introduced, so to ensure everything continues to work as expected, I re-ran the range test locally.
While debugging, I found that the test was failing in the third scenario where the datetime value falls within the defined range. Due to the newly introduced behavior Here, the form state now includes additional errors such as datetime_required_error and datetime_no_required_error.
To address this, I updated the third scenario’s assertion to only check that range_datetime_element is not present in the form state errors, as this is the specific error we are handling in this case in testRangeValidate() test method. With this change, the test now passes as expected.
Moving this back to Needs Review.Kindly review.
Comment #14
smustgrave commentedRebase seems good
Comment #15
alexpottThis is a nice find. I think the MR needs a few adjustments. See the MR review comments.
Comment #17
prudloff commentedI think comments have been addressed.
Comment #18
oily commentedAdded 101 commits from source branch. Re-ran failed functional test. Pipeline is now green.
Comment #19
smustgrave commentedWas there a merge conflict needed for the rebase?
Feedback has been addressed it seems.
Saving credit for alexpott for the MR reviews.
Comment #20
oily commentedCorrected code comment at line 396. We are validating the date, not 'checking' it. Similar idea but let's be consistent and specific!
Checking is something we do a lot in PHP generally eg using function like is_null() or by using if statements. On the other hand validation is specific to forms and form entry and the validation component
https://symfony.com/doc/6.4/validation.html
Comment #21
oily commentedComment #22
smustgrave commentedPersonally don’t see why the comment change was needed. Read fine before
Comment #23
smustgrave commentedComment #24
oily commentedRE: #23 @smustgrave It could help if someone greps the codebase? They'd return i think a lot more with 'check' than 'validate'. Also the IS distinguishes between the 'checking' done client-side by the browser to the entity validation api validation done 'server-side'. We want the field value to be validated as opposed to just 'checked'? Also 'checking' can create muddle as we also 'check' checkboxes in forms api.
In fact, browser-side 'checking' is also 'validation'.
https://developer.mozilla.org/en-US/docs/Learn_web_development/Extension...
So describing the browser-side an 'initial check' or a 'check' prior to the full-on 'validation' server-side still seems like a useful semantic distinction to preserve. Generally it seems an important distinction because client-side 'validation' is always unsafe and can easily be bypassed whereas if used correctly, server-side is secure.
It seems useful to me to know I can grep the codebase or a portion of it for 'validation' and see what role is played by the entity valdiation api in Drupal..
Comment #25
oily commentedComment #26
oily commentedUpdated IS according to #21 and #24.
Comment #27
smustgrave commentedRestoring previous status.
Comment #28
quietone commentedThis is passing the core gates and I updated credit. I read the MR and didn't see anything amiss.
Comment #31
alexpottCommitted 2558bc8 and pushed to 11.x. Thanks!
Committed 6c481f7 and pushed to 11.2.x. Thanks!
This didn't cherry pick clealy to 10.6.x / 10.5.x so I did not backport there.
Comment #35
anybodyThis bugfix caused some kind of "regression", because before this fix (from users perspective) you were able to enter a date like "2099".
Now with this fixed, these nodes can't be saved any more, as the hard coded limit is used and limits to 2037 or 2050!
See #2942828: Remove hard-coded #date_year_range making it impossible to enter dates < 1900, > 2050. Instead make them optional and configurable in the UI. I've been wondering why I suddenly ran into these cases after the last core update. Not being able to enter such future dates is a major issue in my eyes? Even worse it's not configurable: #2836054: Allow configuring of datelist year range date_year_range via UI
Should this get reverted until the other issues are fixed or how can we put a focus on that? I assume we'll see not just a few affected projects!