form.inc 108 KB
Newer Older
1
<?php
2
3
// $Id$

4
/**
5
6
7
8
9
10
 * @defgroup forms Form builder functions
 * @{
 * Functions that build an abstract representation of a HTML form.
 *
 * All modules should declare their form builder functions to be in this
 * group and each builder function should reference its validate and submit
11
 * functions using \@see. Conversely, validate and submit functions should
12
 * reference the form builder function using \@see. For examples, of this see
13
 * system_modules_uninstall() or user_pass(), the latter of which has the
14
15
16
17
18
19
20
21
22
23
24
 * following in its doxygen documentation:
 *
 * \@ingroup forms
 * \@see user_pass_validate().
 * \@see user_pass_submit().
 *
 * @} End of "defgroup forms".
 */

/**
 * @defgroup form_api Form generation
25
 * @{
26
 * Functions to enable the processing and display of HTML forms.
27
 *
28
29
30
31
 * Drupal uses these functions to achieve consistency in its form processing and
 * presentation, while simplifying code and reducing the amount of HTML that
 * must be explicitly generated by modules.
 *
32
 * The drupal_get_form() function handles retrieving and processing an HTML
33
 * form for modules automatically. For example:
34
 *
35
 * @code
36
 * // Display the user registration form.
37
 * $output = drupal_get_form('user_register');
38
 * @endcode
39
40
 *
 * Forms can also be built and submitted programmatically without any user input
41
 * using the drupal_form_submit() function.
42
43
 *
 * For information on the format of the structured arrays used to define forms,
44
 * and more detailed explanations of the Form API workflow, see the
45
46
 * @link http://api.drupal.org/api/file/developer/topics/forms_api_reference.html reference @endlink
 * and the @link http://api.drupal.org/api/file/developer/topics/forms_api.html quickstart guide. @endlink
47
48
49
 */

/**
50
 * Wrapper for drupal_build_form() for use when $form_state is not needed.
51
52
 *
 * @param $form_id
53
54
55
56
57
58
 *   The unique string identifying the desired form. If a function with that
 *   name exists, it is called to build the form array. Modules that need to
 *   generate the same form (or very similar forms) using different $form_ids
 *   can implement hook_forms(), which maps different $form_id values to the
 *   proper form constructor function. Examples may be found in node_forms(),
 *   search_forms(), and user_forms().
59
 * @param ...
60
 *   Any additional arguments are passed on to the functions called by
61
62
63
 *   drupal_get_form(), including the unique form constructor function. For
 *   example, the node_edit form requires that a node object is passed in here
 *   when it is called.
64
 * @return
65
 *   The form array.
66
67
 *
 * @see drupal_build_form()
68
69
 */
function drupal_get_form($form_id) {
70
  $form_state = array();
71
72

  $args = func_get_args();
73
74
75
76
77
78
79
80
  // Remove $form_id from the arguments.
  array_shift($args);
  $form_state['args'] = $args;

  return drupal_build_form($form_id, $form_state);
}

/**
81
 * Build and process a form based on a form id.
82
83
84
 *
 * The form may also be retrieved from the cache if the form was built in a
 * previous page-load. The form is then passed on for processing, validation
85
 * and submission if there is proper input.
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
 *
 * @param $form_id
 *   The unique string identifying the desired form. If a function with that
 *   name exists, it is called to build the form array. Modules that need to
 *   generate the same form (or very similar forms) using different $form_ids
 *   can implement hook_forms(), which maps different $form_id values to the
 *   proper form constructor function. Examples may be found in node_forms(),
 *   search_forms(), and user_forms().
 * @param &$form_state
 *   An array which stores information about the form. This is passed as a
 *   reference so that the caller can use it to examine what the form changed
 *   when the form submission process is complete.
 *
 *   The following parameters may be set in $form_state to affect how the form
 *   is rendered:
 *   - args: An array of arguments to pass to the form builder.
 *   - input: An array of input that corresponds to $_POST or $_GET, depending
 *     on the 'method' chosen (see below).
 *   - method: The HTTP form method to use for finding the input for this form.
 *     May be 'post' or 'get'. Defaults to 'post'. Note that 'get' method
 *     forms do not use form ids so are always considered to be submitted, which
 *     can have unexpected effects. The 'get' method should only be used on
 *     forms that do not change data, as that is exclusively the domain of post.
 *   - no_redirect: If set to TRUE the form will NOT perform a drupal_goto(),
 *     even if a redirect is set.
 *   - always_process: If TRUE and the method is GET, a form_id is not
 *     necessary. This should only be used on RESTful GET forms that do NOT
 *     write data, as this could lead to security issues. It is useful so that
 *     searches do not need to have a form_id in their query arguments to
 *     trigger the search.
 *   - must_validate: Ordinarily, a form is only validated once but there are
 *     times when a form is resubmitted internally and should be validated
 *     again. Setting this to TRUE will force that to happen. This is most
 *     likely to occur during AHAH or AJAX operations.
 * @return
 *   The rendered form or NULL, depending upon the $form_state flags that were set.
 */
