Commit 08ff47b5 authored by webchick's avatar webchick

Issue #742344 by sun, pillarsdotnet, tarmstrong, neilnz, wamilton, lucascaro:...

Issue #742344 by sun, pillarsdotnet, tarmstrong, neilnz, wamilton, lucascaro: Allow forms to set custom validation error messages on required fields.
parent 14677a3b
......@@ -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;
}
......
......@@ -38,7 +38,7 @@ function testLoadMenuInclude() {
}
/**
* Tests loading a custom specified inlcude.
* Tests loading a custom specified include.
*/
function testLoadCustomInclude() {
$this->drupalPost('form-test/load-include-custom', array(), t('Save'));
......
......@@ -172,7 +172,15 @@ function testRequiredCheckboxesRadio() {
// 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.
......
......@@ -186,4 +186,50 @@ function testPatternValidation() {
$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.'));
}
}
......@@ -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',
......@@ -501,6 +507,16 @@ function form_test_validate_required_form($form, &$form_state) {
return $form;
}
/**
* 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().
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment