Problem

For being able to solve #2395831: Entity forms skip validation of fields that are not in the EntityFormDisplay (critical) we need to be able to define general, entity-level validation constraints, which run regardless of which fields are being edited. Our use case in core is the "changed" validation, which needs to be converted. Further possible uses could be constraints for #2105797: Add CompositeConstraintBase so that constraints involving multiple fields, such as CommentNameConstraint, can be discovered.

Proposed resolution

  • Allow defining entity level constraints via the entity type annotation (as it works for data types)
  • Allow defining entity level constraints per hook: hook_entity_type_build()
  • Allow altering entity level constraints hook_entity_type_alter()
  • Extend the ContentEntityType object with a getConstraints() method
  • Apply entity constraints by defining type constraints at the EntityDeriver or in EntityDataDefinition::getConstraints()
  • Remove the EntityType and Bundle constraints from entity objects as they're already added by EntityDataDefinition::{setEntityTypeId|setBundle}
  • Do not add the constraints of referenced data in in TypedDataManager::getDefaultConstraints any more - not all of those constraints might be relevant for validating the referenced data is right, but might validate the data itself. Instead just add constraints to the the data reference property (entity, language) directly, what will now work nicely as the passed on data is always the same.

Remaining tasks

Do it.

User interface changes

-

API changes

  • EntityTypeInterface gets extended with methods to add,set,get constraints. As the EntityType implements those methods, this is a non-issue for everyone using the provided class.

Allow adding entity level constraints for general validation logic that should run for all changes (e.g. entity changed validation)

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue priority Critical because it's required for solving a critical bug: #2395831: Entity forms skip validation of fields that are not in the EntityFormDisplay
Disruption Very minor as it's highly unlikely someone would run in the API change.

Comments

fago’s picture

Issue summary: View changes
fago’s picture

Issue summary: View changes

ok, here a proposal:

Use the same process as for defining base fields:

  • Allow defining entity level constraints via a static method on the Entity class: ContentEntityBase::entityConstraints()
  • Allow defining entity level constraints per hook: hook_entity_constraints($entity_type)
  • Allow altering entity level constraints hook_entity_constraints_alter($entity_type, array $constraints)
  • Add a method to get entity constraints on the EM: getEntityConstraints($entity_type)
  • Add entity constraints via defining type constraints at the EntityDeriver or in EntityDataDefinition::getConstraints()

Early feedback welcome!

(added that to the issue summary)

fago’s picture

What I've been wondering whether we should stress that you use constraint definitions (arrays) and not plugin instances in those hooks/methods by naming them:
ContentEntityBase::entityConstraintDefinitions()
hook_entity_constraint_info()
hook_entity_constraint_info_alter()
EM::getEntityConstraintDefinitions()

On the other hand, we already have EM::getDefaultConstraints() and Field/DataDefiniton::getConstraints() not using the definition term in code, but return constraint definitions as well.

yched’s picture

Last item in the propsed resolution:

Add entity constraints via defining type constraints at the EntityDeriver or in EntityDataDefinition::getConstraints()

I don't think I got that one :-)

fago’s picture

Data types (typed data) can define constraints in their type definition below the 'constraints' key. Those are added in for the respective type by default via TDM::getDefaultConstraints() - thus that would be a way to add our constraints in. We'd probably have to do that per bundle tough, as those have another type (entity:node:page) - so it would be probably only viable if we can do it such that the constraint arrays would remain untouched, and so equal and so serialized only once. If that doesn't work out we can still add them in via EntityDataDefinition::getConstraints() in which case the constraints wouldn't be returned from TDM::getDefaultConstraints() though.

klausi’s picture

Sounds good, I have no better idea. We could also use the convention to add entity constraints to the ID field of the entity in baseFieldDefinitions(), but an explicit method is probably better.

larowlan’s picture

A lot of static entity-type definitions are handled in the annotation - is there scope to allow definition of entity-level constraints there too?

larowlan’s picture

Also, willing to help here - assume you're working on it because of the assigned field, but count me in for helping.

fago’s picture

A lot of static entity-type definitions are handled in the annotation - is there scope to allow definition of entity-level constraints there too?