function drupal_build_form($form_id, &$form_state) {
  // Ensure some defaults; if already set they will not be overridden.
  $form_state += form_state_defaults();

  if (!isset($form_state['input'])) {
    $form_state['input'] = $form_state['method'] == 'get' ? $_GET : $_POST;
  }

131
  $cacheable = FALSE;
132
133
134
135
136
137
138

  if (isset($_SESSION['batch_form_state'])) {
    // We've been redirected here after a batch processing : the form has
    // already been processed, so we grab the post-process $form_state value
    // and move on to form display. See _batch_finished() function.
    $form_state = $_SESSION['batch_form_state'];
    unset($_SESSION['batch_form_state']);
139
140
  }
  else {
141
    // If the incoming input contains a form_build_id, we'll check the
142
143
144
145
    // cache for a copy of the form in question. If it's there, we don't
    // have to rebuild the form to proceed. In addition, if there is stored
    // form_state data from a previous step, we'll retrieve it so it can
    // be passed on to the form processing code.
146
147
    if (isset($form_state['input']['form_id']) && $form_state['input']['form_id'] == $form_id && !empty($form_state['input']['form_build_id'])) {
      $form = form_get_cache($form_state['input']['form_build_id'], $form_state);
148
149
    }

150
151
152
153
    // If the previous bit of code didn't result in a populated $form
    // object, we're hitting the form for the first time and we need
    // to build it from scratch.
    if (!isset($form)) {
154
      $form = drupal_retrieve_form($form_id, $form_state);
155
      $form_build_id = 'form-' . md5(uniqid(mt_rand(), TRUE));
156
      $form['#build_id'] = $form_build_id;
157
158
159
160
161
162

      // Fix the form method, if it is 'get' in $form_state, but not in $form.
      if ($form_state['method'] == 'get' && !isset($form['#method'])) {
        $form['#method'] = 'get';
      }

163
      drupal_prepare_form($form_id, $form, $form_state);
164
165
166
167
      // Store a copy of the unprocessed form for caching and indicate that it
      // is cacheable if #cache will be set.
      $original_form = $form;
      $cacheable = TRUE;
168
    }
169

170
171
172
173
174
175
    // Now that we know we have a form, we'll process it (validating,
    // submitting, and handling the results returned by its submission
    // handlers. Submit handlers accumulate data in the form_state by
    // altering the $form_state variable, which is passed into them by
    // reference.
    drupal_process_form($form_id, $form, $form_state);
176
177

    if ($cacheable && !empty($form['#cache']) && empty($form['#no_cache'])) {
178
      // Caching is done past drupal_process_form so #process callbacks can
179
180
      // set #cache.
      form_set_cache($form_build_id, $original_form, $form_state);
181
    }
182
183
184
185
186
187
188
189
190
  }

  // Most simple, single-step forms will be finished by this point --
  // drupal_process_form() usually redirects to another page (or to
  // a 'fresh' copy of the form) once processing is complete. If one
  // of the form's handlers has set $form_state['redirect'] to FALSE,
  // the form will simply be re-rendered with the values still in its
  // fields.
  //
191
192
193
194
195
196
197
198
  // If $form_state['storage'] or $form_state['rebuild'] has been set
  // and the form has been submitted, we know that we're in a complex
  // multi-part process of some sort and the form's workflow is NOT
  // complete. We need to construct a fresh copy of the form, passing
  // in the latest $form_state in addition to any other variables passed
  // into drupal_get_form().

  if ((!empty($form_state['storage']) || !empty($form_state['rebuild'])) && !empty($form_state['submitted']) && !form_get_errors()) {
199
    $form = drupal_rebuild_form($form_id, $form_state);
200
  }
201

202
203
204
205
206
207
208
209
  // Don't override #theme if someone already set it.
  if (!isset($form['#theme'])) {
    init_theme();
    $registry = theme_get_registry();
    if (isset($registry[$form_id])) {
      $form['#theme'] = $form_id;
    }
  }
210

211
  return $form;
212
}
213

214
215
216
217
218
219
220
221
222
/**
 * Retrieve default values for the $form_state array.
 */
function form_state_defaults() {
  return array(
    'storage' => NULL,
    'submitted' => FALSE,
    'method' => 'post',
    'programmed' => FALSE,
223
    'groups' => array(),
224
225
226
  );
}

227
228
229
230
231
232
233
234
235
236
237
238
239
240
/**
 * Retrieves a form, caches it and processes it with an empty $_POST.
 *
 * This function clears $_POST and passes the empty $_POST to the form_builder.
 * To preserve some parts from $_POST, pass them in $form_state.
 *
 * If your AHAH callback simulates the pressing of a button, then your AHAH
 * callback will need to do the same as what drupal_get_form would do when the
 * button is pressed: get the form from the cache, run drupal_process_form over
 * it and then if it needs rebuild, run drupal_rebuild_form over it. Then send
 * back a part of the returned form.
 * $form_state['clicked_button']['#array_parents'] will help you to find which
 * part.
 *
241
242
243
 * When getting a form from the cache, the $form_id must be shifted off from
 * $form['#args'], so the resulting array can be given to $form_state['args'].
 *
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
 * @param $form_id
 *   The unique string identifying the desired form. If a function
 *   with that name exists, it is called to build the form array.
 *   Modules that need to generate the same form (or very similar forms)
 *   using different $form_ids can implement hook_forms(), which maps
 *   different $form_id values to the proper form constructor function. Examples
 *   may be found in node_forms(), search_forms(), and user_forms().
 * @param $form_state
 *   A keyed array containing the current state of the form. Most
 *   important is the $form_state['storage'] collection.
 * @param $form_build_id
 *   If the AHAH callback calling this function only alters part of the form,
 *   then pass in the existing form_build_id so we can re-cache with the same
 *   csid.
 * @return
 *   The newly built form.
 */
