Validation in Drupal is tied to the Form API, we need a proper validation framework so that validation is defined by the objects/entities that needs to be validated, while still allowing the use of Constraints on FAPI.
This will allow validation when using:
- Validation of web service calls
- Node import, migrate
- Edit (Spark)
As discussed in #1696648: Untie entity validation from form validation, we have the options of rolling our own vs. using the Symfony validator component. Thanks to the help of Bernhard Schussek (bschussek) from symfony, integrating the symfony component works well now. So the proposal is to build upon that to implement validation for typed data, what covers entity validation. As a follow-up, we could then allow using symfony validation constraints directly from fapi also.
User interface changes
None for now. Typed data validation is something the API prepared for, but wasn't implemented yet. If we decide to use it as the only way to validate forms as a follow-up, that obviously would be a rather big API change.
The code is developed in the entity api improvements sandbox, under the validation and validation-symfony (only symfony component) branch. The issue for adding the symfony component is #1849564: Add the symfony validator component to core despite Symfony potentially releasing BC-breaking updates after 2.3., upon which the patches posted here build.
- Validation constraints can be defined in type data defintions below the 'constraints' key. If the data type specified already 'constraints' at its plugin definitions, those are applied as well. This will be important for further added data types like 'email', which should validate the value is an email.
- There is built-in validation support for all primitive types of the typed data API. The constraint is added automatically once the mapping to a primitive type is specifeid in the type plugin definition, e.g. if the 'email' type specifies it is a string, the PrimitiveType constraint will be added to check its a 'string' also.
- There are some general Drupal-specific validation classes which override symfony-classes for making violation messages translatable. Then, there are some typed data specific validator-metadata implementations which are needed for validating typed data. For implementing the symfony validation API for forms I'd expect us to implement similar classes for forms also, but that can be investigated further in a form follow-up issue.
- Typed data constraints shoud be moved below the TypedData component, what requires #1828616: AnnotatedClassDiscovery is not finding plugins in Drupal\(Core|Component)\COMPONENT_NAME\Plugin directory to be fixed first.
- The typed data manager should be handled as proper dependency in the typed data classes. I'd prefer to not do that in this patch though as it would just result in conflicts with #1778178: Convert comments to the new Entity Field API. Let's better handle it over there or in a separate follow-up.
- The patch changes how the primitive typed data objects deal with invalid values. Instead of throwing exceptions when an invalid data type is set, the value is just set. Instead, validation will fail afterwards. This means, that you can only really rely on typed data definitions to apply if validation gives you a green light, but I think that's reasonable.
- Validation constraint plugins are currently not namespaced. For core, that might make sense to do in order to provide a better DX. It's easy to avoid name clashes from inside core, however modules would have to properly prefix their constraint plugin ids.
- Translation violation messages is figured out at #1853096: Integrate symfony validation violations with Drupal translation.
- Implement translating violation messages as discussed at #1853096: Integrate symfony validation violations with Drupal translation
- Add in plugin definitions for all Symfony validation constraints that are useful for us.
- Use it to implement #1696648: Untie entity validation from form validation
- Make sure validation groups are supported by our metadata classes
- Implement validation of the uri type to accept all URIs as specified by the RFC.
- Allow using symfony validation constraints for form validation
- Allow configuring validation constraints via field UI
- Various cleanups of the TypedDataManager/Factory and base classes. #1899950: Make TypedData plugins conform better to the Plugin Interfaces
Original report by attiks
Since there are only 10 days left before feature freeze, I would love to know what has to be committed before December 1st and what is allowed to be added/done after December 1st. I can make time to work on this, but only if I know this has a chance to be added to Drupal 8, otherwise I probably can spent my time on other issues.
As discussed in #1696648: Untie entity validation from form validation, we have to options:
- Use the Symfony validator component, but this is designed to work using metadata about a class, not with an instance, a widget or a form not tight to an entity. Bernhard Schussek (bschussek) is investigating how it can be changed so we can use it.
- Roll our own framework, a starting patch can be found in #1696648: Untie entity validation from form validation, it supports everything from the list below except 6 and 8
We need to be able to specify Constraints on
- TypedData definitions (ex: Drupal\Core\TypedData\Type\Integer can only containts NULL or an integer)
- Field definitions (ex: an integer field only accepts numbers)
- Entity definitions (ex: a node needs a title)
- Form API, for forms/form elements not tight to an entity (ex: captcha)
- Field instance (ex: a user reference can only reference certain roles)
- Field widgets (ex: a user reference field accepts a user name as input, but stores an integer)
- Constraints need to be translatable
- Allow easy transfer of the Constraints to the client side
- Create Constraints (plugins) so they can be used as a class and using the drupal_container, a constraint defines a condition that has to be checked like required, integer, range, ... Some are already provided, but creating all of them will take some time.
- Alter the definition of TypedData and Fields to use those Constraints, this is already done in the patch
- Remove the validation of TypedData and Field, this removes the existing implementation of the validation and is basically cleanup
- Alter core/modules/field_ui/field_ui.admin.inc so a user can select constraints on a field instance, the patch includes part of this, but it needs to be further extended with a form so people can enter some data needed for a constraint. Example: the min_integer constraint allows you to define a minimum value for an integer field, the user has to enter that value in the field instance settings form.
- Remove the validation of Field Widgets, this is cleanup, it removes all existing settings related to validation
- Change drupal_get_form so it supports Constraints on custom forms, the patch only addresses forms build using a form controller, this needs to be extended so we can support custom forms, not tight to an entity, as well.
- Allow custom binding between FAPI and entity, for the moment the patch assume that the form api key is the name of the field, but this isn't always acceptable, so we should allow people to specify which form api element is bound to which field of an entity
User interface changes
Field admin UI will change, the interface for constraints/validation will be made more uniform and easier to extend.
Yes, but most of it is new. The goal is to remove all form_validation except for specific things that can not be done by a constraint.
For the moment the idea is to make the validation phase optional, it will not be enforced when calling save() on an entity, it's only enforced during form_validate (like it is now).
#required can be converted to a Constraint (but will not cease to exist)
#maxlength can be converted to a Constraint (but will not cease to exist)
Most of the #element_validate can be replaced by constraints
Most of the #validate
_form_validate can be simplified
- #1696648: Untie entity validation from form validation
- #1797438: HTML5 validation is not fully accessible
- #742344: Allow forms to set custom validation error messages on required fields
- #1493324: Inline form errors for accessibility and UX
- #52051: Validation API/UI
- #471264: Consistently name validation/sanitation functions
- #478758: DX: Allow ordering of #validate and #submit callbacks
- #1829420: Validate #required, #maxlength and #options in standard #element_validate handlers
- #567104: Should entities perform field validation if FAPI validation fails?
- #1218814: PDOException because of incorrect validation of number fields
- #93447: Deleting the first value in a required, multivalue field fails validation
- #57518: drupal 4.8: need to decouple node validation from forms
- more: http://drupal.org/project/issues/drupal?text=validate&version=8.x