/[drupal]/drupal/includes/form.inc
ViewVC logotype

Contents of /drupal/includes/form.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.393 - (show annotations) (download) (as text)
Wed Nov 4 05:39:14 2009 UTC (3 weeks, 4 days ago) by webchick
Branch: MAIN
Changes since 1.392: +19 -9 lines
File MIME type: text/x-php
#571086 follow-up by sun: Allow specifying a 'wrapper callback' before executing a form builder function.
1 <?php
2 // $Id: form.inc,v 1.392 2009/11/04 04:56:54 webchick Exp $
3
4 /**
5 * @defgroup forms Form builder functions
6 * @{
7 * Functions that build an abstract representation of a HTML form.
8 *
9 * All modules should declare their form builder functions to be in this
10 * 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 * following in its doxygen documentation:
15 *
16 * \@ingroup forms
17 * \@see user_pass_validate().
18 * \@see user_pass_submit().
19 *
20 * @} End of "defgroup forms".
21 */
22
23 /**
24 * @defgroup form_api Form generation
25 * @{
26 * Functions to enable the processing and display of HTML forms.
27 *
28 * Drupal uses these functions to achieve consistency in its form processing and
29 * presentation, while simplifying code and reducing the amount of HTML that
30 * must be explicitly generated by modules.
31 *
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_form');
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 * @link http://api.drupal.org/api/file/developer/topics/forms_api_reference.html reference @endlink
46 * 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 * The unique string identifying the desired form. If a function with that
54 * name exists, it is called to build the form array. Modules that need to
55 * generate the same form (or very similar forms) using different $form_ids
56 * can implement hook_forms(), which maps different $form_id values to the
57 * proper form constructor function. Examples may be found in node_forms(),
58 * search_forms(), and user_forms().
59 * @param ...
60 * Any additional arguments are passed on to the functions called by
61 * drupal_get_form(), including the unique form constructor function. For
62 * example, the node_edit form requires that a node object is passed in here
63 * 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 // Remove $form_id from the arguments.
74 array_shift($args);
75 $form_state['build_info']['args'] = $args;
76
77 return drupal_build_form($form_id, $form_state);
78 }
79
80 /**
81 * Build and process a form based on a form id.
82 *
83 * The form may also be retrieved from the cache if the form was built in a
84 * previous page-load. The form is then passed on for processing, validation
85 * and submission if there is proper input.
86 *
87 * @param $form_id
88 * The unique string identifying the desired form. If a function with that
89 * name exists, it is called to build the form array. Modules that need to
90 * generate the same form (or very similar forms) using different $form_ids
91 * can implement hook_forms(), which maps different $form_id values to the
92 * proper form constructor function. Examples may be found in node_forms(),
93 * search_forms(), and user_forms().
94 * @param &$form_state
95 * An array which stores information about the form. This is passed as a
96 * reference so that the caller can use it to examine what in the form changed
97 * when the form submission process is complete.
98 * The following parameters may be set in $form_state to affect how the form
99 * is rendered:
100 * - build_info: A keyed array of build information that is necessary to
101 * rebuild the form from cache when the original context may no longer be
102 * available:
103 * - args: An array of arguments to pass to the form builder.
104 * - file: An optional include file that contains the form and is
105 * automatically loaded by form_get_cache(). Defaults to the current menu
106 * router item's 'file' definition, if existent.
107 * - input: An array of input that corresponds to $_POST or $_GET, depending
108 * on the 'method' chosen (see below).
109 * - method: The HTTP form method to use for finding the input for this form.
110 * May be 'post' or 'get'. Defaults to 'post'. Note that 'get' method
111 * forms do not use form ids so are always considered to be submitted, which
112 * can have unexpected effects. The 'get' method should only be used on
113 * forms that do not change data, as that is exclusively the domain of post.
114 * - no_redirect: If set to TRUE the form will NOT perform a drupal_goto(),
115 * even if a redirect is set.
116 * - always_process: If TRUE and the method is GET, a form_id is not
117 * necessary. This should only be used on RESTful GET forms that do NOT
118 * write data, as this could lead to security issues. It is useful so that
119 * searches do not need to have a form_id in their query arguments to
120 * trigger the search.
121 * - must_validate: Ordinarily, a form is only validated once but there are
122 * times when a form is resubmitted internally and should be validated
123 * again. Setting this to TRUE will force that to happen. This is most
124 * likely to occur during AHAH or AJAX operations.
125 * - wrapper_callback: Modules that wish to pre-populate certain forms with
126 * common elements, such as back/next/save buttons in multi-step form
127 * wizards, may define a form builder function name that returns a form
128 * structure, which is passed on to the actual form builder function.
129 * Such implementations may either define the 'wrapper_callback' via
130 * hook_forms() or have to invoke drupal_build_form() (instead of
131 * drupal_get_form()) on their own in a custom menu callback to prepare
132 * $form_state accordingly.
133 * Further $form_state properties controlling the redirection behavior after
134 * form submission may be found in drupal_redirect_form().
135 *
136 * @return
137 * The rendered form or NULL, depending upon the $form_state flags that were set.
138 *
139 * @see drupal_redirect_form()
140 */
141 function drupal_build_form($form_id, &$form_state) {
142 // Ensure some defaults; if already set they will not be overridden.
143 $form_state += form_state_defaults();
144
145 if (!isset($form_state['input'])) {
146 $form_state['input'] = $form_state['method'] == 'get' ? $_GET : $_POST;
147 }
148
149 $cacheable = FALSE;
150
151 if (isset($_SESSION['batch_form_state'])) {
152 // We've been redirected here after a batch processing : the form has
153 // already been processed, so we grab the post-process $form_state value
154 // and move on to form display. See _batch_finished() function.
155 $form_state = $_SESSION['batch_form_state'];
156 unset($_SESSION['batch_form_state']);
157 }
158 else {
159 // If the incoming input contains a form_build_id, we'll check the
160 // cache for a copy of the form in question. If it's there, we don't
161 // have to rebuild the form to proceed. In addition, if there is stored
162 // form_state data from a previous step, we'll retrieve it so it can
163 // be passed on to the form processing code.
164 if (isset($form_state['input']['form_id']) && $form_state['input']['form_id'] == $form_id && !empty($form_state['input']['form_build_id'])) {
165 $form = form_get_cache($form_state['input']['form_build_id'], $form_state);
166 }
167
168 // If the previous bit of code didn't result in a populated $form
169 // object, we're hitting the form for the first time and we need
170 // to build it from scratch.
171 if (!isset($form)) {
172 // Record the filepath of the include file containing the original form,
173 // so the form builder callbacks can be loaded when the form is being
174 // rebuilt from cache on a different path (such as 'system/ajax').
175 // @see form_get_cache()
176 // menu_get_item() is not available at installation time.
177 if (!isset($form_state['build_info']['file']) && !defined('MAINTENANCE_MODE')) {
178 $item = menu_get_item();
179 if (!empty($item['file'])) {
180 $form_state['build_info']['file'] = $item['file'];
181 }
182 }
183
184 $form = drupal_retrieve_form($form_id, $form_state);
185 $form_build_id = 'form-' . md5(uniqid(mt_rand(), TRUE));
186 $form['#build_id'] = $form_build_id;
187
188 // Fix the form method, if it is 'get' in $form_state, but not in $form.
189 if ($form_state['method'] == 'get' && !isset($form['#method'])) {
190 $form['#method'] = 'get';
191 }
192
193 drupal_prepare_form($form_id, $form, $form_state);
194 // Store a copy of the unprocessed form for caching and indicate that it
195 // is cacheable if #cache will be set.
196 $original_form = $form;
197 $cacheable = TRUE;
198 }
199
200 // Now that we know we have a form, we'll process it (validating,
201 // submitting, and handling the results returned by its submission
202 // handlers. Submit handlers accumulate data in the form_state by
203 // altering the $form_state variable, which is passed into them by
204 // reference.
205 drupal_process_form($form_id, $form, $form_state);
206
207 if ($cacheable && !empty($form_state['cache']) && empty($form['#no_cache'])) {
208 // Caching is done past drupal_process_form so #process callbacks can
209 // set #cache.
210 form_set_cache($form_build_id, $original_form, $form_state);
211 }
212 }
213
214 // Most simple, single-step forms will be finished by this point --
215 // drupal_process_form() usually redirects to another page (or to
216 // a 'fresh' copy of the form) once processing is complete. If one
217 // of the form's handlers has set $form_state['redirect'] to FALSE,
218 // the form will simply be re-rendered with the values still in its
219 // fields.
220 //
221 // If $form_state['storage'] or $form_state['rebuild'] has been set
222 // and the form has been submitted, we know that we're in a complex
223 // multi-part process of some sort and the form's workflow is NOT
224 // complete. We need to construct a fresh copy of the form, passing
225 // in the latest $form_state in addition to any other variables passed
226 // into drupal_get_form().
227 if ((!empty($form_state['storage']) || $form_state['rebuild']) && $form_state['submitted'] && !form_get_errors()) {
228 $form = drupal_rebuild_form($form_id, $form_state);
229 }
230
231 // Don't override #theme if someone already set it.
232 if (!isset($form['#theme'])) {
233 drupal_theme_initialize();
234 $registry = theme_get_registry();
235 if (isset($registry[$form_id])) {
236 $form['#theme'] = $form_id;
237 }
238 }
239
240 return $form;
241 }
242
243 /**
244 * Retrieve default values for the $form_state array.
245 */
246 function form_state_defaults() {
247 return array(
248 'args' => array(),
249 'rebuild' => FALSE,
250 'redirect' => NULL,
251 'build_info' => array(),
252 'storage' => NULL,
253 'submitted' => FALSE,
254 'programmed' => FALSE,
255 'cache'=> FALSE,
256 'method' => 'post',
257 'groups' => array(),
258 );
259 }
260
261 /**
262 * Retrieves a form, caches it and processes it with an empty $_POST.
263 *
264 * This function clears $_POST and passes the empty $_POST to the form_builder.
265 * To preserve some parts from $_POST, pass them in $form_state.
266 *
267 * If your AHAH callback simulates the pressing of a button, then your AHAH
268 * callback will need to do the same as what drupal_get_form would do when the
269 * button is pressed: get the form from the cache, run drupal_process_form over
270 * it and then if it needs rebuild, run drupal_rebuild_form over it. Then send
271 * back a part of the returned form.
272 * $form_state['clicked_button']['#array_parents'] will help you to find which
273 * part.
274 *
275 * @param $form_id
276 * The unique string identifying the desired form. If a function
277 * with that name exists, it is called to build the form array.
278 * Modules that need to generate the same form (or very similar forms)
279 * using different $form_ids can implement hook_forms(), which maps
280 * different $form_id values to the proper form constructor function. Examples
281 * may be found in node_forms(), search_forms(), and user_forms().
282 * @param $form_state
283 * A keyed array containing the current state of the form. Most
284 * important is the $form_state['storage'] collection.
285 * @param $form_build_id
286 * If the AHAH callback calling this function only alters part of the form,
287 * then pass in the existing form_build_id so we can re-cache with the same
288 * csid.
289 * @return
290 * The newly built form.
291 */
292 function drupal_rebuild_form($form_id, &$form_state, $form_build_id = NULL) {
293 $form = drupal_retrieve_form($form_id, $form_state);
294
295 if (!isset($form_build_id)) {
296 // We need a new build_id for the new version of the form.
297 $form_build_id = 'form-' . md5(mt_rand());
298 }
299 $form['#build_id'] = $form_build_id;
300 drupal_prepare_form($form_id, $form, $form_state);
301
302 if (empty($form['#no_cache'])) {
303 // We cache the form structure so it can be retrieved later for validation.
304 // If $form_state['storage'] is populated, we also cache it so that it can
305 // be used to resume complex multi-step processes.
306 form_set_cache($form_build_id, $form, $form_state);
307 }
308
309 // Clear out all post data, as we don't want the previous step's
310 // data to pollute this one and trigger validate/submit handling,
311 // then process the form for rendering.
312 $form_state['input'] = array();
313
314 // Also clear out all group associations as these might be different
315 // when rerendering the form.
316 $form_state['groups'] = array();
317
318 // Do not call drupal_process_form(), since it would prevent the rebuilt form
319 // to submit.
320 $form = form_builder($form_id, $form, $form_state);
321 return $form;
322 }
323
324 /**
325 * Fetch a form from cache.
326 */
327 function form_get_cache($form_build_id, &$form_state) {
328 if ($cached = cache_get('form_' . $form_build_id, 'cache_form')) {
329 $form = $cached->data;
330
331 global $user;
332 if ((isset($form['#cache_token']) && drupal_valid_token($form['#cache_token'])) || (!isset($form['#cache_token']) && !$user->uid)) {
333 if ($cached = cache_get('form_state_' . $form_build_id, 'cache_form')) {
334 // Re-populate $form_state for subsequent rebuilds.
335 $form_state['build_info'] = $cached->data['build_info'];
336 $form_state['storage'] = $cached->data['storage'];
337
338 // If the original form is contained in an include file, load the file.
339 // @see drupal_build_form()
340 if (!empty($form_state['build_info']['file']) && file_exists($form_state['build_info']['file'])) {
341 require_once DRUPAL_ROOT . '/' . $form_state['build_info']['file'];
342 }
343 }
344 return $form;
345 }
346 }
347 }
348
349 /**
350 * Store a form in the cache.
351 */
352 function form_set_cache($form_build_id, $form, $form_state) {
353 // 6 hours cache life time for forms should be plenty.
354 $expire = 21600;
355 global $user;
356 if ($user->uid) {
357 $form['#cache_token'] = drupal_get_token();
358 }
359 cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire);
360 if (!empty($form_state['build_info']) || !empty($form_state['storage'])) {
361 $data = array(
362 'build_info' => $form_state['build_info'],
363 'storage' => $form_state['storage'],
364 );
365 cache_set('form_state_' . $form_build_id, $data, 'cache_form', REQUEST_TIME + $expire);
366 }
367 }
368
369 /**
370 * Retrieves a form using a form_id, populates it with $form_state['values'],
371 * processes it, and returns any validation errors encountered. This
372 * function is the programmatic counterpart to drupal_get_form().
373 *
374 * @param $form_id
375 * The unique string identifying the desired form. If a function
376 * with that name exists, it is called to build the form array.
377 * Modules that need to generate the same form (or very similar forms)
378 * using different $form_ids can implement hook_forms(), which maps
379 * different $form_id values to the proper form constructor function. Examples
380 * may be found in node_forms(), search_forms(), and user_forms().
381 * @param $form_state
382 * A keyed array containing the current state of the form. Most
383 * important is the $form_state['values'] collection, a tree of data
384 * used to simulate the incoming $_POST information from a user's
385 * form submission.
386 * @param ...
387 * Any additional arguments are passed on to the functions called by
388 * drupal_form_submit(), including the unique form constructor function.
389 * For example, the node_edit form requires that a node object be passed
390 * in here when it is called.
391 * For example:
392 *
393 * @code
394 * // register a new user
395 * $form_state = array();
396 * $form_state['values']['name'] = 'robo-user';
397 * $form_state['values']['mail'] = 'robouser@example.com';
398 * $form_state['values']['pass'] = 'password';
399 * $form_state['values']['op'] = t('Create new account');
400 * drupal_form_submit('user_register_form', $form_state);
401 *
402 * // Create a new node
403 * $form_state = array();
404 * module_load_include('inc', 'node', 'node.pages');
405 * $node = array('type' => 'story');
406 * $form_state['values']['title'] = 'My node';
407 * $form_state['values']['body'] = 'This is the body text!';
408 * $form_state['values']['name'] = 'robo-user';
409 * $form_state['values']['op'] = t('Save');
410 * drupal_form_submit('story_node_form', $form_state, (object)$node);
411 * @endcode
412 */
413 function drupal_form_submit($form_id, &$form_state) {
414 if (!isset($form_state['build_info']['args'])) {
415 $args = func_get_args();
416 array_shift($args);
417 array_shift($args);
418 $form_state['build_info']['args'] = $args;
419 }
420
421 $form = drupal_retrieve_form($form_id, $form_state);
422 $form_state['input'] = $form_state['values'];
423 $form_state['programmed'] = TRUE;
424 // Programmed forms are always submitted.
425 $form_state['submitted'] = TRUE;
426 // Merge in default values.
427 $form_state += form_state_defaults();
428
429 drupal_prepare_form($form_id, $form, $form_state);
430 drupal_process_form($form_id, $form, $form_state);
431 }
432
433 /**
434 * Retrieves the structured array that defines a given form.
435 *
436 * @param $form_id
437 * The unique string identifying the desired form. If a function
438 * with that name exists, it is called to build the form array.
439 * Modules that need to generate the same form (or very similar forms)
440 * using different $form_ids can implement hook_forms(), which maps
441 * different $form_id values to the proper form constructor function.
442 * @param $form_state
443 * A keyed array containing the current state of the form.
444 * @param ...
445 * Any additional arguments needed by the unique form constructor
446 * function. Generally, these are any arguments passed into the
447 * drupal_get_form() or drupal_form_submit() functions after the first
448 * argument. If a module implements hook_forms(), it can examine
449 * these additional arguments and conditionally return different
450 * builder functions as well.
451 */
452 function drupal_retrieve_form($form_id, &$form_state) {
453 $forms = &drupal_static(__FUNCTION__);
454
455 // We save two copies of the incoming arguments: one for modules to use
456 // when mapping form ids to constructor functions, and another to pass to
457 // the constructor function itself.
458 $args = $form_state['build_info']['args'];
459
460 // We first check to see if there's a function named after the $form_id.
461 // If there is, we simply pass the arguments on to it to get the form.
462 if (!function_exists($form_id)) {
463 // In cases where many form_ids need to share a central constructor function,
464 // such as the node editing form, modules can implement hook_forms(). It
465 // maps one or more form_ids to the correct constructor functions.
466 //
467 // We cache the results of that hook to save time, but that only works
468 // for modules that know all their form_ids in advance. (A module that
469 // adds a small 'rate this comment' form to each comment in a list
470 // would need a unique form_id for each one, for example.)
471 //
472 // So, we call the hook if $forms isn't yet populated, OR if it doesn't
473 // yet have an entry for the requested form_id.
474 if (!isset($forms) || !isset($forms[$form_id])) {
475 $forms = module_invoke_all('forms', $form_id, $args);
476 }
477 $form_definition = $forms[$form_id];
478 if (isset($form_definition['callback arguments'])) {
479 $args = array_merge($form_definition['callback arguments'], $args);
480 }
481 if (isset($form_definition['callback'])) {
482 $callback = $form_definition['callback'];
483 }
484 // In case $form_state['wrapper_callback'] is not defined already, we also
485 // allow hook_forms() to define one.
486 if (!isset($form_state['wrapper_callback']) && isset($form_definition['wrapper_callback'])) {
487 $form_state['wrapper_callback'] = $form_definition['wrapper_callback'];
488 }
489 }
490
491 $form = array();
492 // We need to pass $form_state by reference in order for forms to modify it,
493 // since call_user_func_array() requires that referenced variables are passed
494 // explicitly.
495 $args = array_merge(array($form, &$form_state), $args);
496
497 // When the passed $form_state (not using drupal_get_form()) defines a
498 // 'wrapper_callback', then it requests to invoke a separate (wrapping) form
499 // builder function to pre-populate the $form array with form elements, which
500 // the actual form builder function ($callback) expects. This allows for
501 // pre-populating a form with common elements for certain forms, such as
502 // back/next/save buttons in multi-step form wizards.
503 // @see drupal_build_form()
504 if (isset($form_state['wrapper_callback']) && function_exists($form_state['wrapper_callback'])) {
505 $form = call_user_func_array($form_state['wrapper_callback'], $args);
506 // Put the prepopulated $form into $args.
507 $args[0] = $form;
508 }
509
510 // If $callback was returned by a hook_forms() implementation, call it.
511 // Otherwise, call the function named after the form id.
512 $form = call_user_func_array(isset($callback) ? $callback : $form_id, $args);
513 $form['#form_id'] = $form_id;
514
515 return $form;
516 }
517
518 /**
519 * Processes a form submission.
520 *
521 * This function is the heart of form API. The form gets built, validated and in
522 * appropriate cases, submitted.
523 *
524 * @param $form_id
525 * The unique string identifying the current form.
526 * @param $form
527 * An associative array containing the structure of the form.
528 * @param $form_state
529 * A keyed array containing the current state of the form. This
530 * includes the current persistent storage data for the form, and
531 * any data passed along by earlier steps when displaying a
532 * multi-step form. Additional information, like the sanitized $_POST
533 * data, is also accumulated here.
534 */
535 function drupal_process_form($form_id, &$form, &$form_state) {
536 $form_state['values'] = array();
537
538 // With $_GET, these forms are always submitted if requested.
539 if ($form_state['method'] == 'get' && !empty($form_state['always_process'])) {
540 if (!isset($form_state['input']['form_build_id'])) {
541 $form_state['input']['form_build_id'] = $form['#build_id'];
542 }
543 if (!isset($form_state['input']['form_id'])) {
544 $form_state['input']['form_id'] = $form_id;
545 }
546 if (!isset($form_state['input']['form_token']) && isset($form['#token'])) {
547 $form_state['input']['form_token'] = drupal_get_token($form['#token']);
548 }
549 }
550
551 // Build the form.
552 $form = form_builder($form_id, $form, $form_state);
553
554 // Only process the input if we have a correct form submission.
555 if ($form_state['process_input']) {
556 drupal_validate_form($form_id, $form, $form_state);
557
558 // drupal_html_id() maintains a cache of element IDs it has seen,
559 // so it can prevent duplicates. We want to be sure we reset that
560 // cache when a form is processed, so scenarios that result in
561 // the form being built behind the scenes and again for the
562 // browser don't increment all the element IDs needlessly.
563 drupal_static_reset('drupal_html_id');
564
565 if ($form_state['submitted'] && !form_get_errors() && !$form_state['rebuild']) {
566 // Execute form submit handlers.
567 form_execute_handlers('submit', $form, $form_state);
568
569 // We'll clear out the cached copies of the form and its stored data
570 // here, as we've finished with them. The in-memory copies are still
571 // here, though.
572 if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED && !empty($form_state['values']['form_build_id'])) {
573 cache_clear_all('form_' . $form_state['values']['form_build_id'], 'cache_form');
574 cache_clear_all('storage_' . $form_state['values']['form_build_id'], 'cache_form');
575 }
576
577 // If batches were set in the submit handlers, we process them now,
578 // possibly ending execution. We make sure we do not react to the batch
579 // that is already being processed (if a batch operation performs a
580 // drupal_form_submit).
581 if ($batch =& batch_get() && !isset($batch['current_set'])) {
582 // The batch uses its own copies of $form and $form_state for
583 // late execution of submit handlers and post-batch redirection.
584 $batch['form'] = $form;
585 $batch['form_state'] = $form_state;
586 $batch['progressive'] = !$form_state['programmed'];
587 batch_process();
588 // Execution continues only for programmatic forms.
589 // For 'regular' forms, we get redirected to the batch processing
590 // page. Form redirection will be handled in _batch_finished(),
591 // after the batch is processed.
592 }
593
594 // Set a flag to indicate the the form has been processed and executed.
595 $form_state['executed'] = TRUE;
596
597 // Redirect the form based on values in $form_state.
598 drupal_redirect_form($form_state);
599 }
600 }
601 }
602
603 /**
604 * Prepares a structured form array by adding required elements,
605 * executing any hook_form_alter functions, and optionally inserting
606 * a validation token to prevent tampering.
607 *
608 * @param $form_id
609 * A unique string identifying the form for validation, submission,
610 * theming, and hook_form_alter functions.
611 * @param $form
612 * An associative array containing the structure of the form.
613 * @param $form_state
614 * A keyed array containing the current state of the form. Passed
615 * in here so that hook_form_alter() calls can use it, as well.
616 */
617 function drupal_prepare_form($form_id, &$form, &$form_state) {
618 global $user;
619
620 $form['#type'] = 'form';
621 $form_state['programmed'] = isset($form_state['programmed']) ? $form_state['programmed'] : FALSE;
622
623 if (isset($form['#build_id'])) {
624 $form['form_build_id'] = array(
625 '#type' => 'hidden',
626 '#value' => $form['#build_id'],
627 '#id' => $form['#build_id'],
628 '#name' => 'form_build_id',
629 );
630 }
631
632 // Add a token, based on either #token or form_id, to any form displayed to
633 // authenticated users. This ensures that any submitted form was actually
634 // requested previously by the user and protects against cross site request
635 // forgeries.
636 if (isset($form['#token'])) {
637 if ($form['#token'] === FALSE || $user->uid == 0 || $form_state['programmed']) {
638 unset($form['#token']);
639 }
640 else {
641 $form['form_token'] = array('#type' => 'token', '#default_value' => drupal_get_token($form['#token']));
642 }
643 }
644 elseif (isset($user->uid) && $user->uid && !$form_state['programmed']) {
645 $form['#token'] = $form_id;
646 $form['form_token'] = array(
647 '#id' => drupal_html_id('edit-' . $form_id . '-form-token'),
648 '#type' => 'token',
649 '#default_value' => drupal_get_token($form['#token']),
650 );
651 }
652
653 if (isset($form_id)) {
654 $form['form_id'] = array(
655 '#type' => 'hidden',
656 '#value' => $form_id,
657 '#id' => drupal_html_id("edit-$form_id"),
658 );
659 }
660 if (!isset($form['#id'])) {
661 $form['#id'] = drupal_html_id($form_id);
662 }
663
664 $form += element_info('form');
665 $form += array('#tree' => FALSE, '#parents' => array());
666
667 if (!isset($form['#validate'])) {
668 if (function_exists($form_id . '_validate')) {
669 $form['#validate'] = array($form_id . '_validate');
670 }
671 }
672
673 if (!isset($form['#submit'])) {
674 if (function_exists($form_id . '_submit')) {
675 // We set submit here so that it can be altered.
676 $form['#submit'] = array($form_id . '_submit');
677 }
678 }
679
680 // Invoke hook_form_FORM_ID_alter() implementations.
681 drupal_alter('form_' . $form_id, $form, $form_state);
682
683 // Invoke hook_form_alter() implementations.
684 drupal_alter('form', $form, $form_state, $form_id);
685 }
686
687
688 /**
689 * Validates user-submitted form data from the $form_state using
690 * the validate functions defined in a structured form array.
691 *
692 * @param $form_id
693 * A unique string identifying the form for validation, submission,
694 * theming, and hook_form_alter functions.
695 * @param $form
696 * An associative array containing the structure of the form.
697 * @param $form_state
698 * A keyed array containing the current state of the form. The current
699 * user-submitted data is stored in $form_state['values'], though
700 * form validation functions are passed an explicit copy of the
701 * values for the sake of simplicity. Validation handlers can also
702 * $form_state to pass information on to submit handlers. For example:
703 * $form_state['data_for_submision'] = $data;
704 * This technique is useful when validation requires file parsing,
705 * web service requests, or other expensive requests that should
706 * not be repeated in the submission step.
707 */
708 function drupal_validate_form($form_id, $form, &$form_state) {
709 $validated_forms = &drupal_static(__FUNCTION__, array());
710
711 if (isset($validated_forms[$form_id]) && empty($form_state['must_validate'])) {
712 return;
713 }
714
715 // If the session token was set by drupal_prepare_form(), ensure that it
716 // matches the current user's session.
717 if (isset($form['#token'])) {
718 if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
719 // Setting this error will cause the form to fail validation.
720 form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
721 }
722 }
723
724 _form_validate($form, $form_state, $form_id);
725 $validated_forms[$form_id] = TRUE;
726 }
727
728 /**
729 * Redirects the user to a URL after a form has been processed.
730 *
731 * After a form was executed, the data in $form_state controls whether the form
732 * is redirected. By default, we redirect to a new destination page. The path of
733 * the destination page can be set in $form_state['redirect']. If that is not
734 * set, the user is redirected to the current page to display a fresh,
735 * unpopulated copy of the form.
736 *
737 * There are several triggers that may prevent a redirection though:
738 * - If $form_state['redirect'] is FALSE, a form builder function or form
739 * validation/submit handler does not want a user to be redirected, which
740 * means that drupal_goto() is not invoked. For most forms, the redirection
741 * logic will be the same regardless of whether $form_state['redirect'] is
742 * undefined or FALSE. However, in case it was not defined and the current
743 * request contains a 'destination' query string, drupal_goto() will redirect
744 * to that given destination instead. Only setting $form_state['redirect'] to
745 * FALSE will prevent any redirection.
746 * - If $form_state['no_redirect'] is TRUE, then the callback that originally
747 * built the form explicitly disallows any redirection, regardless of the
748 * redirection value in $form_state['redirect']. For example, ajax_get_form()
749 * defines $form_state['no_redirect'] when building a form in an AJAX
750 * callback to prevent any redirection. $form_state['no_redirect'] should NOT
751 * be altered by form builder functions or form validation/submit handlers.
752 * - If $form_state['programmed'] is TRUE, the form submission was usually
753 * invoked via drupal_form_submit(), so any redirection would break the script
754 * that invoked drupal_form_submit().
755 * - If $form_state['rebuild'] is TRUE or $form_state['storage'] is populated,
756 * the form is most probably a multi-step form and needs to be rebuilt without
757 * redirection.
758 *
759 * @param $form_state
760 * A keyed array containing the current state of the form.
761 *
762 * @see drupal_process_form()
763 * @see drupal_build_form()
764 */
765 function drupal_redirect_form($form_state) {
766 // Skip redirection for form submissions invoked via drupal_form_submit().
767 if (!empty($form_state['programmed'])) {
768 return;
769 }
770 // Skip redirection for multi-step forms.
771 if (!empty($form_state['rebuild']) || !empty($form_state['storage'])) {
772 return;
773 }
774 // Skip redirection if it was explicitly disallowed.
775 if (!empty($form_state['no_redirect'])) {
776 return;
777 }
778 // Only invoke drupal_goto() if redirect value was not set to FALSE.
779 if (!isset($form_state['redirect']) || $form_state['redirect'] !== FALSE) {
780 if (isset($form_state['redirect'])) {
781 if (is_array($form_state['redirect'])) {
782 call_user_func_array('drupal_goto', $form_state['redirect']);
783 }
784 else {
785 // This function can be called from the installer, which guarantees
786 // that $redirect will always be a string, so catch that case here
787 // and use the appropriate redirect function.
788 $function = drupal_installation_attempted() ? 'install_goto' : 'drupal_goto';
789 $function($form_state['redirect']);
790 }
791 }
792 drupal_goto($_GET['q']);
793 }
794 }
795
796 /**
797 * Performs validation on form elements. First ensures required fields are
798 * completed, #maxlength is not exceeded, and selected options were in the
799 * list of options given to the user. Then calls user-defined validators.
800 *
801 * @param $elements
802 * An associative array containing the structure of the form.
803 * @param $form_state
804 * A keyed array containing the current state of the form. The current
805 * user-submitted data is stored in $form_state['values'], though
806 * form validation functions are passed an explicit copy of the
807 * values for the sake of simplicity. Validation handlers can also
808 * $form_state to pass information on to submit handlers. For example:
809 * $form_state['data_for_submision'] = $data;
810 * This technique is useful when validation requires file parsing,
811 * web service requests, or other expensive requests that should
812 * not be repeated in the submission step.
813 * @param $form_id
814 * A unique string identifying the form for validation, submission,
815 * theming, and hook_form_alter functions.
816 */
817 function _form_validate($elements, &$form_state, $form_id = NULL) {
818 // Also used in the installer, pre-database setup.
819 $t = get_t();
820
821 // Recurse through all children.
822 foreach (element_children($elements) as $key) {
823 if (isset($elements[$key]) && $elements[$key]) {
824 _form_validate($elements[$key], $form_state);
825 }
826 }
827 // Validate the current input.
828 if (!isset($elements['#validated']) || !$elements['#validated']) {
829 if (isset($elements['#needs_validation'])) {
830 // Make sure a value is passed when the field is required.
831 // A simple call to empty() will not cut it here as some fields, like
832 // checkboxes, can return a valid value of '0'. Instead, check the
833 // length if it's a string, and the item count if it's an array.
834 if ($elements['#required'] && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0))) {
835 form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
836 }
837
838 // Verify that the value is not longer than #maxlength.
839 if (isset($elements['#maxlength']) && drupal_strlen($elements['#value']) > $elements['#maxlength']) {
840 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']))));
841 }
842
843 if (isset($elements['#options']) && isset($elements['#value'])) {
844 if ($elements['#type'] == 'select') {
845 $options = form_options_flatten($elements['#options']);
846 }
847 else {
848 $options = $elements['#options'];
849 }
850 if (is_array($elements['#value'])) {
851 $value = $elements['#type'] == 'checkboxes' ? array_keys(array_filter($elements['#value'])) : $elements['#value'];
852 foreach ($value as $v) {
853 if (!isset($options[$v])) {
854 form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
855 watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
856 }
857 }
858 }
859 elseif (!isset($options[$elements['#value']])) {
860 form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
861 watchdog('form', 'Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
862 }
863 }
864 }
865
866 // Call user-defined form level validators.
867 if (isset($form_id)) {
868 form_execute_handlers('validate', $elements, $form_state);
869 }
870 // Call any element-specific validators. These must act on the element
871 // #value data.
872 elseif (isset($elements['#element_validate'])) {
873 foreach ($elements['#element_validate'] as $function) {
874 if (function_exists($function)) {
875 $function($elements, $form_state, $form_state['complete form']);
876 }
877 }
878 }
879 $elements['#validated'] = TRUE;
880 }
881 }
882
883 /**
884 * A helper function used to execute custom validation and submission
885 * handlers for a given form. Button-specific handlers are checked
886 * first. If none exist, the function falls back to form-level handlers.
887 *
888 * @param $type
889 * The type of handler to execute. 'validate' or 'submit' are the
890 * defaults used by Form API.
891 * @param $form
892 * An associative array containing the structure of the form.
893 * @param $form_state
894 * A keyed array containing the current state of the form. If the user
895 * submitted the form by clicking a button with custom handler functions
896 * defined, those handlers will be stored here.
897 */
898 function form_execute_handlers($type, &$form, &$form_state) {
899 $return = FALSE;
900 if (isset($form_state[$type . '_handlers'])) {
901 $handlers = $form_state[$type . '_handlers'];
902 }
903 elseif (isset($form['#' . $type])) {
904 $handlers = $form['#' . $type];
905 }
906 else {
907 $handlers = array();
908 }
909
910 foreach ($handlers as $function) {
911 if (function_exists($function)) {
912 // Check to see if a previous _submit handler has set a batch, but
913 // make sure we do not react to a batch that is already being processed
914 // (for instance if a batch operation performs a drupal_form_submit()).
915 if ($type == 'submit' && ($batch =& batch_get()) && !isset($batch['current_set'])) {
916 // Some previous _submit handler has set a batch. We store the call
917 // in a special 'control' batch set, for execution at the correct
918 // time during the batch processing workflow.
919 $batch['sets'][] = array('form_submit' => $function);
920 }
921 else {
922 $function($form, $form_state);
923 }
924 $return = TRUE;
925 }
926 }
927 return $return;
928 }
929
930 /**
931 * File an error against a form element.
932 *
933 * @param $name
934 * The name of the form element. If the #parents property of your form
935 * element is array('foo', 'bar', 'baz') then you may set an error on 'foo'
936 * or 'foo][bar][baz'. Setting an error on 'foo' sets an error for every
937 * element where the #parents array starts with 'foo'.
938 * @param $message
939 * The error message to present to the user.
940 * @param $reset
941 * Reset the form errors static cache.
942 * @return
943 * Never use the return value of this function, use form_get_errors and
944 * form_get_error instead.
945 */
946 function form_set_error($name = NULL, $message = '') {
947 $form = &drupal_static(__FUNCTION__, array());
948 if (isset($name) && !isset($form[$name])) {
949 $form[$name] = $message;
950 if ($message) {
951 drupal_set_message($message, 'error');
952 }
953 }
954 return $form;
955 }
956
957 /**
958 * Clear all errors against all form elements made by form_set_error().
959 */
960 function form_clear_error() {
961 drupal_static_reset('form_set_error');
962 }
963
964 /**
965 * Return an associative array of all errors.
966 */
967 function form_get_errors() {
968 $form = form_set_error();
969 if (!empty($form)) {
970 return $form;
971 }
972 }
973
974 /**
975 * Return the error message filed against the form with the specified name.
976 */
977 function form_get_error($element) {
978 $form = form_set_error();
979 $key = $element['#parents'][0];
980 if (isset($form[$key])) {
981 return $form[$key];
982 }
983 $key = implode('][', $element['#parents']);
984 if (isset($form[$key])) {
985 return $form[$key];
986 }
987 }
988
989 /**
990 * Flag an element as having an error.
991 */
992 function form_error(&$element, $message = '') {
993 form_set_error(implode('][', $element['#parents']), $message);
994 }
995
996 /**
997 * Walk through the structured form array, adding any required
998 * properties to each element and mapping the incoming input
999 * data to the proper elements. Also, execute any #process handlers
1000 * attached to a specific element.
1001 *
1002 * @param $form_id
1003 * A unique string identifying the form for validation, submission,
1004 * theming, and hook_form_alter functions.
1005 * @param $element
1006 * An associative array containing the structure of the current element.
1007 * @param $form_state
1008 * A keyed array containing the current state of the form. In this
1009 * context, it is used to accumulate information about which button
1010 * was clicked when the form was submitted, as well as the sanitized
1011 * $_POST data.
1012 */
1013 function form_builder($form_id, $element, &$form_state) {
1014 // Initialize as unprocessed.
1015 $element['#processed'] = FALSE;
1016
1017 // Use element defaults.
1018 if ((!empty($element['#type'])) && ($info = element_info($element['#type']))) {
1019 // Overlay $info onto $element, retaining preexisting keys in $element.
1020 $element += $info;
1021 $element['#defaults_loaded'] = TRUE;
1022 }
1023
1024 // Special handling if we're on the top level form element.
1025 if (isset($element['#type']) && $element['#type'] == 'form') {
1026 if (!empty($element['#https']) && variable_get('https', FALSE) &&
1027 !url_is_external($element['#action'])) {
1028 global $base_root;
1029
1030 // Not an external URL so ensure that it is secure.
1031 $element['#action'] = str_replace('http://', 'https://', $base_root) . $element['#action'];
1032 }
1033
1034 // Store a complete copy of the form in form_state prior to building the form.
1035 $form_state['complete form'] = $element;
1036 // Set a flag if we have a correct form submission. This is always TRUE for
1037 // programmed forms coming from drupal_form_submit(), or if the form_id coming
1038 // from the POST data is set and matches the current form_id.
1039 if ($form_state['programmed'] || (!empty($form_state['input']) && (isset($form_state['input']['form_id']) && ($form_state['input']['form_id'] == $form_id)))) {
1040 $form_state['process_input'] = TRUE;
1041 }
1042 else {
1043 $form_state['process_input'] = FALSE;
1044 }
1045 }
1046
1047 if (!isset($element['#id'])) {
1048 $element['#id'] = drupal_html_id('edit-' . implode('-', $element['#parents']));
1049 }
1050 // Handle input elements.
1051 if (!empty($element['#input'])) {
1052 _form_builder_handle_input_element($form_id, $element, $form_state);
1053 }
1054 // Allow for elements to expand to multiple elements, e.g., radios,
1055 // checkboxes and files.
1056 if (isset($element['#process']) && !$element['#processed']) {
1057 foreach ($element['#process'] as $process) {
1058 if (function_exists($process)) {
1059 $element = $process($element, $form_state, $form_state['complete form']);
1060 }
1061 }
1062 $element['#processed'] = TRUE;
1063 }
1064
1065 // We start off assuming all form elements are in the correct order.
1066 $element['#sorted'] = TRUE;
1067
1068 // Recurse through all child elements.
1069 $count = 0;
1070 foreach (element_children($element) as $key) {
1071 // Don't squash an existing tree value.
1072 if (!isset($element[$key]['#tree'])) {
1073 $element[$key]['#tree'] = $element['#tree'];
1074 }
1075
1076 // Deny access to child elements if parent is denied.
1077 if (isset($element['#access']) && !$element['#access']) {
1078 $element[$key]['#access'] = FALSE;
1079 }
1080
1081 // Don't squash existing parents value.
1082 if (!isset($element[$key]['#parents'])) {
1083 // Check to see if a tree of child elements is present. If so,
1084 // continue down the tree if required.
1085 $element[$key]['#parents'] = $element[$key]['#tree'] && $element['#tree'] ? array_merge($element['#parents'], array($key)) : array($key);
1086 $array_parents = isset($element['#array_parents']) ? $element['#array_parents'] : array();
1087 $array_parents[] = $key;
1088 $element[$key]['#array_parents'] = $array_parents;
1089 }
1090
1091 // Assign a decimal placeholder weight to preserve original array order.
1092 if (!isset($element[$key]['#weight'])) {
1093 $element[$key]['#weight'] = $count/1000;
1094 }
1095 else {
1096 // If one of the child elements has a weight then we will need to sort
1097 // later.
1098 unset($element['#sorted']);
1099 }
1100 $element[$key] = form_builder($form_id, $element[$key], $form_state);
1101 $count++;
1102 }
1103
1104 // The #after_build flag allows any piece of a form to be altered
1105 // after normal input parsing has been completed.
1106 if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
1107 foreach ($element['#after_build'] as $function) {
1108 $element = $function($element, $form_state);
1109 $element['#after_build_done'] = TRUE;
1110 }
1111 }
1112
1113 // Now that we've processed everything, we can go back to handle the funky
1114 // Internet Explorer button-click scenario.
1115 _form_builder_ie_cleanup($element, $form_state);
1116
1117 // If some callback set #cache, we need to flip a flag so later it
1118 // can be found.
1119 if (!empty($element['#cache'])) {
1120 $form_state['cache'] = $element['#cache'];
1121 }
1122
1123 // If there is a file element, we need to flip a flag so later the
1124 // form encoding can be set.
1125 if (isset($element['#type']) && $element['#type'] == 'file') {
1126 $form_state['has_file_element'] = TRUE;
1127 }
1128
1129 if (isset($element['#type']) && $element['#type'] == 'form') {
1130 // We are on the top form.
1131 // If there is a file element, we set the form encoding.
1132 if (isset($form_state['has_file_element'])) {
1133 $element['#attributes']['enctype'] = 'multipart/form-data';
1134 }
1135 // Update the copy of the complete form for usage in validation handlers.
1136 $form_state['complete form'] = $element;
1137 }
1138 return $element;
1139 }
1140
1141 /**
1142 * Populate the #value and #name properties of input elements so they
1143 * can be processed and rendered.
1144 */
1145 function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
1146 if (!isset($element['#name'])) {
1147 $name = array_shift($element['#parents']);
1148 $element['#name'] = $name;
1149 if ($element['#type'] == 'file') {
1150 // To make it easier to handle $_FILES in file.inc, we place all
1151 // file fields in the 'files' array. Also, we do not support
1152 // nested file names.
1153 $element['#name'] = 'files[' . $element['#name'] . ']';
1154 }
1155 elseif (count($element['#parents'])) {
1156 $element['#name'] .= '[' . implode('][', $element['#parents']) . ']';
1157 }
1158 array_unshift($element['#parents'], $name);
1159 }
1160
1161 if (!empty($element['#disabled'])) {
1162 $element['#attributes']['disabled'] = 'disabled';
1163 }
1164
1165 // Set the element's #value property.
1166 if (!isset($element['#value']) && !array_key_exists('#value', $element)) {
1167 $value_callback = !empty($element['#value_callback']) ? $element['#value_callback'] : 'form_type_' . $element['#type'] . '_value';
1168
1169 if ($form_state['programmed'] || ($form_state['process_input'] && (!isset($element['#access']) || $element['#access']))) {
1170 $input = $form_state['input'];
1171 foreach ($element['#parents'] as $parent) {
1172 $input = isset($input[$parent]) ? $input[$parent] : NULL;
1173 }
1174 // If we have input for the current element, assign it to the #value property.
1175 if (!$form_state['programmed'] || isset($input)) {
1176 // Call #type_value to set the form value;
1177 if (function_exists($value_callback)) {
1178 $element['#value'] = $value_callback($element, $input, $form_state);
1179 }
1180 if (!isset($element['#value']) && isset($input)) {
1181 $element['#value'] = $input;
1182 }
1183 }
1184 // Mark all posted values for validation.
1185 if (isset($element['#value']) || (!empty($element['#required']))) {
1186 $element['#needs_validation'] = TRUE;
1187 }
1188 }
1189 // Load defaults.
1190 if (!isset($element['#value'])) {
1191 // Call #type_value without a second argument to request default_value handling.
1192 if (function_exists($value_callback)) {
1193 $element['#value'] = $value_callback($element, FALSE, $form_state);
1194 }
1195 // Final catch. If we haven't set a value yet, use the explicit default value.
1196 // Avoid image buttons (which come with garbage value), so we only get value
1197 // for the button actually clicked.
1198 if (!isset($element['#value']) && empty($element['#has_garbage_value'])) {
1199 $element['#value'] = isset($element['#default_value']) ? $element['#default_value'] : '';
1200 }
1201 }
1202 }
1203
1204 // Determine which button (if any) was clicked to submit the form.
1205 // We compare the incoming values with the buttons defined in the form,
1206 // and flag the one that matches. We have to do some funky tricks to
1207 // deal with Internet Explorer's handling of single-button forms, though.
1208 if (!empty($form_state['input']) && isset($element['#executes_submit_callback'])) {
1209 // First, accumulate a collection of buttons, divided into two bins:
1210 // those that execute full submit callbacks and those that only validate.
1211 $button_type = $element['#executes_submit_callback'] ? 'submit' : 'button';
1212 $form_state['buttons'][$button_type][] = $element;
1213
1214 if (_form_button_was_clicked($element, $form_state)) {
1215 $form_state['submitted'] = $form_state['submitted'] || $element['#executes_submit_callback'];
1216
1217 // In most cases, we want to use form_set_value() to manipulate
1218 // the global variables. In this special case, we want to make sure that
1219 // the value of this element is listed in $form_variables under 'op'.
1220 $form_state['values'][$element['#name']] = $element['#value'];
1221 $form_state['clicked_button'] = $element;
1222
1223 if (isset($element['#validate'])) {
1224 $form_state['validate_handlers'] = $element['#validate'];
1225 }
1226 if (isset($element['#submit'])) {
1227 $form_state['submit_handlers'] = $element['#submit'];
1228 }
1229 }
1230 }
1231 form_set_value($element, $element['#value'], $form_state);
1232 }
1233
1234 /**
1235 * Helper function to handle the sometimes-convoluted logic of button
1236 * click detection.
1237 *
1238 * In Internet Explorer, if ONLY one submit button is present, AND the
1239 * enter key is used to submit the form, no form value is sent for it
1240 * and we'll never detect a match. That special case is handled by
1241 * _form_builder_ie_cleanup().
1242 */
1243 function _form_button_was_clicked($form, &$form_state) {
1244 // First detect normal 'vanilla' button clicks. Traditionally, all
1245 // standard buttons on a form share the same name (usually 'op'),
1246 // and the specific return value is used to determine which was
1247 // clicked. This ONLY works as long as $form['#name'] puts the
1248 // value at the top level of the tree of $_POST data.
1249 if (isset($form_state['input'][$form['#name']]) && $form_state['input'][$form['#name']] == $form['#value']) {
1250 return TRUE;
1251 }
1252 // When image buttons are clicked, browsers do NOT pass the form element
1253 // value in $_POST. Instead they pass an integer representing the
1254 // coordinates of the click on the button image. This means that image
1255 // buttons MUST have unique $form['#name'] values, but the details of
1256 // their $_POST data should be ignored.
1257 elseif (!empty($form['#has_garbage_value']) && isset($form['#value']) && $form['#value'] !== '') {
1258 return TRUE;
1259 }
1260 return FALSE;
1261 }
1262
1263 /**
1264 * In IE, if only one submit button is present, AND the enter key is
1265 * used to submit the form, no form value is sent for it and our normal
1266 * button detection code will never detect a match. We call this
1267 * function after all other button-detection is complete to check
1268 * for the proper conditions, and treat the single button on the form
1269 * as 'clicked' if they are met.
1270 */
1271 function _form_builder_ie_cleanup($form, &$form_state) {
1272 // Quick check to make sure we're always looking at the full form
1273 // and not a sub-element.
1274 if (!empty