261
262
function drupal_rebuild_form($form_id, &$form_state, $form_build_id = NULL) {
  $form = drupal_retrieve_form($form_id, $form_state);
263
264
265

  if (!isset($form_build_id)) {
    // We need a new build_id for the new version of the form.
266
    $form_build_id = 'form-' . md5(mt_rand());
267
268
269
270
  }
  $form['#build_id'] = $form_build_id;
  drupal_prepare_form($form_id, $form, $form_state);

271
272
273
274
275
276
  if (empty($form['#no_cache'])) {
    // We cache the form structure so it can be retrieved later for validation.
    // If $form_state['storage'] is populated, we also cache it so that it can
    // be used to resume complex multi-step processes.
    form_set_cache($form_build_id, $form, $form_state);
  }
277
278
279
280

  // Clear out all post data, as we don't want the previous step's
  // data to pollute this one and trigger validate/submit handling,
  // then process the form for rendering.
281
282
  $form_state['input'] = array();

283
284
285
286
  // Also clear out all group associations as these might be different
  // when rerendering the form.
  $form_state['groups'] = array();

287
288
289
  // Do not call drupal_process_form(), since it would prevent the rebuilt form
  // to submit.
  $form = form_builder($form_id, $form, $form_state);
290
291
292
  return $form;
}

293
294
295
296
/**
 * Fetch a form from cache.
 */
function form_get_cache($form_build_id, &$form_state) {
297
  if ($cached = cache_get('form_' . $form_build_id, 'cache_form')) {
298
    $form = $cached->data;
299
300
301
302
303
304
    global $user;
    if ((isset($form['#cache_token']) && drupal_valid_token($form['#cache_token'])) || (!isset($form['#cache_token']) && !$user->uid)) {
      if ($cached = cache_get('storage_' . $form_build_id, 'cache_form')) {
        $form_state['storage'] = $cached->data;
      }
      return $form;
305
306
307
308
309
310
311
312
    }
  }
}

/**
 * Store a form in the cache
 */
function form_set_cache($form_build_id, $form, $form_state) {
313
314
  // 6 hours cache life time for forms should be plenty.
  $expire = 21600;
315
316
317
318
  global $user;
  if ($user->uid) {
    $form['#cache_token'] = drupal_get_token();
  }
319
  cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire);
320
  if (!empty($form_state['storage'])) {
321
    cache_set('storage_' . $form_build_id, $form_state['storage'], 'cache_form', REQUEST_TIME + $expire);
322
323
324
  }
}

325
/**
326
 * Retrieves a form using a form_id, populates it with $form_state['values'],
327
328
329
330
331
332
333
334
 * processes it, and returns any validation errors encountered. This
 * function is the programmatic counterpart to drupal_get_form().
 *
 * @param $form_id
 *   The unique string identifying the desired form. If a function
 *   with that name exists, it is called to build the form array.
 *   Modules that need to generate the same form (or very similar forms)
 *   using different $form_ids can implement hook_forms(), which maps
335
 *   different $form_id values to the proper form constructor function. Examples
336
 *   may be found in node_forms(), search_forms(), and user_forms().
337
338
339
340
341
 * @param $form_state
 *   A keyed array containing the current state of the form. Most
 *   important is the $form_state['values'] collection, a tree of data
 *   used to simulate the incoming $_POST information from a user's
 *   form submission.
342
 * @param ...
343
 *   Any additional arguments are passed on to the functions called by
344
 *   drupal_form_submit(), including the unique form constructor function.
345
346
 *   For example, the node_edit form requires that a node object be passed
 *   in here when it is called.
347
348
 * For example:
 *
349
 * @code
350
 * // register a new user
351
352
353
354
 * $form_state = array();
 * $form_state['values']['name'] = 'robo-user';
 * $form_state['values']['mail'] = 'robouser@example.com';
 * $form_state['values']['pass'] = 'password';
355
 * $form_state['values']['op'] = t('Create new account');
356
 * drupal_form_submit('user_register', $form_state);
357
358
 *
 * // Create a new node
359
 * $form_state = array();
360
 * module_load_include('inc', 'node', 'node.pages');
361
 * $node = array('type' => 'story');
362
363
364
 * $form_state['values']['title'] = 'My node';
 * $form_state['values']['body'] = 'This is the body text!';
 * $form_state['values']['name'] = 'robo-user';
365
 * $form_state['values']['op'] = t('Save');
366
 * drupal_form_submit('story_node_form', $form_state, (object)$node);
367
 * @endcode
368
 */
369
function drupal_form_submit($form_id, &$form_state) {
370
371
372
373
374
375
  if (!isset($form_state['args'])) {
    $args = func_get_args();
    array_shift($args);
    array_shift($args);
    $form_state['args'] = $args;
  }
Dries's avatar
Dries committed
376

377
378
379
380
381
  $form = drupal_retrieve_form($form_id, $form_state);
  $form_state['input'] = $form_state['values'];
  $form_state['programmed'] = TRUE;
  // Merge in default values.
  $form_state += form_state_defaults();
382

383
384
  drupal_prepare_form($form_id, $form, $form_state);
  drupal_process_form($form_id, $form, $form_state);
385
386
}

