On Entity Reference validation, the current field value's parent entity isn't being submitted to the field handler. This could cause problems for handlers that configure the reference query based on the parent entity. It causes the initial query to not match the follow-up validation query.

Adding a patch to add the current value's parent entity to the handler on initialization.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

grathbone created an issue. See original summary.

Status: Needs review » Needs work

The last submitted patch, ValidReferenceConstraintValidator-parent-entity.diff, failed testing.

grathbone’s picture

Issue summary: View changes
grathbone’s picture

Added a check on the parent. Now passes in default NULL as a fallback.

grathbone’s picture

Status: Needs work » Needs review
Sam152’s picture

Status: Needs review » Needs work
Issue tags: -Entity Reference, -validation, -field validation, -entity +Needs tests

Removing the tags as per the guidelines: https://www.drupal.org/issue-tags. Generally not adding a tag unless aids discovery in a way that the other fields don't allow for. In this case we have the component, which I think covers it.

This fix makes total sense. Why not pass the entity through to the plugin manager if we have it. Small item of feedback:

+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
@@ -91,8 +91,14 @@ public function validate($value, Constraint $constraint) {

@@ -91,8 +91,14 @@ public function validate($value, Constraint $constraint) {
+    if ($value_parent = $value->getParent()) {
+      $value_parent_entity = $value_parent->getValue();
+    } else {
+      $value_parent_entity = NULL;
+    }
...
+    $handler = $this->selectionManager->getSelectionHandler($value->getFieldDefinition(), $value_parent_entity);

The FieldItemListInterface specifies:

  /**
   * Gets the entity that field belongs to.
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *   The entity object.
   */
  public function getEntity();

So I think it's safe to assume you'll always get an entity from ->getParent(). Thus I think we can simply pass $value->getParent() to $this->selectionManager->getSelectionHandler.

For me, this is right on the line for needing a test. It uses an API in a way which seems obviously more correct, but wondering if there is a test case which obviously exposes this as a bug we can use? We'd possibly need a test handler which uses the entity, but since it's an optional param, most handlers should work with NULL if possible anyway.

grathbone’s picture

@sam152

Check out the unit test results from my first patch, where getParent() does return NULL. And since getEntity() is just a wrapper method that calls $this->getParent()->getValue() anyway, it succumbs to the same fate.

Also, since the EntityFieldTest class does test the issue, I'm not sure we'd need to write another test.

The other option would be to use getEntity() and then do an IF-statement in the \Drupal\Core\Field\FieldItemList::getEntity() method.

Going to switch this back to Needs Review for further input.

grathbone’s picture

Status: Needs work » Needs review
amateescu’s picture

Status: Needs review » Closed (duplicate)
Issue tags: -Needs tests

I just RTBC'd a very similar patch in #2879918: Send entity to selection handler on validate., so I'm going to close this one as a duplicate.

@grathbone, thanks for the patch, I asked the core committers to credit you in that issue :)

grathbone’s picture

@amateescu Coolio. Thank you!