Commit 7f08110a authored by Dries's avatar Dries

- Improved form handling.

  + Introduced two new functions:
      1. form_set_error($name, $message): files an error against the form
         element with the specified  $name.
      2. form_has_errors(): returns true if errors has been filed against
         form elements.

  + Updated the form handling:
       1. The form_ functions will add 'class="error"' when a form field
          has been found to be erroneous.
       2. The error message is passed to theme_form_element() when the
          particular form field has been found to be erroneous.

  + I updated the user and profile module to take advantage of these new
    functions.

  + IMPORTANT: the _user() hook changed.  The 'validate' case should no
    longer retun an error message when something goes wrong but should
    set it with form_set_error().
parent 2954836f
......@@ -57,6 +57,7 @@ function drupal_get_messages() {
return $messages;
}
/* @} */
/**
......@@ -1012,8 +1013,34 @@ function form($form, $method = "post", $action = NULL, $attributes = NULL) {
return "<form action=\"$action\" method=\"$method\"". drupal_attributes($attributes) .">\n$form\n</form>\n";
}
function form_item($title, $value, $description = NULL, $id = NULL, $required = FALSE) {
return theme("form_element", $title, $value, $description, $id, $required);
/**
* File an error against the form with the specified name.
*/
function form_set_error($name, $message) {
$GLOBALS['form'][$name] = $message;
drupal_set_message($message, 'error');
}
/**
* Return true when errors have been set.
*/
function form_has_errors() {
return isset($GLOBALS['form']);
}
/**
* Return the error message filed against the form with the specified name.
*/
function _form_get_error($name) {
return $GLOBALS['form'][$name];
}
function _form_get_class($name, $required, $error) {
return $name. ($required ? ' required' : '') . ($error ? ' error' : '');
}
function form_item($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) {
return theme("form_element", $title, $value, $description, $id, $required, $error);
}
function form_group($legend, $group, $description = NULL) {
......@@ -1021,11 +1048,11 @@ function form_group($legend, $group, $description = NULL) {
}
function form_radio($title, $name, $value = 1, $checked = 0, $description = NULL, $attributes = NULL, $required = FALSE) {
$element = "<input type=\"radio\" class=\"form-radio\" name=\"edit[$name]\" value=\"$value\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) .' />';
$element = "<input type=\"radio\" class=\"". _form_get_class('form-radio', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" value=\"$value\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) .' />';
if (!is_null($title)) {
$element = "<label class=\"option\">$element $title</label>";
}
return theme('form_element', NULL, $element, $description, $required);
return theme('form_element', NULL, $element, $description, $required, _form_get_error($name));
}
function form_radios($title, $name, $value, $options, $description = NULL, $required = FALSE) {
......@@ -1034,16 +1061,16 @@ function form_radios($title, $name, $value, $options, $description = NULL, $requ
foreach ($options as $key => $choice) {
$choices .= "<label class=\"option\"><input type=\"radio\" class=\"form-radio\" name=\"edit[$name]\" value=\"$key\"". ($key == $value ? " checked=\"checked\"" : "") ." /> $choice</label><br />";
}
return theme('form_element', $title, $choices, $description, $required);
return theme('form_element', $title, $choices, $description, $required, _form_get_error($name));
}
}
function form_checkbox($title, $name, $value = 1, $checked = 0, $description = NULL, $attributes = NULL, $required = FALSE) {
$element = "<input type=\"checkbox\" class=\"form-checkbox\" name=\"edit[$name]\" id=\"edit-$name\" value=\"". $value ."\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) .' />';
$element = "<input type=\"checkbox\" class=\"". _form_get_class('form-checkbox', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" id=\"edit-$name\" value=\"". $value ."\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) .' />';
if (!is_null($title)) {
$element = "<label class=\"option\">$element $title</label>";
}
return form_hidden($name, 0) . theme('form_element', NULL, $element, $description, $required);
return form_hidden($name, 0) . theme('form_element', NULL, $element, $description, $required, _form_get_error($name));
}
function form_checkboxes($title, $name, $values, $options, $description = NULL, $required = FALSE) {
......@@ -1055,24 +1082,24 @@ function form_checkboxes($title, $name, $values, $options, $description = NULL,
foreach ($options as $key => $choice) {
$choices .= "<label class=\"option\"><input type=\"checkbox\" class=\"form-checkbox\" name=\"edit[$name][]\" value=\"$key\"". (in_array($key, $values) ? " checked=\"checked\"" : "") ." /> $choice</label><br />";
}
return theme('form_element', $title, $choices, $description, $required);
return theme('form_element', $title, $choices, $description, $required, _form_get_error($name));
}
}
function form_textfield($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) {
$size = $size ? " size=\"$size\"" : "";
return theme("form_element", $title, "<input type=\"text\" maxlength=\"$maxlength\" class=\"form-text\" name=\"edit[$name]\" id=\"$name\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description, $name, $required);
return theme("form_element", $title, "<input type=\"text\" maxlength=\"$maxlength\" class=\"". _form_get_class('form-text', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" id=\"$name\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description, $name, $required, _form_get_error($name));
}
function form_password($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) {
$size = $size ? " size=\"$size\"" : "";
return theme("form_element", $title, "<input type=\"password\" class=\"form-password\" maxlength=\"$maxlength\" name=\"edit[$name]\" id=\"$name\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description, $name, $required);
return theme("form_element", $title, "<input type=\"password\" class=\"". _form_get_class('form-password', $required, _form_get_error($name)) ."\" maxlength=\"$maxlength\" name=\"edit[$name]\" id=\"$name\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description, $name, $required, _form_get_error($name));
}
function form_textarea($title, $name, $value, $cols, $rows, $description = NULL, $attributes = NULL, $required = FALSE) {
$cols = $cols ? " cols=\"$cols\"" : "";
module_invoke_all("textarea", $name); // eg. optionally plug in a WYSIWYG editor
return theme("form_element", $title, "<textarea wrap=\"virtual\"$cols rows=\"$rows\" name=\"edit[$name]\" id=\"$name\"". drupal_attributes($attributes) .">". check_form($value) ."</textarea>", $description, $name, $required);
return theme("form_element", $title, "<textarea wrap=\"virtual\"$cols rows=\"$rows\" name=\"edit[$name]\" id=\"$name\"". drupal_attributes($attributes) .">". check_form($value) ."</textarea>", $description, $name, $required, _form_get_error($name));
}
/**
......@@ -1102,11 +1129,11 @@ function form_select($title, $name, $value, $options, $description = NULL, $extr
$select .= "<option value=\"$key\"". (is_array($value) ? (in_array($key, $value) ? " selected=\"selected\"" : "") : ($value == $key ? " selected=\"selected\"" : "")) .">". check_form($choice) ."</option>";
}
}
return theme("form_element", $title, "<select name=\"edit[$name]". ($multiple ? "[]" : "") ."\"". ($multiple ? " multiple=\"multiple\" " : "") . ($extra ? " $extra" : "") ." id=\"$name\">$select</select>", $description, $name, $required);
return theme("form_element", $title, "<select name=\"edit[$name]". ($multiple ? "[]" : "") ."\"". ($multiple ? " multiple=\"multiple\" " : "") . ($extra ? " $extra" : "") ." id=\"$name\">$select</select>", $description, $name, $required, _form_get_error($name));
}
function form_file($title, $name, $size, $description = NULL, $required = FALSE) {
return theme("form_element", $title, "<input type=\"file\" class=\"form-file\" name=\"edit[$name]\" id=\"$name\" size=\"$size\" />\n", $description, $name, $required);
return theme("form_element", $title, "<input type=\"file\" class=\"". _form_get_class('form-file', $required, _form_get_error($name)) ."\" name=\"edit[$name]\" id=\"$name\" size=\"$size\" />\n", $description, $name, $required, _form_get_error($error));
}
function form_hidden($name, $value) {
......
......@@ -269,11 +269,12 @@ function theme_node($node, $main = 0, $page = 0) {
* @param $value the form element's data
* @param $description the form element's description or explanation
* @param $id the form element's ID used by the &lt;label&gt; tag
* @param $required a boolean to indicate whether this is a required field or not
* @param $error a string with an error message filed against this form element
*
* @return a string representing the form element
*/
function theme_form_element($title, $value, $description = NULL, $id = NULL, $required = FALSE) {
function theme_form_element($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) {
$output = "<div class=\"form-item\">\n";
......
......@@ -132,6 +132,9 @@ td.menu-disabled {
.form-item {
margin-bottom: 1em;
}
.form-item input.error {
border: 2px solid red;
}
.form-item .description {
font-size: 0.85em;
}
......
......@@ -281,7 +281,7 @@ function comment_post($edit) {
** Validate the comment's body.
*/
if ($edit["comment"] == "") {
if ($edit['comment'] == '') {
return array(t("Empty comment"), t("The comment you submitted is empty."));
}
......
......@@ -281,7 +281,7 @@ function comment_post($edit) {
** Validate the comment's body.
*/
if ($edit["comment"] == "") {
if ($edit['comment'] == '') {
return array(t("Empty comment"), t("The comment you submitted is empty."));
}
......
......@@ -183,11 +183,11 @@ function profile_validate_profile($edit) {
while ($field = db_fetch_object($result)) {
if ($edit[$field->name]) {
if ($field->type == 'url' && !valid_url($edit[$field->name], true)) {
return t("The value provided for '%field' is not a valid URL.", array('%field' => $field->title));
form_set_error($field->name, t("The value provided for '%field' is not a valid URL.", array('%field' => $field->title)));
}
}
else if ($field->required) {
return t("The field '%field' is required.", array('%field' => $field->title));
form_set_error($field->name, t("The field '%field' is required.", array('%field' => $field->title)));
}
}
......@@ -215,22 +215,22 @@ function profile_validate_form($edit) {
// Validate the title:
if (!$edit['title']) {
return t('You must enter a title.');
form_set_error('title', t('You must enter a title.'));
}
// Validate the 'form name':
if (eregi('[^a-z0-9_-]', $edit['name'])) {
return t('The specified form name contains one or more illegal characters. Spaces or any other special characters expect dash (-) and underscore (_) are not allowed.');
form_set_error('name', t('The specified form name contains one or more illegal characters. Spaces or any other special characters expect dash (-) and underscore (_) are not allowed.'));
}
if (in_array($edit['name'], user_fields())) {
return t('The specified form name is reserved for use by Drupal.');
form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
}
// Validate the category:
if (!$edit['category']) {
return t('You must enter a category.');
form_set_error('category', t('You must enter a category.'));
}
}
......@@ -241,16 +241,18 @@ function profile_admin_add($type) {
if ($_POST['op']) {
$data = $_POST['edit'];
if ($error = profile_validate_form($data)) {
drupal_set_message($error, 'error');
}
else if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s'", $data['title']))) {
drupal_set_message(t('the specified title is already in use'), 'error');
// Validate the form:
profile_validate_form($data);
if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s'", $data['title']))) {
form_set_error('title', t('the specified title is already in use.'));
}
else if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", $data['name']))) {
drupal_set_message(t('the specified name is already in use'), 'error');
if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", $data['name']))) {
form_set_error('name', t('the specified name is already in use.'));
}
else {
if (!form_has_errors()) {
db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, required, overview, options, page) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', '%s')", $data['title'], $data['name'], $data['explanation'], $data['category'], $type, $data['weight'], $data['required'], $data['overview'], $data['options'], $data['page']);
drupal_set_message(t('the field has been created.'));
......@@ -268,11 +270,10 @@ function profile_admin_edit($fid) {
if ($_POST['op']) {
$data = $_POST['edit'];
if ($error = profile_validate_form($data)) {
drupal_set_message($error, 'error');
// Validate form:
profile_validate_form($data);
}
else {
if (!form_has_errors()) {
db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, required = %d, overview = %d, options = '%s', page = '%s' WHERE fid = %d", $data['title'], $data['name'], $data['explanation'], $data['category'], $data['weight'], $data['required'], $data['overview'], $data['options'], $data['page'], $fid);
drupal_set_message(t('the field has been updated.'));
......
......@@ -183,11 +183,11 @@ function profile_validate_profile($edit) {
while ($field = db_fetch_object($result)) {
if ($edit[$field->name]) {
if ($field->type == 'url' && !valid_url($edit[$field->name], true)) {
return t("The value provided for '%field' is not a valid URL.", array('%field' => $field->title));
form_set_error($field->name, t("The value provided for '%field' is not a valid URL.", array('%field' => $field->title)));
}
}
else if ($field->required) {
return t("The field '%field' is required.", array('%field' => $field->title));
form_set_error($field->name, t("The field '%field' is required.", array('%field' => $field->title)));
}
}
......@@ -215,22 +215,22 @@ function profile_validate_form($edit) {
// Validate the title:
if (!$edit['title']) {
return t('You must enter a title.');
form_set_error('title', t('You must enter a title.'));
}
// Validate the 'form name':
if (eregi('[^a-z0-9_-]', $edit['name'])) {
return t('The specified form name contains one or more illegal characters. Spaces or any other special characters expect dash (-) and underscore (_) are not allowed.');
form_set_error('name', t('The specified form name contains one or more illegal characters. Spaces or any other special characters expect dash (-) and underscore (_) are not allowed.'));
}
if (in_array($edit['name'], user_fields())) {
return t('The specified form name is reserved for use by Drupal.');
form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
}
// Validate the category:
if (!$edit['category']) {
return t('You must enter a category.');
form_set_error('category', t('You must enter a category.'));
}
}
......@@ -241,16 +241,18 @@ function profile_admin_add($type) {
if ($_POST['op']) {
$data = $_POST['edit'];
if ($error = profile_validate_form($data)) {
drupal_set_message($error, 'error');
}
else if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s'", $data['title']))) {
drupal_set_message(t('the specified title is already in use'), 'error');
// Validate the form:
profile_validate_form($data);
if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s'", $data['title']))) {
form_set_error('title', t('the specified title is already in use.'));
}
else if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", $data['name']))) {
drupal_set_message(t('the specified name is already in use'), 'error');
if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", $data['name']))) {
form_set_error('name', t('the specified name is already in use.'));
}
else {
if (!form_has_errors()) {
db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, required, overview, options, page) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', '%s')", $data['title'], $data['name'], $data['explanation'], $data['category'], $type, $data['weight'], $data['required'], $data['overview'], $data['options'], $data['page']);
drupal_set_message(t('the field has been created.'));
......@@ -268,11 +270,10 @@ function profile_admin_edit($fid) {
if ($_POST['op']) {
$data = $_POST['edit'];
if ($error = profile_validate_form($data)) {
drupal_set_message($error, 'error');
// Validate form:
profile_validate_form($data);
}
else {
if (!form_has_errors()) {
db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, required = %d, overview = %d, options = '%s', page = '%s' WHERE fid = %d", $data['title'], $data['name'], $data['explanation'], $data['category'], $data['weight'], $data['required'], $data['overview'], $data['options'], $data['page'], $fid);
drupal_set_message(t('the field has been updated.'));
......
This diff is collapsed.
This diff is collapsed.
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