387
388
389
390
391
392
393
394
/**
 * Retrieves the structured array that defines a given form.
 *
 * @param $form_id
 *   The unique string identifying the desired form. If a function
 *   with that name exists, it is called to build the form array.
 *   Modules that need to generate the same form (or very similar forms)
 *   using different $form_ids can implement hook_forms(), which maps
395
 *   different $form_id values to the proper form constructor function.
396
397
 * @param $form_state
 *   A keyed array containing the current state of the form.
398
 * @param ...
399
400
 *   Any additional arguments needed by the unique form constructor
 *   function. Generally, these are any arguments passed into the
401
 *   drupal_get_form() or drupal_form_submit() functions after the first
402
403
404
 *   argument. If a module implements hook_forms(), it can examine
 *   these additional arguments and conditionally return different
 *   builder functions as well.
405
 */
406
function drupal_retrieve_form($form_id, &$form_state) {
407
  $forms = &drupal_static(__FUNCTION__);
408

409
  // We save two copies of the incoming arguments: one for modules to use
410
  // when mapping form ids to constructor functions, and another to pass to
411
412
  // the constructor function itself.
  $args = $form_state['args'];
413
414
415

  // We first check to see if there's a function named after the $form_id.
  // If there is, we simply pass the arguments on to it to get the form.
416
  if (!drupal_function_exists($form_id)) {
417
    // In cases where many form_ids need to share a central constructor function,
418
    // such as the node editing form, modules can implement hook_forms(). It
419
    // maps one or more form_ids to the correct constructor functions.
420
421
422
423
424
425
426
427
428
    //
    // We cache the results of that hook to save time, but that only works
    // for modules that know all their form_ids in advance. (A module that
    // adds a small 'rate this comment' form to each comment in a list
    // would need a unique form_id for each one, for example.)
    //
    // So, we call the hook if $forms isn't yet populated, OR if it doesn't
    // yet have an entry for the requested form_id.
    if (!isset($forms) || !isset($forms[$form_id])) {
429
      $forms = module_invoke_all('forms', $form_id, $args);
430
431
432
433
434
435
436
    }
    $form_definition = $forms[$form_id];
    if (isset($form_definition['callback arguments'])) {
      $args = array_merge($form_definition['callback arguments'], $args);
    }
    if (isset($form_definition['callback'])) {
      $callback = $form_definition['callback'];
437
      drupal_function_exists($callback);
438
439
    }
  }
440

441
  $args = array_merge(array(&$form_state), $args);
442

443
444
  // If $callback was returned by a hook_forms() implementation, call it.
  // Otherwise, call the function named after the form id.
445
  $form = call_user_func_array(isset($callback) ? $callback : $form_id, $args);
446
447
  $form['#form_id'] = $form_id;
  $form['#args'] = $form_state['args'];
448
  return $form;
449
450
451
452
453
454
455
456
}

/**
 * This function is the heart of form API. The form gets built, validated and in
 * appropriate cases, submitted.
 *
 * @param $form_id
 *   The unique string identifying the current form.
457
458
 * @param $form
 *   An associative array containing the structure of the form.
459
460
 * @param $form_state
 *   A keyed array containing the current state of the form. This
Dries's avatar
Dries committed
461
 *   includes the current persistent storage data for the form, and
462
463
464
 *   any data passed along by earlier steps when displaying a
 *   multi-step form. Additional information, like the sanitized $_POST
 *   data, is also accumulated here.
465
 */
466
467
468
function drupal_process_form($form_id, &$form, &$form_state) {
  $form_state['values'] = array();

469
470
471
472
473
474
475
476
477
478
479
480
481
  // With $_GET, these forms are always submitted if requested.
  if ($form_state['method'] == 'get' && !empty($form_state['always_process'])) {
    if (!isset($form_state['input']['form_build_id'])) {
      $form_state['input']['form_build_id'] = $form['#build_id'];
    }
    if (!isset($form_state['input']['form_id'])) {
      $form_state['input']['form_id'] = $form_id;
    }
    if (!isset($form_state['input']['form_token']) && isset($form['#token'])) {
      $form_state['input']['form_token'] = drupal_get_token($form['#token']);
    }
  }

482
  $form = form_builder($form_id, $form, $form_state);
483
484
  // Only process the form if it is programmed or the form_id coming
  // from the POST data is set and matches the current form_id.
485
  if ((!empty($form_state['programmed'])) || (!empty($form_state['input']) && (isset($form_state['input']['form_id']) && ($form_state['input']['form_id'] == $form_id)))) {
486
487
    drupal_validate_form($form_id, $form, $form_state);

488
489
    // form_clean_id() maintains a cache of element IDs it has seen,
    // so it can prevent duplicates. We want to be sure we reset that
490
    // cache when a form is processed, so scenarios that result in
491
492
    // the form being built behind the scenes and again for the
    // browser don't increment all the element IDs needlessly.
493
    drupal_static_reset('form_clean_id');
494

495
496
497
498
499
500
501
    if ((!empty($form_state['submitted'])) && !form_get_errors() && empty($form_state['rebuild'])) {
      $form_state['redirect'] = NULL;
      form_execute_handlers('submit', $form, $form_state);

      // We'll clear out the cached copies of the form and its stored data
      // here, as we've finished with them. The in-memory copies are still
      // here, though.
502
      if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED && !empty($form_state['values']['form_build_id'])) {
503
504
        cache_clear_all('form_' . $form_state['values']['form_build_id'], 'cache_form');
        cache_clear_all('storage_' . $form_state['values']['form_build_id'], 'cache_form');
505
506
507
      }

      // If batches were set in the submit handlers, we process them now,
508
509
      // possibly ending execution. We make sure we do not react to the batch
      // that is already being processed (if a batch operation performs a
510
      // drupal_form_submit).
511
      if ($batch =& batch_get() && !isset($batch['current_set'])) {
512
        // The batch uses its own copies of $form and $form_state for
513
        // late execution of submit handlers and post-batch redirection.
514
515
        $batch['form'] = $form;
        $batch['form_state'] = $form_state;
516
        $batch['progressive'] = !$form_state['programmed'];
517
        batch_process();
518
519
520
521
        // Execution continues only for programmatic forms.
        // For 'regular' forms, we get redirected to the batch processing
        // page. Form redirection will be handled in _batch_finished(),
        // after the batch is processed.
522
      }
523
524
525
526
527

      // If no submit handlers have populated the $form_state['storage']
      // bundle, and the $form_state['rebuild'] flag has not been set,
      // we're finished and should redirect to a new destination page
      // if one has been set (and a fresh, unpopulated copy of the form
528
      // if one hasn't). If the form was called by drupal_form_submit(),
529
530
      // however, we'll skip this and let the calling function examine
      // the resulting $form_state bundle itself.
531
532
533
534
535
536
537
      if (!$form_state['programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) {
        if (!empty($form_state['no_redirect'])) {
          $form_state['executed'] = TRUE;
        }
        else {
          drupal_redirect_form($form, $form_state['redirect']);
        }
538
      }
539
540
541
542
543
544
545
546
547
548
549
550
551
552
    }
  }
}

