Same name and namespace in other branches
  1. 5.x includes/form.inc \form_builder()
  2. 6.x includes/form.inc \form_builder()
  3. 7.x includes/form.inc \form_builder()

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.

Parameters

$form_id: A unique string identifying the form. Allows each form to be themed.

$form: An associative array containing the structure of the form.

Related topics

3 calls to form_builder()
drupal_get_form in includes/form.inc
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 drupal_validate_form(), and then submit the form using drupal_submit_form().
poll_form in modules/poll.module
Implementation of hook_form().
upload_js in modules/upload.module
Menu-callback for JavaScript-based uploads.

File

includes/form.inc, line 337

Code

function form_builder($form_id, $form) {
  global $form_values, $form_submitted, $form_button_counter;

  // Initialize as unprocessed.
  $form['#processed'] = FALSE;

  /* Use element defaults */
  if (!empty($form['#type']) && ($info = _element_info($form['#type']))) {

    // 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']);
    }
    $posted = isset($_POST['edit']) && $_POST['edit']['form_id'] == $form_id;
    $edit = $posted ? $_POST['edit'] : array();
    foreach ($form['#parents'] as $parent) {
      $edit = isset($edit[$parent]) ? $edit[$parent] : NULL;
    }
    if (!isset($form['#value']) && !array_key_exists('#value', $form)) {
      if ($posted) {
        switch ($form['#type']) {
          case 'checkbox':
            $form['#value'] = !empty($edit) ? $form['#return_value'] : 0;
            break;
          case 'select':
            if (isset($form['#multiple']) && $form['#multiple']) {
              if (isset($edit) && is_array($edit)) {
                $form['#value'] = drupal_map_assoc($edit);
              }
              else {
                $form['#value'] = array();
              }
            }
            elseif (isset($edit)) {
              $form['#value'] = $edit;
            }
            break;
          case 'textfield':
            if (isset($edit)) {

              // Equate $edit to the form value to ensure it's marked for validation
              $edit = str_replace(array(
                "\r",
                "\n",
              ), '', $edit);
              $form['#value'] = $edit;
            }
            break;
          case 'token':
            $form['#value'] = (string) $edit;
            break;
          default:
            if (isset($edit)) {
              $form['#value'] = $edit;
            }
        }

        // Mark all posted values for validation
        if (isset($form['#value']) && $form['#value'] === $edit || isset($form['#required']) && $form['#required']) {
          $form['#needs_validation'] = TRUE;
        }
      }
      if (!isset($form['#value'])) {
        $function = $form['#type'] . '_value';
        if (function_exists($function)) {
          $function($form);
        }
        else {
          $form['#value'] = $form['#default_value'];
        }
      }
    }
    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'];
      }
    }
  }

  // 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);
      }
    }
    $form['#processed'] = TRUE;
  }

  // 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']);
  }

  // Recurse through all child elements.
  $count = 0;
  foreach (element_children($form) as $key) {

    // don't squash an existing tree value
    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,
      );
    }

    # 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]);
    $count++;
  }
  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;
  }
  return $form;
}