Problem/Motivation
Date formats have 2 property paths that are not yet validatable:
./vendor/bin/drush config:inspect --filter-keys=core.date_format.html_date --detail --list-constraints --fields=key,validatability,constraints
➜ 🤖 Analyzing…
----------------------- ------------- -------------------------------------------------------------------------
Key Validatable Validation constraints
----------------------- ------------- -------------------------------------------------------------------------
core.date_format.html 82% ValidKeys: '<infer>'
_date
core.date_format.htm Validatable ValidKeys: '<infer>'
l_date:
core.date_format.htm Validatable ValidKeys:
l_date:_core - default_config_hash
core.date_format.htm Validatable NotNull: { }
l_date:_core.default_ Regex: '/^[a-zA-Z0-9\-_]+$/'
config_hash Length: 43
↣ PrimitiveType: { }
core.date_format.htm Validatable ValidKeys: '<infer>'
l_date:dependencies
core.date_format.htm NOT ⚠️ @todo Add validation constraints to config entity type:
l_date:id core.date_format.*
core.date_format.htm Validatable Regex:
l_date:label pattern: '/([^\PC])/u'
match: false
message: 'Labels are not allowed to span multiple lines or contain
control characters.'
NotBlank: { }
↣ PrimitiveType: { }
core.date_format.htm Validatable NotNull: { }
l_date:langcode Choice:
callback:
'Drupal\Core\TypedData\Plugin\DataType\LanguageReference::getAllValidLa
ngcodes'
↣ PrimitiveType: { }
core.date_format.htm Validatable ↣ PrimitiveType: { }
l_date:locked
core.date_format.htm NOT ⚠️ @todo Add validation constraints to config entity type:
l_date:pattern core.date_format.*
core.date_format.htm Validatable ↣ PrimitiveType: { }
l_date:status
core.date_format.htm Validatable Uuid: { }
l_date:uuid ↣ PrimitiveType: { }
----------------------- ------------- -------------------------------------------------------------------------
On my local umami install, they are also with 11 in the top 25 of config objects the closest to 100% validatability. (See ./vendor/bin/drush config:inspect --todo=50)
Steps to reproduce
- Get a local git clone of Drupal core
11.x. composer require drupal/config_inspector— or manually install https://www.drupal.org/project/config_inspector/releases/2.1.5 or newer (which supports Drupal 11!)composer require drush/drushvendor/bin/drush config:inspect --filter-keys=core.date_format.html_date --detail --list-constraints
Proposed resolution
Add validation constraints to:
core.date_format.*:idcore.date_format.*:pattern
This requires looking at the existing code and admin UI (if any) to understand which values could be considered valid. Eventually this needs to be reviewed by the relevant subsystem maintainer.
For examples, search *.schema.yml files for the string constraints: 😊
Reach out to @borisson_ or @wimleers in the #distributions-and-recipes.
Remaining tasks
core.date_format.*:idcore.date_format.*:pattern
User interface changes
None.
API changes
None.
Data model changes
More validation 🚀
Release notes snippet
None.
| Comment | File | Size | Author |
|---|
Issue fork drupal-3397491
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:
Comments
Comment #3
borisson_Comment #4
borisson_I'm not sure how to add validation to the format, because it looks like all different kinds of things are allowed, so I've added not null, so we at least have something to validate against.
Passing null into DateTime::format is also not allowed, so it also helps that case.
Comment #5
borisson_Comment #6
smustgrave commentedLooks good to me. Surprised didn't cause more test failures besides the 1 but woo!
Comment #7
wim leersOne nitpicky question 😇
Comment #8
borisson_Setting to needs work to apply the
NotBlankto this as well. I'm not sure about the regex.Comment #9
borisson_Actually, when thinking about this again, I don't think it makes sense for people to use a date formatter without using one of the letters that are actually transforming the date into something that has to do with the input.
So the regex, while it will be a long one, does make sense.
Comment #10
borisson_This will need a test to validate the regex being applied, but I would like to get a review on the approach first.
Comment #11
smustgrave commentedQuestion how often could a new character be added to php date?
Comment #12
borisson_Well, as soon as php updates the date formatting handling. The changelog notes a change in 8.0 and 8.2, so with following minor release we'd have to recheck this?
Comment #13
smustgrave commentedThat's true guess it will just have to be remembered. Will leave in NR if you want another vote, agree though on the need for tests.
Comment #14
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #15
borisson_Updated the yaml file to add a cspell ignore line, to fix #14.
Comment #16
smustgrave commentedSee there is a test in there now. Should that be expanded though?
Comment #17
borisson_I already included this test change in the very first commit, because otherwise it was failing. But you are right, this should be expanded.
Comment #18
borisson_Added a kernel test that covers this, per @smustgrave.
Comment #19
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #20
borisson_Merged 11.x back into this branch.
Comment #21
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #22
borisson_Merged 11.x into the MR.
Comment #23
borisson_Removed the @needs-review-queue-bot files.
Comment #24
smustgrave commentedSurprised the bot hasn't got this, but appears to have build failure.
Comment #25
borisson_Pushed phpcs fix,
Comment #26
smustgrave commentedRan the test-only job and got several test failures (which is good as it shows coverage) https://git.drupalcode.org/issue/drupal-3397491/-/jobs/463228
There is 1 thread open but I believe it has been addressed by @borisson_
Think this is good.
Comment #27
wim leersComment #28
borisson_I will change the test coverage, but I'm not sure how to change the validation error message. What would you prefer?
Comment #29
wim leersYeah that's … tricky 😬 Maybe something like ? 🤔
Comment #30
borisson_Setting to needs review to get help with the writing of the error message.
Comment #31
wim leersComment #33
wim leers@sourabhjain Please do not ask for a review on every review thread. Also: it seems like you just blindly modified these lines, without running tests locally?
is nonsense 😳 If you'd run it, you'd see you introduced a PHP fatal error:
This is a contribution that slows progress down. 😔
Comment #35
phenaproximaComment #36
wim leersOne usability nit, but other than that this looks great!
(And thanks for already adding
FullyValidatable!)Comment #37
phenaproximaAgreed and fixed.
Comment #38
wim leers🚢
Comment #39
catch#11 is a good question. If PHP 8.4 adds support for a new letter, then we would need to add it here, but that would then potentially allow invalid formats for sites running PHP 8.3.
Then I wondered - do we need a callback somewhere that provides a different string for the regex depending on PHP version? But that seems like overkill.
So what if we just allowed
[a-z][A-Z]and it would be a bit looser than reality but we'd never have to think about the above, and it would still catch most completely invalid date formats. Someone can still make a case error with the new validation as long as something else in the string is valid, so it's not completely preventing mistakes.Comment #40
borisson_Sure, adding [a-z][A-Z] is a MUCH simpler option, but that doesn't solve the question asked by @Wim Leers originally:
Comment #41
wim leersInteresting. 🤔
This would not catch the following test cases though:
Alternative idea: what if we made a custom validator that checked if each individual
[a-z][A-Z]character actually yielded output? Because characters that are not supported by PHP will just get printed as-is:— https://3v4l.org/PIAV2
Comment #42
borisson_I don't think that'd be right solution, people might want to print something like: "Happened on Fri, Feb 9 2024 around 14:00". That is currently possible, and would no longer be with that solution?
Comment #43
wim leers#42: I doubt that's ever been intentionally supported? 😅 See the test coverage, for example
\Drupal\Tests\system\Functional\Common\FormatDateTest— none of that works that way. Or maybe I'm entirely wrong?Also … the example you provide is also forbidden by the current MR?
Comment #44
borisson_You're right - it is currently also broken, but it is what I had intended to write, to allow something like this https://3v4l.org/HIK4D. Not sure if we want to support this usecase.
Comment #45
wim leersAFAICT that's supposed to be a translatable string, and the translatable string has a placeholder for this formatted date. Putting the string into the formatted date is the wrong way around IMHO.
Comment #46
phenaproximaHow often does PHP add new letters to date formats? If the available letters haven't changed in aeons, I'm not sure it's worth making this more complex than the regex we already have in the MR.
Comment #47
wim leers#46 is also what I was thinking honestly 😅
Comment #48
phenaproximaAnother option here: rather than the regex only listing the characters we allow in a date format, list the characters we forbid. (In other words, just invert the logical outcome of the current regex.) If a new version of PHP comes along that (for example) adds support for the letter Q, we can just remove it from the rejectlist, and older versions of PHP will just harmlessly pass it through.
Comment #49
catchI also thought #44 was allowed (if not recommended), it's what PHP allows you to do, #48 would explicitly break that behaviour then but if it's not already possible, maybe that is fine?
Comment #50
phenaproximaOh wow, I didn't know you could escape formatting characters. What a pain.
Okay, in light of that, maybe we should just go back to something simple and relatively naïve, like "forbid control characters". So just reuse
type: label.Comment #51
wim leers… which implies "yeah you'll have to check and see how this works". That's probably true already anyway. So … not unreasonable I think.
I don't like it, but considering all factors at play here, it might be the best possible trade-off indeed to just go with
type: label+ a comment explaining the factors that led to that decision.OTOH
That should not be the question here. The question should be: How does Drupal intend this
DateFormatconfig entity to be used? And then I think the conclusion would be different, because the validation thattype: labelgets us is virtually useless 🙈Comment #52
phenaproximaWait a minute here. Might we not be massively overcomplicating this?
In the MR, the constraint we have for the date pattern is this:
In other words: "this string must contain, somewhere, at least one of the characters that we know is valid to use in a date format as of right now".
This regex has no opinion about unsupported characters, or escaping anything, or characters that might be supported in the future. All of those things would sail through it. It merely says you must have at least one of the characters that is supported now.
So, except in the highly unlikely event that PHP 8.4 drops support for all of these characters in date formats...this pattern will continue to be valid. Even if PHP adds support for a new character. And rightfully so - this is already a very permissive validation. Because of that, it's also very future-proof.
Therefore, I'm not sure #11 is looking at this correctly.
I'm restoring RTBC, but if I'm barking up the wrong tree, feel free to knock it back.
EDIT: We could beef up this regex slightly by making it say, in effect, "your string must contain at least one of these characters and it cannot be escaped". Something like:
[^\\][aABcdDeFgGhHiIjlLmMnNoOpPrsStTuUvwWxXyYzZ]Comment #53
catchThe issue would be that someone adds a new date format using only the new character that PHP supports, and then it fails validation.
I don't know whether that will actually happen, but it seems as likely as them adding an unsupported letter by accident that would pass the type: label regex and fail the one here.
Comment #54
phenaproximaMy feeling is, if that happened - which already feels edge-casey to me, but who knows - it would be a perfectly legitimate reason to open an issue to add the newly-supported letter to our regex. :) That'd be a one-line fix and probably wouldn't even need test coverage.
And if the functionality was needed right away, one could easily implement hook_config_schema_alter() to change the constraint.
Comment #55
catchOK I'm convinced. Thanks for talking through it.
Committed/pushed to 11.x, thanks!
Comment #57
wim leersThanks!
(Fixing status, silly d.o and its non-handling of race conditions 😅)
Comment #58
wim leers