/**
 * Prepares a structured form array by adding required elements,
 * executing any hook_form_alter functions, and optionally inserting
 * a validation token to prevent tampering.
 *
 * @param $form_id
 *   A unique string identifying the form for validation, submission,
 *   theming, and hook_form_alter functions.
 * @param $form
 *   An associative array containing the structure of the form.
553
554
555
 * @param $form_state
 *   A keyed array containing the current state of the form. Passed
 *   in here so that hook_form_alter() calls can use it, as well.
556
 */
557
function drupal_prepare_form($form_id, &$form, &$form_state) {
558
559
  global $user;

560
  $form['#type'] = 'form';
561
  $form_state['programmed'] = isset($form_state['programmed']) ? $form_state['programmed'] : FALSE;
562

563
564
565
566
567
568
569
570
571
  if (isset($form['#build_id'])) {
    $form['form_build_id'] = array(
      '#type' => 'hidden',
      '#value' => $form['#build_id'],
      '#id' => $form['#build_id'],
      '#name' => 'form_build_id',
    );
  }

572
573
574
575
  // Add a token, based on either #token or form_id, to any form displayed to
  // authenticated users. This ensures that any submitted form was actually
  // requested previously by the user and protects against cross site request
  // forgeries.
576
  if (isset($form['#token'])) {
577
    if ($form['#token'] === FALSE || $user->uid == 0 || $form_state['programmed']) {
578
      unset($form['#token']);
579
    }
580
    else {
581
      $form['form_token'] = array('#type' => 'token', '#default_value' => drupal_get_token($form['#token']));
582
    }
583
  }
584
  elseif (isset($user->uid) && $user->uid && !$form_state['programmed']) {
585
586
    $form['#token'] = $form_id;
    $form['form_token'] = array(
587
      '#id' => form_clean_id('edit-' . $form_id . '-form-token'),
588
589
590
591
592
      '#type' => 'token',
      '#default_value' => drupal_get_token($form['#token']),
    );
  }

593
  if (isset($form_id)) {
594
595
596
597
598
    $form['form_id'] = array(
      '#type' => 'hidden',
      '#value' => $form_id,
      '#id' => form_clean_id("edit-$form_id"),
    );
599
  }
600
  if (!isset($form['#id'])) {
601
    $form['#id'] = form_clean_id($form_id);
602
  }
Steven Wittens's avatar
Steven Wittens committed
603

604
  $form += element_info('form');
605
  $form += array('#tree' => FALSE, '#parents' => array());
606

Dries's avatar
Dries committed
607
  if (!isset($form['#validate'])) {
608
    if (drupal_function_exists($form_id . '_validate')) {
609
      $form['#validate'] = array($form_id . '_validate');
Dries's avatar
Dries committed
610
611
612
    }
  }

613
  if (!isset($form['#submit'])) {
614
    if (drupal_function_exists($form_id . '_submit')) {
615
      // We set submit here so that it can be altered.
616
      $form['#submit'] = array($form_id . '_submit');
Dries's avatar
Dries committed
617
618
619
    }
  }

620
621
622
623
624
625
626
627
  // Normally, we would call drupal_alter($form_id, $form, $form_state).
  // However, drupal_alter() normally supports just one byref parameter. Using
  // the __drupal_alter_by_ref key, we can store any additional parameters
  // that need to be altered, and they'll be split out into additional params
  // for the hook_form_alter() implementations.
  // @todo: Remove this in Drupal 7.
  $data = &$form;
  $data['__drupal_alter_by_ref'] = array(&$form_state);
628
  drupal_alter('form_' . $form_id, $data);
629
630
631
632
633

  // __drupal_alter_by_ref is unset in the drupal_alter() function, we need
  // to repopulate it to ensure both calls get the data.
  $data['__drupal_alter_by_ref'] = array(&$form_state);
  drupal_alter('form', $data, $form_id);
634
635
}

636
637

/**
638
 * Validates user-submitted form data from the $form_state using
639
640
641
642
643
644
645
 * the validate functions defined in a structured form array.
 *
 * @param $form_id
 *   A unique string identifying the form for validation, submission,
 *   theming, and hook_form_alter functions.
 * @param $form
 *   An associative array containing the structure of the form.
646
647
648
649
650
651
652
653
654
655
 * @param $form_state
 *   A keyed array containing the current state of the form. The current
 *   user-submitted data is stored in $form_state['values'], though
 *   form validation functions are passed an explicit copy of the
 *   values for the sake of simplicity. Validation handlers can also
 *   $form_state to pass information on to submit handlers. For example:
 *     $form_state['data_for_submision'] = $data;
 *   This technique is useful when validation requires file parsing,
 *   web service requests, or other expensive requests that should
 *   not be repeated in the submission step.
656
 */
657
function drupal_validate_form($form_id, $form, &$form_state) {
658
  $validated_forms = &drupal_static(__FUNCTION__, array());
659

660
  if (isset($validated_forms[$form_id]) && empty($form_state['must_validate'])) {
661
662
    return;
  }
663

664
  // If the session token was set by drupal_prepare_form(), ensure that it
665
  // matches the current user's session.
666
  if (isset($form['#token'])) {
667
    if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
668
      // Setting this error will cause the form to fail validation.
669
      form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
670
671
672
    }
  }

673
  _form_validate($form, $form_state, $form_id);
674
  $validated_forms[$form_id] = TRUE;
675
676
}

677
678
679
680
681
682
/**
 * Redirect the user to a URL after a form has been processed.
 *
 * @param $form
 *   An associative array containing the structure of the form.
 * @param $redirect
683
 *   An optional value containing the destination path to redirect
684
685
686
 *   to if none is specified by the form.
 */
function drupal_redirect_form($form, $redirect = NULL) {
687
  $goto = NULL;
688
689
690
  if (isset($redirect)) {
    $goto = $redirect;
  }
691
  if ($goto !== FALSE && isset($form['#redirect'])) {
692
693
    $goto = $form['#redirect'];
  }
694
695
696
697
698
699
700
701
702
703
704
  if (!isset($goto) || ($goto !== FALSE)) {
    if (isset($goto)) {
      if (is_array($goto)) {
        call_user_func_array('drupal_goto', $goto);
      }
      else {
        drupal_goto($goto);
      }
    }
    drupal_goto($_GET['q']);
  }
705
706
}

707
708
709
710
711
712
713
/**
 * Performs validation on form elements. First ensures required fields are
 * completed, #maxlength is not exceeded, and selected options were in the
 * list of options given to the user. Then calls user-defined validators.
 *
 * @param $elements
 *   An associative array containing the structure of the form.
714
715
716
717
718
719
720
721
722
723
 * @param $form_state
 *   A keyed array containing the current state of the form. The current
 *   user-submitted data is stored in $form_state['values'], though
 *   form validation functions are passed an explicit copy of the
 *   values for the sake of simplicity. Validation handlers can also
 *   $form_state to pass information on to submit handlers. For example:
 *     $form_state['data_for_submision'] = $data;
 *   This technique is useful when validation requires file parsing,
 *   web service requests, or other expensive requests that should
 *   not be repeated in the submission step.
724
725
726
727
 * @param $form_id
 *   A unique string identifying the form for validation, submission,
 *   theming, and hook_form_alter functions.
 */
728
function _form_validate($elements, &$form_state, $form_id = NULL) {
729
  $complete_form = &drupal_static(__FUNCTION__);
730

731
732
  // Also used in the installer, pre-database setup.
  $t = get_t();
733

734
735
736
  // Recurse through all children.
  foreach (element_children($elements) as $key) {
    if (isset($elements[$key]) && $elements[$key]) {
737
      _form_validate($elements[$key], $form_state);
738
739
    }
  }
740
  // Validate the current input.
drumm's avatar
drumm committed
741
  if (!isset($elements['#validated']) || !$elements['#validated']) {
742
    if (isset($elements['#needs_validation'])) {
743
744
745
746
747
      // Make sure a value is passed when the field is required.
      // A simple call to empty() will not cut it here as some fields, like
      // checkboxes, can return a valid value of '0'. Instead, check the
      // length if it's a string, and the item count if it's an array.
      if ($elements['#required'] && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0))) {
748
        form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
749
      }
750

751
752
      // Verify that the value is not longer than #maxlength.
      if (isset($elements['#maxlength']) && drupal_strlen($elements['#value']) > $elements['#maxlength']) {
753
        form_error($elements, $t('!name cannot be longer than %max characters but is currently %length characters long.', array('!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'], '%max' => $elements['#maxlength'], '%length' => drupal_strlen($elements['#value']))));
754
755
      }

756
      if (isset($elements['#options']) && isset($elements['#value'])) {
757
758
759
760
761
762
763
764
765
766
        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])) {
767
              form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
768
              watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
769
            }
770
771
          }
        }
772
        elseif (!isset($options[$elements['#value']])) {
773
          form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
774
          watchdog('form', 'Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
775
        }
776
777
778
      }
    }

779
780
781
    // Call user-defined form level validators and store a copy of the full
    // form so that element-specific validators can examine the entire structure
    // if necessary.
782
783
    if (isset($form_id)) {
      form_execute_handlers('validate', $elements, $form_state);
784
      $complete_form = $elements;
785
786
787
788
789
    }
    // Call any element-specific validators. These must act on the element
    // #value data.
    elseif (isset($elements['#element_validate'])) {
      foreach ($elements['#element_validate'] as $function) {
790
        if (drupal_function_exists($function))  {
791
          $function($elements, $form_state, $complete_form);
792
793
794
        }
      }
    }
