Problem/Motivation

system.date has 4 property path that are not yet validatable:

./vendor/bin/drush config:inspect --filter-keys=system.date --detail --list-constraints
➜  🤖 Analyzing…

 Legend for Data: 
  ✅❓  → Correct primitive type, detailed validation impossible.
  ✅✅  → Correct primitive type, passed all validation constraints.
 ----------------------------------------- --------- ------------- ------ ------------------------------------------ 
  Key                                       Status    Validatable   Data   Validation constraints                    
 ----------------------------------------- --------- ------------- ------ ------------------------------------------ 
  system.date                               Correct   67%           ✅❓   ValidKeys: '<infer>'                      
   system.date:                             Correct   Validatable   ✅✅   ValidKeys: '<infer>'                      
   system.date:_core                        Correct   Validatable   ✅✅   ValidKeys:                                
                                                                             - default_config_hash                   
   system.date:_core.default_config_hash    Correct   Validatable   ✅✅   NotNull: {  }                             
                                                                           Regex: '/^[a-zA-Z0-9\-_]+$/'              
                                                                           Length: 43                                
                                                                           ↣ PrimitiveType: {  }                     
   system.date:country                      Correct   Validatable   ✅✅   ValidKeys: '<infer>'                      
   system.date:country.default              Correct   NOT           ✅❓   ⚠️  @todo Add validation constraints here  
   system.date:first_day                    Correct   NOT           ✅❓   ⚠️  @todo Add validation constraints here  
   system.date:timezone                     Correct   Validatable   ✅✅   ValidKeys: '<infer>'                      
   system.date:timezone.default             Correct   NOT           ✅❓   ⚠️  @todo Add validation constraints here  
   system.date:timezone.user                Correct   Validatable   ✅✅   ValidKeys: '<infer>'                      
   system.date:timezone.user.configurable   Correct   Validatable   ✅✅   ↣ PrimitiveType: {  }                     
   system.date:timezone.user.default        Correct   NOT           ✅❓   ⚠️  @todo Add validation constraints here  
   system.date:timezone.user.warn           Correct   Validatable   ✅✅   ↣ PrimitiveType: {  }                     
 ----------------------------------------- --------- ------------- ------ ------------------------------------------ 

Steps to reproduce

  1. Get a local git clone of Drupal core 11.x.
  2. 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!)
  3. composer require drush/drush
  4. vendor/bin/drush config:inspect --filter-keys=system.date --detail --list-constraints

Proposed resolution

Add validation constraints to:

  1. system.date:country.default
  2. system.date:first_day
  3. system.date:timezone.default
  4. system.date:timezone.user.default

For examples, search *.schema.yml files for the string constraints: 😊

Reach out to @borisson_ or @wimleers in the #distributions-and-recipes.

Remaining tasks

User interface changes

None.

API changes

Data model changes

More validation 🚀

Release notes snippet

None.

Issue fork drupal-3437325

Command icon 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

narendraR created an issue. See original summary.

narendrar’s picture

Issue summary: View changes
Status: Active » Needs work
narendrar’s picture

Version: 11.x-dev » 10.3.x-dev

narendraR changed the visibility of the branch 3437325-add-validation-constraints to hidden.

narendrar’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new2.21 KB

The 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 necessarily 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.

wim leers’s picture

Interesting failures:

Drupal\FunctionalTests\Installer\InstallerSiteConfigProfileTest::testInstaller
Behat\Mink\Exception\ExpectationException: The field "date_default_timezone" value is "Africa/Abidjan", but "America/Los_Angeles" expected.

and

Drupal\FunctionalTests\Installer\InstallerTest::testInstaller
Failed asserting that null matches expected 'Australia/Sydney'.

This is looking very close though! :)

phenaproxima made their first commit to this issue’s fork.

narendrar’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new2.21 KB

The 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 necessarily 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.

narendrar’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new2.21 KB

The 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 necessarily 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.

phenaproxima’s picture

Status: Needs work » Needs review

No, bot, it does not need work.

phenaproxima’s picture

Status: Needs review » Needs work

Only one tiny comment, then I don't really see a problem here.

narendrar’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new2.21 KB

The 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 necessarily 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.

wim leers’s picture

#3439439: Remove country setting from the installer landed today! It conflicts with this MR.

I don't see how this could land without at least an update path — fortunately it's a trivial one! I suspect we'll also need explicit tests for \Drupal\system\Form\RegionalForm.

narendrar’s picture

Status: Needs work » Needs review
Issue tags: -Needs update path, -Needs update path tests, -Needs tests
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily 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.

phenaproxima’s picture

Status: Needs work » Needs review
Issue tags: +no-needs-review-bot
wim leers’s picture

Good progress!

In the final stretch to the finish line now :)

Problems I spotted in review:

  1. validation of timezone.user.default is misleading — easily fixed 👍
  2. form test coverage is giving a false sense of security — it should be a functional test, not a kernel test

P.S.: please push #2951046: Allow parsing and writing PHP class constants and enums in YAML files forward so that we can land #3402178: [PP-1] Enum cases stored in config — that'd make validation of timezone.user.default in this issue simpler/more maintainable/clearer. It'd also help many other (config) validation issues!

narendrar’s picture

Status: Needs work » Needs review
phenaproxima’s picture

