diff --git a/core/includes/form.inc b/core/includes/form.inc index 5fe031e..ff9d7c9 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -279,6 +279,15 @@ function form_set_error($name, array &$form_state, $message = '') { } /** + * Clears all errors against all form elements made by form_set_error(). + * + * @deprecated as of Drupal 8.0. Use \Drupal::formBuilder()->clearErrors() + */ +function form_clear_error(array &$form_state) { + \Drupal::formBuilder()->clearErrors($form_state); +} + +/** * Returns an associative array of all errors. * * @deprecated as of Drupal 8.0. Use \Drupal::formBuilder()->getErrors() @@ -1118,18 +1127,15 @@ function form_process_password_confirm($element) { * Validates a password_confirm element. */ function password_confirm_validate($element, &$element_state) { - // @todo Find a way to pass through the correct $form_state. - $form_state = form_state_defaults(); - $pass1 = trim($element['pass1']['#value']); $pass2 = trim($element['pass2']['#value']); if (!empty($pass1) || !empty($pass2)) { if (strcmp($pass1, $pass2)) { - form_error($element, $form_state, t('The specified passwords do not match.')); + form_error($element, $element_state, t('The specified passwords do not match.')); } } elseif ($element['#required'] && !empty($element_state['input'])) { - form_error($element, $form_state, t('Password field is required.')); + form_error($element, $element_state, t('Password field is required.')); } // Password field must be converted from a two-element array into a single @@ -2925,7 +2931,7 @@ function _form_set_attributes(&$element, $class = array()) { $element['#attributes']['required'] = 'required'; $element['#attributes']['aria-required'] = 'true'; } - if (isset($element['#parents']) && isset($element['#errors']) && !empty($element['#validated'])) { + if (isset($element['#parents']) && !empty($element['#errors']) && !empty($element['#validated'])) { $element['#attributes']['class'][] = 'error'; $element['#attributes']['aria-invalid'] = 'true'; } diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index dd15bef..979ed47 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -454,7 +454,7 @@ public function submitForm($form_arg, &$form_state) { // Reset form validation. $form_state['must_validate'] = TRUE; - $form_state['errors'] = array(); + $this->clearErrors($form_state); $this->prepareForm($form_id, $form, $form_state); $this->processForm($form_id, $form, $form_state); @@ -605,12 +605,12 @@ public function processForm($form_id, &$form, &$form_state) { // form is processed, so scenarios that result in the form being built // behind the scenes and again for the browser don't increment all the // element IDs needlessly. - if (!$this->getErrors($form_state)) { + if (!$this->getAnyErrors($form_state)) { // In case of errors, do not break HTML IDs of other forms. $this->drupalStaticReset('drupal_html_id'); } - if ($form_state['submitted'] && !$this->getErrors($form_state) && !$form_state['rebuild']) { + if ($form_state['submitted'] && !$this->getAnyErrors($form_state) && !$form_state['rebuild']) { // Execute form submit handlers. $this->executeHandlers('submit', $form, $form_state); @@ -675,7 +675,7 @@ public function processForm($form_id, &$form, &$form_state) { // along with element-level #submit properties, it makes no sense to // have divergent form execution based on whether the triggering element // has #executes_submit_callback set to TRUE. - if (($form_state['rebuild'] || !$form_state['executed']) && !$this->getErrors($form_state)) { + if (($form_state['rebuild'] || !$form_state['executed']) && !$this->getAnyErrors($form_state)) { // Form building functions (e.g., self::handleInputElement()) may use // $form_state['rebuild'] to determine if they are running in the // context of a rebuild, so ensure it is set. @@ -1205,6 +1205,7 @@ public function setErrorByName($name, array &$form_state, $message = '') { } if ($record) { $form_state['errors'][$name] = $message; + $this->request->attributes->set('_form_errors', TRUE); if ($message) { $this->drupalSetMessage($message, 'error'); } @@ -1217,24 +1218,51 @@ public function setErrorByName($name, array &$form_state, $message = '') { /** * {@inheritdoc} */ - public function getErrors(array &$form_state) { - if (!isset($form_state['errors'])) { - debug(format_backtrace(debug_backtrace())); - } + public function clearErrors(array &$form_state) { + $form_state['errors'] = array(); + $this->request->attributes->set('_form_errors', FALSE); + } + + /** + * {@inheritdoc} + */ + public function getErrors(array $form_state) { return $form_state['errors']; } /** + * Returns if there have been any errors during build. + * + * This will include any other forms built during this request. + * + * @param array $form_state + * An associative array containing the current state of the form. + * + * @return bool + * Whether there have been any errors. + */ + protected function getAnyErrors(array $form_state) { + if (!empty($form_state['errors'])) { + return TRUE; + } + if ($this->request->attributes->has('_form_errors')) { + return $this->request->attributes->get('_form_errors'); + } + return FALSE; + } + + /** * {@inheritdoc} */ public function getError($element, array &$form_state) { - $errors = $this->getErrors($form_state); - $parents = array(); - foreach ($element['#parents'] as $parent) { - $parents[] = $parent; - $key = implode('][', $parents); - if (isset($errors[$key])) { - return $errors[$key]; + if ($errors = $this->getErrors($form_state)) { + $parents = array(); + foreach ($element['#parents'] as $parent) { + $parents[] = $parent; + $key = implode('][', $parents); + if (isset($errors[$key])) { + return $errors[$key]; + } } } } @@ -1264,6 +1292,7 @@ public function doBuildForm($form_id, &$element, &$form_state) { '#required' => FALSE, '#attributes' => array(), '#title_display' => 'before', + '#errors' => NULL, ); // Special handling if we're on the top level form element. diff --git a/core/lib/Drupal/Core/Form/FormBuilderInterface.php b/core/lib/Drupal/Core/Form/FormBuilderInterface.php index fe4ae1e..ed5a0f8 100644 --- a/core/lib/Drupal/Core/Form/FormBuilderInterface.php +++ b/core/lib/Drupal/Core/Form/FormBuilderInterface.php @@ -607,6 +607,14 @@ public function executeHandlers($type, &$form, &$form_state); public function setErrorByName($name, array &$form_state, $message = ''); /** + * Clears all errors against all form elements made by form_set_error(). + * + * @param array $form_state + * An associative array containing the current state of the form. + */ + public function clearErrors(array &$form_state); + + /** * Returns an associative array of all errors. * * @param array $form_state @@ -615,7 +623,7 @@ public function setErrorByName($name, array &$form_state, $message = ''); * @return array * An array of all errors, keyed by the name of the form element. */ - public function getErrors(array &$form_state); + public function getErrors(array $form_state); /** * Returns the error message filed against the given form element.