summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwebchick2012-10-06 11:12:27 -0700
committerwebchick2012-10-06 11:12:27 -0700
commit08ff47b5fd1e9ff1039dba129ac1c4ea97d47e3c (patch)
tree190bd3d21c2089ea8d78e512a93dafb9aea89ac8
parent14677a3b9c6b2063f7930aa4c09bbf5507e53855 (diff)
Issue #742344 by sun, pillarsdotnet, tarmstrong, neilnz, wamilton, lucascaro: Allow forms to set custom validation error messages on required fields.
-rw-r--r--core/includes/form.inc36
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Form/FileInclusionTest.php2
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php10
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Form/ValidationTest.php46
-rw-r--r--core/modules/system/tests/modules/form_test/form_test.module18
5 files changed, 99 insertions, 13 deletions
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 39203d2..5d6b32e 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1407,16 +1407,11 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
$is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0);
$is_empty_value = ($elements['#value'] === 0);
if ($is_empty_multiple || $is_empty_string || $is_empty_value) {
- // Although discouraged, a #title is not mandatory for form elements. In
- // case there is no #title, we cannot set a form error message.
- // Instead of setting no #title, form constructors are encouraged to set
- // #title_display to 'invisible' to improve accessibility.
- if (isset($elements['#title'])) {
- form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
- }
- else {
- form_error($elements);
- }
+ // Flag this element as #required_but_empty to allow #element_validate
+ // handlers to set a custom required error message, but without having
+ // to re-implement the complex logic to figure out whether the field
+ // value is empty.
+ $elements['#required_but_empty'] = TRUE;
}
}
@@ -1431,6 +1426,27 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
$function($elements, $form_state, $form_state['complete_form']);
}
}
+
+ // Ensure that a #required form error is thrown, regardless of whether
+ // #element_validate handlers changed any properties. If $is_empty_value
+ // is defined, then above #required validation code ran, so the other
+ // variables are also known to be defined and we can test them again.
+ if (isset($is_empty_value) && ($is_empty_multiple || $is_empty_string || $is_empty_value)) {
+ if (isset($elements['#required_error'])) {
+ form_error($elements, $elements['#required_error']);
+ }
+ // A #title is not mandatory for form elements, but without it we cannot
+ // set a form error message. So when a visible title is undesirable, form
+ // constructors are encouraged to set #title anyway, and then set
+ // #title_display to 'invisible'. This improves accessibility.
+ elseif (isset($elements['#title'])) {
+ form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+ }
+ else {
+ form_error($elements);
+ }
+ }
+
$elements['#validated'] = TRUE;
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FileInclusionTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FileInclusionTest.php
index 4dad937..1a499d3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FileInclusionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FileInclusionTest.php
@@ -38,7 +38,7 @@ class FileInclusionTest extends WebTestBase {
}
/**
- * Tests loading a custom specified inlcude.
+ * Tests loading a custom specified include.
*/
function testLoadCustomInclude() {
$this->drupalPost('form-test/load-include-custom', array(), t('Save'));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index 2586aa3..92898e0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -172,7 +172,15 @@ class FormTest extends WebTestBase {
// messages for each field.
$expected = array();
foreach (array('textfield', 'checkboxes', 'select', 'radios') as $key) {
- $expected[] = t('!name field is required.', array('!name' => $form[$key]['#title']));
+ if (isset($form[$key]['#required_error'])) {
+ $expected[] = $form[$key]['#required_error'];
+ }
+ elseif (isset($form[$key]['#form_test_required_error'])) {
+ $expected[] = $form[$key]['#form_test_required_error'];
+ }
+ else {
+ $expected[] = t('!name field is required.', array('!name' => $form[$key]['#title']));
+ }
}
// Check the page for error messages.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ValidationTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ValidationTest.php
index 7491df2..a76856b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/ValidationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/ValidationTest.php
@@ -186,4 +186,50 @@ class ValidationTest extends WebTestBase {
$this->drupalPost('form-test/pattern', $edit, 'Submit');
$this->assertNoRaw(t('%name field is not in the right format.', array('%name' => 'Client side validation')));
}
+
+ /**
+ * Tests #required with custom validation errors.
+ *
+ * @see form_test_validate_required_form()
+ */
+ function testCustomRequiredError() {
+ $form = $form_state = array();
+ $form = form_test_validate_required_form($form, $form_state);
+
+ // Verify that a custom #required error can be set.
+ $edit = array();
+ $this->drupalPost('form-test/validate-required', $edit, 'Submit');
+
+ foreach (element_children($form) as $key) {
+ if (isset($form[$key]['#required_error'])) {
+ $this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
+ $this->assertText($form[$key]['#required_error']);
+ }
+ elseif (isset($form[$key]['#form_test_required_error'])) {
+ $this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
+ $this->assertText($form[$key]['#form_test_required_error']);
+ }
+ }
+ $this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
+
+ // Verify that no custom validation error appears with valid values.
+ $edit = array(
+ 'textfield' => $this->randomString(),
+ 'checkboxes[foo]' => TRUE,
+ 'select' => 'foo',
+ );
+ $this->drupalPost('form-test/validate-required', $edit, 'Submit');
+
+ foreach (element_children($form) as $key) {
+ if (isset($form[$key]['#required_error'])) {
+ $this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
+ $this->assertNoText($form[$key]['#required_error']);
+ }
+ elseif (isset($form[$key]['#form_test_required_error'])) {
+ $this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
+ $this->assertNoText($form[$key]['#form_test_required_error']);
+ }
+ }
+ $this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
+ }
}
diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module
index 3cdb746..6ea5aa3 100644
--- a/core/modules/system/tests/modules/form_test/form_test.module
+++ b/core/modules/system/tests/modules/form_test/form_test.module
@@ -461,23 +461,29 @@ function form_test_validate_form_validate(&$form, &$form_state) {
*/
function form_test_validate_required_form($form, &$form_state) {
$options = drupal_map_assoc(array('foo', 'bar'));
+ $validate = array('form_test_validate_required_form_element_validate');
$form['textfield'] = array(
'#type' => 'textfield',
- '#title' => 'Textfield',
+ '#title' => 'Name',
'#required' => TRUE,
+ '#required_error' => t('Please enter a name.'),
);
$form['checkboxes'] = array(
'#type' => 'checkboxes',
'#title' => 'Checkboxes',
'#options' => $options,
'#required' => TRUE,
+ '#form_test_required_error' => t('Please choose at least one option.'),
+ '#element_validate' => $validate,
);
$form['select'] = array(
'#type' => 'select',
'#title' => 'Select',
'#options' => $options,
'#required' => TRUE,
+ '#form_test_required_error' => t('Please select something.'),
+ '#element_validate' => $validate,
);
$form['radios'] = array(
'#type' => 'radios',
@@ -502,6 +508,16 @@ function form_test_validate_required_form($form, &$form_state) {
}
/**
+ * Form element validation handler for 'Name' field in form_test_validate_required_form().
+ */
+function form_test_validate_required_form_element_validate($element, &$form_state) {
+ // Set a custom validation error on the #required element.
+ if (!empty($element['#required_but_empty']) && isset($element['#form_test_required_error'])) {
+ form_error($element, $element['#form_test_required_error']);
+ }
+}
+
+/**
* Form submission handler for form_test_validate_required_form().
*/
function form_test_validate_required_form_submit($form, &$form_state) {