diff -u b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php --- b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php +++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface; use Drupal\Core\Entity\EntityReferenceSelection\SelectionWithAutocreateInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\EntityReferenceFieldItemList; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Validator\Constraint; @@ -120,7 +121,23 @@ if (isset($entity->recursiveValidationRunning)) { continue; } - $violations = $entity->getTypedData()->validate(); + + if ($entity instanceof FieldableEntityInterface) { + // If the referenced entity has been validated somewhere else then + // we don't need to validate it again, as code validating the entity + // and leaving the validated flag set to TRUE is required of taking + // care of the errors. + if ($entity->isValidated()) { + continue; + } + else { + $violations = $entity->validate(); + } + } + else { + $violations = $entity->getTypedData()->validate(); + } + if ($violations->count() != 0) { // Concatenate the violations to show them as a single violation. $reasons = []; only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -464,6 +464,21 @@ public function validate() { return new EntityConstraintViolationList($this, iterator_to_array($violations)); } + /** + * {@inheritdoc} + */ + public function isValidated() { + return $this->validated; + } + + /** + * {@inheritdoc} + */ + public function setValidated($validated) { + $this->validated = $validated; + return $this; + } + /** * {@inheritdoc} */ only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/FieldableEntityInterface.php +++ b/core/lib/Drupal/Core/Entity/FieldableEntityInterface.php @@ -212,12 +212,36 @@ public function onChange($field_name); /** * Validates the currently set values. * + * Note that by calling this method the entity will be flagged as validated + * and validation logic might be skipped, because ::isValidated() would return + * TRUE. To prevent this the validated flag could be reset by calling + * ::setValidated(FALSE). + * * @return \Drupal\Core\Entity\EntityConstraintViolationListInterface * A list of constraint violations. If the list is empty, validation * succeeded. */ public function validate(); + /** + * Checks whether the entity has been validated. + * + * @return bool + * TRUE if the entity has been validated, FALSE if not. + */ + public function isValidated(); + + /** + * Sets the validated flag. + * + * @param bool $validated + * If set to TRUE the entity will be flagged as validated, otherwise as not + * validated. + * + * @return $this + */ + public function setValidated($validated); + /** * Checks whether entity validation is required before saving the entity. *