795
    $elements['#validated'] = TRUE;
796
797
798
  }
}

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
/**
 * A helper function used to execute custom validation and submission
 * handlers for a given form. Button-specific handlers are checked
 * first. If none exist, the function falls back to form-level handlers.
 *
 * @param $type
 *   The type of handler to execute. 'validate' or 'submit' are the
 *   defaults used by Form API.
 * @param $form
 *   An associative array containing the structure of the form.
 * @param $form_state
 *   A keyed array containing the current state of the form. If the user
 *   submitted the form by clicking a button with custom handler functions
 *   defined, those handlers will be stored here.
 */
function form_execute_handlers($type, &$form, &$form_state) {
  $return = FALSE;
816
817
  if (isset($form_state[$type . '_handlers'])) {
    $handlers = $form_state[$type . '_handlers'];
818
  }
819
820
  elseif (isset($form['#' . $type])) {
    $handlers = $form['#' . $type];
821
822
823
824
825
826
  }
  else {
    $handlers = array();
  }

  foreach ($handlers as $function) {
827
    if (drupal_function_exists($function))  {
828
829
      // Check to see if a previous _submit handler has set a batch, but
      // make sure we do not react to a batch that is already being processed
830
      // (for instance if a batch operation performs a drupal_form_submit()).
831
      if ($type == 'submit' && ($batch =& batch_get()) && !isset($batch['current_set'])) {
832
833
834
        // Some previous _submit handler has set a batch. We store the call
        // in a special 'control' batch set, for execution at the correct
        // time during the batch processing workflow.
835
        $batch['sets'][] = array('form_submit' => $function);
836
837
      }
      else {
838
        $function($form, $form_state);
839
840
841
842
843
844
845
      }
      $return = TRUE;
    }
  }
  return $return;
}

846
/**
847
848
849
850
851
852
853
854
855
 * File an error against a form element.
 *
 * @param $name
 *   The name of the form element. If the #parents property of your form
 *   element is array('foo', 'bar', 'baz') then you may set an error on 'foo'
 *   or 'foo][bar][baz'. Setting an error on 'foo' sets an error for every
 *   element where the #parents array starts with 'foo'.
 * @param $message
 *   The error message to present to the user.
856
857
 * @param $reset
 *   Reset the form errors static cache.
858
859
860
 * @return
 *   Never use the return value of this function, use form_get_errors and
 *   form_get_error instead.
861
 */
862
863
function form_set_error($name = NULL, $message = '') {
  $form = &drupal_static(__FUNCTION__, array());
864
865
  if (isset($name) && !isset($form[$name])) {
    $form[$name] = $message;
866
867
868
    if ($message) {
      drupal_set_message($message, 'error');
    }
869
870
871
872
  }
  return $form;
}

873
874
875
876
877
878
879
/**
 * Clear all errors against all form elements made by form_set_error().
 */
function form_clear_error() {
  drupal_static_reset('form_set_error');
}

880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
/**
 * 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];
  }
}

905
906
907
/**
 * Flag an element as having an error.
 */
908
function form_error(&$element, $message = '') {
909
  form_set_error(implode('][', $element['#parents']), $message);
910
911
912
}

/**
913
914
 * Walk through the structured form array, adding any required
 * properties to each element and mapping the incoming $_POST
915
916
 * data to the proper elements. Also, execute any #process handlers
 * attached to a specific element.
917
918
 *
 * @param $form_id
919
920
 *   A unique string identifying the form for validation, submission,
 *   theming, and hook_form_alter functions.
921
922
 * @param $form
 *   An associative array containing the structure of the form.
923
924
925
926
927
 * @param $form_state
 *   A keyed array containing the current state of the form. In this
 *   context, it is used to accumulate information about which button
 *   was clicked when the form was submitted, as well as the sanitized
 *   $_POST data.
928
 */
929
function form_builder($form_id, $form, &$form_state) {
930
931
932
  $complete_form = &drupal_static(__FUNCTION__);
  $cache = &drupal_static(__FUNCTION__ . ':cache');
  $file = &drupal_static(__FUNCTION__ . ':file');
933

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

937
  // Use element defaults.
938
  if ((!empty($form['#type'])) && ($info = element_info($form['#type']))) {
939
    // Overlay $info onto $form, retaining preexisting keys in $form.
940
941
942
    $form += $info;
  }

943
  if (isset($form['#type']) && $form['#type'] == 'form') {
944
    $cache = NULL;
945
    $complete_form = $form;
946
    if (!empty($form_state['programmed'])) {
947
948
      $form_state['submitted'] = TRUE;
    }
949
950
  }

951
952
953
  if (!isset($form['#id'])) {
    $form['#id'] = form_clean_id('edit-' . implode('-', $form['#parents']));
  }
954
  if (isset($form['#input']) && $form['#input']) {
955
    _form_builder_handle_input_element($form_id, $form, $form_state, $complete_form);
956
  }
957
958
959
960
961
962
963
964
965
966
  // 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) {
      if (drupal_function_exists($process)) {
        $form = $process($form, $form_state, $complete_form);
      }
    }
    $form['#processed'] = TRUE;
  }
967
  $form['#defaults_loaded'] = TRUE;
968

969
970
971
  // We start off assuming all form elements are in the correct order.
  $form['#sorted'] = TRUE;

972
  // Recurse through all child elements.
973
  $count = 0;
