summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2005-10-07 06:11:12 +0000
committerDries Buytaert <dries@buytaert.net>2005-10-07 06:11:12 +0000
commit7e1527ee61bc10b3765b95b9af8faaa2254da5a8 (patch)
tree2225c7f571b4a3f635564f8281406a12b2a271a7 /includes
parent7b5b460534e5c54b07d28467c2aa2fc670c714e4 (diff)
downloadbrdo-7e1527ee61bc10b3765b95b9af8faaa2254da5a8.tar.gz
brdo-7e1527ee61bc10b3765b95b9af8faaa2254da5a8.tar.bz2
- Patch #29465: new form API by Adrian et al.
TODO: + The contact.module was broken; a new patch for contact.module is needed. + Documentation is needed. + The most important modules need to be updated ASAP.
Diffstat (limited to 'includes')
-rw-r--r--includes/common.inc631
-rw-r--r--includes/form.inc1078
-rw-r--r--includes/legacy.inc584
-rw-r--r--includes/locale.inc133
-rw-r--r--includes/theme.inc49
-rw-r--r--includes/unicode.inc4
6 files changed, 1754 insertions, 725 deletions
diff --git a/includes/common.inc b/includes/common.inc
index eacb23a14..9ef5e6d7b 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -479,38 +479,6 @@ function fix_gpc_magic() {
}
/**
- * An unchecked checkbox is not present in $_POST so we fix it here by
- * proving a default value of 0. Also, with form_checkboxes() we expect
- * an array, but HTML does not send the empty array. This is also taken
- * care off.
- */
-function fix_checkboxes() {
- if (isset($_POST['form_array'])) {
- $_POST['edit'] = _fix_checkboxes($_POST['edit'], $_POST['form_array'], array());
- }
- if (isset($_POST['form_zero'])) {
- $_POST['edit'] = _fix_checkboxes($_POST['edit'], $_POST['form_zero'], 0);
- }
-}
-
-function _fix_checkboxes($array1, $array2, $value) {
- if (is_array($array2) && count($array2)) {
- foreach ($array2 as $k => $v) {
- if (is_array($v) && count($v)) {
- $array1[$k] = _fix_checkboxes($array1[$k], $v, $value);
- }
- else if (!isset($array1[$k])) {
- $array1[$k] = $value;
- }
- }
- }
- else {
- $array1 = $value;
- }
- return $array1;
-}
-
-/**
* @name Conversion
* @{
* Converts data structures to different types.
@@ -549,6 +517,7 @@ function object2array($object) {
return $array;
}
+
/**
* @} End of "Conversion".
*/
@@ -1000,600 +969,6 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
*/
/**
- * @defgroup form Form generation
- * @{
- * Functions to enable output of HTML forms and form elements.
- *
- * Drupal uses these functions to achieve consistency in its form presentation,
- * while at the same time simplifying code and reducing the amount of HTML that
- * must be explicitly generated by modules.
- */
-
-/**
- * Generate a form from a set of form elements.
- *
- * @param $form
- * An HTML string containing one or more form elements.
- * @param $method
- * The query method to use ("post" or "get").
- * @param $action
- * The URL to send the form contents to, if not the current page.
- * @param $attributes
- * An associative array of attributes to add to the form tag.
- * @result
- * An HTML string with the contents of $form wrapped in a form tag.
- */
-function form($form, $method = 'post', $action = NULL, $attributes = NULL) {
- if (!$action) {
- $action = request_uri();
- }
- // Anonymous div to satisfy XHTML compliancy.
- return '<form action="'. check_url($action) .'" method="'. $method .'"'. drupal_attributes($attributes) .">\n<div>". $form ."\n</div></form>\n";
-}
-
-/**
- * Set a hidden 'form_token' field to be included in a form, used to validate
- * that the resulting submission was actually generated by a local form.
- *
- * @param $key
- * A unique key to identify the form that is currently being displayed.
- * This identical key is later used to validate that the resulting submission
- * actually originated with this form.
- * @result
- * A themed HTML string representing the hidden token field.
- */
-function form_token($key) {
- // this private key should always be kept secret
- if (!variable_get('drupal_private_key', '')) {
- variable_set('drupal_private_key', mt_rand());
- }
-
- // the verification token is an md5 hash of the form key and our private key
- return form_hidden('form_token', md5($_SERVER['REMOTE_ADDR'] . $key . variable_get('drupal_private_key', '')));
-}
-
-/**
- * Verify that the hidden 'form_token' field was actually generated with our
- * private key.
- *
- * @param $edit
- * An array containing the form that needs to be validated.
- * @param $key
- * The same key that was used to generate the 'form_token'.
- * @param $error_message
- * An optional error message to display if the form does not validate.
- * @result
- * There is nothing returned from this function, but if the 'form_token' does
- * not validate an error is generated, preventing the submission.
- */
-function form_validate($edit, $key, $error_message = NULL) {
- if ($error_message == NULL) {
- // set a generic default error message
- $error = t('Validation error, please try again. If this error persists, please contact the site administrator.');
- }
-
- if ($edit['form_token'] != md5($_SERVER['REMOTE_ADDR'] . $key . variable_get('drupal_private_key', ''))) {
- // setting this error will cause the form to fail validation
- form_set_error('form_token', $error);
- }
-}
-
-/**
- * File an error against the form element with the specified name.
- */
-function form_set_error($name, $message) {
- $GLOBALS['form'][$name] = $message;
- drupal_set_message($message, 'error');
-}
-
-/**
- * Return an associative array of all errors.
- */
-function form_get_errors() {
- if (array_key_exists('form', $GLOBALS)) {
- return $GLOBALS['form'];
- }
-}
-
-/**
- * Return the error message filed against the form with the specified name.
- */
-function _form_get_error($name) {
- if (array_key_exists('form', $GLOBALS)) {
- return $GLOBALS['form'][$name];
- }
-}
-
-function _form_get_class($name, $required, $error) {
- return $name. ($required ? ' required' : '') . ($error ? ' error' : '');
-}
-
-/**
- * Format a general form item.
- *
- * @param $title
- * The label for the form item.
- * @param $value
- * The contents of the form item.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $id
- * A unique identifier for the form item.
- * @param $required
- * Whether the user must fill in this form element before submitting the form.
- * @param $error
- * An error message to display alongside the form element.
- * @return
- * A themed HTML string representing the form item.
- */
-function form_item($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) {
- return theme('form_element', $title, $value, $description, $id, $required, $error);
-}
-
-/**
- * Format a group of form items.
- *
- * @param $legend
- * The label for the form item group.
- * @param $group
- * The form items within the group, as an HTML string.
- * @param $description
- * Explanatory text to display after the form item group.
- * @param $attributes
- * An associative array of HTML attributes to add to the fieldset tag.
- * @return
- * A themed HTML string representing the form item group.
- */
-function form_group($legend, $group, $description = NULL, $attributes = NULL) {
- return '<fieldset' . drupal_attributes($attributes) .'>' . ($legend ? '<legend>'. $legend .'</legend>' : '') . $group . ($description ? '<div class="description">'. $description .'</div>' : '') . "</fieldset>\n";
-}
-
-/**
- * Format a group of form items.
- *
- * @param $legend
- * The label for the form item group.
- * @param $group
- * The form items within the group, as an HTML string.
- * @param $collapsed
- * A boolean value decided whether the group starts collapsed.
- * @param $description
- * Explanatory text to display after the form item group.
- * @param $attributes
- * An associative array of HTML attributes to add to the fieldset tag.
- * @return
- * A themed HTML string representing the form item group.
- */
-function form_group_collapsible($legend, $group, $collapsed = FALSE, $description = NULL, $attributes = NULL) {
- drupal_add_js('misc/collapse.js');
-
- $attributes['class'] .= ' collapsible';
- if ($collapsed) {
- $attributes['class'] .= ' collapsed';
- }
-
- return '<fieldset' . drupal_attributes($attributes) .'>' . ($legend ? '<legend>'. $legend .'</legend>' : '') . $group . ($description ? '<div class="description">'. $description .'</div>' : '') . "</fieldset>\n";
-}
-
-/**
- * Format a radio button.
- *
- * @param $title
- * The label for the radio button.
- * @param $name
- * The internal name used to refer to the button.
- * @param $value
- * The value that the form element takes on when selected.
- * @param $checked
- * Whether the button will be initially selected when the page is rendered.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to the button.
- * @param $required
- * Whether the user must select this radio button before submitting the form.
- * @return
- * A themed HTML string representing the radio button.
- */
-function form_radio($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) {
- $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, $name, $required, _form_get_error($name));
-}
-
-/**
- * Format a set of radio buttons.
- *
- * @param $title
- * The label for the radio buttons as a group.
- * @param $name
- * The internal name used to refer to the buttons.
- * @param $value
- * The currently selected radio button's key.
- * @param $options
- * An associative array of buttons to display. The keys in this array are
- * button values, while the values are the labels to display for each button.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $required
- * Whether the user must select a radio button before submitting the form.
- * @param $attributes
- * An associative array of HTML attributes to add to each button.
- * @return
- * A themed HTML string representing the radio button set.
- */
-function form_radios($title, $name, $value, $options, $description = NULL, $required = FALSE, $attributes = NULL) {
- if (count($options) > 0) {
- $choices = '';
- foreach ($options as $key => $choice) {
- $choices .= '<label class="option"><input type="radio" class="form-radio" name="edit['. $name .']" value="'. $key .'"'. ($key == $value ? ' checked="checked"' : ''). drupal_attributes($attributes) .' /> '. $choice .'</label><br />';
- }
- return theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name));
- }
-}
-
-/**
- * Format a checkbox.
- *
- * @param $title
- * The label for the checkbox.
- * @param $name
- * The internal name used to refer to the button.
- * @param $value
- * The value that the form element takes on when selected.
- * @param $checked
- * Whether the button will be initially selected when the page is rendered.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to the button.
- * @param $required
- * Whether the user must check this box before submitting the form.
- * @return
- * A themed HTML string representing the checkbox.
- */
-function form_checkbox($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) {
- $element = '<input type="checkbox" class="'. _form_get_class('form-checkbox', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name).'" value="'. $value .'"'. ($checked ? ' checked="checked"' : '') . drupal_attributes($attributes) .' />';
- if (!is_null($title)) {
- $element = '<label class="option">'. $element .' '. $title .'</label>';
- }
- return form_hidden($name, 1, 'form_zero') . theme('form_element', NULL, $element, $description, $name, $required, _form_get_error($name));
-}
-
-/**
- * Format a set of checkboxes.
- *
- * @param $title
- * The label for the checkboxes as a group.
- * @param $name
- * The internal name used to refer to the buttons.
- * @param $values
- * A linear array of keys of the initially checked boxes.
- * @param $options
- * An associative array of buttons to display. The keys in this array are
- * button values, while the values are the labels to display for each button.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to each button.
- * @param $required
- * Whether the user must check a box before submitting the form.
- * @return
- * A themed HTML string representing the checkbox set.
- */
-function form_checkboxes($title, $name, $values, $options, $description = NULL, $attributes = NULL, $required = FALSE) {
- if (count($options) > 0) {
- if (!isset($values) || $values == 0) {
- $values = array();
- }
- $choices = '';
- 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"' : ''). drupal_attributes($attributes) .' /> '. $choice .'</label><br />';
- }
- return form_hidden($name, 1, 'form_array') . theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name));
- }
-}
-
-/**
- * Format a single-line text field.
- *
- * @param $title
- * The label for the text field.
- * @param $name
- * The internal name used to refer to the field.
- * @param $value
- * The initial value for the field at page load time.
- * @param $size
- * A measure of the visible size of the field (passed directly to HTML).
- * @param $maxlength
- * The maximum number of characters that may be entered in the field.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to the form item.
- * @param $required
- * Whether the user must enter some text in the field.
- * @return
- * A themed HTML string representing the field.
- */
-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_get_class('form-text', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'"'. $size .' value="'. check_plain($value) .'"'. drupal_attributes($attributes) .' />', $description, 'edit-'. $name, $required, _form_get_error($name));
-}
-
-/**
- * Format a single-line text field that uses Ajax for autocomplete.
- *
- * @param $title
- * The label for the text field.
- * @param $name
- * The internal name used to refer to the field.
- * @param $value
- * The initial value for the field at page load time.
- * @param $size
- * A measure of the visible size of the field (passed directly to HTML).
- * @param $maxlength
- * The maximum number of characters that may be entered in the field.
- * @param $callback_path
- * A drupal path for the Ajax autocomplete callback.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to the form item.
- * @param $required
- * Whether the user must enter some text in the field.
- * @return
- * A themed HTML string representing the field.
- */
-function form_autocomplete($title, $name, $value, $size, $maxlength, $callback_path, $description = NULL, $attributes = NULL, $required = FALSE) {
- drupal_add_js('misc/autocomplete.js');
-
- $size = $size ? ' size="'. $size .'"' : '';
-
- $output = theme('form_element', $title, '<input type="text" maxlength="'. $maxlength .'" class="'. _form_get_class('form-text form-autocomplete', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'"'. $size .' value="'. check_plain($value) .'"'. drupal_attributes($attributes) .' />', $description, 'edit-'. $name, $required, _form_get_error($name));
- $output .= '<input class="autocomplete" type="hidden" id="edit-'. form_clean_id($name) .'-autocomplete" value="'. check_url(url($callback_path, NULL, NULL, TRUE)) .'" disabled="disabled" />';
-
- return $output;
-}
-
-/**
- * Format a single-line text field that does not display its contents visibly.
- *
- * @param $title
- * The label for the text field.
- * @param $name
- * The internal name used to refer to the field.
- * @param $value
- * The initial value for the field at page load time.
- * @param $size
- * A measure of the visible size of the field (passed directly to HTML).
- * @param $maxlength
- * The maximum number of characters that may be entered in the field.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to the form item.
- * @param $required
- * Whether the user must enter some text in the field.
- * @return
- * A themed HTML string representing the field.
- */
-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_get_class('form-password', $required, _form_get_error($name)) .'" maxlength="'. $maxlength .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'"'. $size .' value="'. check_plain($value) .'"'. drupal_attributes($attributes) .' />', $description, 'edit-'. $name, $required, _form_get_error($name));
-}
-
-/**
- * Format a multiple-line text field.
- *
- * @param $title
- * The label for the text field.
- * @param $name
- * The internal name used to refer to the field.
- * @param $value
- * The initial value for the field at page load time.
- * @param $cols
- * The width of the field, in columns of text.
- * @param $rows
- * The height of the field, in rows of text.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $attributes
- * An associative array of HTML attributes to add to the form item.
- * @param $required
- * Whether the user must enter some text in the field.
- * @return
- * A themed HTML string representing the field.
- */
-function form_textarea($title, $name, $value, $cols, $rows, $description = NULL, $attributes = NULL, $required = FALSE) {
- $cols = $cols ? ' cols="'. $cols .'"' : '';
- $pre = '';
- $post = '';
-
- // optionally plug in a WYSIWYG editor
- foreach (module_list() as $module_name) {
- if (module_hook($module_name, 'textarea')) {
- $pre .= module_invoke($module_name, 'textarea', 'pre', $name);
- $post .= module_invoke($module_name, 'textarea', 'post', $name);
- }
- }
-
- return theme('form_element', $title, $pre .'<textarea'. $cols .' rows="'. $rows .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'" class="'. _form_get_class('textarea', $required, _form_get_error($name)) .'"'. drupal_attributes($attributes) .'>'. check_plain($value) .'</textarea>'. $post, $description, 'edit-'. $name, $required, _form_get_error($name));
-}
-
-/**
- * Format a dropdown menu or scrolling selection box.
- *
- * @param $title
- * The label for the form element.
- * @param $name
- * The internal name used to refer to the form element.
- * @param $value
- * The key of the currently selected item, or a linear array of keys of all the
- * currently selected items if multiple selections are allowed.
- * @param $options
- * An associative array of buttons to display. The keys in this array are
- * button values, while the values are the labels to display for each button.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $extra
- * Additional HTML to inject into the select element tag.
- * @param $multiple
- * Whether the user may select more than one item.
- * @param $required
- * Whether the user must select a value before submitting the form.
- * @return
- * A themed HTML string representing the form element.
- *
- * It is possible to group options together; to do this, change the format of
- * $options to an associative array in which the keys are group labels, and the
- * values are associative arrays in the normal $options format.
- */
-function form_select($title, $name, $value, $options, $description = NULL, $extra = 0, $multiple = FALSE, $required = FALSE) {
- $select = '';
- foreach ($options as $key => $choice) {
- if (is_array($choice)) {
- $select .= '<optgroup label="'. $key .'">';
- foreach ($choice as $key => $choice) {
- $select .= '<option value="'. $key .'"'. (is_array($value) ? (in_array($key, $value) ? ' selected="selected"' : '') : ($value == $key ? ' selected="selected"' : '')) .'>'. check_plain($choice) .'</option>';
- }
- $select .= '</optgroup>';
- }
- else {
- $select .= '<option value="'. $key .'"'. (is_array($value) ? (in_array($key, $value) ? ' selected="selected"' : '') : ($value == $key ? ' selected="selected"' : '')) .'>'. check_plain($choice) .'</option>';
- }
- }
- return theme('form_element', $title, '<select name="edit['. $name .']'. ($multiple ? '[]' : '') .'"'. ($multiple ? ' multiple="multiple" ' : '') . ($extra ? ' '. $extra : '') .' id="edit-'. form_clean_id($name) .'">'. $select .'</select>', $description, 'edit-'. $name, $required, _form_get_error($name));
-}
-
-/**
- * Format a file upload field.
- *
- * @param $title
- * The label for the file upload field.
- * @param $name
- * The internal name used to refer to the field.
- * @param $size
- * A measure of the visible size of the field (passed directly to HTML).
- * @param $description
- * Explanatory text to display after the form item.
- * @param $required
- * Whether the user must upload a file to the field.
- * @return
- * A themed HTML string representing the field.
- *
- * For assistance with handling the uploaded file correctly, see the API
- * provided by file.inc.
- */
-function form_file($title, $name, $size, $description = NULL, $required = FALSE) {
- return theme('form_element', $title, '<input type="file" class="'. _form_get_class('form-file', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'" size="'. $size ."\" />\n", $description, 'edit-'. $name, $required, _form_get_error($name));
-}
-
-/**
- * Store data in a hidden form field.
- *
- * @param $name
- * The internal name used to refer to the field.
- * @param $value
- * The stored data.
- * @param $edit
- * The array name to prefix to the $name.
- * @param $attributes
- * An array of HTML attributes for the input tag.
- * @return
- * A themed HTML string representing the hidden field.
- *
- * This function can be useful in retaining information between page requests,
- * but be sure to validate the data on the receiving page as it is possible for
- * an attacker to change the value before it is submitted.
- */
-function form_hidden($name, $value, $edit = 'edit', $attributes = NULL) {
- return '<input type="hidden" name="'. $edit .'['. $name .']" id="'. form_clean_id($edit .'-'. $name) .'" value="'. check_plain($value) .'"'. drupal_attributes($attributes) ." />\n";
-}
-
-/**
- * Format an action button.
- *
- * @param $value
- * Both the label for the button, and the value passed to the target page
- * when this button is clicked.
- * @param $name
- * The internal name used to refer to the button.
- * @param $type
- * What type to pass to the HTML input tag.
- * @param $attributes
- * An associative array of HTML attributes to add to the form item.
- * @return
- * A themed HTML string representing the button.
- */
-function form_button($value, $name = 'op', $type = 'submit', $attributes = NULL) {
- return '<input type="'. $type .'" class="form-'. $type .'" name="'. $name .'" id="'. form_clean_id($name) .'" value="'. check_plain($value) .'" '. drupal_attributes($attributes) ." />\n";
-}
-
-/**
- * Format a form submit button.
- *
- * @param $value
- * Both the label for the button, and the value passed to the target page
- * when this button is clicked.
- * @param $name
- * The internal name used to refer to the button.
- * @param $attributes
- * An associative array of HTML attributes to add to the form item.
- * @return
- * A themed HTML string representing the button.
- */
-function form_submit($value, $name = 'op', $attributes = NULL) {
- return form_button($value, $name, 'submit', $attributes);
-}
-
-/**
- * Format a weight selection menu.
- *
- * @param $title
- * The label for the form element.
- * @param $name
- * The internal name used to refer to the form element.
- * @param $value
- * The selected weight value at page load time.
- * @param $delta
- * The largest in absolute value the weight can be. For example, if set to 10,
- * weights could range from -10 to 10 inclusive.
- * @param $description
- * Explanatory text to display after the form item.
- * @param $extra
- * Additional HTML to inject into the select element tag.
- * @return
- * A themed HTML string representing the form element.
- */
-function form_weight($title = NULL, $name = 'weight', $value = 0, $delta = 10, $description = NULL, $extra = 0) {
- for ($n = (-1 * $delta); $n <= $delta; $n++) {
- $weights[$n] = $n;
- }
-
- return form_select($title, $name, $value, $weights, $description, $extra);
-}
-
-/**
- * Remove invalid characters from an HTML ID attribute string
- *
- * @param $id
- * The ID to clean
- * @return
- * The cleaned ID
- */
-function form_clean_id($id = NULL) {
- $id = str_replace('][', '-', $id);
- return $id;
-}
-
-/**
- * @} End of "defgroup form".
- */
-
-/**
* Generate an internal Drupal URL.
*
* @param $path
@@ -1622,7 +997,7 @@ function url($path = NULL, $query = NULL, $fragment = NULL, $absolute = FALSE) {
// Apache.
$script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === false) ? 'index.php' : '';
}
-
+
$path = drupal_get_path_alias($path);
if (isset($fragment)) {
@@ -1952,6 +1327,8 @@ function _drupal_bootstrap_full() {
require_once './includes/file.inc';
require_once './includes/unicode.inc';
require_once './includes/image.inc';
+ require_once './includes/form.inc';
+ require_once './includes/legacy.inc';
// Set the Drupal custom error handler.
set_error_handler('error_handler');
// Emit the correct charset HTTP header.
diff --git a/includes/form.inc b/includes/form.inc
new file mode 100644
index 000000000..0408db883
--- /dev/null
+++ b/includes/form.inc
@@ -0,0 +1,1078 @@
+<?php
+/**
+ * @defgroup form Form generation
+ * @{
+ * Functions to enable output of HTML forms and form elements.
+ *
+ * Drupal uses these functions to achieve consistency in its form presentation,
+ * while at the same time simplifying code and reducing the amount of HTML that
+ * must be explicitly generated by modules.
+ */
+
+/**
+ * Form property constants.
+ *
+ * These constants are defined to keep the namespace of the form tree available for elements.
+ * Properties are strings that start with '_' (underscore) and have special meaning for the form api.
+ */
+
+/**
+ * Keyword: type.
+ * Required: true
+ * Description: Used to specify the form element type. Form elements are defined by implementation of hook_elements.
+ */
+define('type', '_type');
+
+define('theme', '_theme');
+
+define('theme_used', '_theme_used');
+/**
+ * Keyword: name.
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: The form_builder function populates this property based on the location of the form element in the form tree.
+ */
+define('name', '_name');
+
+/**
+ * Keyword: id.
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: The form_builder function populates this property based on the location of the form element in the form tree.
+ * This is used for the form_set_error notification, along with the stylesheets to be used.
+ */
+define('id', '_id');
+
+/**
+ * Keyword: printed
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: Used by form_render to ascertain wether or not a form element has been printed yet
+ */
+define('printed', '_printed');
+
+/**
+ * Keyword: built
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: Used by _form_builder to ascertain wether or not a form element has been built yet
+ */
+define('built', '_built');
+
+/**
+ * Keyword: processed
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: Used by _form_builder to ascertain wether or not a form element has been processed (ie: expanded to multiple elements)
+ */
+define('processed', '_processed');
+
+
+/**
+ * Keyword: variable
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: used by form builder to populate a global form_variables array.
+ */
+define('variable', '_variable');
+
+/**
+ * Keyword: id.
+ * Internal: For use within the form api. Should not be set by the developer.
+ * Description: The form_builder function uses this property to keep track of the parent form elements, and uses this to generate the id and name properties.
+ */
+define('parents', '_parents');
+
+/**
+ * Keyword: input.
+ * Description: Wether or not an input is possible for this form element. True / False. Set in the hook_elements implementation.
+ */
+define('input', '_input');
+
+/**
+ * Keyword: validated.
+ * Description: Wether or not an input has been validated.
+ */
+define('validated', '_validated');
+
+/**
+ * Keyword: value.
+ * Used: For all form elements except 'textarea' and the 'default' fallback.
+ * Description: The value the form element should be set as. Setting this yourself is not required, although it might be a good idea for form elements that
+ * don't change. See the default_value property.
+ */
+define('value', '_value');
+
+/**
+ * Keyword: default_value.
+ * Used: For all form elements that have a value property.
+ * Description: The value the form element should be initialized as. If no submission for this element exists, the element will be set to this value.
+ * This means that you do not have to set the value properties for form elements, as they will be automatically handled by the form api.
+ */
+define('default_value', '_default_value');
+
+/**
+ * Keyword: return_value.
+ * Used: For select , radio and checkbox elements.
+ * Description: The value the form element will return.
+ */
+define('return_value', '_return_value');
+
+/**
+ * Keyword: title
+ * Used: For all form elements that have visible output.
+ * Description: The title of the form element. The developer should use the t() function to translate this property.
+ */
+define('title', '_title');
+
+/**
+ * Keyword: description
+ * Used: For all form elements that have visible output.
+ * Description: The description of the form element. The developer should use the t() function to translate this property.
+ */
+define('description', '_description');
+
+/**
+ * Keyword: required
+ * Used: For all form elements that have visible output.
+ * Description: Wether or not the element is required. This automatically validates for empty fields, and flags inputs as required.
+ */
+define('required', '_required');
+
+/**
+ * Keyword: cols
+ * Used: textarea elements.
+ * Description: How many columns wide the textarea should be.
+ */
+define('cols', '_cols');
+
+/**
+ * Keyword: rows
+ * Used: textarea elements.
+ * Description: How many rows high the textarea should be.
+ */
+define('rows', '_rows');
+
+/**
+ * Keyword: size
+ * Used: textfield elements.
+ * Description: How many characters wide should the textfield be.
+ */
+define('size', '_size');
+
+/**
+ * Keyword: maxlength
+ * Used: For textfield element types.
+ * Description: The maximum amount of characters to accept as input.
+ */
+define('maxlength', '_maxlength');
+
+/**
+ * Keyword: valid
+ * Used: For all form elements that have the value property.
+ * Description: A list of validation functions that need to be passed.
+ */
+define('valid', '_valid');
+define('validation_arguments', '_validation_arguments');
+
+/**
+ * Keyword: weight
+ * Used: all elements.
+ * Description: Used by the form_render function to sort the list of elements before being output.
+ */
+define('weight', '_weight');
+
+/**
+ * Keyword: collapsible
+ * Used: fieldset elements.
+ * Description: Wether or not the fieldset can be collapsed with javascript.
+ */
+define('collapsible', '_collapsible');
+
+/**
+ * Keyword: collapsed
+ * Used: fieldset elements.
+ * Description: Wether or not the fieldset is collapsed by default. See collapsible property.
+ */
+define('collapsed', '_collapsed');
+
+/**
+ * Keyword: autocomplete_path
+ * Used: textfield elements.
+ * Description: The path the AJAX autocomplete script uses as the source for autocompletion.
+ */
+define('autocomplete_path', '_autocomplete_path');
+
+/**
+ * Keyword: action
+ * Used: form elements.
+ * Description: The path to which the form will be submitted.
+ */
+define('action', '_action');
+
+/**
+ * Keyword: method
+ * Used: form elements.
+ * Description: The HTTP method the form will be submitted with (GET/POST). Default is 'post'.
+ */
+define('method', '_method');
+
+/**
+ * Keyword: attributes
+ * Used: all visible form elements.
+ * Description: Additional html attributes, such as 'class' can be set using this mechanism.
+ */
+define('attributes', '_attributes');
+
+/**
+ * Keyword: options
+ * Used: select boxes, checkboxes and radios form elements.
+ * Description: An associative array containing the options to be used. In the format 'return_value' => 'Display Value'
+ *
+ * It is possible to group options together; to do this, change the format of
+ * $options to an associative array in which the keys are group labels, and the
+ * values are associative arrays in the normal $options format.
+ */
+define('options', '_options');
+
+/**
+ * Keyword: extra
+ * Used: select boxes.
+ * Description: Additional HTML to inject into the select element tag.
+ */
+define('extra', '_extra');
+
+/**
+ * Keyword: multiple
+ * Used: select boxes.
+ * Description: Wether the user may select more than one item.
+ */
+define('multiple', '_multiple');
+
+/**
+ * Keyword: button_type
+ * Used: buttons.
+ * Description: The type of button to display (cancel or submit)
+ */
+define('button_type', '_button_type');
+
+
+
+/**
+ * Keyword: error
+ * Used: All visible form elements.
+ * Description: Wether or not a form element has been flagged as having an error.
+ */
+define('error', '_error');
+
+/**
+ * Keyword: prefix
+ * Used: markup element.
+ * Description: Text to include before the value and children properties.
+ */
+define('prefix', '_prefix');
+
+/**
+ * Keyword: suffix
+ * Used: markup element.
+ * Description: Text to include after the value and children properties.
+ */
+define('suffix', '_suffix');
+
+/**
+ * Keyword: error
+ * Used: weight form element.
+ * Description: Number of weights to have selectable.
+ */
+define('delta', '_delta');
+
+/**
+ * Multiple elements. For use in the poll module, and for file uploads.
+ */
+
+/**
+ * Keyword : process
+ * Used : By any element, used to modify a form element.
+ */
+define('process', '_process');
+
+/**
+ * Keyword: multiple
+ */
+define('multiple', '_multiple');
+
+/**
+ * Keyword: min
+ */
+define('minimum', '_minimum');
+
+/**
+ * Keyword: max
+ */
+define('maximum', '_maximum');
+
+/**
+ * Keyword: increment
+ */
+define('increment', '_increment');
+
+define('spawned', '_spawned');
+
+define('tree', '_tree');
+
+define('token', '_token');
+
+define('execute', '_execute');
+
+/**
+ * Check if the key is a property.
+ */
+function element_property($key) {
+ return (substr($key, 0, 1) == '_');
+}
+
+function element_properties($element) {
+ return array_filter(array_keys($element), 'element_property');
+}
+
+/**
+ * Check if the key is a child.
+ */
+function element_child($key) {
+ return (substr($key, 0, 1) != '_');
+}
+
+function element_children($element) {
+ return array_filter(array_keys($element), 'element_child');
+}
+
+/**
+ * Processes a form array, and produces the HTML output of a form.
+ * If there is input in the $_POST['edit'] variable, this function
+ * will attempt to validate it, using <code>drupal_validate_form</code>,
+ * and then execute the form using <code>drupal_execute_form</code>.
+ *
+ * @param $form_id
+ * A unique string identifying the form. Allows each form to be themed.
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $callback
+ * An optional callback that will be used in addition to the form_id.
+ *
+ */
+function drupal_get_form($form_id, &$form, $callback = NULL) {
+ global $form_values, $form_execute;
+ $form_values = array();
+ $form_execute = FALSE;
+ $form[type] = 'form';
+ $form[attributes]['class'] .= ' form-api';
+ if (isset($form[token])) {
+ $form['form_token'] = array(type => 'hidden', value => md5($_SERVER['REMOTE_ADDR'] . $form[token] . variable_get('drupal_private_key', '')));
+ }
+ $form = array_merge(_element_info('form'), $form);
+
+ foreach (module_implements('form_alter') as $module) {
+ $function = $module .'_form_alter';
+ $function($form);
+ }
+
+ $function = $form_id . '_alter';
+ if (function_exists($function)) {
+ $function($form);
+ }
+
+ if (!$form[built]) {
+ $form = _form_builder($form);
+ }
+ if ($form_execute) {
+ drupal_execute_form($form_id, $form, $callback);
+ }
+
+ if (function_exists('theme_' . $form_id)) {
+ $form[theme] = $form_id;
+ }
+ elseif (function_exists('theme_' . $callback)) {
+ $form[theme] = $callback;
+ }
+ return form_render($form);
+}
+
+function drupal_validate_form($form_id, &$form, $callback = NULL) {
+ global $form_values;
+
+ if (isset($form[token])) {
+ if ($form_values['form_token'] != md5($_SERVER['REMOTE_ADDR'] . $form[token] . variable_get('drupal_private_key', ''))) {
+ // setting this error will cause the form to fail validation
+ form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
+ }
+ }
+
+ foreach (module_implements('form_validate_alter') as $module) {
+ $function = $module .'_form_validate_alter';
+ $function($form_id, $form_values);
+ }
+
+ _form_validate($form);
+
+ if (function_exists($form_id . '_validate')) {
+ call_user_func($form_id . '_validate', $form_id, $form_values);
+ }
+ if (function_exists($callback . '_validate')) {
+ call_user_func($callback . '_validate', $form_id, $form_values);
+ }
+}
+
+function drupal_execute_form($form_id, $form, $callback = NULL) {
+ global $form_values;
+ if (!empty($_POST['edit'])) {
+ drupal_validate_form($form_id, $form, $callback);
+ if (!form_get_errors()) {
+ foreach (module_implements('form_execute_alter') as $module) {
+ $function = $module .'_form_execute_alter';
+ $function($form_id, $form_values);
+ }
+
+ if (function_exists($form_id . '_execute')) {
+ call_user_func($form_id . '_execute', $form_id, $form_values);
+ }
+ elseif (function_exists($callback . '_execute')) {
+ call_user_func($callback . '_execute', $form_id, $form_values);
+ }
+ }
+ }
+}
+
+function _form_validate(&$elements) {
+
+ // Recurse through all children.
+ foreach (element_children($elements) as $key) {
+ _form_validate($elements[$key]);
+ }
+
+ /* Validate the current input */
+ if (!$elements[validated] && $elements[input]) {
+ if ($elements[required]) {
+ if (!$elements[value]) {
+ form_error($elements, t('%name field is required', array('%name' => $elements[title])));
+ }
+ if ($elements[valid]) {
+ if (is_array($elements[valid])) {
+ foreach ($elements[valid] as $key => $valid) {
+ $args = is_array($elements[validation_arguments][$key]) ? $elements[validation_arguments][$key] : array();
+ if (function_exists('valid_' . $valid)) {
+ call_user_func_array('valid_' . $valid, array_merge(array($elements), $args));
+ }
+ }
+ }
+ else {
+ $args = is_array($elements[validation_arguments]) ? $elements[validation_arguments] : array();
+ if (function_exists('valid_' . $elements[valid])) {
+ call_user_func_array('valid_' . $elements[valid], array_merge(array($elements), $args));
+ }
+ }
+
+ }
+ }
+ $elements[validated] = TRUE;
+ }
+}
+
+/**
+ * Flag an element as having an error.
+ */
+function form_error(&$element, $message) {
+ $element[error] = TRUE;
+ $GLOBALS['form'][$element[name]] = $message;
+ drupal_set_message($message, 'error');
+}
+
+
+/**
+ * Adds some required properties to each form element, which are used internally in the form api.
+ * This function also automatically assigns the value property from the $edit array, provided the
+ * element doesn't already have an assigned value.
+ */
+function _form_builder($form, $parents = array(), $multiple = FALSE) {
+ global $form_values;
+ global $form_execute;
+
+ if ($form[built] == TRUE) {
+ return $form;
+ }
+ $form[built] = TRUE;
+
+ $form[parents] = ($form[parents]) ? $form[parents] : $parents;
+ /* Use element defaults */
+ if ((!empty($form[type])) && ($info = _element_info($form[type]))) {
+ $form += $info;
+ }
+
+ if ($form[input]) {
+ if (!$form[tree]) {
+ $form[parents] = array(array_pop($form[parents]));
+ }
+
+ $form[name] = ($form[name]) ? $form[name] : 'edit[' . implode('][', $form[parents]) . ']';
+ $form[id] = ($form[id]) ? $form[id] : 'edit-' . implode('-', $form[parents]);
+
+ $posted = isset($_POST['edit']);
+ $edit = $posted ? $_POST['edit'] : array();
+ $ref =& $form_values;
+ foreach ($form[parents] as $parent) {
+ $edit = isset($edit[$parent]) ? $edit[$parent] : NULL;
+ $ref =& $ref[$parent];
+ }
+ $default_value = $posted ? $edit : $form[default_value];
+ $form[value] = $form[value] ? $form[value] : $default_value;
+ if (isset($form[execute])) {
+ if ($_POST[$form[name]] == $form[value]) {
+ $form_execute = $form_execute || $form[execute];
+ }
+ }
+
+ $ref = $form[value];
+ }
+
+ // Allow for elements to expand to multiple elements. Radios, checkboxes and files for instance.
+ if (function_exists($form[process]) && !$form[processed]) {
+ $form = call_user_func($form[process], $form);
+ $form[processed] = TRUE;
+ }
+
+ // Recurse through all child elements.
+ $count = 0;
+ foreach (element_children($form) as $key) {
+ $form[$key][tree] = (isset($form[$key][tree])) ? $form[$key][tree] : $form[tree];
+ # Assign a decimal placeholder weight, to preserve original array order
+ $form[$key][weight] = $form[$key][weight] ? $form[$key][weight] : $count/10;
+ $form[$key] = _form_builder($form[$key], array_merge($form[parents], array($key)));
+ $count++;
+ }
+
+
+ return $form;
+}
+
+/**
+ * Renders a HTML form given an form tree. Recursively iterates over each of
+ * each of the form elements generating HTML code. This function is usually
+ * called from within a theme. To render a form from within a module, use
+ * <code>drupal_get_form()</code>.
+ *
+ * @param $elements
+ * The form tree describing the form.
+ * @return
+ * The rendered HTML form.
+ */
+function form_render(&$elements) {
+ $content = '';
+ if (is_array($elements)) {
+ uasort($elements, "_form_sort");
+ }
+
+ if (!$elements[children]) {
+ /* render all the children using a theme function */
+ if ($elements[theme] && !$elements[theme_used]) {
+ $elements[theme_used] = TRUE;
+ $previous_type = $elements[type];
+ $elements[type] = 'markup';
+ $content = theme($elements[theme], $elements);
+ $elements[type] = $previous_type;
+ }
+ /* render each of the children using form_render and concatenate them */
+ if (!$content) {
+ foreach (element_children($elements) as $key) {
+ $content .= form_render($elements[$key]);
+ }
+ }
+ }
+ if ($content) {
+ $elements[children] = $content;
+ }
+
+ /* Call the form element renderer */
+ if (!$elements[printed]) {
+ $content = theme(($elements[type]) ? $elements[type]: 'markup', $elements);
+ $elements[printed] = TRUE;
+ }
+
+ return $elements[prefix] . $content . $elements[suffix];
+}
+
+function _print_rp($var) {
+ echo "<pre>";
+ print_r($var);
+ echo "</pre>";
+}
+
+/**
+ * Function used by uasort in form render to sort form via weight.
+ */
+function _form_sort($a, $b) {
+ if ($a[weight] == $b[weight]) {
+ return 0;
+ }
+ return ($a[weight] < $b[weight]) ? -1 : 1;
+}
+
+/**
+ * Retrieve the default properties for the defined element type.
+ */
+function _element_info($type, $refresh = null) {
+ static $cache;
+ $basic_defaults = array(
+ description => NULL,
+ attributes => array(),
+ required => FALSE,
+ tree => FALSE
+ );
+ if ($refresh || !is_array($cache)) {
+ $cache = array();
+ foreach (module_implements('elements') as $module) {
+ $elements = module_invoke($module, 'elements');
+ if (is_array($elements)) {
+ $cache = array_merge($cache, $elements);
+ }
+ }
+ if (sizeof($cache)) {
+ foreach ($cache as $element_type => $info) {
+ $cache[$element_type] = array_merge($basic_defaults, $info);
+ }
+ }
+ }
+
+ return $cache[$type];
+}
+
+/**
+ * Format a dropdown menu or scrolling selection box.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, options, description, extra, multiple, required
+ * @return
+ * A themed HTML string representing the form element.
+ *
+ * It is possible to group options together; to do this, change the format of
+ * $options to an associative array in which the keys are group labels, and the
+ * values are associative arrays in the normal $options format.
+ */
+function theme_select($element) {
+ $select = '';
+ foreach ($element[options] as $key => $choice) {
+ if (is_array($choice)) {
+ $select .= '<optgroup label="'. $key .'">';
+ foreach ($choice as $key => $choice) {
+ $select .= '<option value="'. $key .'"'. (is_array($elementp[value]) ? (in_array($key, $element[value]) ? ' selected="selected"' : '') : ($element[value] == $key ? ' selected="selected"' : '')) .'>'. check_plain($choice) .'</option>';
+ }
+ $select .= '</optgroup>';
+ }
+ else {
+ $select .= '<option value="'. $key .'"'. (is_array($element[value]) ? (in_array($key, $element[value]) ? ' selected="selected"' : '') : ($element[value] == $key ? ' selected="selected"' : '')) .'>'. check_plain($choice) .'</option>';
+ }
+ }
+ return theme('form_element', $element[title], '<select name="'. $element[name] .''. ($element[multiple] ? '[]' : '') .'"'. ($element[multiple] ? ' multiple="multiple" ' : '') . ($element[extra] ? ' '. $element[extra] : '') .' id="' . $element[id] .'">'. $select .'</select>', $element[description], $element[name], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Format a group of form items.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : attributes, title, description, children, collapsible, collapsed
+ * @return
+ * A themed HTML string representing the form item group.
+ */
+function theme_fieldset($element) {
+ if ($element[collapsible]) {
+ drupal_add_js('misc/collapse.js');
+
+ $element[attributes]['class'] .= ' collapsible';
+ if ($element[collapsed]) {
+ $element[attributes]['class'] .= ' collapsed';
+ }
+ }
+
+ return '<fieldset' . drupal_attributes($element[attributes]) .'>' . ($element[title] ? '<legend>'. $element[title] .'</legend>' : '') . $element[children] . $element[value] . ($element[description] ? '<div class="description">'. $element[description] .'</div>' : '') . "</fieldset>\n";
+
+}
+
+
+/**
+ * Format a radio button.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : required, return_value, value, attributes, title, description
+ * @return
+ * A themed HTML string representing the form item group.
+ */
+function theme_radio($element) {
+ $output = '<input type="radio" ';
+ $output .= 'class="'. _form_get_class('form-radio', $element[required], _form_get_error($element[name])) .'" ';
+ $output .= 'name="' . $element[name] .'" ';
+ $output .= 'value="'. $element[return_value] .'" ';
+ $output .= ($element[value] == $element[return_value]) ? ' checked="checked" ' : ' ';
+ $output .= drupal_attributes($element[attributes]) .' />';
+ if (!is_null($element[title])) {
+ $output = '<label class="option">'. $output .' '. $element[title] .'</label>';
+ }
+ return theme('form_element', NULL, $output, $element[description], $element[name], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Format a set of radio buttons.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, options, description, required and attributes.
+ * @return
+ * A themed HTML string representing the radio button set.
+ */
+function theme_radios($element) {
+ if ($element[title] || $element[description]) {
+ return theme('form_element', $element[title], $element[children], $element[description], $element[id], $element[required], _form_get_error($element[name]));
+ }
+ else {
+ return $element[children];
+ }
+}
+
+/**
+ * Format a set of radio buttons.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, options, description, required and attributes.
+ * @return
+ * A themed HTML string representing the radio button set.
+ */
+function theme_date($element) {
+ $output = '<div class="container-inline">' . $element[children] . '</div>';
+ return theme('form_element', $element[title], $output, $element[description], $element[id], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Roll out a single checkbox element to a list of checkboxes, using the options array as index.
+ */
+function expand_date($element) {
+ // Default to current date
+ if (!isset($element[value])) {
+ $element[value] = array('day' => format_date(time(), 'custom', 'j'),
+ 'month' => format_date(time(), 'custom', 'n'),
+ 'year' => format_date(time(), 'custom', 'Y'));
+ }
+
+ // Determine the order of day, month, year in the site's chosen date format.
+ $format = variable_get('date_format_short', 'm/d/Y');
+ $sort = array();
+ $sort['day'] = max(strpos($format, 'd'), strpos($format, 'j'));
+ $sort['month'] = max(strpos($format, 'm'), strpos($format, 'M'));
+ $sort['year'] = strpos($format, 'Y');
+ asort($sort);
+ $order = array_keys($sort);
+
+ // Output multi-selector for date
+ foreach ($order as $type) {
+ switch ($type) {
+ case 'day':
+ $options = drupal_map_assoc(range(1, 31));
+ break;
+ case 'month':
+ $options = drupal_map_assoc(range(1, 12), '_profile_map_month');
+ break;
+ case 'year':
+ $options = drupal_map_assoc(range(1900, 2050));
+ break;
+ }
+ $element[$type] = array(type => 'radio', value => $element[value][$type], attributes => $element[attributes], parents => $element[parents], options => $options, tree => TRUE);
+ }
+
+ return $element;
+}
+
+
+/**
+ * Roll out a single checkbox element to a list of checkboxes, using the options array as index.
+ */
+function expand_radios($element) {
+ if (count($element[options]) > 0) {
+ foreach ($element[options] as $key => $choice) {
+ if (!$element[$key]) {
+ $element[$key] = array(type => 'radio', title => $choice, return_value => $key, default_value => $element[default_value], attributes => $element[attributes], parents => $element[parents], spawned => TRUE);
+ }
+ }
+ }
+
+ return $element;
+}
+
+
+/**
+ * Format a form item.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, description, required, error
+ * @return
+ * A themed HTML string representing the form item.
+ */
+function theme_item($element) {
+ return theme('form_element', $element[title], $element[value] . $element[children], $element[description], $element[id], $element[required], $element[error]);
+}
+
+
+/**
+ * Format a checkbox.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, return_value, description, required
+ * @return
+ * A themed HTML string representing the checkbox.
+ */
+function theme_checkbox($element) {
+ $checkbox = '<input ';
+ $checkbox .= 'type="checkbox" ';
+ $checkbox .= 'class="'. _form_get_class('form-checkbox', $element[required], _form_get_error($element[name])) . '" ';
+ $checkbox .= 'name="'. $element[name] .'" ';
+ $checkbox .= 'id="'. $element[id].'" ' ;
+ $checkbox .= 'value="'. $element[return_value] .'" ';
+ $checkbox .= ($element[value] == $element[return_value]) ? ' checked="checked" ' : ' ';
+ $checkbox .= drupal_attributes($element[attributes]) . ' />';
+
+ if (!is_null($element[title])) {
+ $checkbox = '<label class="option">'. $checkbox .' '. $element[title] .'</label>';
+ }
+
+ return theme('form_element', NULL, $checkbox, $element[description], $element[name], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Format a set of checkboxes.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * @return
+ * A themed HTML string representing the checkbox set.
+ */
+function theme_checkboxes($element) {
+ if ($element[title] || $element[description]) {
+ return theme('form_element', $element[title], $element[children], $element[description], 'edit-'. $element[name], $element[required], _form_get_error($element[name]));
+ }
+ else {
+ return $element[children];
+ }
+}
+
+function expand_checkboxes($element) {
+ $value = is_array($element[value]) ? $element[value] : array();
+ if (count($element[options]) > 0) {
+ if (!isset($element[default_value]) || $element[default_value] == 0) {
+ $element[default_value] = array();
+ }
+ foreach ($element[options] as $key => $choice) {
+ if (!isset($element[$key])) {
+ $element[$key] = array(
+ type => 'checkbox', processed => TRUE, title => $choice, tree => TRUE,
+ value => in_array($key, $value), attributes => $element[attributes]
+ );
+ }
+ }
+ }
+ return $element;
+}
+
+
+function theme_submit($element) {
+ return theme('button', $element);
+}
+
+function theme_button($element) {
+ return '<input type="submit" class="form-'. $element[button_type] .'" name="'. $element[name] .'" value="'. check_plain($element[value]) .'" '. drupal_attributes($element[attributes]) ." />\n";
+}
+
+/**
+ * Format a hidden form field.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : value, edit
+ * @return
+ * A themed HTML string representing the hidden form field.
+ */
+function theme_hidden($element) {
+ return '<input type="hidden" name="'. $element[name] . '" id="' . $element[id] . '" value="'. check_plain($element[value]) ."\" " . drupal_attributes($element[attributes]) ." />\n";
+}
+
+/**
+ * Format a textfield.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, description, size, maxlength, required, attributes autocomplete_path
+ * @return
+ * A themed HTML string representing the textfield.
+ */
+function theme_textfield($element) {
+ $size = $element[size] ? ' size="' . $element[size] . '"' : '';
+ if ($element[autocomplete_path]) {
+ drupal_add_js('misc/autocomplete.js');
+ $class = ' form-autocomplete';
+ $extra = '<input class="autocomplete" type="hidden" id="'. $element[id] .'-autocomplete" value="'. check_url(url($element[autocomplete_path], NULL, NULL, TRUE)) .'" disabled="disabled" />';
+ }
+
+ $output = '<input type="text" maxlength="'. $element[maxlength] .'" class="'. _form_get_class("form-text$class", $element[required], _form_get_error($element[name])) .'" name="'. $element[name] .'" id="'. $element[id] .'" '. $size .' value="'. check_plain($element[value]) .'"'. drupal_attributes($element[attributes]) .' />';
+ return theme('form_element', $element[title], $output, $element[description], $element[id], $element[required], _form_get_error($element[name])). $extra;
+}
+
+/**
+ * Format a form.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : action, method, attributes, children
+ * @return
+ * A themed HTML string representing the form.
+ */
+function theme_form($element) {
+ // Anonymous div to satisfy XHTML compliancy.
+ $action = $element[action] ? 'action="' . check_url($element[action]) . '" ' : '';
+ return '<form '. $action . ' method="'. $element[method] .'" '. drupal_attributes($element[attributes]) .">\n<div>". $element[children] ."\n</div></form>\n";
+}
+
+
+/**
+ * Format a textarea.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, value, description, rows, cols, required, attributes
+ * @return
+ * A themed HTML string representing the textarea.
+ */
+function theme_textarea($element) {
+ $cols = $element[cols] ? ' cols="'. $element[cols] .'"' : '';
+
+ return theme('form_element', $element[title], '<textarea'. $cols .' rows="'. $element[rows] .'" name="'. $element[name] .'" id="' . $element[id] .'" class="'. _form_get_class('textarea', $element[required], _form_get_error($element[name])) .'"'. drupal_attributes($element[attributes]) .'>'. check_plain($element[value]) .'</textarea>', $element[description], $element[id], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Format HTML markup for use in forms.
+ *
+ * This is used in more advanced forms, such as theme selection and filter format.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : prefix, value, children and suffix.
+ * @return
+ * A themed HTML string representing the HTML markup.
+ */
+
+function theme_markup($element) {
+ return $element[value] . $element[children];
+}
+
+
+
+/**
+* Format a password field.
+*
+* @param $element
+* An associative array containing the properties of the element.
+* Properties used : title, value, description, size, maxlength, required, attributes
+* @return
+* A themed HTML string representing the form.
+*/
+function theme_password($element) {
+ $size = $element[size] ? ' size="'. $element[size] .'" ' : '';
+
+ $output = '<input type="password" maxlength="'. $element[maxlength] .'" class="'. _form_get_class("form-text $class", $element[required], _form_get_error($element[name])) .'" name="'. $element[name] .'" id="'. $element[id] .'" '. $size . drupal_attributes($element[attributes]) .' />';
+
+ return theme('form_element', $element[title], $output, $element[description], $element[id], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Format a weight selection menu.
+ *
+ * @param $element
+ * An associative array containing the properties of the element.
+ * Properties used : title, delta, description
+ * @return
+ * A themed HTML string representing the form.
+ */
+function theme_weight($element) {
+ for ($n = (-1 * $element[delta]); $n <= $element[delta]; $n++) {
+ $weights[$n] = $n;
+ }
+ $element[options] = $weights;
+ $element[type] = 'select';
+
+ return form_render($element);
+}
+
+/**
+ * File an error against the form element with the specified name.
+ */
+function form_set_error($name, $message) {
+ $GLOBALS['form'][$name] = $message;
+ drupal_set_message($message, 'error');
+}
+
+/**
+ * Return an associative array of all errors.
+ */
+function form_get_errors() {
+ if (array_key_exists('form', $GLOBALS)) {
+ return $GLOBALS['form'];
+ }
+}
+
+/**
+ * Format a file upload field.
+ *
+ * @param $title
+ * The label for the file upload field.
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $size
+ * A measure of the visible size of the field (passed directly to HTML).
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $required
+ * Whether the user must upload a file to the field.
+ * @return
+ * A themed HTML string representing the field.
+ *
+ * For assistance with handling the uploaded file correctly, see the API
+ * provided by file.inc.
+ */
+function theme_file($element) {
+ return theme('form_element', $element[title], '<input type="file" class="'. _form_get_class('form-file', $element[required], _form_get_error($element[name])) .'" name="'. $element[name] .'" id="'. form_clean_id($element[id]) .'" size="'. $element[size] ."\" />\n", $element[description], $element[id], $element[required], _form_get_error($element[name]));
+}
+
+/**
+ * Return the error message filed against the form with the specified name.
+ */
+function _form_get_error($name) {
+ if (array_key_exists('form', $GLOBALS)) {
+ return $GLOBALS['form'][$name];
+ }
+}
+
+function _form_get_class($name, $required, $error) {
+ return $name. ($required ? ' required' : '') . ($error ? ' error' : '');
+}
+
+/**
+ * Remove invalid characters from an HTML ID attribute string
+ *
+ * @param $id
+ * The ID to clean
+ * @return
+ * The cleaned ID
+ */
+function form_clean_id($id = NULL) {
+ $id = str_replace('][', '-', $id);
+ return $id;
+}
+
+/**
+ * @} End of "defgroup form".
+ */
+
+?>
diff --git a/includes/legacy.inc b/includes/legacy.inc
new file mode 100644
index 000000000..ad17aeaa5
--- /dev/null
+++ b/includes/legacy.inc
@@ -0,0 +1,584 @@
+<?
+
+/**
+ * An unchecked checkbox is not present in $_POST so we fix it here by
+ * proving a default value of 0. Also, with form_checkboxes() we expect
+ * an array, but HTML does not send the empty array. This is also taken
+ * care off.
+ */
+function fix_checkboxes() {
+ if (isset($_POST['form_array'])) {
+ $_POST['edit'] = _fix_checkboxes($_POST['edit'], $_POST['form_array'], array());
+ }
+ if (isset($_POST['form_zero'])) {
+ $_POST['edit'] = _fix_checkboxes($_POST['edit'], $_POST['form_zero'], 0);
+ }
+}
+
+function _fix_checkboxes($array1, $array2, $value) {
+ if (is_array($array2) && count($array2)) {
+ foreach ($array2 as $k => $v) {
+ if (is_array($v) && count($v)) {
+ $array1[$k] = _fix_checkboxes($array1[$k], $v, $value);
+ }
+ else if (!isset($array1[$k])) {
+ $array1[$k] = $value;
+ }
+ }
+ }
+ else {
+ $array1 = $value;
+ }
+ return $array1;
+}
+/**
+ * @defgroup form Form generation (deprecated)
+ * @{
+ * Functions to enable output of HTML forms and form elements.
+ *
+ * Drupal uses these functions to achieve consistency in its form presentation,
+ * while at the same time simplifying code and reducing the amount of HTML that
+ * must be explicitly generated by modules.
+ */
+
+/**
+ * Generate a form from a set of form elements.
+ *
+ * @param $form
+ * An HTML string containing one or more form elements.
+ * @param $method
+ * The query method to use ("post" or "get").
+ * @param $action
+ * The URL to send the form contents to, if not the current page.
+ * @param $attributes
+ * An associative array of attributes to add to the form tag.
+ * @result
+ * An HTML string with the contents of $form wrapped in a form tag.
+ */
+function form($form, $method = 'post', $action = NULL, $attributes = NULL) {
+ if (!$action) {
+ $action = request_uri();
+ }
+ // Anonymous div to satisfy XHTML compliancy.
+ return '<form action="'. check_url($action) .'" method="'. $method .'"'. drupal_attributes($attributes) .">\n<div>". $form ."\n</div></form>\n";
+}
+/**
+ * Format a general form item.
+ *
+ * @param $title
+ * The label for the form item.
+ * @param $value
+ * The contents of the form item.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $id
+ * A unique identifier for the form item.
+ * @param $required
+ * Whether the user must fill in this form element before submitting the form.
+ * @param $error
+ * An error message to display alongside the form element.
+ * @return
+ * A themed HTML string representing the form item.
+ */
+function form_item($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) {
+ return theme('form_element', $title, $value, $description, $id, $required, $error);
+}
+
+/**
+ * Format a group of form items.
+ *
+ * @param $legend
+ * The label for the form item group.
+ * @param $group
+ * The form items within the group, as an HTML string.
+ * @param $description
+ * Explanatory text to display after the form item group.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the fieldset tag.
+ * @return
+ * A themed HTML string representing the form item group.
+ */
+function form_group($legend, $group, $description = NULL, $attributes = NULL) {
+ return '<fieldset' . drupal_attributes($attributes) .'>' . ($legend ? '<legend>'. $legend .'</legend>' : '') . $group . ($description ? '<div class="description">'. $description .'</div>' : '') . "</fieldset>\n";
+}
+
+/**
+ * Format a group of form items.
+ *
+ * @param $legend
+ * The label for the form item group.
+ * @param $group
+ * The form items within the group, as an HTML string.
+ * @param $collapsed
+ * A boolean value decided whether the group starts collapsed.
+ * @param $description
+ * Explanatory text to display after the form item group.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the fieldset tag.
+ * @return
+ * A themed HTML string representing the form item group.
+ */
+function form_group_collapsible($legend, $group, $collapsed = FALSE, $description = NULL, $attributes = NULL) {
+ drupal_add_js('misc/collapse.js');
+
+ $attributes['class'] .= ' collapsible';
+ if ($collapsed) {
+ $attributes['class'] .= ' collapsed';
+ }
+
+ return '<fieldset' . drupal_attributes($attributes) .'>' . ($legend ? '<legend>'. $legend .'</legend>' : '') . $group . ($description ? '<div class="description">'. $description .'</div>' : '') . "</fieldset>\n";
+}
+
+/**
+ * Format a radio button.
+ *
+ * @param $title
+ * The label for the radio button.
+ * @param $name
+ * The internal name used to refer to the button.
+ * @param $value
+ * The value that the form element takes on when selected.
+ * @param $checked
+ * Whether the button will be initially selected when the page is rendered.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the button.
+ * @param $required
+ * Whether the user must select this radio button before submitting the form.
+ * @return
+ * A themed HTML string representing the radio button.
+ */
+function form_radio($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) {
+ $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, $name, $required, _form_get_error($name));
+}
+
+/**
+ * Format a set of radio buttons.
+ *
+ * @param $title
+ * The label for the radio buttons as a group.
+ * @param $name
+ * The internal name used to refer to the buttons.
+ * @param $value
+ * The currently selected radio button's key.
+ * @param $options
+ * An associative array of buttons to display. The keys in this array are
+ * button values, while the values are the labels to display for each button.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $required
+ * Whether the user must select a radio button before submitting the form.
+ * @param $attributes
+ * An associative array of HTML attributes to add to each button.
+ * @return
+ * A themed HTML string representing the radio button set.
+ */
+function form_radios($title, $name, $value, $options, $description = NULL, $required = FALSE, $attributes = NULL) {
+ if (count($options) > 0) {
+ $choices = '';
+ foreach ($options as $key => $choice) {
+ $choices .= '<label class="option"><input type="radio" class="form-radio" name="edit['. $name .']" value="'. $key .'"'. ($key == $value ? ' checked="checked"' : ''). drupal_attributes($attributes) .' /> '. $choice .'</label><br />';
+ }
+ return theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name));
+ }
+}
+
+/**
+ * Format a checkbox.
+ *
+ * @param $title
+ * The label for the checkbox.
+ * @param $name
+ * The internal name used to refer to the button.
+ * @param $value
+ * The value that the form element takes on when selected.
+ * @param $checked
+ * Whether the button will be initially selected when the page is rendered.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the button.
+ * @param $required
+ * Whether the user must check this box before submitting the form.
+ * @return
+ * A themed HTML string representing the checkbox.
+ */
+function form_checkbox($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) {
+ $element = '<input type="checkbox" class="'. _form_get_class('form-checkbox', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name).'" value="'. $value .'"'. ($checked ? ' checked="checked"' : '') . drupal_attributes($attributes) .' />';
+ if (!is_null($title)) {
+ $element = '<label class="option">'. $element .' '. $title .'</label>';
+ }
+ return form_hidden($name, 1, 'form_zero') . theme('form_element', NULL, $element, $description, $name, $required, _form_get_error($name));
+}
+
+/**
+ * Format a set of checkboxes.
+ *
+ * @param $title
+ * The label for the checkboxes as a group.
+ * @param $name
+ * The internal name used to refer to the buttons.
+ * @param $values
+ * A linear array of keys of the initially checked boxes.
+ * @param $options
+ * An associative array of buttons to display. The keys in this array are
+ * button values, while the values are the labels to display for each button.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to each button.
+ * @param $required
+ * Whether the user must check a box before submitting the form.
+ * @return
+ * A themed HTML string representing the checkbox set.
+ */
+function form_checkboxes($title, $name, $values, $options, $description = NULL, $attributes = NULL, $required = FALSE) {
+ if (count($options) > 0) {
+ if (!isset($values) || $values == 0) {
+ $values = array();
+ }
+ $choices = '';
+ 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"' : ''). drupal_attributes($attributes) .' /> '. $choice .'</label><br />';
+ }
+ return form_hidden($name, 1, 'form_array') . theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name));
+ }
+}
+
+/**
+ * Format a single-line text field.
+ *
+ * @param $title
+ * The label for the text field.
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $value
+ * The initial value for the field at page load time.
+ * @param $size
+ * A measure of the visible size of the field (passed directly to HTML).
+ * @param $maxlength
+ * The maximum number of characters that may be entered in the field.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the form item.
+ * @param $required
+ * Whether the user must enter some text in the field.
+ * @return
+ * A themed HTML string representing the field.
+ */
+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_get_class('form-text', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'"'. $size .' value="'. check_plain($value) .'"'. drupal_attributes($attributes) .' />', $description, 'edit-'. $name, $required, _form_get_error($name));
+}
+
+/**
+ * Format a single-line text field that uses Ajax for autocomplete.
+ *
+ * @param $title
+ * The label for the text field.
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $value
+ * The initial value for the field at page load time.
+ * @param $size
+ * A measure of the visible size of the field (passed directly to HTML).
+ * @param $maxlength
+ * The maximum number of characters that may be entered in the field.
+ * @param $callback_path
+ * A drupal path for the Ajax autocomplete callback.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the form item.
+ * @param $required
+ * Whether the user must enter some text in the field.
+ * @return
+ * A themed HTML string representing the field.
+ */
+function form_autocomplete($title, $name, $value, $size, $maxlength, $callback_path, $description = NULL, $attributes = NULL, $required = FALSE) {
+ drupal_add_js('misc/autocomplete.js');
+
+ $size = $size ? ' size="'. $size .'"' : '';
+
+ $output = theme('form_element', $title, '<input type="text" maxlength="'. $maxlength .'" class="'. _form_get_class('form-text form-autocomplete', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'"'. $size .' value="'. check_plain($value) .'"'. drupal_attributes($attributes) .' />', $description, 'edit-'. $name, $required, _form_get_error($name));
+ $output .= '<input class="autocomplete" type="hidden" id="edit-'. form_clean_id($name) .'-autocomplete" value="'. check_url(url($callback_path, NULL, NULL, TRUE)) .'" disabled="disabled" />';
+
+ return $output;
+}
+
+/**
+ * Format a single-line text field that does not display its contents visibly.
+ *
+ * @param $title
+ * The label for the text field.
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $value
+ * The initial value for the field at page load time.
+ * @param $size
+ * A measure of the visible size of the field (passed directly to HTML).
+ * @param $maxlength
+ * The maximum number of characters that may be entered in the field.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the form item.
+ * @param $required
+ * Whether the user must enter some text in the field.
+ * @return
+ * A themed HTML string representing the field.
+ */
+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_get_class('form-password', $required, _form_get_error($name)) .'" maxlength="'. $maxlength .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'"'. $size .' value="'. check_plain($value) .'"'. drupal_attributes($attributes) .' />', $description, 'edit-'. $name, $required, _form_get_error($name));
+}
+
+/**
+ * Format a multiple-line text field.
+ *
+ * @param $title
+ * The label for the text field.
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $value
+ * The initial value for the field at page load time.
+ * @param $cols
+ * The width of the field, in columns of text.
+ * @param $rows
+ * The height of the field, in rows of text.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the form item.
+ * @param $required
+ * Whether the user must enter some text in the field.
+ * @return
+ * A themed HTML string representing the field.
+ */
+function form_textarea($title, $name, $value, $cols, $rows, $description = NULL, $attributes = NULL, $required = FALSE) {
+ $cols = $cols ? ' cols="'. $cols .'"' : '';
+ $pre = '';
+ $post = '';
+
+ // optionally plug in a WYSIWYG editor
+ foreach (module_list() as $module_name) {
+ if (module_hook($module_name, 'textarea')) {
+ $pre .= module_invoke($module_name, 'textarea', 'pre', $name);
+ $post .= module_invoke($module_name, 'textarea', 'post', $name);
+ }
+ }
+
+ return theme('form_element', $title, $pre .'<textarea'. $cols .' rows="'. $rows .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'" class="'. _form_get_class('textarea', $required, _form_get_error($name)) .'"'. drupal_attributes($attributes) .'>'. check_plain($value) .'</textarea>'. $post, $description, 'edit-'. $name, $required, _form_get_error($name));
+}
+
+/**
+ * Format a dropdown menu or scrolling selection box.
+ *
+ * @param $title
+ * The label for the form element.
+ * @param $name
+ * The internal name used to refer to the form element.
+ * @param $value
+ * The key of the currently selected item, or a linear array of keys of all the
+ * currently selected items if multiple selections are allowed.
+ * @param $options
+ * An associative array of buttons to display. The keys in this array are
+ * button values, while the values are the labels to display for each button.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $extra
+ * Additional HTML to inject into the select element tag.
+ * @param $multiple
+ * Whether the user may select more than one item.
+ * @param $required
+ * Whether the user must select a value before submitting the form.
+ * @return
+ * A themed HTML string representing the form element.
+ *
+ * It is possible to group options together; to do this, change the format of
+ * $options to an associative array in which the keys are group labels, and the
+ * values are associative arrays in the normal $options format.
+ */
+function form_select($title, $name, $value, $options, $description = NULL, $extra = 0, $multiple = FALSE, $required = FALSE) {
+ $select = '';
+ foreach ($options as $key => $choice) {
+ if (is_array($choice)) {
+ $select .= '<optgroup label="'. $key .'">';
+ foreach ($choice as $key => $choice) {
+ $select .= '<option value="'. $key .'"'. (is_array($value) ? (in_array($key, $value) ? ' selected="selected"' : '') : ($value == $key ? ' selected="selected"' : '')) .'>'. check_plain($choice) .'</option>';
+ }
+ $select .= '</optgroup>';
+ }
+ else {
+ $select .= '<option value="'. $key .'"'. (is_array($value) ? (in_array($key, $value) ? ' selected="selected"' : '') : ($value == $key ? ' selected="selected"' : '')) .'>'. check_plain($choice) .'</option>';
+ }
+ }
+ return theme('form_element', $title, '<select name="edit['. $name .']'. ($multiple ? '[]' : '') .'"'. ($multiple ? ' multiple="multiple" ' : '') . ($extra ? ' '. $extra : '') .' id="edit-'. form_clean_id($name) .'">'. $select .'</select>', $description, 'edit-'. $name, $required, _form_get_error($name));
+}
+
+/**
+ * Format a file upload field.
+ *
+ * @param $title
+ * The label for the file upload field.
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $size
+ * A measure of the visible size of the field (passed directly to HTML).
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $required
+ * Whether the user must upload a file to the field.
+ * @return
+ * A themed HTML string representing the field.
+ *
+ * For assistance with handling the uploaded file correctly, see the API
+ * provided by file.inc.
+ */
+function form_file($title, $name, $size, $description = NULL, $required = FALSE) {
+ return theme('form_element', $title, '<input type="file" class="'. _form_get_class('form-file', $required, _form_get_error($name)) .'" name="edit['. $name .']" id="edit-'. form_clean_id($name) .'" size="'. $size ."\" />\n", $description, 'edit-'. $name, $required, _form_get_error($name));
+}
+
+/**
+ * Store data in a hidden form field.
+ *
+ * @param $name
+ * The internal name used to refer to the field.
+ * @param $value
+ * The stored data.
+ * @param $edit
+ * The array name to prefix to the $name.
+ * @param $attributes
+ * An array of HTML attributes for the input tag.
+ * @return
+ * A themed HTML string representing the hidden field.
+ *
+ * This function can be useful in retaining information between page requests,
+ * but be sure to validate the data on the receiving page as it is possible for
+ * an attacker to change the value before it is submitted.
+ */
+function form_hidden($name, $value, $edit = 'edit', $attributes = NULL) {
+ return '<input type="hidden" name="'. $edit .'['. $name .']" id="'. form_clean_id($edit .'-'. $name) .'" value="'. check_plain($value) .'"'. drupal_attributes($attributes) ." />\n";
+}
+
+/**
+ * Format an action button.
+ *
+ * @param $value
+ * Both the label for the button, and the value passed to the target page
+ * when this button is clicked.
+ * @param $name
+ * The internal name used to refer to the button.
+ * @param $type
+ * What type to pass to the HTML input tag.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the form item.
+ * @return
+ * A themed HTML string representing the button.
+ */
+function form_button($value, $name = 'op', $type = 'submit', $attributes = NULL) {
+ return '<input type="'. $type .'" class="form-'. $type .'" name="'. $name .'" id="'. form_clean_id($name) .'" value="'. check_plain($value) .'" '. drupal_attributes($attributes) ." />\n";
+}
+
+/**
+ * Format a form submit button.
+ *
+ * @param $value
+ * Both the label for the button, and the value passed to the target page
+ * when this button is clicked.
+ * @param $name
+ * The internal name used to refer to the button.
+ * @param $attributes
+ * An associative array of HTML attributes to add to the form item.
+ * @return
+ * A themed HTML string representing the button.
+ */
+function form_submit($value, $name = 'op', $attributes = NULL) {
+ return form_button($value, $name, 'submit', $attributes);
+}
+
+/**
+ * Format a weight selection menu.
+ *
+ * @param $title
+ * The label for the form element.
+ * @param $name
+ * The internal name used to refer to the form element.
+ * @param $value
+ * The selected weight value at page load time.
+ * @param $delta
+ * The largest in absolute value the weight can be. For example, if set to 10,
+ * weights could range from -10 to 10 inclusive.
+ * @param $description
+ * Explanatory text to display after the form item.
+ * @param $extra
+ * Additional HTML to inject into the select element tag.
+ * @return
+ * A themed HTML string representing the form element.
+ */
+function form_weight($title = NULL, $name = 'weight', $value = 0, $delta = 10, $description = NULL, $extra = 0) {
+ for ($n = (-1 * $delta); $n <= $delta; $n++) {
+ $weights[$n] = $n;
+ }
+
+ return form_select($title, $name, $value, $weights, $description, $extra);
+}
+
+/**
+ * Set a hidden 'form_token' field to be included in a form, used to validate
+ * that the resulting submission was actually generated by a local form.
+ *
+ * @param $key
+ * A unique key to identify the form that is currently being displayed.
+ * This identical key is later used to validate that the resulting submission
+ * actually originated with this form.
+ * @result
+ * A themed HTML string representing the hidden token field.
+ */
+function form_token($key) {
+ // this private key should always be kept secret
+ if (!variable_get('drupal_private_key', '')) {
+ variable_set('drupal_private_key', mt_rand());
+ }
+
+ // the verification token is an md5 hash of the form key and our private key
+ return form_hidden('form_token', md5($_SERVER['REMOTE_ADDR'] . $key . variable_get('drupal_private_key', '')));
+}
+
+/**
+ * Verify that the hidden 'form_token' field was actually generated with our
+ * private key.
+ *
+ * @param $edit
+ * An array containing the form that needs to be validated.
+ * @param $key
+ * The same key that was used to generate the 'form_token'.
+ * @param $error_message
+ * An optional error message to display if the form does not validate.
+ * @result
+ * There is nothing returned from this function, but if the 'form_token' does
+ * not validate an error is generated, preventing the submission.
+ */
+function form_validate($edit, $key, $error_message = NULL) {
+ if ($error_message == NULL) {
+ // set a generic default error message
+ $error = t('Validation error, please try again. If this error persists, please contact the site administrator.');
+ }
+
+ if ($edit['form_token'] != md5($_SERVER['REMOTE_ADDR'] . $key . variable_get('drupal_private_key', ''))) {
+ // setting this error will cause the form to fail validation
+ form_set_error('form_token', $error);
+ }
+}
+
+/**
+ * @} End of "defgroup form".
+ */
+
+
diff --git a/includes/locale.inc b/includes/locale.inc
index 0bacb47e3..8779a8c67 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -36,17 +36,22 @@ function _locale_add_language($code, $name, $onlylanguage = TRUE) {
* User interface for the language management screen
*/
function _locale_admin_manage_screen() {
- $edit = &$_POST['edit'];
$languages = locale_supported_languages(TRUE, TRUE);
- $header = array(array('data' => t('Code')), array('data' => t('English name')), array('data' => t('Enabled')), array('data' => t('Default')), array('data' => t('Translated')), array('data' => t('Operations')));
-
+ $options = array();
+ $form[action] = url('admin/locale');
+ $form['name'] = array(tree => TRUE);
foreach ($languages['name'] as $key => $lang) {
-
+ $options[$key] = '';
$status = db_fetch_object(db_query("SELECT isdefault, enabled FROM {locales_meta} WHERE locale = '%s'", $key));
-
+ if ($status->enabled) {
+ $enabled[] = $key;
+ }
+ if ($status->isdefault) {
+ $isdefault = $key;
+ }
if ($key == 'en') {
- $rows[] = array('en', check_plain($lang), form_checkbox('', 'enabled][en', 1, $status->enabled), form_radio('', 'sitedefault', $key, $status->isdefault), message_na(), '');
+ $form['name']['en'] = array(type => 'markup', value => check_plain($lang));
}
else {
$original = db_fetch_object(db_query("SELECT COUNT(*) AS strings FROM {locales_source}"));
@@ -54,11 +59,28 @@ function _locale_admin_manage_screen() {
$ratio = ($original->strings > 0 && $translation->translation > 0) ? round(($translation->translation/$original->strings)*100., 2) : 0;
- $rows[] = array(check_plain($key), ($key != 'en' ? form_textfield('', 'name]['. $key, $lang, 15, 64) : $lang), form_checkbox('', 'enabled]['. $key, 1, $status->enabled), form_radio('', 'sitedefault', $key, $status->isdefault), "$translation->translation/$original->strings ($ratio%)", ($key != 'en' ? l(t('delete'), 'admin/locale/language/delete/'. urlencode($key)) : ''));
+ $form['name'][$key] = array(type => 'textfield', default_value => $lang, size => 15, maxlength => 64);
+ $form['translation'][$key] = array(type => 'markup', default_value => "$translation->translation/$original->strings ($ratio%)");
}
}
+ $form['enabled'] = array(type => 'checkboxes', options => $options, default_value => $enabled, return_value => 1);
+ $form['sitedefault'] = array(type => 'radios', options => $options, default_value => $isdefault, return_value => 1);
+ $form['submit'] = array(type => 'submit', value => t('Save configuration'));
+
+ return drupal_get_form('_locale_admin_manage_screen', $form);
+}
- return form(theme('table', $header, $rows) . form_submit(t('Save configuration')), 'post', url('admin/locale'));
+function theme__locale_admin_manage_screen($form) {
+ foreach ($form['name'] as $key => $element) {
+ // Don't take form control structures
+ if (is_array($element) && element_child($key)) {
+ $rows[] = array(check_plain($key), form_render($form['name'][$key]), form_render($form['enabled'][$key]), form_render($form['sitedefault'][$key]), ($key != 'en' ? form_render($form['translation'][$key]) : message_na()), ($key != 'en' ? l(t('delete'), 'admin/locale/language/delete/'. urlencode($key)) : ''));
+ }
+ }
+ $header = array(array('data' => t('Code')), array('data' => t('English name')), array('data' => t('Enabled')), array('data' => t('Default')), array('data' => t('Translated')), array('data' => t('Operations')));
+ $output = theme('table', $header, $rows);
+ $output .= form_render($form);
+ return $output;
}
/**
@@ -68,28 +90,30 @@ function _locale_admin_manage_add_screen() {
$isocodes = _locale_prepare_iso_list();
- $output = '<h2>'. t('From language list') .'</h2>';
- $form = form_select(t('Language name'), 'langcode', key($isocodes), $isocodes, t('Select your language here, or add it below, if you are unable to find it.'));
- $form .= form_submit(t('Add language'));
- $output .= form($form);
+ $form = array();
+ $form['header'] = array(prefix => '<h2>', value => t('Language list'), suffix => '</h2>');
+ $form['langcode'] = array(type => 'select', title => t('Language name'), default_value => key($isocodes), options => $isocodes, description => t('Select your language here, or add it below, if you are unable to find it.'));
+ $form['submit'] = array(type => 'submit', value => t('Add language'));
+ $output = drupal_get_form('locale_add_language', $form);
$edit = &$_POST['edit'];
- $output .= '<h2>'. t('Custom language') .'</h2>';
- $form = form_textfield(t('Language code'), 'langcode', $edit['langcode'], 60, 12, t("Commonly this is an <a href=\"%iso-codes\">ISO 639 language code</a> with an optional country code for regional variants. Examples include 'en', 'en-US' and 'zh-cn'.", array('%iso-codes' => 'http://www.w3.org/WAI/ER/IG/ert/iso639.htm')));
- $form .= form_textfield(t('Language name in English'), 'langname', $edit['langname'], 60, 64, t('Name of the language. Will be available for translation in all languages.'));
- $form .= form_submit(t('Add language'));
- $output .= form($form);
+ $form = array();
+ $form['header'] = array(prefix => '<h2>', value => t('Custom language') , suffix => '</h2>');
+ $form['langcode'] = array(type => 'textfield', title => t('Language code'), default_value => $edit['langcode'], size => 12, maxlength => 60, description => t("Commonly this is an <a href=\"%iso-codes\">ISO 639 language code</a> with an optional country code for regional variants. Examples include 'en', 'en-US' and 'zh-cn'.", array('%iso-codes' => 'http://www.w3.org/WAI/ER/IG/ert/iso639.htm')));
+ $form['langname'] = array(type => 'textfield', title => t('Language name in English'), default_value => $edit['langname'], size => 60, maxlength => 64, description => t('Name of the language. Will be available for translation in all languages.'));
+ $form['submit'] = array(type => 'submit', value => t('Add custom language'));
+
+ $output .= drupal_get_form('_locale_custom_language', $form);
return $output;
}
-
/**
* User interface for the translation import screen
*/
function _locale_admin_import_screen() {
$languages = locale_supported_languages(FALSE, TRUE);
- $languages = array_map("t", $languages['name']);
+ $languages = array_map('t', $languages['name']);
unset($languages['en']);
if (!count($languages)) {
@@ -102,12 +126,15 @@ function _locale_admin_import_screen() {
);
}
- $form = form_file(t('Language file'), 'file', 50, t('A gettext Portable Object (.po) file.'));
- $form .= form_select(t('Import into'), 'langcode', '', $languages, t('Choose the language you want to add strings into. If you choose a language which is not yet set up, then it will be added.'));
- $form .= form_radios(t('Mode'), 'mode', 'overwrite', array('overwrite' => t('Strings in the uploaded file replace existing ones, new ones are added'), 'keep' => t('Existing strings are kept, only new strings are added')));
- $form .= form_submit(t('Import'));
- $output = form($form, 'post', url('admin/locale/language/import'), array('enctype' => 'multipart/form-data'));
- return $output;
+ $form = array();
+ $form['file'] = array(type => 'file', title => t('Language file'), size => 50, description => t('A gettext Portable Object (.po) file.'));
+ $form['langcode'] = array(type => 'select', title => t('Import into'), options => $languages, description => t('Choose the language you want to add strings into. If you choose a language which is not yet set up, then it will be added.'));
+ $form['mode'] = array(type => 'radios', title => t('Mode'), default_value => 'overwrite', options => array('overwrite' => t('Strings in the uploaded file replace existing ones, new ones are added'), 'keep' => t('Existing strings are kept, only new strings are added')));
+ $form['submit'] = array(type => 'submit', value => t('Import'));
+ $form[attributes]['enctype'] = 'multipart/form-data';
+ $form[action] = 'admin/locale/language/import';
+
+ return drupal_get_form('_locale_admin_import', $form);
}
/**
@@ -705,16 +732,18 @@ function _locale_admin_export_screen() {
// Offer language specific export if any language is set up
if (count($languages)) {
$output .= '<h2>'. t('Export translation') .'</h2>';
- $form = form_select(t('Language name'), 'langcode', '', $languages, t('Select the language you would like to export in gettext Portable Object (.po) format.'));
- $form .= form_submit(t('Export'));
- $output .= form($form);
+ $form = array();
+ $form['langcode'] = array(type => 'select', title => t('Language name'), options => $languages, description => t('Select the language you would like to export in gettext Portable Object (.po) format.'));
+ $form['submit'] = array(type => 'submit', value => t('Export'));
+ $output .= drupal_get_form('_locale_export_po', $form);
}
// Complete template export of the strings
$output .= '<h2>'. t('Export template') .'</h2>';
- $form = t('<p>Generate a gettext Portable Object Template (.pot) file with all the interface strings from the Drupal locale database.</p>');
- $form .= form_submit(t('Export'));
- $output .= form($form);
+ $output .= t('<p>Generate a gettext Portable Object Template (.pot) file with all the interface strings from the Drupal locale database.</p>');
+ $form = array();
+ $form['submit'] = array(type => 'submit', value => t('Export'));
+ $output .= drupal_get_form('_locale_export_pot', $form);
return $output;
}
@@ -947,20 +976,24 @@ function _locale_string_edit($lid) {
unset($languages['name']['en']);
$result = db_query('SELECT DISTINCT s.source, t.translation, t.locale FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE s.lid = %d', $lid);
- $form = '';
+ $form = array();
while ($translation = db_fetch_object($result)) {
$orig = $translation->source;
- $form .= (strlen($orig) > 40) ? form_textarea($languages['name'][$translation->locale], $translation->locale, $translation->translation, 60, 15) : form_textfield($languages['name'][$translation->locale], $translation->locale, $translation->translation, 60, 128);
+ $form[$translation->locale] = (strlen($orig) > 40) ?
+ array(type => 'textarea', title => $languages['name'][$translation->locale], default_value => $translation->translation, cols => 60, rows => 15)
+ : array(type => 'textfield', title => $languages['name'][$translation->locale], default_value => $translation->translation, size => 60, maxlength => 128);
unset($languages['name'][$translation->locale]);
}
+ $form = array(type => 'item', title => t('Original text'), value => wordwrap(check_plain($orig, 0)));
foreach ($languages['name'] as $key => $lang) {
- $form .= (strlen($orig) > 40) ? form_textarea($lang, $key, '', 60, 15) : form_textfield($lang, $key, '', 60, 128);
+ $form[$key] = (strlen($orig) > 40) ?
+array(type => 'textarea', title => $lang, cols => 60, rows => 15) :
+array(type => 'textfield', title => $lang, size => 60, maxlength => 128);
}
- $form = form_item(t('Original text'), wordwrap(check_plain($orig, 0))) . $form;
- $form .= form_submit(t('Save translations'));
+ $form['submit'] = array(type => 'submit', value => t('Save translations'));
- return form($form);
+ return $form;
}
/**
@@ -1065,9 +1098,12 @@ function _locale_string_seek() {
}
}
- $output .= theme('table', $header, $rows);
-
- $output .= theme('pager', NULL, 50, 0, $request);
+ if (count($rows)) {
+ $output .= theme('table', $header, $rows);
+ }
+ if ($pager = theme('pager', NULL, 50, 0, $request)) {
+ $output .= $pager;
+ }
}
return $output;
@@ -1085,14 +1121,15 @@ function _locale_string_seek_form() {
// Present edit form preserving previous user settings
$query = _locale_string_seek_query();
- $form .= form_textfield(t('Strings to search for'), 'string', $query->string, 30, 30, t('Leave blank to show all strings. The search is case sensitive.'));
- $form .= form_radios(t('Language'), 'language', ($query->language ? $query->language : 'all'), array_merge(array('all' => t('All languages'), 'en' => t('English (provided by Drupal)')), $languages['name']));
- $form .= form_radios(t('Search in'), 'searchin', ($query->searchin ? $query->searchin : 'all'), array('all' => t('All strings in that language'), 'translated' => t('Only translated strings'), 'untranslated' => t('Only untranslated strings')));
-
- $form .= form_submit(t('Search'));
- $output = form(form_group(t('Search strings'), $form), 'post', url('admin/locale/string/search'));
-
- return $output;
+ $form = array();
+ $form['search'] = array(type => 'fieldset', title => t('Search'));
+ $form['search']['string'] = array(type => 'textfield', title => t('Strings to search for'), default_value => $query->string, size => 30, maxlength => 30, description => t('Leave blank to show all strings. The search is case sensitive.'));
+ $form['search']['language'] = array(type => 'radios', title => t('Language'), default_value => ($query->language ? $query->language : 'all'), options => array_merge(array('all' => t('All languages'), 'en' => t('English (provided by Drupal)')), $languages['name']));
+ $form['search']['searchin'] = array(type => 'radios', title => t('Search in'), default_value => ($query->searchin ? $query->searchin : 'all'), options => array('all' => t('All strings in that language'), 'translated' => t('Only translated strings'), 'untranslated' => t('Only untranslated strings')));
+ $form['search']['submit'] = array(type => 'submit', value => t('Search'));
+ $form[action] = 'admin/locale/string/search';
+
+ return drupal_get_form('_locale_string_seek', $form);
}
// ---------------------------------------------------------------------------------
diff --git a/includes/theme.inc b/includes/theme.inc
index 2f3e64b6f..ba2051ff7 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -959,55 +959,6 @@ function theme_blocks($region) {
}
/**
- * Output a confirmation form
- *
- * This function outputs a complete form for confirming an action. A link is
- * offered to go back to the item that is being changed in case the user changes
- * his/her mind.
- *
- * You should use $_POST['edit'][$name] (where $name is usually 'confirm') to
- * check if the confirmation was successful.
- *
- * @param $question
- * The question to ask the user (e.g. "Are you sure you want to delete the
- * block <em>foo</em>?").
- * @param $path
- * The page to go to if the user denies the action.
- * @param $description
- * Additional text to display (defaults to "This action cannot be undone.").
- * @param $yes
- * A caption for the button which confirms the action (e.g. "Delete",
- * "Replace", ...).
- * @param $no
- * A caption for the link which denies the action (e.g. "Cancel").
- * @param $extra
- * Additional HTML to inject into the form, for example form_hidden()s.
- * @param $name
- * The internal name used to refer to the confirmation item.
- * @return
- * A themed HTML string representing the form.
- */
-function theme_confirm($question, $path, $description = NULL, $yes = NULL, $no = NULL, $extra = NULL, $name = 'confirm') {
- drupal_set_title($question);
-
- if (is_null($description)) {
- $description = t('This action cannot be undone.');
- }
-
- $output .= '<p>'. $description ."</p>\n";
- if (!is_null($extra)) {
- $output .= $extra;
- }
- $output .= '<div class="container-inline">';
- $output .= form_submit($yes ? $yes : t('Confirm'));
- $output .= l($no ? $no : t('Cancel'), $path);
- $output .= "</div>\n";
-
- $output .= form_hidden($name, 1);
- return form($output, 'post', NULL, array('class' => 'confirmation'));
-}
-
-/**
* Format a username.
*
* @param $object
diff --git a/includes/unicode.inc b/includes/unicode.inc
index 04751ed79..ce6ba32ac 100644
--- a/includes/unicode.inc
+++ b/includes/unicode.inc
@@ -81,7 +81,8 @@ function unicode_settings() {
$options = array(UNICODE_SINGLEBYTE => t('Standard PHP: operations on Unicode strings are emulated on a best-effort basis. Install the <a href="%url">PHP mbstring extension</a> for improved Unicode support.', array('%url' => 'http://www.php.net/mbstring')),
UNICODE_MULTIBYTE => t('Multi-byte: operations on Unicode strings are supported through the <a href="%url">PHP mbstring extension</a>.', array('%url' => 'http://www.php.net/mbstring')),
UNICODE_ERROR => t('Invalid: the current configuration is incompatible with Drupal.'));
- return form_item(t('String handling method'), $options[$status]);
+ $form['settings'] = array(type => 'item', title =>t('String handling method'), value => $options[$status]);
+ return $form;
}
/**
@@ -474,3 +475,4 @@ function drupal_substr($text, $start, $length = NULL) {
}
}
+