Problem/Motivation

Vocabulary config entities are mostly validatable using the typed config system, but not quite. There is one property (weight) that are not yet validatable:

$ ./vendor/bin/drush config:inspect --filter-keys=taxonomy.vocabulary.tags --detail --list-constraints  --fields=key,validatability,constraints
➜  🤖 Analyzing…

 -------------------- ------------- ----------------------------------------------------------------- 
  Key                  Validatable   Validation constraints                                           
 -------------------- ------------- ----------------------------------------------------------------- 
  taxonomy.vocabular   92%           ValidKeys: '<infer>'                                             
  y.tags                                                                                              
   taxonomy.vocabula   Validatable   ValidKeys: '<infer>'                                             
  ry.tags:                                                                                            
   taxonomy.vocabula   Validatable   ValidKeys:                                                       
  ry.tags:_core                        - default_config_hash                                          
   taxonomy.vocabula   Validatable   NotNull: {  }                                                    
  ry.tags:_core.defa                 Regex: '/^[a-zA-Z0-9\-_]+$/'                                     
  ult_config_hash                    Length: 43                                                       
                                     ↣ PrimitiveType: {  }                                            
   taxonomy.vocabula   Validatable   ValidKeys: '<infer>'                                             
  ry.tags:dependenci                                                                                  
  es                                                                                                  
   taxonomy.vocabula   Validatable   Regex:                                                           
  ry.tags:descriptio                   pattern: '/([^\PC])/u'                                         
  n                                    match: false                                                   
                                       message: 'Labels are not allowed to span multiple lines or     
                                     contain control characters.'                                     
                                     ↣ PrimitiveType: {  }                                            
   taxonomy.vocabula   Validatable   NotNull: {  }                                                    
  ry.tags:langcode                   Choice:                                                          
                                       callback:                                                      
                                     'Drupal\Core\TypedData\Plugin\DataType\LanguageReference::getAl  
                                     lValidLangcodes'                                                 
                                     ↣ PrimitiveType: {  }                                            
   taxonomy.vocabula   Validatable   Regex:                                                           
  ry.tags:name                         pattern: '/([^\PC])/u'                                         
                                       match: false                                                   
                                       message: 'Labels are not allowed to span multiple lines or     
                                     contain control characters.'                                     
                                     NotBlank: {  }                                                   
                                     ↣ PrimitiveType: {  }                                            
   taxonomy.vocabula   Validatable   ↣ PrimitiveType: {  }                                            
  ry.tags:new_revisi                                                                                  
  on                                                                                                  
   taxonomy.vocabula   Validatable   ↣ PrimitiveType: {  }                                            
  ry.tags:status                                                                                      
   taxonomy.vocabula   Validatable   Uuid: {  }                                                       
  ry.tags:uuid                       ↣ PrimitiveType: {  }                                            
   taxonomy.vocabula   Validatable   Length:                                                          
  ry.tags:vid                          max: 32                                                        
                                     ↣ PrimitiveType: {  }                                            
                                     ↣ Regex:                                                         
                                       pattern: '/^[a-z0-9_]+$/'                                      
                                       message: 'The %value machine name is not valid.'               
   taxonomy.vocabula   NOT           ⚠️  @todo Add validation constraints to config entity type:      
  ry.tags:weight                     taxonomy.vocabulary.*                                            
 -------------------- ------------- ----------------------------------------------------------------- 