974
  foreach (element_children($form) as $key) {
975
    // Don't squash an existing tree value.
976
977
978
    if (!isset($form[$key]['#tree'])) {
      $form[$key]['#tree'] = $form['#tree'];
    }
Steven Wittens's avatar
Steven Wittens committed
979

980
    // Deny access to child elements if parent is denied.
981
982
983
984
    if (isset($form['#access']) && !$form['#access']) {
      $form[$key]['#access'] = FALSE;
    }

985
    // Don't squash existing parents value.
986
    if (!isset($form[$key]['#parents'])) {
987
988
      // Check to see if a tree of child elements is present. If so,
      // continue down the tree if required.
989
      $form[$key]['#parents'] = $form[$key]['#tree'] && $form['#tree'] ? array_merge($form['#parents'], array($key)) : array($key);
990
991
992
      $array_parents = isset($form['#array_parents']) ? $form['#array_parents'] : array();
      $array_parents[] = $key;
      $form[$key]['#array_parents'] = $array_parents;
Steven Wittens's avatar
Steven Wittens committed
993
994
    }

995
    // Assign a decimal placeholder weight to preserve original array order.
996
997
998
    if (!isset($form[$key]['#weight'])) {
      $form[$key]['#weight'] = $count/1000;
    }
999
    else {
1000
1001
      // If one of the child elements has a weight then we will need to sort
      // later.
1002
1003
      unset($form['#sorted']);
    }
1004
    $form[$key] = form_builder($form_id, $form[$key], $form_state);
1005
1006
1007
    $count++;
  }

1008
1009
  // The #after_build flag allows any piece of a form to be altered
  // after normal input parsing has been completed.
1010
1011
  if (isset($form['#after_build']) && !isset($form['#after_build_done'])) {
    foreach ($form['#after_build'] as $function) {
1012
      $form = $function($form, $form_state);
1013
1014
1015
1016
1017
      $form['#after_build_done'] = TRUE;
    }
  }

  // Now that we've processed everything, we can go back to handle the funky
Dries's avatar
Dries committed
1018
  // Internet Explorer button-click scenario.
1019
  _form_builder_ie_cleanup($form, $form_state);
1020

1021
  // We should keep the buttons array until the IE clean up function
1022
1023
1024
1025
1026
1027
  // has recognized the submit button so the form has been marked
  // as submitted. If we already know which button was submitted,
  // we don't need the array.
  if (!empty($form_state['submitted'])) {
    unset($form_state['buttons']);
  }
1028

1029
1030
  // If some callback set #cache, we need to flip a static flag so later it
  // can be found.
1031
  if (!empty($form['#cache'])) {
1032
1033
    $cache = $form['#cache'];
  }
1034
1035
  // If there is a file element, we need to flip a static flag so later the
  // form encoding can be set.
1036
  if (isset($form['#type']) && $form['#type'] == 'file') {
1037
1038
1039
1040
1041
1042
1043
    $file = TRUE;
  }
  if (isset($form['#type']) && $form['#type'] == 'form') {
    // We are on the top form, we can copy back #cache if it's set.
    if (isset($cache)) {
      $form['#cache'] = TRUE;
    }
1044
1045
1046
1047
    // If there is a file element, we set the form encoding.
    if (isset($file)) {
      $form['#attributes']['enctype'] = 'multipart/form-data';
    }
1048
  }
1049
1050
1051
1052
1053
  return $form;
}

/**
 * Populate the #value and #name properties of input elements so they
1054
 * can be processed and rendered.
1055
 */
1056
function _form_builder_handle_input_element($form_id, &$form, &$form_state, $complete_form) {
1057
1058
1059
1060
1061
1062
1063
  if (!isset($form['#name'])) {
    $name = array_shift($form['#parents']);
    $form['#name'] = $name;
    if ($form['#type'] == 'file') {
      // To make it easier to handle $_FILES in file.inc, we place all
      // file fields in the 'files' array. Also, we do not support
      // nested file names.
1064
      $form['#name'] = 'files[' . $form['#name'] . ']';
1065
1066
    }
    elseif (count($form['#parents'])) {
1067
      $form['#name'] .= '[' . implode('][', $form['#parents']) . ']';
1068
1069
1070
1071
1072
1073
1074
1075
1076
    }
    array_unshift($form['#parents'], $name);
  }

  if (!empty($form['#disabled'])) {
    $form['#attributes']['disabled'] = 'disabled';
  }

  if (!isset($form['#value']) && !array_key_exists('#value', $form)) {
1077
    $function = !empty($form['#value_callback']) ? $form['#value_callback'] : 'form_type_' . $form['#type'] . '_value';
1078
1079
    if (($form_state['programmed']) || ((!isset($form['#access']) || $form['#access']) && isset($form_state['input']) && (isset($form_state['input']['form_id']) && $form_state['input']['form_id'] == $form_id))) {
      $edit = $form_state['input'];
1080
1081
1082
      foreach ($form['#parents'] as $parent) {
        $edit = isset($edit[$parent]) ? $edit[$parent] : NULL;
      }
1083
      if (!$form_state['programmed'] || isset($edit)) {
1084
1085
        // Call #type_value to set the form value;
        if (function_exists($function)) {
1086
          $form['#value'] = $function($form, $edit, $form_state);
1087
        }
1088
1089
        if (!isset($form['#value']) && isset($edit)) {
          $form['#value'] = $edit;
1090
1091
        }
      }
1092
1093
1094
1095
      // Mark all posted values for validation.
      if (isset($form['#value']) || (isset($form['#required']) && $form['#required'])) {
        $form['#needs_validation'] = TRUE;
      }