You are here

public function WidgetBase::flagErrors in Drupal 8

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::flagErrors()

Reports field-level validation errors against actual form elements.

Parameters

\Drupal\Core\Field\FieldItemListInterface $items: The field values.

\Symfony\Component\Validator\ConstraintViolationListInterface $violations: A list of constraint violations to flag.

array $form: The form structure where field elements are attached to. This might be a full form structure, or a sub-element of a larger form.

\Drupal\Core\Form\FormStateInterface $form_state: The form state.

Overrides WidgetBaseInterface::flagErrors

2 calls to WidgetBase::flagErrors()
FileWidget::flagErrors in core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
Reports field-level validation errors against actual form elements.
LinkWidget::flagErrors in core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
Override the '%uri' message parameter, to ensure that 'internal:' URIs show a validation error message that doesn't mention that scheme.
2 methods override WidgetBase::flagErrors()
FileWidget::flagErrors in core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
Reports field-level validation errors against actual form elements.
LinkWidget::flagErrors in core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
Override the '%uri' message parameter, to ensure that 'internal:' URIs show a validation error message that doesn't mention that scheme.

File

core/lib/Drupal/Core/Field/WidgetBase.php, line 409

Class

WidgetBase
Base class for 'Field widget' plugin implementations.

Namespace

Drupal\Core\Field

Code

public function flagErrors(FieldItemListInterface $items, ConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) {
  $field_name = $this->fieldDefinition
    ->getName();
  $field_state = static::getWidgetState($form['#parents'], $field_name, $form_state);
  if ($violations
    ->count()) {

    // Locate the correct element in the form.
    $element = NestedArray::getValue($form_state
      ->getCompleteForm(), $field_state['array_parents']);

    // Do not report entity-level validation errors if Form API errors have
    // already been reported for the field.
    // @todo Field validation should not be run on fields with FAPI errors to
    //   begin with. See https://www.drupal.org/node/2070429.
    $element_path = implode('][', $element['#parents']);
    if ($reported_errors = $form_state
      ->getErrors()) {
      foreach (array_keys($reported_errors) as $error_path) {
        if (strpos($error_path, $element_path) === 0) {
          return;
        }
      }
    }

    // Only set errors if the element is visible.
    if (Element::isVisibleElement($element)) {
      $handles_multiple = $this
        ->handlesMultipleValues();
      $violations_by_delta = $item_list_violations = [];
      foreach ($violations as $violation) {

        // Separate violations by delta.
        $property_path = explode('.', $violation
          ->getPropertyPath());
        $delta = array_shift($property_path);
        if (is_numeric($delta)) {
          $violations_by_delta[$delta][] = $violation;
        }
        else {
          $item_list_violations[] = $violation;
        }
        $violation->arrayPropertyPath = $property_path;
      }

      /** @var \Symfony\Component\Validator\ConstraintViolationInterface[] $delta_violations */
      foreach ($violations_by_delta as $delta => $delta_violations) {

        // Pass violations to the main element if this is a multiple-value
        // widget.
        if ($handles_multiple) {
          $delta_element = $element;
        }
        else {
          $original_delta = $field_state['original_deltas'][$delta];
          $delta_element = $element[$original_delta];
        }
        foreach ($delta_violations as $violation) {

          // @todo: Pass $violation->arrayPropertyPath as property path.
          $error_element = $this
            ->errorElement($delta_element, $violation, $form, $form_state);
          if ($error_element !== FALSE) {
            $form_state
              ->setError($error_element, $violation
              ->getMessage());
          }
        }
      }

      /** @var \Symfony\Component\Validator\ConstraintViolationInterface[] $item_list_violations */

      // Pass violations to the main element without going through
      // errorElement() if the violations are at the ItemList level.
      foreach ($item_list_violations as $violation) {
        $form_state
          ->setError($element, $violation
          ->getMessage());
      }
    }
  }
}