Remarks:

  1. There is a plan to deprecate weight, but that's an independent concern: #3008064: Deprecate vocabulary weight property
  2. The type for description is wrong in two ways: A) it currently is label and should be text, because multiple lines are allowed, B) the description is optional, just like it is for NodeType for example (see #3379091: Make NodeType config entities fully validatable and its change record), so it should be marked nullable: true and needs an update path to convert an empty string to NULL

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=announcements_feed--detail --list-constraints

Proposed resolution

  1. Add validation constraints.
  2. Mark FullyValidatable.
  3. Write update path + update path test

Remaining tasks

Review.

User interface changes

None.

API changes

description is no longer allowed to be the empty string ('') — vocabularies without a description must use null. Change record: https://www.drupal.org/node/3421927

Data model changes

None.

Release notes snippet

N/A

Issue fork drupal-2002174

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

Berdir’s picture

vocabularies are config entities now, not sure this is possible yet?

Berdir’s picture

Issue tags: +Entity Field API

Tagging anyway.

fago’s picture

Status: Active » Postponed
ianthomas_uk’s picture

This issue is part of a D8 critical meta, but is postponed against a D9 issue.

fago’s picture

Given entity validation works on typed data validation, we don't necessarily need entity fields to be able to use it. Given that I think this should be postponed on #1928868: Typed config incorrectly implements Typed Data interfaces.

effulgentsia’s picture

Priority: Normal » Critical
Berdir’s picture

I don't think this issue should be part of that meta anymore, while there might be possibilties to do validation, it's no longer a content entity and not special in any way compared to other config entities, so they should either be all in that meta or none of them.

effulgentsia’s picture

Title: Convert form validation of vocabularies to entity validation » Convert form validation of vocabularies to config validation
Priority: Critical » Major
Issue tags: -Entity Field API, -Entity validation +CMI, +config validation
Parent issue: #1696648: [META] Untie content entity validation from form validation » #2164373: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs …

Per #7.

xjm’s picture

xjm’s picture

Title: Convert form validation of vocabularies to config validation » Allow vocabularies to be validated via the API, not just during form submissions
xjm’s picture

So I'm not actually finding any validation logic in VocabularyForm that would be missing elsewhere; is this issue still relevant?

xjm’s picture

Issue tags: -CMI, -config validation +Configuration system
effulgentsia’s picture

So I'm not actually finding any validation logic in VocabularyForm that would be missing elsewhere; is this issue still relevant?

Good question. Looks to me like the last form validation of this was removed in #1978112: Convert taxonomy admin path to follow other core entity patterns, which landed 3 weeks before this issue was opened.

effulgentsia’s picture

A bit more info:

  • VocabularyForm::form() invokes protectBundleIdElement(), and that is also validated at the API level via ConfigEntityBundleBase::preSave().
  • VocabularyForm::form() sets the #maxlength of 'name' to 255, but I don't think anything validates that at the API level. I bet we have a similar lack of length validation for many configuration values throughout all of Drupal, but I don't know to what extent that's really a problem.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Wim Leers’s picture

Status: Postponed » Active

All blockers here have been solved years ago.

Since then, the Editor config entity when configured to use CKEditor 5 has become the first piece of complex configuration 100% validated via the API, not via form logic.

See my write-up at #2164373-23: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs ….

I think vocabularies are sufficiently simple that they'd be a great starting point for starting to convert all config entities in Drupal core to use validation constraints.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Wim Leers’s picture

Component: entity system » taxonomy.module
Issue tags: -Configuration system +Configuration schema, +validation

Wim Leers’s picture

I think tests will now pass. But we'll still need an update path test + actual update path logic.

There's nothing to update in VocabularyForm — there's zero validation in \Drupal\taxonomy\VocabularyForm::validateForm(). Besides, #3231342: [PP-2] Introduce ConfigEntityForm to standardize use of validation constraints for config entities will introduce the necessary infrastructure to make that simple and consistent.

Wim Leers’s picture

RE ::validateForm() being empty — @effulgentsia's #14 is relevant here:

A bit more info:

  • VocabularyForm::form() invokes protectBundleIdElement(), and that is also validated at the API level via ConfigEntityBundleBase::preSave().
  • VocabularyForm::form() sets the #maxlength of 'name' to 255, but I don't think anything validates that at the API level. I bet we have a similar lack of length validation for many configuration values throughout all of Drupal, but I don't know to what extent that's really a problem.

The first bullet was covered by #3382580: Add new `ImmutableProperties` constraint and solved this generically, for all config entity types 👍

The second bullet talks about the maximum length for the human-readable label for the vocabulary. That uses type: label which gained validation constraints in #3377030: Add validation constraint to `type: label`: disallow multiple lines and was refined in #3379102: Add validation constraint to `type: label` + `type: text`: disallow control characters. There is no technical limit to config entity labels at this time.

But there are things that need to be validated, as this issue's MR and VocabularyValidationTest's inherited test coverage shows.

So: consider @xjm's question in #11 addressed.

Wim Leers’s picture

Status: Active » Needs work

Green! Marking Needs work for update path.

Wim Leers’s picture

Issue summary: View changes
Issue tags: -Needs change record

Update path test added; should fail. CR created: https://www.drupal.org/node/3421927.

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs update path, -Needs update path tests

Update path test failed — just pushed the missing update path to make tests green 🥳

smustgrave’s picture

Status: Needs review » Needs work

Left some small comments.

fago’s picture

exciting to see this after soo many years!

I studied the MR and it seems mostly great, I found only one small remark (see above)

Wim Leers’s picture

Assigned: Unassigned » Wim Leers

Thanks for the reviews, both of you!

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Review Queue Initiative

Feedback appears to be addressed.

Should drop a comment on #3008064: Deprecate vocabulary weight property to make sure that todo gets removed.

Wim Leers’s picture

catch’s picture

Status: Reviewed & tested by the community » Needs work

One comment on the MR.

catch’s picture

I'm not convinced we should do #3008064: Deprecate vocabulary weight property and once this has landed that issue should be responsible for deprecations, so think we could just remove the @todo here.

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community

#47: 👍 closed that issue and re-activated its sibling to get it back on track: #1821274-20: Add back ability to sort on vocabulary weight and name.

Given that the feedback was trivial to address, self-re-RTBC'ing

  • catch committed 578a7ba1 on 10.3.x
    Issue #2002174 by Wim Leers, xjm, fago, effulgentsia, catch, smustgrave...

  • catch committed 1be0f07e on 11.x
    Issue #2002174 by Wim Leers, xjm, fago, effulgentsia, catch, smustgrave...
catch’s picture

Version: 11.x-dev » 10.3.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 11.x and cherry-picked to 10.3.x, thanks!

Wim Leers’s picture

Status: Fixed » Closed (fixed)

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