Status: Needs review » Needs work

Some minor points, but this generally looks pretty good to me.

narendrar’s picture

Status: Needs work » Needs review
phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Ship it!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

\Drupal\system\Form\RegionalForm::getEditableConfigNames can be removed and the form can use \Drupal\Core\Form\RedundantEditableConfigNamesTrait now.

narendrar’s picture

Status: Needs work » Needs review
wim leers’s picture

Status: Needs review » Reviewed & tested by the community

3 nits, one of which seems indisputably an improvement, so applied that. The other 2 I'll leave to the core committer reviewing this.

Other than that: looks great! 😊

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I don't think we should be suing static methods and \Drupal::service - see MR comments.

Also do we have any BC concerns about moving from empty string to NULLs?

phenaproxima’s picture

Status: Needs work » Needs review
wim leers’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs change record

https://git.drupalcode.org/project/drupal/-/merge_requests/7271/diffs?co... → 🤩

Too bad you reverted and went with a custom constraint in the end. I think what you did originally would've been more broadly applicable.

OTOH … what you've done now is declarative and is easier to interpret on the client side! This is now essentially a validator for https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2. It's similar to Symfony's \Symfony\Component\Validator\Constraints\Country, but that depends on symfony/intl, which Drupal core does not use.

Conclusion: this change is 👍😄

P.S.: I think a change record to allow others to use the new CountryCode validation constraint would be great 😊 But that can easily happen post-commit.

phenaproxima’s picture

Too bad you reverted and went with a custom constraint in the end

Yeah, I was disappointed I had to revert also. But I realized that there was a very subtle bug in my original approach, just waiting to give somebody a splitting headache. The problem is that getAllCountryCodes() is not part of CountryManagerInterface. So the validation constraint was coupled to a non-interface service method.

If someone (or some module) swapped out core's CountryManager for a different implementation of CountryManagerInterface -- one without the validation method -- they would have run into some very obscure, hard-to-trace errors.

In light of that, I decided it was best to go with a custom constraint that wraps specifically around CountryManagerInterface::getList(), which is an interface method and therefore won't break if the implementation is swapped out.

I agree that making Choice aware of the callable resolver is likely to be useful in the future, and as soon as we have a concrete case for it, I'll happily restore it. :)

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I yhtink the test is in the wrong location. I suggested a kernel test but a unit test would work just as well i think

wim leers’s picture

Status: Needs work » Reviewed & tested by the community

#33 is a great point — it made swapping out the default implementation impossible indeed! 👍

The unit test @alexpott requested already passed, so re-RTBC'ing even before CI is completely done.

P.S.: change record? 🤞

phenaproxima’s picture

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 8cd02c7f00 to 11.x and 338d4d046a to 10.3.x. Thanks!

  • alexpott committed 338d4d04 on 10.3.x
    Issue #3437325 by narendraR, phenaproxima, alexpott, Wim Leers: Add...

  • alexpott committed 8cd02c7f on 11.x
    Issue #3437325 by narendraR, phenaproxima, alexpott, Wim Leers: Add...
wim leers’s picture

That was a deliberate choice on my part. If I used real country codes, there's an infinitesimally slim chance (maybe some accidental bad refactoring in the future) that we could be calling the real country manager, instead of the mock. Using fake country codes proves, unambiguously, that the mock was called.

Wow, excellent call, @phenaproxima! 👏

berdir’s picture

This breaks commerce hard, because it expects that country is a string, so this change results in a fatal error there atm. See #3173772: TypeError: Argument 1 passed to Drupal\commerce\Country::__construct() must be of the type string, null given. While it can easily be fixed there and the change makes sense anyway, instead of returning a Country object with an empty country string, this is still a pretty hard BC break.

wim leers’s picture

#42: I don't think that's entirely accurate; that module does something rather special: #3173772-15: TypeError: Argument 1 passed to Drupal\commerce\Country::__construct() must be of the type string, null given — it uses core config as if it was its own config (with schema it controls). I do not think that is a widespread practice?

If anything, after this (somewhat painful — although the changes in the module seem trivial) transition, any module doing something like this will have stronger guarantees after the value is being strictly validated: they'll know much more precisely what data to expect.

berdir’s picture

The combined usage with the strict type type is special, but using that config is not.

From your comment in the other issue:
> IOW: this is all caused by this module using core config as if it was this module's config.

That's not a thing. Drupal has the concept of a default country, and reading this config file is the only way to access it. There is no rule that you're not allowed to read config of other modules.

Using config like that is common. See https://git.drupalcode.org/search?group_id=2&scope=blobs&search=%22get%2...

https://www.drupal.org/about/core/policies/core-change-policies/bc-polic... is IMHO a bit confusing, as it then only lists composer related config, but I understand that as changing/removing config structure is covered by our BC policy.

wim leers’s picture

Drupal has the concept of a default country, and reading this config file is the only way to access it.

Hm, good point! 😬

What path forward do you propose?

berdir’s picture

> What path forward do you propose?

I don't know. The commerce issue has been fixed and will be available in a release soon. It's now in the alpha release, so I guess reverting this would just cause a bigger confusion. Might hit people trying out the alpha release, but nothing can be done about that at this point I guess except getting out a new commerce release out asap.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.