Issue #1174766 by Niklas Fiekas, ericduran: Added Support the #pattern FAPI property for native HTML5 pattern attribute.
parent
bd30dbfc09
commit
a82955bfd5
core
includes
modules/system
tests
modules/form_test
|
@ -3213,6 +3213,56 @@ function form_process_actions($element, &$form_state) {
|
|||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* #process callback for #pattern form element property.
|
||||
*
|
||||
* @param $element
|
||||
* An associative array containing the properties and children of the
|
||||
* generic input element.
|
||||
* @param $form_state
|
||||
* The $form_state array for the form this element belongs to.
|
||||
*
|
||||
* @return
|
||||
* The processed element.
|
||||
*
|
||||
* @see form_validate_pattern()
|
||||
*/
|
||||
function form_process_pattern($element, &$form_state) {
|
||||
if (isset($element['#pattern']) && !isset($element['#attributes']['pattern'])) {
|
||||
$element['#attributes']['pattern'] = $element['#pattern'];
|
||||
$element['#element_validate'][] = 'form_validate_pattern';
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* #element_validate callback for #pattern form element property.
|
||||
*
|
||||
* @param $element
|
||||
* An associative array containing the properties and children of the
|
||||
* generic form element.
|
||||
* @param $form_state
|
||||
* The $form_state array for the form this element belongs to.
|
||||
*
|
||||
* @see form_process_pattern()
|
||||
*/
|
||||
function form_validate_pattern($element, &$form_state) {
|
||||
if ($element['#value'] !== '') {
|
||||
// The pattern must match the entire string and should have the same
|
||||
// behavior as the RegExp object in ECMA 262.
|
||||
// - Use bracket-style delimiters to avoid introducing a special delimiter
|
||||
// character like '/' that would have to be escaped.
|
||||
// - Put in brackets so that the pattern can't interfere with what's
|
||||
// prepended and appended.
|
||||
$pattern = '{^(?:' . $element['#pattern'] . ')$}';
|
||||
|
||||
if (!preg_match($pattern, $element['#value'])) {
|
||||
form_error($element, t('%name field is not in the right format.', array('%name' => $element['#title'])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a container element.
|
||||
*
|
||||
|
|
|
@ -361,7 +361,7 @@ function system_element_info() {
|
|||
'#size' => 60,
|
||||
'#maxlength' => 128,
|
||||
'#autocomplete_path' => FALSE,
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
|
||||
'#theme' => 'textfield',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
);
|
||||
|
@ -370,7 +370,7 @@ function system_element_info() {
|
|||
'#size' => 30,
|
||||
'#maxlength' => 128,
|
||||
'#autocomplete_path' => FALSE,
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
|
||||
'#theme' => 'tel',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
);
|
||||
|
@ -379,7 +379,7 @@ function system_element_info() {
|
|||
'#size' => 60,
|
||||
'#maxlength' => EMAIL_MAX_LENGTH,
|
||||
'#autocomplete_path' => FALSE,
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
|
||||
'#element_validate' => array('form_validate_email'),
|
||||
'#theme' => 'email',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
|
@ -389,7 +389,7 @@ function system_element_info() {
|
|||
'#size' => 60,
|
||||
'#maxlength' => 255,
|
||||
'#autocomplete_path' => FALSE,
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
|
||||
'#element_validate' => array('form_validate_url'),
|
||||
'#theme' => 'url',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
|
@ -437,7 +437,7 @@ function system_element_info() {
|
|||
'#input' => TRUE,
|
||||
'#size' => 60,
|
||||
'#maxlength' => 128,
|
||||
'#process' => array('ajax_process_form'),
|
||||
'#process' => array('ajax_process_form', 'form_process_pattern'),
|
||||
'#theme' => 'password',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
);
|
||||
|
|
|
@ -784,6 +784,65 @@ class FormValidationTestCase extends DrupalWebTestCase {
|
|||
$this->assertText(t('!name field is required.', array('!name' => 'Title')));
|
||||
$this->assertText('Test element is invalid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests #pattern validation.
|
||||
*/
|
||||
function testPatternValidation() {
|
||||
$textfield_error = t('%name field is not in the right format.', array('%name' => 'One digit followed by lowercase letters'));
|
||||
$tel_error = t('%name field is not in the right format.', array('%name' => 'Everything except numbers'));
|
||||
$password_error = t('%name field is not in the right format.', array('%name' => 'Password'));
|
||||
|
||||
// Invalid textfield, valid tel.
|
||||
$edit = array(
|
||||
'textfield' => 'invalid',
|
||||
'tel' => 'valid',
|
||||
);
|
||||
$this->drupalPost('form-test/pattern', $edit, 'Submit');
|
||||
$this->assertRaw($textfield_error);
|
||||
$this->assertNoRaw($tel_error);
|
||||
$this->assertNoRaw($password_error);
|
||||
|
||||
// Valid textfield, invalid tel, valid password.
|
||||
$edit = array(
|
||||
'textfield' => '7seven',
|
||||
'tel' => '818937',
|
||||
'password' => '0100110',
|
||||
);
|
||||
$this->drupalPost('form-test/pattern', $edit, 'Submit');
|
||||
$this->assertNoRaw($textfield_error);
|
||||
$this->assertRaw($tel_error);
|
||||
$this->assertNoRaw($password_error);
|
||||
|
||||
// Non required fields are not validated if empty.
|
||||
$edit = array(
|
||||
'textfield' => '',
|
||||
'tel' => '',
|
||||
);
|
||||
$this->drupalPost('form-test/pattern', $edit, 'Submit');
|
||||
$this->assertNoRaw($textfield_error);
|
||||
$this->assertNoRaw($tel_error);
|
||||
$this->assertNoRaw($password_error);
|
||||
|
||||
// Invalid password.
|
||||
$edit = array(
|
||||
'password' => $this->randomName(),
|
||||
);
|
||||
$this->drupalPost('form-test/pattern', $edit, 'Submit');
|
||||
$this->assertNoRaw($textfield_error);
|
||||
$this->assertNoRaw($tel_error);
|
||||
$this->assertRaw($password_error);
|
||||
|
||||
// The pattern attribute overrides #pattern and is not validated on the
|
||||
// server side.
|
||||
$edit = array(
|
||||
'textfield' => '',
|
||||
'tel' => '',
|
||||
'url' => 'http://www.example.com/',
|
||||
);
|
||||
$this->drupalPost('form-test/pattern', $edit, 'Submit');
|
||||
$this->assertNoRaw(t('%name field is not in the right format.', array('%name' => 'Client side validation')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,12 @@ function form_test_menu() {
|
|||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['form-test/pattern'] = array(
|
||||
'title' => 'Pattern validation',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('form_test_pattern_form'),
|
||||
'access callback' => TRUE,
|
||||
);
|
||||
|
||||
$items['form_test/tableselect/multiple-true'] = array(
|
||||
'title' => 'Tableselect checkboxes test',
|
||||
|
@ -531,6 +537,41 @@ function form_test_limit_validation_errors_form_partial_submit($form, $form_stat
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a simple form using the FAPI #pattern proterty.
|
||||
*/
|
||||
function form_test_pattern_form($form, &$form_state) {
|
||||
$form['textfield'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => 'One digit followed by lowercase letters',
|
||||
'#pattern' => '[0-9][a-z]+',
|
||||
);
|
||||
$form['tel'] = array(
|
||||
'#type' => 'tel',
|
||||
'#title' => 'Everything except numbers',
|
||||
'#pattern' => '[^\d]*',
|
||||
);
|
||||
$form['password'] = array(
|
||||
'#type' => 'password',
|
||||
'#title' => 'Password',
|
||||
'#pattern' => '[01]+',
|
||||
);
|
||||
$form['url'] = array(
|
||||
'#type' => 'url',
|
||||
'#title' => 'Client side validation',
|
||||
'#decription' => 'Just client side validation, using the #pattern attribute.',
|
||||
'#attributes' => array(
|
||||
'pattern' => '.*foo.*',
|
||||
),
|
||||
'#pattern' => 'ignored',
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => 'Submit',
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a header and options array. Helper function for callbacks.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue