Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
entity system
Priority:
Critical
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
18 Feb 2015 at 20:01 UTC
Updated:
26 Sep 2015 at 20:03 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
fagoComment #2
fagook, here a proposal:
Use the same process as for defining base fields:
ContentEntityBase::entityConstraints()hook_entity_constraints($entity_type)hook_entity_constraints_alter($entity_type, array $constraints)getEntityConstraints($entity_type)EntityDeriveror inEntityDataDefinition::getConstraints()Early feedback welcome!
(added that to the issue summary)
Comment #3
fagoWhat 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()andField/DataDefiniton::getConstraints()not using the definition term in code, but return constraint definitions as well.Comment #4
yched commentedLast item in the propsed resolution:
I don't think I got that one :-)
Comment #5
fagoData 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.
Comment #6
klausiSounds 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.
Comment #7
larowlanA lot of static entity-type definitions are handled in the annotation - is there scope to allow definition of entity-level constraints there too?
Comment #8
larowlanAlso, willing to help here - assume you're working on it because of the assigned field, but count me in for helping.
Comment #9
fagooh 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 :-)
Great, thanks! I'm in IRC and will unassign me when I stopped actively working so you can help out! :-)
Comment #10
larowlanThanks, will keep an eye on the issue
Comment #11
fagoUpdated proposed resolution based on larowan's suggestion.
Comment #12
fagoHere 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.
Comment #15
fagoComment #16
larowlanComment #17
larowlanfails 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).
Comment #18
kim.pepperMinor nitpick:
Accidental?
Comment #19
larowlanfull revert (fixed #18)
Comment #20
fagoGood 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.
Comment #21
larowlanAnything else need doing here?
Comment #22
fagoWell, 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.
Comment #23
fagoops - this is the correct patch file, interdiff was right.
Comment #25
larowlanAre we losing the 'EntityType' constraint here?
Same - are we losing the Bundle here?
Comment #26
fagoThe 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.
Comment #27
jibranDo we have an issue for this?
Comment #28
fagoyes, this one. :-)
Comment #29
klausiCool, otherwise this looks good, I'm glad larowlan had the idea to have this in the entity annotation :-)
Comment #30
fagook, 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.
Comment #31
jibranPerfect let's wait for bot.
Comment #33
fagoThe 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.
Comment #34
fagoUpdated #2346373: Data reference validation constraints are applied wrong with a plan to solve it.
For this issue only the following point would be required:
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.
Comment #35
fagoComment #36
fagoImplemented #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.
Comment #39
klausiSo 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.
Comment #40
fagoPossibly yes, but also the validator is no service but instantiated for each validation.
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?
Comment #41
fagoI'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?
Comment #42
klausiBut we can just inject the validator instead of the TypedDataManager in QuickEditFieldForm.php, correct? We would do
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).
Comment #43
larowlanworking on #42
Comment #44
larowlanFixes #42
Comment #46
fagoAs 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?
Comment #47
larowlandoh, two ValidatorInterfaces
Comment #48
effulgentsia commentedThe basic approach here looks good to me.
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?
Let's delete the getChangedFieldName() method while we're at it.
Comment #49
larowlanFixes #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}.
Comment #50
effulgentsia commentedCool. Thanks. What about the last part of #48.1?
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.
Comment #51
larowlanRE #50 please see #34 and #2346373: Data reference validation constraints are applied wrong (relevant parts are in this issue).
Updated IS
Comment #52
yched commentedIt 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 ?
Comment #53
klausiI 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.
Comment #54
fagoGood 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.
Comment #55
jibranWould anyone like to help me in fixing this for DER?
Thanks.
Comment #56
fagoAdded 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.
Comment #57
fagoComment #58
fagoAlso created #2438017: Entity reference does not validate auto-created entities per our discussion.
Comment #59
jibranRTBC as per #53
Comment #60
fagoComment #61
fagoAdded 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 :/
Comment #62
fagoDiscussed 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.
Comment #63
effulgentsia commentedComment #64
effulgentsia commentedTagging 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.
Comment #65
fagoComment #66
effulgentsia commentedThis both blocks #2395831: Entity forms skip validation of fields that are not in the EntityFormDisplay and is required for secure web services, so adding a bunch of tags. Also, triaged based on same reasoning as #2105797-43: Add CompositeConstraintBase so that constraints involving multiple fields, such as CommentNameConstraint, can be discovered.
Comment #67
jibranComment #68
yesct commented@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.
Comment #69
fagoGreat! I re-rolled the previous already RTBC patch to account for entities being passed to the validator now.
Comment #71
fagoThe temporary fix for QuickEditForm validation needs to be updated as well, done so.
Comment #72
jibranBack to RTBC
Love this change magic++
Comment #73
jibranFor #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.
Comment #74
alexpottThe 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?
The removed use statements above can be removed due to this patch.
Comment #75
dawehnerYes it was, see #2438017: Entity reference does not validate auto-created entities
Comment #76
fago- Update the CR draft.
- Re-rolled with #74 addressed. Fortunately alexpott is really great in catching those deprecated use statements :-)
Comment #77
dawehnerI'm still envy for the fabpot being able to automatically detect those problems, as well as CS problems.
Back to RTBC
Comment #78
stefan.r commented@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...
Comment #79
fagoad #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.
Comment #80
alexpottThis 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!
Comment #82
stefan.r commentedjust 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?Comment #83
fagoYeah, 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.
Comment #85
wim leersThis caused a regression in Quick Edit: #2475483: Cannot quickedit an image or date field
Comment #86
yched commentedHelp 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 :
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']) :-)