Problem/Motivation

#2164373: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs … proposed to start using validation constraints for validating all config entities.

One of the generic aspects of config entities is this:

config_entity:
  type: mapping
  mapping:
…
    dependencies:
      type: config_dependencies
      label: 'Dependencies'
…

which is defined as:

config_dependencies_base:
  type: mapping
  mapping:
    config:
      type: sequence
      label: 'Configuration entity dependencies'
      sequence:
        type: string
    content:
      type: sequence
      label: 'Content entity dependencies'
      sequence:
        type: string
    module:
      type: sequence
      label: 'Module dependencies'
      sequence:
        type: string
    theme:
      type: sequence
      label: 'Theme dependencies'
      sequence:
        type: string

config_dependencies:
  type: config_dependencies_base
  label: 'Configuration dependencies'
  mapping:
    enforced:
      type: config_dependencies_base
      label: 'Enforced configuration dependencies'

If validation constraints are written for this, then … all config entities will already have some validation! Plus, it will help make validation "complete" for config entity types whose specific validation constraints are already written (first in line: #3324140: Convert field_storage_config and field_config's form validation logic to validation constraints).

Proposed resolution

  1. Validate that only supported top-level dependency types are specified.
  2. Validate that dependencies.config dependencies actually exist
  3. … do the same for dependencies.content, dependencies.module and dependencies.theme
  4. Stop using type: string for every case where the value is not just any string but a particular kind of string

Bonus (because not sure if actually feasible): if a config entity type is known to depend on another config entity (for example: a field_config entity always needs a field_storage_config entity — at minimum), but it doesn't specify such a dependency, fail validation in that case too.

Note: dependencies.enforced.* should then "just work"! 😊

Remaining tasks

TBD

User interface changes

None.

API changes

None.

Data model changes

None.

Release notes snippet

Config dependencies now have validation constraints. These are not actively used by Drupal core, but will take effect as support is added for validating config entities at the data layer.

Issue fork drupal-3324150

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers created an issue. See original summary.

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

Wim Leers’s picture

Assigned: Unassigned » phenaproxima
Status: Active » Needs work

Review

Review posted. Looks fantastic IMHO 🤩 👏

Test failures

Looks like 99% of the failures are in Drupal\Tests\ckeditor5\Kernel\ValidatorsTest, which … sort of makes sense: it's the only other place in Drupal core that uses config entity validation. So in an unexpected way, that is the perfect proof that this indeed works across all Drupal config entities! 😄👍

However … since that file does not actually specify dependencies: […] anywhere … I think it's actually an edge case bug in the validator.
Turns out that var_dump(array_is_list([])); prints TRUE (see https://3v4l.org/fCJQ8) — meaning that dependencies: [] would also be considered invalid.
I think this is simply caused by \Drupal\Core\Entity\DependencyTrait::$dependencies, which looks like this:

  /**
   * The object's dependencies.
   *
   * @var array
   */
  protected $dependencies = [];

Next

What do you think about

Bonus (because not sure if actually feasible): if a config entity type is known to depend on another config entity (for example: a field_config entity always needs a field_storage_config entity — at minimum), but it doesn't specify such a dependency, fail validation in that case too.

?

Do you think it could be done? 🤓

phenaproxima’s picture

Status: Needs work » Needs review
Wim Leers’s picture

Epic progress here! 🤩

phenaproxima’s picture

Crediting Gábor for his assistance with removing the hook_config_schema_info_alter() implementations.

Wim Leers’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record

I think this issue represents a massive leap forward for #2164373: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs …! 🤩🚀

Last round of feedback on the MR, just to make this as future-ready as possible. And on that same note: we might want to add the RequiredConfigDependencies constraint to all core config entity types? 🤞

Finally, this definitely needs a change record before it can go in.

But … I think this is very close to RTBC 😊

phenaproxima’s picture

we might want to add the RequiredConfigDependencies constraint to all core config entity types?

Why would we do that? It's only there to validate config entities that have hard dependencies on other config entities, which (AFAIK) is not the case for most core entity types.

phenaproxima’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record
Wim Leers’s picture

CR looks great — but makes it sounds like config validation is actually being used already, but it's not. I think we should clarify that the validation constraints have been added, and test coverage is included, but it's not yet enabled — TBD in #2164373: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs … when it actually gets enabled.

Still have one important future-looking remark on the MR that I mentioned in #9 but failed to submit to the GitLab MR last night 🫣 Sorry!

Why would we do that? It's only there to validate config entities that have hard dependencies on other config entities, which (AFAIK) is not the case for most core entity types.

I of course meant only the ones that need it. I thought it was most of them!

And clearly that's not the case! 🤩

phenaproxima’s picture

Title: Validation constraint for validating config_entity.dependencies » Add validation constraints to config_entity.dependencies
Wim Leers’s picture

Assigned: phenaproxima » Unassigned
Status: Needs review » Reviewed & tested by the community
Issue tags: +blocker

The 5 generic validation constraints that this adds will come in handy when working to add validation constraints to specific config/config entity types — I already see uses for several in #3324140: Convert field_storage_config and field_config's form validation logic to validation constraints!

I can't believe how far this has come along in such a short time, thank you so much, @phenaproxima! I only needed to post suggestions and you then made it a reality 🤩

bnjmnm’s picture

Patch version in hopes of avoiding a cycle of tests complete + rebase required.

phenaproxima’s picture

Category: Task » Feature request

  • bnjmnm committed adfa35d on 10.1.x
    Issue #3324150 by phenaproxima, Wim Leers, Gábor Hojtsy: Add validation...
bnjmnm’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: +Needs release note

Went over this with @phenaproxima and @Wim Leers. This addition of more validation constraints is welcome and hope to see more in the future. Protecting config with validation constraints means we ultimately have more flexibility regarding how config gets updated, which can greatly improve headless.

It's possible that in an issue this size an edge case or two may have been missed in the validator implementations, but none appear to be the type that would result in false failures. I.e. this looks like a safe addition that can be optimized in followups if needed. Test coverage is good, and 👍 on putting Symfony to work.

Discussing this with @phenaproxima we thought it best to keep this to 10.1.x without backports.

phenaproxima’s picture

Added a release note.

idebr’s picture

The change record mentions:

⚠️ To be clear, this validation is not actually used yet in Drupal core. These changes will take effect as more and more config entities are converted to do validation at the data layer, rather than via the form system.

Does "This validation is not actually used" mean constraints are not actually validated when calling $configEntity->validate()?
If so, at what point will constraints be called?
And also: what is the point of adding constraints if these are not validated?

Wim Leers’s picture

@idebr: they are if you do call $config_entity->validate() … if that method even existed 🫣😅 That is how far removed we are from having validatable config entities. See the test coverage that was committed to find out how one can validate config entities today.

If so, at what point will constraints be called?

For sure when #2164373: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs … is complete.

And also: what is the point of adding constraints if these are not validated?

Like the change record indicates (but perhaps insufficiently clearly?): because we have to start somewhere, we can't commit a multi-megabyte patch that adds validation constraints to 100% of core's config schema's in one fell swoop.

Status: Fixed » Closed (fixed)

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

xjm’s picture

This was already added to the 10.1.0 release notes draft.

Wim Leers’s picture