summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxjm2017-02-06 08:07:18 (GMT)
committerxjm2017-02-06 08:07:18 (GMT)
commitcd05ee426b71db8f371569403192281f7c31a4b4 (patch)
treeb48953125e7621f6b66393dadba8f77b465baf67
parent5eb0425b0d6cf238e69d12fbb713d10db65419d7 (diff)
Issue #177124 by hgoto, roblav, mrfelton, AjitS, wturrell, lyricnz, ADLongwell, tim.plunkett, effulgentsia, sun, GoddamnNoise, Liam Morland, Xano, drumm, guschilds, cilefen: Form validation messages appear in incorrect order
-rw-r--r--core/lib/Drupal/Core/Form/FormValidator.php8
-rw-r--r--core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php92
2 files changed, 98 insertions, 2 deletions
diff --git a/core/lib/Drupal/Core/Form/FormValidator.php b/core/lib/Drupal/Core/Form/FormValidator.php
index dbefe00..d4f3ee5 100644
--- a/core/lib/Drupal/Core/Form/FormValidator.php
+++ b/core/lib/Drupal/Core/Form/FormValidator.php
@@ -229,8 +229,12 @@ class FormValidator implements FormValidatorInterface {
* theming, and hook_form_alter functions.
*/
protected function doValidateForm(&$elements, FormStateInterface &$form_state, $form_id = NULL) {
- // Recurse through all children.
- foreach (Element::children($elements) as $key) {
+ // Recurse through all children, sorting the elements so that the order of
+ // error messages displayed to the user matches the order of elements in
+ // the form. Use a copy of $elements so that it is not modified by the
+ // sorting itself.
+ $elements_sorted = $elements;
+ foreach (Element::children($elements_sorted, TRUE) as $key) {
if (isset($elements[$key]) && $elements[$key]) {
$this->doValidateForm($elements[$key], $form_state);
}
diff --git a/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php b/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php
new file mode 100644
index 0000000..33ff22b
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Form;
+
+use Drupal\Core\Form\FormInterface;
+use Drupal\Core\Form\FormState;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests form validation mesages are displayed in the same order as the fields.
+ *
+ * @group Form
+ */
+class FormValidationMessageOrderTest extends KernelTestBase implements FormInterface {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'form_validation_error_message_order_test';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ // Prepare fields with weights specified.
+ $form['one'] = [
+ '#type' => 'textfield',
+ '#title' => 'One',
+ '#required' => TRUE,
+ '#weight' => 40,
+ ];
+ $form['two'] = [
+ '#type' => 'textfield',
+ '#title' => 'Two',
+ '#required' => TRUE,
+ '#weight' => 30,
+ ];
+ $form['three'] = [
+ '#type' => 'textfield',
+ '#title' => 'Three',
+ '#required' => TRUE,
+ '#weight' => 10,
+ ];
+ $form['four'] = [
+ '#type' => 'textfield',
+ '#title' => 'Four',
+ '#required' => TRUE,
+ '#weight' => 20,
+ ];
+ $form['actions'] = [
+ '#type' => 'actions',
+ 'submit' => [
+ '#type' => 'submit',
+ '#value' => 'Submit',
+ ],
+ ];
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ }
+
+ /**
+ * Tests that fields validation messages are sorted in the fields order.
+ */
+ function testLimitValidationErrors() {
+ $form_state = new FormState();
+ $form_builder = $this->container->get('form_builder');
+ $form_builder->submitForm($this, $form_state);
+
+ $messages = drupal_get_messages();
+ $this->assertTrue(isset($messages['error']));
+ $error_messages = $messages['error'];
+ $this->assertEqual($error_messages[0], 'Three field is required.');
+ $this->assertEqual($error_messages[1], 'Four field is required.');
+ $this->assertEqual($error_messages[2], 'Two field is required.');
+ $this->assertEqual($error_messages[3], 'One field is required.');
+ }
+
+}