Newer
Older
/**
* @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

Dries Buytaert
committed
* must be explicitly generated by modules. See the reference at
* http://api.drupal.org/api/HEAD/file/developer/topics/forms_api_reference.html

Dries Buytaert
committed
* and the quickstart guide at
* http://api.drupal.org/api/HEAD/file/developer/topics/forms_api.html
*/
/**
* Check if the key is a property.
*/
function element_property($key) {
return $key[0] == '#';
/**
* Get properties of a form tree element. Properties begin with '#'.
*/
function element_properties($element) {
return array_filter(array_keys((array) $element), 'element_property');
}
/**
* Check if the key is a child.
*/
function element_child($key) {
return $key[0] != '#';
/**
* Get keys of a form tree element that are not properties (i.e., do not begin with '#').
*/
function element_children($element) {
return array_filter(array_keys((array) $element), 'element_child');

Dries Buytaert
committed
* Processes a form array and produces the HTML output of a form.
* If there is input in the $_POST['edit'] variable, this function

Dries Buytaert
committed
* will attempt to validate it, using drupal_validate_form(),
* and then submit the form using drupal_submit_form().
* A unique string identifying the form. Allows each form to be
* themed. Pass NULL to suppress the form_id parameter (produces
* a shorter URL with method=get)
* @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) {

Steven Wittens
committed
global $form_values, $form_submitted, $user, $form_button_counter;

Steven Wittens
committed
$form_button_counter = array(0, 0);

Dries Buytaert
committed
$form['#type'] = 'form';
if (isset($form['#token'])) {

Gerhard Killesreiter
committed
if (variable_get('cache', 0) && !$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET') {
unset($form['#token']);

Gerhard Killesreiter
committed
else {
// Make sure that a private key is set:
if (!variable_get('drupal_private_key', '')) {
variable_set('drupal_private_key', mt_rand());
}

Gerhard Killesreiter
committed
$form['form_token'] = array('#type' => 'hidden', '#default_value' => md5(session_id() . $form['#token'] . variable_get('drupal_private_key', '')));
}
if (isset($form_id)) {
$form['form_id'] = array('#type' => 'hidden', '#value' => $form_id);
}
if (!isset($form['#id'])) {
$form['#id'] = $form_id;
}
$form += _element_info('form');
if (!isset($form['#validate'])) {
if (function_exists($form_id .'_validate')) {
$form['#validate'] = array($form_id .'_validate' => array());
}
elseif (function_exists($callback .'_validate')) {
$form['#validate'] = array($callback .'_validate' => array());

Dries Buytaert
committed
if (!isset($form['#submit'])) {
if (function_exists($form_id .'_submit')) {
// we set submit here so that it can be altered but use reference for
// $form_values because it will change later

Gerhard Killesreiter
committed
$form['#submit'] = array($form_id .'_submit' => array());

Dries Buytaert
committed
elseif (function_exists($callback .'_submit')) {

Gerhard Killesreiter
committed
$form['#submit'] = array($callback .'_submit' => array());
foreach (module_implements('form_alter') as $module) {
$function = $module .'_form_alter';

Dries Buytaert
committed
$function($form_id, $form);
$form = form_builder($form_id, $form);

Steven Wittens
committed
if (!empty($_POST['edit']) && (($_POST['edit']['form_id'] == $form_id) || ($_POST['edit']['form_id'] == $callback))) {

Dries Buytaert
committed
drupal_validate_form($form_id, $form, $callback);

Steven Wittens
committed
// IE does not send a button value when there is only one submit button (and no non-submit buttons)
// and you submit by pressing enter.
// In that case we accept a submission without button values.
if (($form_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) {
$redirect = drupal_submit_form($form_id, $form, $callback);
if (isset($redirect)) {
$goto = $redirect;
}

Gerhard Killesreiter
committed
if (isset($form['#redirect'])) {
$goto = $form['#redirect'];
}
if ($goto !== FALSE) {
if (is_array($goto)) {
call_user_func_array('drupal_goto', $goto);
}

Gerhard Killesreiter
committed
elseif (!isset($goto)) {
drupal_goto($_GET['q']);
}
else {
drupal_goto($goto);
}

Dries Buytaert
committed
}
if (theme_get_function($form_id)) {

Dries Buytaert
committed
$form['#theme'] = $form_id;
elseif (theme_get_function($callback)) {

Dries Buytaert
committed
$form['#theme'] = $callback;
if (isset($form['#pre_render'])) {
foreach ($form['#pre_render'] as $function) {
if (function_exists($function)) {
$function($form_id, $form);
}
}
}
return form_render($form);
}

Gerhard Killesreiter
committed
function drupal_validate_form($form_id, $form, $callback = NULL) {
static $validated_forms = array();
if (isset($validated_forms[$form_id])) {
return;
}

Dries Buytaert
committed
if (isset($form['#token'])) {
if ($form_values['form_token'] != md5(session_id() . $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.'));
}
}
_form_validate($form, $form_id);
$validated_forms[$form_id] = TRUE;

Dries Buytaert
committed
function drupal_submit_form($form_id, $form, $callback = NULL) {

Gerhard Killesreiter
committed
global $form_values;
$default_args = array($form_id, &$form_values);

Dries Buytaert
committed
if (isset($form['#submit'])) {
foreach ($form['#submit'] as $function => $args) {
if (function_exists($function)) {

Gerhard Killesreiter
committed
$args = array_merge($default_args, (array) $args);
// Since we can only redirect to one page, only the last redirect will work
$redirect = call_user_func_array($function, $args);
if (isset($redirect)) {
$goto = $redirect;
}
return $goto;
function _form_validate($elements, $form_id = NULL) {
/* Validate the current input */
if (!$elements['#validated']) {
if (isset($elements['#needs_validation'])) {
// An empty textfield returns '' so we use empty(). An empty checkbox
// and a textfield could return '0' and empty('0') returns TRUE so we
// need a special check for the '0' string.
if ($elements['#required'] && empty($elements['#value']) && $elements['#value'] !== '0') {
form_error($elements, t('%name field is required.', array('%name' => $elements['#title'])));
// Add legal choice check if element has #options. Can be skipped, but then you must validate your own element.
if (isset($elements['#options']) && isset($elements['#value']) && !isset($elements['#DANGEROUS_SKIP_CHECK'])) {
if ($elements['#type'] == 'select') {
$options = form_options_flatten($elements['#options']);
}
else {
$options = $elements['#options'];
}
if (is_array($elements['#value'])) {
$value = $elements['#type'] == 'checkboxes' ? array_keys(array_filter($elements['#value'])) : $elements['#value'];
foreach ($value as $v) {
if (!isset($options[$v])) {
form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.'));
watchdog('form', t('Illegal choice %choice in %name element.', array('%choice' => theme('placeholder', check_plain($v)), '%name' => theme_placeholder(empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'])), WATCHDOG_ERROR));
}
elseif (!isset($options[$elements['#value']])) {
form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.'));
watchdog('form', t('Illegal choice %choice in %name element.', array('%choice' => theme_placeholder(check_plain($v)), '%name' => theme('placeholder', empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'])), WATCHDOG_ERROR));
}
}
}
// User-applied checks.
foreach ($elements['#validate'] as $function => $args) {
$args = array_merge(array($elements), $args);
// for the full form we hand over a copy of $form_values
if (isset($form_id)) {
$args = array_merge(array($form_id, $GLOBALS['form_values']), $args);
if (function_exists($function)) {
call_user_func_array($function, $args);

Dries Buytaert
committed
$elements['#validated'] = TRUE;
// Recurse through all children.
foreach (element_children($elements) as $key) {
if (isset($elements[$key]) && $elements[$key]) {
_form_validate($elements[$key]);
}
}
/**
* File an error against a form element. If the name of the element is
* edit[foo][bar] then you may pass either foo or foo][bar as $name
* foo will set an error for all its children.
*/

Dries Buytaert
committed
function form_set_error($name = NULL, $message = '') {
static $form = array();
if (isset($name) && !isset($form[$name])) {
$form[$name] = $message;

Dries Buytaert
committed
if ($message) {
drupal_set_message($message, 'error');
}
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
}
return $form;
}
/**
* Return an associative array of all errors.
*/
function form_get_errors() {
$form = form_set_error();
if (!empty($form)) {
return $form;
}
}
/**
* Return the error message filed against the form with the specified name.
*/
function form_get_error($element) {
$form = form_set_error();
$key = $element['#parents'][0];
if (isset($form[$key])) {
return $form[$key];
}
$key = implode('][', $element['#parents']);
if (isset($form[$key])) {
return $form[$key];
}
}
/**
* Flag an element as having an error.
*/

Dries Buytaert
committed
function form_error(&$element, $message = '') {

Dries Buytaert
committed
$element['#error'] = TRUE;
form_set_error(implode('][', $element['#parents']), $message);
* 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.
*
* @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.
function form_builder($form_id, $form) {

Steven Wittens
committed
global $form_values, $form_submitted, $form_button_counter;
/* Use element defaults */

Dries Buytaert
committed
if ((!empty($form['#type'])) && ($info = _element_info($form['#type']))) {

Dries Buytaert
committed
// overlay $info onto $form, retaining preexisting keys in $form
$form += $info;
}
if (isset($form['#input']) && $form['#input']) {
if (!isset($form['#name'])) {
$form['#name'] = 'edit[' . implode('][', $form['#parents']) . ']';
}
if (!isset($form['#id'])) {
$form['#id'] = 'edit-' . implode('-', $form['#parents']);
}

Steven Wittens
committed
$posted = (isset($_POST['edit']) && ($_POST['edit']['form_id'] == $form_id));
$edit = $posted ? $_POST['edit'] : array();

Dries Buytaert
committed
foreach ($form['#parents'] as $parent) {
$edit = isset($edit[$parent]) ? $edit[$parent] : NULL;
}
if (!isset($form['#value']) && !array_key_exists('#value', $form)) {

Dries Buytaert
committed
if ($posted) {

Dries Buytaert
committed
switch ($form['#type']) {
case 'checkbox':

Gerhard Killesreiter
committed
$form['#value'] = !empty($edit) ? $form['#return_value'] : 0;

Dries Buytaert
committed
break;
case 'select':
if (isset($edit)) {
$form['#value'] = $edit;
}
elseif (isset($form['#multiple']) && $form['#multiple']) {
$form['#value'] = array();
}

Dries Buytaert
committed
break;
case 'textfield':
if (isset($edit)) {

Gerhard Killesreiter
committed
// Equate $edit to the form value to ensure it's marked for validation
$edit = str_replace(array("\r", "\n"), '', $edit);
$form['#value'] = $edit;

Dries Buytaert
committed
}
break;
default:
if (isset($edit)) {
$form['#value'] = $edit;
}

Dries Buytaert
committed
}

Gerhard Killesreiter
committed
// Mark all posted values for validation
if ((isset($form['#value']) && $form['#value'] === $edit) || (isset($form['#required']) && $form['#required'])) {
$form['#needs_validation'] = TRUE;

Dries Buytaert
committed
}
}
if (!isset($form['#value'])) {
$function = $form['#type'] . '_value';
if (function_exists($function)) {
$function($form);
}
else {
$form['#value'] = $form['#default_value'];
}

Dries Buytaert
committed
}

Dries Buytaert
committed
}

Steven Wittens
committed
if (isset($form['#executes_submit_callback'])) {
// Count submit and non-submit buttons
$form_button_counter[$form['#executes_submit_callback']]++;
// See if a submit button was pressed
if (isset($_POST[$form['#name']]) && $_POST[$form['#name']] == $form['#value']) {
$form_submitted = $form_submitted || $form['#executes_submit_callback'];

Dries Buytaert
committed
// Allow for elements to expand to multiple elements, e.g. radios, checkboxes and files.
if (isset($form['#process']) && !$form['#processed']) {
foreach ($form['#process'] as $process => $args) {
if (function_exists($process)) {
$args = array_merge(array($form), $args);
$form = call_user_func_array($process, $args);

Dries Buytaert
committed
$form['#processed'] = TRUE;

Dries Buytaert
committed
// Set the $form_values key that gets passed to validate and submit.
// We call this after #process gets called so that #process has a
// chance to update #value if desired.
if (isset($form['#input']) && $form['#input']) {
form_set_value($form, $form['#value']);

Dries Buytaert
committed
}
// Recurse through all child elements.
$count = 0;
foreach (element_children($form) as $key) {
if (!isset($form[$key]['#tree'])) {
$form[$key]['#tree'] = $form['#tree'];
}
// don't squash existing parents value
if (!isset($form[$key]['#parents'])) {
// Check to see if a tree of child elements is present. If so, continue down the tree if required.
$form[$key]['#parents'] = $form[$key]['#tree'] && $form['#tree'] ? array_merge($form['#parents'], array($key)) : array($key);

Dries Buytaert
committed
# Assign a decimal placeholder weight to preserve original array order
if (!isset($form[$key]['#weight'])) {
$form[$key]['#weight'] = $count/1000;
}
$form[$key] = form_builder($form_id, $form[$key]);

Gerhard Killesreiter
committed
if (isset($form['#after_build']) && !isset($form['#after_build_done'])) {
foreach ($form['#after_build'] as $function) {
if (function_exists($function)) {
$form = $function($form, $form_values);
}
}
$form['#after_build_done'] = TRUE;
* Use this function to make changes to form values in the form validate
* phase, so they will be available in the submit phase in $form_values.
*
* Specifically, if $form['#parents'] is array('foo', 'bar')
* and $value is 'baz' then this function will make
* $form_values['foo']['bar'] to be 'baz'.
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
*
* @param $form
* The form item. Keys used: #parents, #value
* @param $value
* The value for the form item.
*/
function form_set_value($form, $value) {
global $form_values;
_form_set_value($form_values, $form, $form['#parents'], $value);
}
/**
* Helper function for form_set_value().
*
* We iterate of $parents and create nested arrays for them
* in $form_values if needed. Then we insert the value in
* the right array.
*/
function _form_set_value(&$form_values, $form, $parents, $value) {
$parent = array_shift($parents);
if (empty($parents)) {
$form_values[$parent] = $value;
}
else {
if (!isset($form_values[$parent])) {
$form_values[$parent] = array();
}
_form_set_value($form_values[$parent], $form, $parents, $value);
}
return $form;
}

Dries Buytaert
committed
* Renders a HTML form given a form tree. Recursively iterates over 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

Dries Buytaert
committed
* drupal_get_form().
*
* @param $elements
* The form tree describing the form.
* @return
* The rendered HTML form.
*/
function form_render(&$elements) {

Dries Buytaert
committed
if (!isset($elements)) {
return NULL;

Dries Buytaert
committed
$content = '';
uasort($elements, "_form_sort");
if (!isset($elements['#children'])) {

Gerhard Killesreiter
committed
$children = element_children($elements);
/* Render all the children that use a theme function */
if (isset($elements['#theme']) && !$elements['#theme_used']) {

Dries Buytaert
committed
$elements['#theme_used'] = TRUE;
$previous_value = $elements['#value'];

Dries Buytaert
committed
$previous_type = $elements['#type'];
// If we rendered a single element, then we will skip the renderer.
if (empty($children)) {
$elements['#printed'] = TRUE;
}
else {
$elements['#value'] = '';
}

Dries Buytaert
committed
$elements['#type'] = 'markup';

Dries Buytaert
committed
$content = theme($elements['#theme'], $elements);
$elements['#value'] = $previous_value;

Dries Buytaert
committed
$elements['#type'] = $previous_type;
unset($elements['#prefix'], $elements['#suffix']);
}
/* render each of the children using form_render and concatenate them */
if (!$content) {

Gerhard Killesreiter
committed
foreach ($children as $key) {
$content .= form_render($elements[$key]);
}
}
}
if ($content) {

Dries Buytaert
committed
$elements['#children'] = $content;

Gerhard Killesreiter
committed
// Until now, we rendered the children, here we render the element itself
if (!isset($elements['#printed'])) {

Dries Buytaert
committed
$content = theme(($elements['#type']) ? $elements['#type']: 'markup', $elements);
$elements['#printed'] = TRUE;

Dries Buytaert
committed
if ($content) {
$prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
$suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
return $prefix . $content . $suffix;

Dries Buytaert
committed
}

Dries Buytaert
committed
* Function used by uasort in form_render() to sort form by weight.
*/
function _form_sort($a, $b) {
$a_weight = (is_array($a) && isset($a['#weight'])) ? $a['#weight'] : 0;
$b_weight = (is_array($b) && isset($b['#weight'])) ? $b['#weight'] : 0;
if ($a_weight == $b_weight) {
return ($a_weight < $b_weight) ? -1 : 1;
}
/**
* Retrieve the default properties for the defined element type.
*/
function _element_info($type, $refresh = null) {
static $cache;

Dries Buytaert
committed
'#description' => NULL,
'#attributes' => array(),
'#required' => FALSE,
'#parents' => array()
if (!isset($cache) || $refresh) {
$cache = array();
foreach (module_implements('elements') as $module) {
$elements = module_invoke($module, 'elements');

Dries Buytaert
committed
if (isset($elements) && is_array($elements)) {
$cache = array_merge_recursive($cache, $elements);
}
}
if (sizeof($cache)) {
foreach ($cache as $element_type => $info) {
$cache[$element_type] = array_merge_recursive($basic_defaults, $info);
}
}
}
return $cache[$type];
}
function form_options_flatten($array, $reset = TRUE) {
static $return;
if ($reset) {
$return = array();
}
foreach ($array as $key => $value) {
if (is_array($value)) {
form_options_flatten($value, FALSE);
}
else {
$return[$key] = 1;
}
}
return $return;
}
/**
* Format a dropdown menu or scrolling selection box.
*
* @param $element
* An associative array containing the properties of the element.

Dries Buytaert
committed
* 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 = '';
$size = $element['#size'] ? ' size="' . $element['#size'] . '"' : '';

Gerhard Killesreiter
committed
_form_set_class($element, array('form-select'));
return theme('form_element', $element['#title'], '<select name="'. $element['#name'] .''. ($element['#multiple'] ? '[]' : '') .'"'. ($element['#multiple'] ? ' multiple="multiple" ' : '') . drupal_attributes($element['#attributes']) .' id="' . $element['#id'] .'" '. $size .'>'. form_select_options($element) .'</select>', $element['#description'], $element['#id'], $element['#required'], form_get_error($element));

Dries Buytaert
committed
}
function form_select_options($element, $choices = NULL) {
if (!isset($choices)) {
$choices = $element['#options'];
}
// array_key_exists() accommodates the rare event where $element['#value'] is NULL.
// isset() fails in this situation.
$value_valid = isset($element['#value']) || array_key_exists('#value', $element);
$value_is_array = is_array($element['#value']);

Dries Buytaert
committed
$options = '';
foreach ($choices as $key => $choice) {

Dries Buytaert
committed
$options .= '<optgroup label="'. $key .'">';
$options .= form_select_options($element, $choice);
$options .= '</optgroup>';

Dries Buytaert
committed
$key = (string)$key;
if ($value_valid && ($element['#value'] == $key || ($value_is_array && in_array($key, $element['#value'])))) {
$selected = ' selected="selected"';
}
else {
$selected = '';
}

Dries Buytaert
committed
$options .= '<option value="'. $key .'"'. $selected .'>'. check_plain($choice) .'</option>';

Dries Buytaert
committed
return $options;
}
/**
* Format a group of form items.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: attributes, title, value, description, children, collapsible, collapsed
* @return
* A themed HTML string representing the form item group.
*/
function theme_fieldset($element) {

Dries Buytaert
committed
if ($element['#collapsible']) {
drupal_add_js('misc/collapse.js');

Dries Buytaert
committed
$element['#attributes']['class'] .= ' collapsible';
if ($element['#collapsed']) {
$element['#attributes']['class'] .= ' collapsed';
return '<fieldset' . drupal_attributes($element['#attributes']) .'>' . ($element['#title'] ? '<legend>'. $element['#title'] .'</legend>' : '') . ($element['#description'] ? '<div class="description">'. $element['#description'] .'</div>' : '') . $element['#children'] . $element['#value'] . "</fieldset>\n";
}
/**
* Format a radio button.
*
* @param $element
* An associative array containing the properties of the element.

Dries Buytaert
committed
* Properties used: required, return_value, value, attributes, title, description
* @return
* A themed HTML string representing the form item group.
*/
function theme_radio($element) {
_form_set_class($element, array('form-radio'));
$output = '<input type="radio" ';

Dries Buytaert
committed
$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>';

Dries Buytaert
committed
return theme('form_element', NULL, $output, $element['#description'], $element['#id'], $element['#required'], form_get_error($element));
}
/**
* Format a set of radio buttons.
*
* @param $element
* An associative array containing the properties of the element.

Dries Buytaert
committed
* Properties used: title, value, options, description, required and attributes.
* @return
* A themed HTML string representing the radio button set.
*/
function theme_radios($element) {

Dries Buytaert
committed
if ($element['#title'] || $element['#description']) {

Gerhard Killesreiter
committed
return theme('form_element', $element['#title'], $element['#children'], $element['#description'], NULL, $element['#required'], form_get_error($element));

Dries Buytaert
committed
return $element['#children'];
/**
* Format a password_confirm item.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, id, required, error.
* @return
* A themed HTML string representing the form item.
*/
function theme_password_confirm($element) {
return theme('form_element', $element['#title'], '<div class="container-inline">'. $element['#children']. '</div>', $element['#description'], $element['#id'], $element['#required'], form_get_error($element));
}

Gerhard Killesreiter
committed
/*
* Expand a password_confirm field into two text boxes.
*/
function expand_password_confirm($element) {
$element['pass1'] = array('#type' => 'password', '#size' => 12, '#value' => $element['#value']['pass1']);
$element['pass2'] = array('#type' => 'password', '#size' => 12, '#value' => $element['#value']['pass2']);
$element['#validate'] = array('password_confirm_validate' => array());
$element['#tree'] = TRUE;
return $element;
}
/**

Dries Buytaert
committed
* Validate password_confirm element.
*/

Dries Buytaert
committed
function password_confirm_validate($form) {

Gerhard Killesreiter
committed
$pass1 = trim($form['pass1']['#value']);
if (!empty($pass1)) {

Dries Buytaert
committed
$pass2 = trim($form['pass2']['#value']);
if ($pass1 != $pass2) {

Dries Buytaert
committed
form_error($form, t('The specified passwords do not match.'));
}

Dries Buytaert
committed
}
elseif ($form['#required'] && !empty($_POST['edit'])) {

Gerhard Killesreiter
committed
form_error($form, t('Password field is required.'));
}

Gerhard Killesreiter
committed

Gerhard Killesreiter
committed
// Password field must be converted from a two-element array into a single
// string regardless of validation results.
form_set_value($form['pass1'], NULL);
form_set_value($form['pass2'], NULL);
form_set_value($form, $pass1);
return $form;
}

Dries Buytaert
committed
* Format a date selection element.
*
* @param $element
* An associative array containing the properties of the element.

Dries Buytaert
committed
* Properties used: title, value, options, description, required and attributes.

Dries Buytaert
committed
* A themed HTML string representing the date selection boxes.
*/
function theme_date($element) {

Dries Buytaert
committed
$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));

Dries Buytaert
committed
* Roll out a single date element.
*/
function expand_date($element) {
// Default to current date

Dries Buytaert
committed
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'));
}
$element['#tree'] = TRUE;
// 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':

Dries Buytaert
committed
$options = drupal_map_assoc(range(1, 12), 'map_month');
break;
case 'year':
$options = drupal_map_assoc(range(1900, 2050));
break;
}
$parents = $element['#parents'];
$parents[] = $type;
$element[$type] = array(
'#type' => 'select',
'#value' => $element['#value'][$type],
'#attributes' => $element['#attributes'],
'#options' => $options,
);
}
return $element;
}

Dries Buytaert
committed
/**
* Helper function for usage with drupal_map_assoc to display month names.
*/
function map_month($month) {
return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'M', 0);
}
/**
* Helper function to load value from default value for checkboxes
*/
function checkboxes_value(&$form) {
$value = array();
foreach ((array)$form['#default_value'] as $key) {
$value[$key] = 1;
}
$form['#value'] = $value;
}
/**
* If no default value is set for weight select boxes, use 0.
*/
function weight_value(&$form) {
if (isset($form['#default_value'])) {
$form['#value'] = $form['#default_value'];
}
else {
$form['#value'] = 0;
}
}

Dries Buytaert
committed
* Roll out a single radios element to a list of radios,
* using the options array as index.
*/
function expand_radios($element) {

Dries Buytaert
committed
if (count($element['#options']) > 0) {
foreach ($element['#options'] as $key => $choice) {

Dries Buytaert
committed
$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.

Dries Buytaert
committed
* Properties used: title, value, description, required, error
* @return
* A themed HTML string representing the form item.
*/
function theme_item($element) {

Dries Buytaert
committed
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.

Dries Buytaert
committed
* Properties used: title, value, return_value, description, required
* @return
* A themed HTML string representing the checkbox.
*/
function theme_checkbox($element) {
_form_set_class($element, array('form-checkbox'));
$checkbox = '<input ';
$checkbox .= 'type="checkbox" ';

Dries Buytaert
committed
$checkbox .= 'name="'. $element['#name'] .'" ';
$checkbox .= 'id="'. $element['#id'].'" ' ;
$checkbox .= 'value="'. $element['#return_value'] .'" ';
$checkbox .= $element['#value'] ? ' checked="checked" ' : ' ';

Dries Buytaert
committed
$checkbox .= drupal_attributes($element['#attributes']) . ' />';
if (!is_null($element['#title'])) {
$checkbox = '<label class="option">'. $checkbox .' '. $element['#title'] .'</label>';

Dries Buytaert
committed
return theme('form_element', NULL, $checkbox, $element['#description'], $element['#id'], $element['#required'], form_get_error($element));
}
/**
* 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) {

Dries Buytaert
committed
if ($element['#title'] || $element['#description']) {

Gerhard Killesreiter
committed
return theme('form_element', $element['#title'], $element['#children'], $element['#description'], NULL, $element['#required'], form_get_error($element));

Dries Buytaert
committed
return $element['#children'];
}
}
function expand_checkboxes($element) {

Dries Buytaert
committed
$value = is_array($element['#value']) ? $element['#value'] : array();

Dries Buytaert
committed
if (count($element['#options']) > 0) {
if (!isset($element['#default_value']) || $element['#default_value'] == 0) {
$element['#default_value'] = array();

Dries Buytaert
committed
foreach ($element['#options'] as $key => $choice) {
if (!isset($element[$key])) {
$element[$key] = array('#type' => 'checkbox', '#processed' => TRUE, '#title' => $choice, '#return_value' => $key, '#default_value' => isset($value[$key]), '#attributes' => $element['#attributes']);
}
}
}
return $element;
}
function theme_submit($element) {
return theme('button', $element);
}
function theme_button($element) {
//Make sure not to overwrite classes
if (isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
}
else {
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
}
return '<input type="submit" '. (empty($element['#name']) ? '' : '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.

Dries Buytaert
committed
* Properties used: value, edit
* @return
* A themed HTML string representing the hidden form field.
*/
function theme_hidden($element) {

Dries Buytaert
committed
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.

Dries Buytaert
committed
* Properties used: title, value, description, size, maxlength, required, attributes autocomplete_path
* @return
* A themed HTML string representing the textfield.
*/
function theme_textfield($element) {

Dries Buytaert
committed
$size = $element['#size'] ? ' size="' . $element['#size'] . '"' : '';
$class = array('form-text');

Dries Buytaert
committed
if ($element['#autocomplete_path']) {
drupal_add_js('misc/autocomplete.js');
$class[] = 'form-autocomplete';

Dries Buytaert
committed
$extra = '<input class="autocomplete" type="hidden" id="'. $element['#id'] .'-autocomplete" value="'. check_url(url($element['#autocomplete_path'], NULL, NULL, TRUE)) .'" disabled="disabled" />';
_form_set_class($element, $class);
$output = '<input type="text" maxlength="'. $element['#maxlength'] .'" 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)). $extra;