diff --git a/core/lib/Drupal/Core/Entity/ContentEntityForm.php b/core/lib/Drupal/Core/Entity/ContentEntityForm.php index bca3c33..2c1604b 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityForm.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityForm.php @@ -135,10 +135,11 @@ protected function getEditedFieldNames(FormStateInterface $form_state) { protected function flagViolations(EntityConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) { // Flag entity level violations. foreach ($violations->getEntityViolations() as $violation) { - $form_state->setErrorByName('', $violation); + /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */ + $form_state->setErrorByName('', $violation->getMessage()); } // Let the form display flag violations of its fields. - $this->getFormDisplay($form_state)->flagViolations($violations, $form, $form_state); + $this->getFormDisplay($form_state)->flagWidgetsErrorsFromViolations($violations, $form, $form_state); } /** diff --git a/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php b/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php index 345a0bf..b71b0ec 100644 --- a/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php +++ b/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php @@ -179,6 +179,6 @@ public function validateFormValues(FieldableEntityInterface $entity, array &$for * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. */ - public function flagViolations(EntityConstraintViolationListInterface $violations, array &$form, FormStateInterface $form_state); + public function flagWidgetsErrorsFromViolations(EntityConstraintViolationListInterface $violations, array &$form, FormStateInterface $form_state); } diff --git a/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php index 20e978c..2af89b5 100644 --- a/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php +++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php @@ -243,16 +243,17 @@ public function validateFormValues(FieldableEntityInterface $entity, array &$for // Flag entity level violations. foreach ($violations->getEntityViolations() as $violation) { - $form_state->setErrorByName('', $violation); + /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */ + $form_state->setErrorByName('', $violation->getMessage()); } - $this->flagViolations($violations, $form, $form_state); + $this->flagWidgetsErrorsFromViolations($violations, $form, $form_state); } /** * {@inheritdoc} */ - public function flagViolations(EntityConstraintViolationListInterface $violations, array &$form, FormStateInterface $form_state) { + public function flagWidgetsErrorsFromViolations(EntityConstraintViolationListInterface $violations, array &$form, FormStateInterface $form_state) { $entity = $violations->getEntity(); foreach ($violations->getFieldNames() as $field_name) { // Only show violations for fields that actually appear in the form, and diff --git a/core/lib/Drupal/Core/Entity/EntityConstraintViolationList.php b/core/lib/Drupal/Core/Entity/EntityConstraintViolationList.php index 26a0046..507975c 100644 --- a/core/lib/Drupal/Core/Entity/EntityConstraintViolationList.php +++ b/core/lib/Drupal/Core/Entity/EntityConstraintViolationList.php @@ -90,7 +90,7 @@ public function getEntityViolations() { foreach ($this->entityViolationOffsets as $offset) { $violations[] = $this->get($offset); } - return new static($this->entity,$violations); + return new static($this->entity, $violations); } /** @@ -131,16 +131,15 @@ public function filterByFields(array $field_names) { // Keep the composite field if it covers some remaining field and put // a violation on some other covered field instead. if ($remaining_fields = array_diff($covered_fields, $field_names)) { - $message_template = 'The validation failed because the value conflicts with the value in %field_name, which you cannot access.'; $message_params = ['%field_name' => $field_name]; $violation = new ConstraintViolation( - $this->t($message_template, $message_params), - $message_template, + $this->t('The validation failed because the value conflicts with the value in %field_name, which you cannot access.', $message_params), + 'The validation failed because the value conflicts with the value in %field_name, which you cannot access.', $message_params, $violation->getRoot(), reset($remaining_fields), $violation->getInvalidValue(), - $violation->getMessagePluralization(), + $violation->getPlural(), $violation->getCode(), $violation->getConstraint(), $violation->getCause() diff --git a/core/lib/Drupal/Core/Entity/EntityConstraintViolationListInterface.php b/core/lib/Drupal/Core/Entity/EntityConstraintViolationListInterface.php index acf62f3..4231790 100644 --- a/core/lib/Drupal/Core/Entity/EntityConstraintViolationListInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityConstraintViolationListInterface.php @@ -23,7 +23,7 @@ * Gets violations flagged on entity level, not associated with any field. * * @return \Drupal\Core\Entity\EntityConstraintViolationListInterface - * A list of violations of the given fields. + * A list of violations on the entity level. */ public function getEntityViolations(); @@ -53,7 +53,9 @@ public function getByField($field_name); public function getByFields(array $field_names); /** - * Filters the violations by the given fields. + * Filters this violation list by the given fields. + * + * The returned object just has violations attached to the provided fields. * * When violations should be displayed for a sub-set of visible fields only, * this method may be used to filter the set of visible violations first. @@ -66,10 +68,10 @@ public function getByFields(array $field_names); public function filterByFields(array $field_names); /** - * Filters the violations to apply for accessible fields only. + * Filters this violation list to apply for accessible fields only. * - * Violations for inaccessible fields are skipped and remaining violations - * are returned. + * Violations for inaccessible fields are removed so the returned object just + * has the remaining violations. * * @param \Drupal\Core\Session\AccountInterface $account * (optional) The user for which to check access, or NULL to check access diff --git a/core/modules/system/src/Tests/Entity/FieldWidgetConstraintValidatorTest.php b/core/modules/system/src/Tests/Entity/FieldWidgetConstraintValidatorTest.php index b0b3474..5f36973 100644 --- a/core/modules/system/src/Tests/Entity/FieldWidgetConstraintValidatorTest.php +++ b/core/modules/system/src/Tests/Entity/FieldWidgetConstraintValidatorTest.php @@ -138,4 +138,17 @@ public function testValidationWithCompositeConstraint() { $this->assertEqual($errors['type'], SafeMarkup::format('The validation failed because the value conflicts with the value in %field_name, which you cannot access.', ['%field_name' => 'name'])); } + /** + * Tests entity level constraint validation. + */ + public function testEntityLevelConstraintValidation() { + $entity = EntityTestCompositeConstraint::create([ + 'name' => 'entity-level-violation' + ]); + $entity->save(); + + $errors = $this->getErrorsForEntity($entity); + $this->assertEqual($errors[''], 'Entity level validation'); + } + } diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestCompositeConstraint.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestCompositeConstraint.php index 1085c92..e092c1c 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestCompositeConstraint.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestCompositeConstraint.php @@ -29,6 +29,7 @@ * persistent_cache = FALSE, * constraints = { * "EntityTestComposite" = {}, + * "EntityTestEntityLevel" = {}, * } * ) */ diff --git a/core/modules/system/tests/modules/entity_test/src/Plugin/Validation/Constraint/EntityTestEntityLevel.php b/core/modules/system/tests/modules/entity_test/src/Plugin/Validation/Constraint/EntityTestEntityLevel.php new file mode 100644 index 0000000..ec647bd --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/Plugin/Validation/Constraint/EntityTestEntityLevel.php @@ -0,0 +1,25 @@ +name->value === 'entity-level-violation') { + $this->context->buildViolation($constraint->message) + ->addViolation(); + } + } + +}