oh yes, I did not think of that! That's a really interesting idea and would be inline with how it works for data types. Then, this becomes part of the the entity definition and can be extended + altered via that. Less hooks, same functionality - seems to be better choice to me :-)

Also, willing to help here - assume you're working on it because of the assigned field, but count me in for helping.

Great, thanks! I'm in IRC and will unassign me when I stopped actively working so you can help out! :-)

larowlan’s picture

Thanks, will keep an eye on the issue

fago’s picture

Issue summary: View changes

Updated proposed resolution based on larowan's suggestion.

fago’s picture

Assigned: fago » berdir
Status: Active » Needs review
StatusFileSize
new10.5 KB
new10.5 KB

Here is a first patch implementation that. It covers defining the constraints and adds test coverage for that. Missing is now the part of adding the constraints in (last bullet point of the suggestion).

Unfortunately, I stumbled over some cache clearing troubles in the entity unit test, so I had to add the hunk in the default plugin manager to make it work. Please review.

Besides that, I think we should make the entity system automatically add in the general EntityChanged constraint if the entity type implements the respective interface as it won't come with the field any more.

The last submitted patch, 12: d8_entity_validate_general.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 12: d8_entity_validate_general.patch, failed testing.

fago’s picture

Assigned: berdir » Unassigned
larowlan’s picture

Assigned: Unassigned » larowlan
larowlan’s picture

Status: Needs work » Needs review
StatusFileSize
new2.89 KB
new10.38 KB

fails were because of changes to default plugin manager.
reverted those and fixed the root of the issue, calling enableModules builds a new container, so the $this->entityManager refers to a different object from that point on (yay for simpletest).

kim.pepper’s picture

Minor nitpick:

+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -159,6 +159,7 @@ public function getDefinitions() {
+

Accidental?

larowlan’s picture

StatusFileSize
new543 bytes
new9.85 KB

full revert (fixed #18)

fago’s picture

reverted those and fixed the root of the issue, calling enableModules builds a new container, so the $this->entityManager refers to a different object from that point on (yay for simpletest).

Good catch, thanks. The problem in DefaultPluginManager remains though, it doesn't clear caches if the injected cache backend isn't registered in the container. That's another issue though.

larowlan’s picture

Assigned: larowlan » Unassigned

Anything else need doing here?

fago’s picture

Well, first of we need to make sure constraints are applied - attached patch does so.

Moreover, I think the following is left here:
- We need to remove the EntityChanged constraint from the field. Instead, I'd suggest to add logic somewhere that adds in the EntityChanged constraint automatically if the EntityChangedInterface is implemented. E.g., in EntityManager::processDefinitions() ? Then, this needs test-coverage.
- I think we should better move getContraints() to EntityType instead of the ContentEntityType, as FieldableEntityInterface has validate(), so non-content entities could want to specify constraints as well. For other variants of entities like config entities that do not support entity validation there wouldn't be any harm, so I guess it's better that way.

fago’s picture

StatusFileSize
new14.46 KB

ops - this is the correct patch file, interdiff was right.

The last submitted patch, 22: d8_entity_validate_general.patch, failed testing.

larowlan’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php
    @@ -83,7 +84,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
    -        'constraints' => array('EntityType' => $entity_type_id),
    +        'constraints' => $entity_type instanceof ContentEntityTypeInterface ? $entity_type->getConstraints() : [],
    

    Are we losing the 'EntityType' constraint here?

  2. +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php
    @@ -91,10 +92,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
    -            'constraints' => array(
    -              'EntityType' => $entity_type_id,
    -              'Bundle' => $bundle,
    -            ),
    +            'constraints' => $this->derivatives[$entity_type_id]['constraints']
    

    Same - are we losing the Bundle here?

fago’s picture

The constraints were necessary at some point here at the time where entity:node:page wasn't automatically adding those constraints, but EntityDataDefinition does so meanwhile - so they'll be there still. Anyway, validation them does not give us much as they cannot fail validation: The data type is derived from the entity object, therefor the entity object cannot be of a wrong type.

jibran’s picture

+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
@@ -22,7 +24,9 @@ class EntityChangedConstraintValidator extends ConstraintValidator {
+      // @todo: Once the EntityChanged constraint is completely moved to the
+      // entity level, remove the if clause.

Do we have an issue for this?

fago’s picture

Assigned: Unassigned » fago

yes, this one. :-)

klausi’s picture

Status: Needs review » Needs work

Cool, otherwise this looks good, I'm glad larowlan had the idea to have this in the entity annotation :-)

fago’s picture

Assigned: fago » Unassigned
Status: Needs work » Needs review
StatusFileSize
new16.83 KB
new16.77 KB

ok, took care of the remaining points as described in #22 and improved docs a bit. The EntityTypeConstraintTest covers testing that the EntityChanged constraint is added automatically also, just as making sure it applies and works.

Besides that, there is NodeValidationTest covering changed validation and #2142993: Test for EntityChangedConstraintValidator for having a dedicated test case also. Meanwhile, having it covered per EntityTypeConstraintTest and NodeValidationTest should suffice imo.

jibran’s picture

Perfect let's wait for bot.

Status: Needs review » Needs work

The last submitted patch, 30: d8_entity_validate_general.patch, failed testing.

fago’s picture

The entity reference now adds in the EntityChanged constraints as well, what is just wrong as it should only validate that the right entity is set, but not start validating the entity which is referenced. So this is related to #2346373: Data reference validation constraints are applied wrong now.

fago’s picture

Updated #2346373: Data reference validation constraints are applied wrong with a plan to solve it.

For this issue only the following point would be required:

- Do not add the constraints of referenced data in in TypedDataManager::getDefaultConstraints any more - not all of those constraints might be relevant for validating the referenced data is right, but might validate the data itself. Instead just add constraints to the the data reference property (entity, language) directly, what will now work nicely as the passed on data is always the same.

Thus, I'd propose to do that here and leave the rest to the other issue. Still, the rest of #2346373: Data reference validation constraints are applied wrong would improve DX here as it would make the system pass $entity instead of $typed_entity to the validators.

fago’s picture

Assigned: Unassigned » fago
fago’s picture

Assigned: fago » Unassigned
Status: Needs work » Needs review
StatusFileSize
new22.37 KB
new5.54 KB

Implemented #34. Also, quick edit needed to be converted to run entity level constraints also - did so. We'll have to fix it to follow the same approach as complete entity forms in #2395831: Entity forms skip validation of fields that are not in the EntityFormDisplay.

Status: Needs review » Needs work

The last submitted patch, 36: d8_entity_validate_general.patch, failed testing.

klausi’s picture

+++ b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
@@ -148,14 +160,17 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
+    // Run entity-level validation as well, while skipping validation of all
+    // fields. We can do so by fetching and validating the entity-level
+    // constraints manually.
+    // @todo: Improve this in https://www.drupal.org/node/2395831.
+    $typed_entity = $entity->getTypedData();
+    $violations = $this->typedDataManager
+      ->getValidator()
+      ->validateValue($typed_entity, $typed_entity->getConstraints());

So the only purpose of $this->typedDataManger in this class is to spit out the validator? Then you should inject the validator in the first place. Or do you assume that we will use the typed data manager for more stuff later?

And why do you pass $typed_entity to validateValue()? In that method you then get the entity again, so this looks like useless typed data switching back and forth? Please add a comment.

Otherwise looks good.

fago’s picture

So the only purpose of $this->typedDataManger in this class is to spit out the validator? Then you should inject the validator in the first place. Or do you assume that we will use the typed data manager for more stuff later?

Possibly yes, but also the validator is no service but instantiated for each validation.

And why do you pass $typed_entity to validateValue()? In that method you then get the entity again, so this looks like useless typed data switching back and forth? Please add a comment.

Because it works with $typed_entity only - validation work on typed data level and thus requires the typed data object as value. Not sure what you mean with switching back and forth, the $typed_entity is retrieved and used from there? What exactly is here unclear or not logical?

fago’s picture

Status: Needs work » Needs review

I've created a patch for #2346373: Data reference validation constraints are applied wrong also, which is related (see #33,34) to this issue and makes entity-level constraints to receive $entity instead of $typed_entity. If it's ready in time, we might want to get it in first, so we end up with proper DX for entity-level constraints from the beginning here?

klausi’s picture

Status: Needs review » Needs work

But we can just inject the validator instead of the TypedDataManager in QuickEditFieldForm.php, correct? We would do

$container->get('typed_data_manager')->getValidator()

in the create() method.

I didn't realize that we always have to pass typed data objects to the validator, so I think that's fine and #2346373: Data reference validation constraints are applied wrong can take care of the receiving end in the constraint classes, we don't have to do that here (not critical).

larowlan’s picture

Assigned: Unassigned » larowlan

working on #42

larowlan’s picture

Assigned: larowlan » Unassigned
Status: Needs work » Needs review
StatusFileSize
new2.91 KB
new22.36 KB

Fixes #42

Status: Needs review » Needs work

The last submitted patch, 44: entity-constraints.44.patch, failed testing.

fago’s picture

But we can just inject the validator instead of the TypedDataManager in QuickEditFieldForm.php, correct?

As said in #40, the validator is usually instantiated per validation, but from looking at the code it should be ok to re-use it for multiple validations also.

ad #44: Looks like you type-hint on the wrong interface?

larowlan’s picture

Status: Needs work » Needs review
StatusFileSize
new22.35 KB
new638 bytes

doh, two ValidatorInterfaces

effulgentsia’s picture

The basic approach here looks good to me.

  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php
    @@ -83,7 +84,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
    -        'constraints' => array('EntityType' => $entity_type_id),
    ...
    -            'constraints' => array(
    -              'EntityType' => $entity_type_id,
    -              'Bundle' => $bundle,
    -            ),
    ...
    +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
    @@ -400,10 +400,6 @@ public function getDefaultConstraints(DataDefinitionInterface $definition) {
    -    // Add any constraints about referenced data.
    -    if ($definition instanceof DataReferenceDefinitionInterface) {
    -      $constraints += $definition->getTargetDefinition()->getConstraints();
    -    }
    

    Maybe I missed something, but I don't see where these are moved to. If they're being removed entirely, can the reason for that be added to the issue summary?

  2. +++ b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
    @@ -148,14 +160,16 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
    -    if ($changed_field_name = $this->getChangedFieldName($entity)) {
    

    Let's delete the getChangedFieldName() method while we're at it.

larowlan’s picture

Issue summary: View changes
StatusFileSize
new907 bytes
new22.96 KB

Fixes #48.2
Added comments to IS about 48.1, I'd asked the same thing earlier - the answer is they're already added by EntityDataDefinition::{setEntityTypeId|setBundle}.

effulgentsia’s picture

Cool. Thanks. What about the last part of #48.1?

+++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
@@ -400,10 +400,6 @@ public function getDefaultConstraints(DataDefinitionInterface $definition) {
-    // Add any constraints about referenced data.
-    if ($definition instanceof DataReferenceDefinitionInterface) {
-      $constraints += $definition->getTargetDefinition()->getConstraints();
-    }

Looks like this patch changes EntityReferenceItem to add explicit constraints for entity type and bundle, but this code was applying all target constraints (which could have included more than that) to a reference item. What's the reason for us no longer wanting that? I guess it's because something like EntityChanged only makes sense on the target and not on the reference? And that by similar logic we think the same will be true for all other entity-level constraints? But I'm a bit fuzzy on that, so having it spelled out in the issue summary would be helpful.

larowlan’s picture

Issue summary: View changes

RE #50 please see #34 and #2346373: Data reference validation constraints are applied wrong (relevant parts are in this issue).

Updated IS

yched’s picture

It feels right to not automatically reflect the constraints of the referenced entity higher up in the reference field, in the case of referenced entities that already exist.
However, not sure how an autocreated entity ever gets validated ?

klausi’s picture

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

I think we should move all entity reference discussion to #2346373: Data reference validation constraints are applied wrong.

The code looks RTBC to me now, thanks!

I think we need a change notice for this, explaining the differences how it was done in D7 and now in D8. The EntityChanged use case for nodes seems like a good example.

fago’s picture

However, not sure how an autocreated entity ever gets validated ?

Good question. The auto-create functionality should probably take care of that and add constraint for it. However, I don't think this works right now either as it doesn't call $reference->entity->validate() - thus this should probably be its own (probably uncritical) issue.

jibran’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -89,12 +89,17 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel
-      ->setTargetDefinition(EntityDataDefinition::create($settings['target_type']));
+      ->setTargetDefinition(EntityDataDefinition::create($settings['target_type']))
+      ->addConstraint('EntityType', $settings['target_type']);
...
-      $properties['entity']->getTargetDefinition()->addConstraint('Bundle', $settings['target_bundle']);
+      $properties['entity']->addConstraint('Bundle', $settings['target_bundle']);
+      // Set any further bundle constraints on the target definition as well,
+      // such that it can derive more special data types if possible. For
+      // example, "entity:node:page" instead of "entity:node".
+      $properties['entity']->getTargetDefinition()
+        ->addConstraint('Bundle', $settings['target_bundle']);

Would anyone like to help me in fixing this for DER?
Thanks.

fago’s picture

Added the draft: http://drupal.org/node/2438011

@jibran: There shouldn't be anything that you have to change for keeping it working as now, but for adding any further validation constraints to the reference just add them directly to the 'entity' property and you should be good. As discussed on IRC, you might have to make the EntityType constraint to support multiple values first though.

fago’s picture

Status: Needs work » Needs review
fago’s picture

jibran’s picture

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

RTBC as per #53

fago’s picture

Issue summary: View changes
fago’s picture

Added beta evaluation. #2346373: Data reference validation constraints are applied wrong got a bit side-tracked by discussion, so it might be better to not wait for it. However, this means that #2346373: Data reference validation constraints are applied wrong would change the API of this later :/

fago’s picture

Title: Allow adding entity level constraints » [PP1] Allow adding entity level constraints
Status: Reviewed & tested by the community » Postponed

Discussed with alexpott on IRC on how to handle #61 best. We agreed to better avoid such an API change and make sure #2346373: Data reference validation constraints are applied wrong gets in first + postpone this on it.

effulgentsia’s picture

Title: [PP1] Allow adding entity level constraints » [PP-1] Allow adding entity level constraints
effulgentsia’s picture

Tagging for triage as to whether it's critical, because I'm not completely clear on whether this is a hard-blocker for #2395831: Entity forms skip validation of fields that are not in the EntityFormDisplay. In the case of the EntityChanged constraint, why is it better for that to be an entity-level constraint vs. allowing field-level constraints to specify whether they should be applied always vs. only-when-changed? There's probably reasons that the former is better than the latter, just wanting clarity on what they are.

fago’s picture

In the case of the EntityChanged constraint, why is it better for that to be an entity-level constraint vs. allowing field-level constraints to specify whether they should be applied always vs. only-when-changed?

  • Constraints should only validate data at the level they are put at, i.e. entity changed validation requires the whole entity object to fetch it's id and load the unchanged data - so putting it at field level would violate that rule. (It's only our API having $field->getEntity() that makes it even possible to do that). The rule makes not only sense for clarity, but moreover it is important to make sure no constraints are missed as the validator skips drilling down the tree for empty fields. Thus, "always" validated constraints on field items or field item properties of empty fields would not work.
  • Composite constraints need to run on entity-level for being able to put violation messages on multiple paths, e.g. for showing good errors on both field form elements or for generating different violations per cause.
  • While a "validate-always" marker would work as solution for things like EntityChanged constraints, it wouldn't suffice for composite constraints. Thus, there we'd still have to implement the path-based solution and take the constraints into account depending on the fields covered. Given that, it doesn't seem viable to implement two solutions (path-based + always marked fields) for a single problem if one of both solutions (path based) can address it alone.
jibran’s picture

Title: [PP-1] Allow adding entity level constraints » Allow adding entity level constraints
Status: Postponed » Needs work
yesct’s picture

@jibran yes, since #2346373: Data reference validation constraints are applied wrong went in, this issue is not postponed anymore, and I think work here can start again.

fago’s picture

Status: Needs work » Needs review
StatusFileSize
new23.14 KB
new1.29 KB

Great! I re-rolled the previous already RTBC patch to account for entities being passed to the validator now.

Status: Needs review » Needs work

The last submitted patch, 69: d8_entity_constraints.patch, failed testing.

fago’s picture

Status: Needs work » Needs review
StatusFileSize
new23.13 KB
new800 bytes

The temporary fix for QuickEditForm validation needs to be updated as well, done so.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
@@ -19,14 +18,13 @@ class EntityChangedConstraintValidator extends ConstraintValidator {
-  public function validate($value, Constraint $constraint) {
-    if (isset($value)) {
-      /** @var $entity \Drupal\Core\Entity\EntityInterface */
-      $entity = $this->context->getMetadata()->getTypedData()->getEntity();
+  public function validate($entity, Constraint $constraint) {
+    if (isset($entity)) {
+      /** @var \Drupal\Core\Entity\EntityInterface $entity */

Love this change magic++

jibran’s picture

For #55 we have #2405467: Add EntityType and Bundle constraint on entity property of DynamicEntityReferenceItem in DER issue queue. @fago it would be great if you could share some thoughts over there. Thanks for all the help in IRC and the work on this patch.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

The CR needs to be updated now that #2346373: Data reference validation constraints are applied wrong has landed.

Re #54 - did the non-critical followup for auto created entities get created?

diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php
index 7cea3c8..76decd9 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\Entity\Plugin\DataType\Deriver;
 
-use Drupal\Core\Entity\ContentEntityTypeInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
diff --git a/core/modules/quickedit/src/Form/QuickEditFieldForm.php b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
index bdf058f..2db50c4 100644
--- a/core/modules/quickedit/src/Form/QuickEditFieldForm.php
+++ b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\quickedit\Form;
 
-use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityChangedInterface;

The removed use statements above can be removed due to this patch.

dawehner’s picture

Re #54 - did the non-critical followup for auto created entities get created?

Yes it was, see #2438017: Entity reference does not validate auto-created entities

fago’s picture

Status: Needs work » Needs review
StatusFileSize
new23.07 KB
new1.13 KB

- Update the CR draft.
- Re-rolled with #74 addressed. Fortunately alexpott is really great in catching those deprecated use statements :-)

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

- Re-rolled with #74 addressed. Fortunately alexpott is really great in catching those deprecated use statements :-)

I'm still envy for the fabpot being able to automatically detect those problems, as well as CS problems.

Back to RTBC

stefan.r’s picture

@fago there seems to be a lot of overlap between this issue and #2142993: Test for EntityChangedConstraintValidator, should we close the other issue as a duplicate?

As EntityTypeConstraintsTest in this patch does essentially all the things EntityChangedConstraintValidatorTest does in the other issue...

fago’s picture

ad #78: I think it makes a lot of sense to have a dedicated test case per constraint and making sure all cases are covered there - even if the constraint is used in some other general test case as here. It will need a re-roll once this lands though.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed a23ebe2 and pushed to 8.0.x. Thanks!

  • alexpott committed a23ebe2 on 8.0.x
    Issue #2429037 by fago, larowlan: Allow adding entity level constraints
    
stefan.r’s picture

just a quick follow-up question re #79: it seems we cannot do EntityChanged constraint validation on the changed field itself now (Ie $entity->changed->validate()). This is how we want it?

fago’s picture

Yeah, that's fine imo. What we really validate is the whole entity not being changed in the meantime, not the value of the field on its own.

Status: Fixed » Closed (fixed)

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

wim leers’s picture

This caused a regression in Quick Edit: #2475483: Cannot quickedit an image or date field

yched’s picture

Help welcome in #2064191-22: Fix the 'target_bundle' field setting - 'target_bundles' are not validated when entity_reference is enabled :-)

Basically, ER field 'target_bundles' setting really lives on the FieldDefinition level, and the one still present as a FieldStorage-level setting is just a decoy at this point.

That issue over there is trying to clean that up, and remove the dummy 'target_bundle' that still exists on the storage.

This means that the code that assigns the 'Bundle' constraint :

ERItem::propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    if (isset($settings['target_bundle'])) {
      $properties['entity']->addConstraint('Bundle', $settings['target_bundle']);
      // Set any further bundle constraints on the target definition as well,
      // such that it can derive more special data types if possible. For
      // example, "entity:node:page" instead of "entity:node".
      $properties['entity']->getTargetDefinition()
        ->addConstraint('Bundle', $settings['target_bundle']);
    }

cannot live there anymore (we don't know the field-level settings in ERItem::propertyDefinitions()), but needs to go in the runtime ERItem::getConstraints(). But there I have no clue how to set the *second* constraint (the one on $properties['entity']->getTargetDefinition()). It's also not clear to me why that second constraint is needed (as opposed to just the one directly on $properties['entity']) :-)