form_test.module

  1. drupal
    1. 7 modules/simpletest/tests/form_test.module
    2. 8 core/modules/system/tests/modules/form_test/form_test.module

Helper module for the form API tests.

Functions & methods

NameDescription
block_form_form_test_alter_form_alterImplements hook_form_FORM_ID_alter() on behalf of block.module.
form_label_test_formA form for testing form labels and required marks.
form_storage_test_form_continue_submitForm submit handler to continue multi-step form.
form_test_alter_formForm builder for testing hook_form_alter() and hook_form_FORM_ID_alter().
form_test_checkboxes_radiosForm constructor to test expansion of #type checkboxes and radios.
form_test_checkboxes_zero
form_test_checkbox_type_juggling
form_test_clicked_buttonForm builder to test button click detection.
form_test_clicked_button_submitForm submit handler for the form_test_clicked_button() form.
form_test_clicked_button_validateForm validation handler for the form_test_clicked_button() form.
form_test_element_validate_nameForm element validation handler for 'name' in form_test_validate_form().
form_test_form_alterImplements hook_form_alter().
form_test_form_form_test_alter_form_alterImplements hook_form_FORM_ID_alter().
form_test_form_form_test_state_persist_alterImplements hook_form_FORM_ID_alter().
form_test_form_rebuild_preserve_values_formForm builder for testing preservation of values during a rebuild.
form_test_form_rebuild_preserve_values_form_add_moreButton submit handler for form_test_form_rebuild_preserve_values_form().
form_test_form_rebuild_preserve_values_form_submitForm submit handler for form_test_form_rebuild_preserve_values_form().
form_test_form_state_values_clean_formForm builder for form_state_values_clean() test.
form_test_form_state_values_clean_form_submitForm submit handler for form_state_values_clean() test form.
form_test_form_user_register_form_alterImplements hook_form_FORM_ID_alter() for the registration form.
form_test_limit_validation_errors_element_validate_testForm element validation handler for the 'test' element.
form_test_limit_validation_errors_formBuilds a simple form with a button triggering partial validation.
form_test_limit_validation_errors_form_partial_submitForm submit handler for the partial validation submit button.
form_test_load_include_customMenu callback for testing custom form includes.
form_test_menuImplements hook_menu().
form_test_programmatic_formForm builder to test programmatic form submissions.
form_test_programmatic_form_submitForm submit handler for programmatic form submissions.
form_test_programmatic_form_validateForm validation handler for programmatic form submissions.
form_test_selectBuilds a form to test #type 'select' validation.
form_test_select_submitForm submit handler for form_test_select().
form_test_state_persistForm constructor for testing form state persistence.
form_test_state_persist_submitSubmit handler.
form_test_storage_element_validate_value_cachedForm element validation handler for 'value' element in form_test_storage_form().
form_test_storage_formA multistep form for testing the form storage.
form_test_storage_form_submitForm submit handler to finish multi-step form.
form_test_two_instancesMenu callback that returns two instances of the node form.
form_test_user_register_form_rebuildSubmit callback that just lets the form rebuild.
form_test_validate_formForm builder for testing drupal_validate_form().
form_test_validate_form_validateForm validation handler for form_test_validate_form().
form_test_validate_required_formForm constructor to test the #required property.
form_test_validate_required_form_submitForm submission handler for form_test_validate_required_form().
form_test_wrapper_callbackMenu callback; Invokes a form builder function with a wrapper callback.
form_test_wrapper_callback_formForm builder for form wrapper callback test.
form_test_wrapper_callback_wrapperForm wrapper for form_test_wrapper_callback_form().
system_form_form_test_alter_form_alterImplements hook_form_FORM_ID_alter() on behalf of system.module.
_form_test_checkboxBuild a form to test a checkbox.
_form_test_checkboxes_zero_no_redirect
_form_test_checkbox_submitReturn the form values via JSON.
_form_test_disabled_elementsBuild a form to test disabled elements.
_form_test_disabled_elements_submitReturn the form values via JSON.
_form_test_input_forgeryBuild a form to test input forgery of enabled elements.
_form_test_input_forgery_submitReturn the form values via JSON.
_form_test_submit_values_jsonForm submit handler to return form values as JSON.
_form_test_tableselect_empty_formTest functionality of the tableselect #empty property.
_form_test_tableselect_form_builderBuild a form to test the tableselect element.
_form_test_tableselect_get_dataCreate a header and options array. Helper function for callbacks.
_form_test_tableselect_js_select_formTest functionality of the tableselect #js_select property.
_form_test_tableselect_multiple_false_formTest the tableselect #multiple = FALSE functionality.
_form_test_tableselect_multiple_false_form_submitProcess the tableselect #multiple = FALSE submitted values.
_form_test_tableselect_multiple_true_formTest the tableselect #multiple = TRUE functionality.
_form_test_tableselect_multiple_true_form_submitProcess the tableselect #multiple = TRUE submitted values.
_form_test_vertical_tabs_formTests functionality of vertical tabs.

File

modules/simpletest/tests/form_test.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Helper module for the form API tests.
  5. */
  6. /**
  7. * Implements hook_menu().
  8. */
  9. function form_test_menu() {
  10. $items['form-test/alter'] = array(
  11. 'title' => 'Form altering test',
  12. 'page callback' => 'drupal_get_form',
  13. 'page arguments' => array('form_test_alter_form'),
  14. 'access arguments' => array('access content'),
  15. 'type' => MENU_CALLBACK,
  16. );
  17. $items['form-test/validate'] = array(
  18. 'title' => 'Form validation handlers test',
  19. 'page callback' => 'drupal_get_form',
  20. 'page arguments' => array('form_test_validate_form'),
  21. 'access arguments' => array('access content'),
  22. 'type' => MENU_CALLBACK,
  23. );
  24. $items['form-test/validate-required'] = array(
  25. 'title' => 'Form #required validation',
  26. 'page callback' => 'drupal_get_form',
  27. 'page arguments' => array('form_test_validate_required_form'),
  28. 'access callback' => TRUE,
  29. 'type' => MENU_CALLBACK,
  30. );
  31. $items['form-test/limit-validation-errors'] = array(
  32. 'title' => 'Form validation with some error suppression',
  33. 'page callback' => 'drupal_get_form',
  34. 'page arguments' => array('form_test_limit_validation_errors_form'),
  35. 'access arguments' => array('access content'),
  36. 'type' => MENU_CALLBACK,
  37. );
  38. $items['form_test/tableselect/multiple-true'] = array(
  39. 'title' => 'Tableselect checkboxes test',
  40. 'page callback' => 'drupal_get_form',
  41. 'page arguments' => array('_form_test_tableselect_multiple_true_form'),
  42. 'access arguments' => array('access content'),
  43. 'type' => MENU_CALLBACK,
  44. );
  45. $items['form_test/tableselect/multiple-false'] = array(
  46. 'title' => 'Tableselect radio button test',
  47. 'page callback' => 'drupal_get_form',
  48. 'page arguments' => array('_form_test_tableselect_multiple_false_form'),
  49. 'access arguments' => array('access content'),
  50. 'type' => MENU_CALLBACK,
  51. );
  52. $items['form_test/tableselect/empty-text'] = array(
  53. 'title' => 'Tableselect empty text test',
  54. 'page callback' => 'drupal_get_form',
  55. 'page arguments' => array('_form_test_tableselect_empty_form'),
  56. 'access arguments' => array('access content'),
  57. 'type' => MENU_CALLBACK,
  58. );
  59. $items['form_test/tableselect/advanced-select'] = array(
  60. 'title' => 'Tableselect js_select tests',
  61. 'page callback' => 'drupal_get_form',
  62. 'page arguments' => array('_form_test_tableselect_js_select_form'),
  63. 'access arguments' => array('access content'),
  64. 'type' => MENU_CALLBACK,
  65. );
  66. $items['form_test/vertical-tabs'] = array(
  67. 'title' => 'Vertical tabs tests',
  68. 'page callback' => 'drupal_get_form',
  69. 'page arguments' => array('_form_test_vertical_tabs_form'),
  70. 'access arguments' => array('access content'),
  71. 'type' => MENU_CALLBACK,
  72. );
  73. $items['form_test/form-storage'] = array(
  74. 'title' => 'Form storage test',
  75. 'page callback' => 'drupal_get_form',
  76. 'page arguments' => array('form_test_storage_form'),
  77. 'access arguments' => array('access content'),
  78. 'type' => MENU_CALLBACK,
  79. );
  80. $items['form_test/wrapper-callback'] = array(
  81. 'title' => 'Form wrapper callback test',
  82. 'page callback' => 'form_test_wrapper_callback',
  83. 'page arguments' => array('form_test_wrapper_callback_form'),
  84. 'access arguments' => array('access content'),
  85. 'type' => MENU_CALLBACK,
  86. );
  87. $items['form_test/form-state-values-clean'] = array(
  88. 'title' => 'Form state values clearance test',
  89. 'page callback' => 'drupal_get_form',
  90. 'page arguments' => array('form_test_form_state_values_clean_form'),
  91. 'access arguments' => array('access content'),
  92. 'type' => MENU_CALLBACK,
  93. );
  94. $items['form-test/checkbox'] = array(
  95. 'title' => t('Form test'),
  96. 'page callback' => 'drupal_get_form',
  97. 'page arguments' => array('_form_test_checkbox'),
  98. 'access callback' => TRUE,
  99. 'type' => MENU_CALLBACK,
  100. );
  101. $items['form-test/select'] = array(
  102. 'title' => t('Select'),
  103. 'page callback' => 'drupal_get_form',
  104. 'page arguments' => array('form_test_select'),
  105. 'access callback' => TRUE,
  106. );
  107. $items['form-test/checkboxes-radios'] = array(
  108. 'title' => t('Checkboxes, Radios'),
  109. 'page callback' => 'drupal_get_form',
  110. 'page arguments' => array('form_test_checkboxes_radios'),
  111. 'access callback' => TRUE,
  112. );
  113. $items['form-test/disabled-elements'] = array(
  114. 'title' => t('Form test'),
  115. 'page callback' => 'drupal_get_form',
  116. 'page arguments' => array('_form_test_disabled_elements'),
  117. 'access callback' => TRUE,
  118. 'type' => MENU_CALLBACK,
  119. );
  120. $items['form-test/input-forgery'] = array(
  121. 'title' => t('Form test'),
  122. 'page callback' => 'drupal_get_form',
  123. 'page arguments' => array('_form_test_input_forgery'),
  124. 'access callback' => TRUE,
  125. 'type' => MENU_CALLBACK,
  126. );
  127. $items['form-test/form-rebuild-preserve-values'] = array(
  128. 'title' => 'Form values preservation during rebuild test',
  129. 'page callback' => 'drupal_get_form',
  130. 'page arguments' => array('form_test_form_rebuild_preserve_values_form'),
  131. 'access arguments' => array('access content'),
  132. 'type' => MENU_CALLBACK,
  133. );
  134. $items['form_test/form-labels'] = array(
  135. 'title' => 'Form label test',
  136. 'page callback' => 'drupal_get_form',
  137. 'page arguments' => array('form_label_test_form'),
  138. 'access arguments' => array('access content'),
  139. 'type' => MENU_CALLBACK,
  140. );
  141. $items['form-test/state-persist'] = array(
  142. 'title' => 'Form state persistence without storage',
  143. 'page callback' => 'drupal_get_form',
  144. 'page arguments' => array('form_test_state_persist'),
  145. 'access callback' => TRUE,
  146. 'type' => MENU_CALLBACK,
  147. );
  148. $items['form-test/clicked-button'] = array(
  149. 'title' => 'Clicked button test',
  150. 'page callback' => 'drupal_get_form',
  151. 'page arguments' => array('form_test_clicked_button'),
  152. 'access callback' => TRUE,
  153. 'type' => MENU_CALLBACK,
  154. );
  155. if (module_exists('node')) {
  156. $items['form-test/two-instances-of-same-form'] = array(
  157. 'title' => 'AJAX test with two form instances',
  158. 'page callback' => 'form_test_two_instances',
  159. 'access callback' => 'node_access',
  160. 'access arguments' => array('create', 'page'),
  161. 'file path' => drupal_get_path('module', 'node'),
  162. 'file' => 'node.pages.inc',
  163. 'type' => MENU_CALLBACK,
  164. );
  165. }
  166. $items['form-test/load-include-menu'] = array(
  167. 'title' => 'FAPI test loading includes',
  168. 'page callback' => 'drupal_get_form',
  169. 'page arguments' => array('form_test_load_include_menu'),
  170. 'access callback' => TRUE,
  171. 'file' => 'form_test.file.inc',
  172. 'type' => MENU_CALLBACK,
  173. );
  174. $items['form-test/load-include-custom'] = array(
  175. 'title' => 'FAPI test loading includes',
  176. 'page callback' => 'drupal_get_form',
  177. 'page arguments' => array('form_test_load_include_custom'),
  178. 'access callback' => TRUE,
  179. 'type' => MENU_CALLBACK,
  180. );
  181. $items['form-test/checkboxes-zero'] = array(
  182. 'title' => 'FAPI test involving checkboxes and zero',
  183. 'page callback' => 'drupal_get_form',
  184. 'page arguments' => array('form_test_checkboxes_zero'),
  185. 'access callback' => TRUE,
  186. 'type' => MENU_CALLBACK,
  187. );
  188. return $items;
  189. }
  190. /**
  191. * Form submit handler to return form values as JSON.
  192. */
  193. function _form_test_submit_values_json($form, &$form_state) {
  194. drupal_json_output($form_state['values']);
  195. drupal_exit();
  196. }
  197. /**
  198. * Form builder for testing hook_form_alter() and hook_form_FORM_ID_alter().
  199. */
  200. function form_test_alter_form($form, &$form_state) {
  201. // Elements can be added as needed for future testing needs, but for now,
  202. // we're only testing alter hooks that do not require any elements added by
  203. // this function.
  204. return $form;
  205. }
  206. /**
  207. * Implements hook_form_FORM_ID_alter() on behalf of block.module.
  208. */
  209. function block_form_form_test_alter_form_alter(&$form, &$form_state) {
  210. drupal_set_message('block_form_form_test_alter_form_alter() executed.');
  211. }
  212. /**
  213. * Implements hook_form_alter().
  214. */
  215. function form_test_form_alter(&$form, &$form_state, $form_id) {
  216. if ($form_id == 'form_test_alter_form') {
  217. drupal_set_message('form_test_form_alter() executed.');
  218. }
  219. }
  220. /**
  221. * Implements hook_form_FORM_ID_alter().
  222. */
  223. function form_test_form_form_test_alter_form_alter(&$form, &$form_state) {
  224. drupal_set_message('form_test_form_form_test_alter_form_alter() executed.');
  225. }
  226. /**
  227. * Implements hook_form_FORM_ID_alter() on behalf of system.module.
  228. */
  229. function system_form_form_test_alter_form_alter(&$form, &$form_state) {
  230. drupal_set_message('system_form_form_test_alter_form_alter() executed.');
  231. }
  232. /**
  233. * Form builder for testing drupal_validate_form().
  234. *
  235. * Serves for testing form processing and alterations by form validation
  236. * handlers, especially for the case of a validation error:
  237. * - form_set_value() should be able to alter submitted values in
  238. * $form_state['values'] without affecting the form element.
  239. * - #element_validate handlers should be able to alter the $element in the form
  240. * structure and the alterations should be contained in the rebuilt form.
  241. * - #validate handlers should be able to alter the $form and the alterations
  242. * should be contained in the rebuilt form.
  243. */
  244. function form_test_validate_form($form, &$form_state) {
  245. $form['name'] = array(
  246. '#type' => 'textfield',
  247. '#title' => 'Name',
  248. '#default_value' => '',
  249. '#element_validate' => array('form_test_element_validate_name'),
  250. );
  251. $form['submit'] = array(
  252. '#type' => 'submit',
  253. '#value' => 'Save',
  254. );
  255. // To simplify this test, enable form caching and use form storage to
  256. // remember our alteration.
  257. $form_state['cache'] = TRUE;
  258. return $form;
  259. }
  260. /**
  261. * Form element validation handler for 'name' in form_test_validate_form().
  262. */
  263. function form_test_element_validate_name(&$element, &$form_state) {
  264. $triggered = FALSE;
  265. if ($form_state['values']['name'] == 'element_validate') {
  266. // Alter the form element.
  267. $element['#value'] = '#value changed by #element_validate';
  268. // Alter the submitted value in $form_state.
  269. form_set_value($element, 'value changed by form_set_value() in #element_validate', $form_state);
  270. $triggered = TRUE;
  271. }
  272. if ($form_state['values']['name'] == 'element_validate_access') {
  273. $form_state['storage']['form_test_name'] = $form_state['values']['name'];
  274. // Alter the form element.
  275. $element['#access'] = FALSE;
  276. $triggered = TRUE;
  277. }
  278. elseif (!empty($form_state['storage']['form_test_name'])) {
  279. // To simplify this test, just take over the element's value into $form_state.
  280. form_set_value($element, $form_state['storage']['form_test_name'], $form_state);
  281. $triggered = TRUE;
  282. }
  283. if ($triggered) {
  284. // Output the element's value from $form_state.
  285. drupal_set_message(t('@label value: @value', array('@label' => $element['#title'], '@value' => $form_state['values']['name'])));
  286. // Trigger a form validation error to see our changes.
  287. form_set_error('');
  288. }
  289. }
  290. /**
  291. * Form validation handler for form_test_validate_form().
  292. */
  293. function form_test_validate_form_validate(&$form, &$form_state) {
  294. if ($form_state['values']['name'] == 'validate') {
  295. // Alter the form element.
  296. $form['name']['#value'] = '#value changed by #validate';
  297. // Alter the submitted value in $form_state.
  298. form_set_value($form['name'], 'value changed by form_set_value() in #validate', $form_state);
  299. // Output the element's value from $form_state.
  300. drupal_set_message(t('@label value: @value', array('@label' => $form['name']['#title'], '@value' => $form_state['values']['name'])));
  301. // Trigger a form validation error to see our changes.
  302. form_set_error('');
  303. }
  304. }
  305. /**
  306. * Form constructor to test the #required property.
  307. */
  308. function form_test_validate_required_form($form, &$form_state) {
  309. $options = drupal_map_assoc(array('foo', 'bar'));
  310. $form['textfield'] = array(
  311. '#type' => 'textfield',
  312. '#title' => 'Textfield',
  313. '#required' => TRUE,
  314. );
  315. $form['checkboxes'] = array(
  316. '#type' => 'checkboxes',
  317. '#title' => 'Checkboxes',
  318. '#options' => $options,
  319. '#required' => TRUE,
  320. );
  321. $form['select'] = array(
  322. '#type' => 'select',
  323. '#title' => 'Select',
  324. '#options' => $options,
  325. '#required' => TRUE,
  326. );
  327. $form['radios'] = array(
  328. '#type' => 'radios',
  329. '#title' => 'Radios',
  330. '#options' => $options,
  331. '#required' => TRUE,
  332. );
  333. $form['radios_optional'] = array(
  334. '#type' => 'radios',
  335. '#title' => 'Radios (optional)',
  336. '#options' => $options,
  337. );
  338. $form['actions'] = array('#type' => 'actions');
  339. $form['actions']['submit'] = array('#type' => 'submit', '#value' => 'Submit');
  340. return $form;
  341. }
  342. /**
  343. * Form submission handler for form_test_validate_required_form().
  344. */
  345. function form_test_validate_required_form_submit($form, &$form_state) {
  346. drupal_set_message('The form_test_validate_required_form form was submitted successfully.');
  347. }
  348. /**
  349. * Builds a simple form with a button triggering partial validation.
  350. */
  351. function form_test_limit_validation_errors_form($form, &$form_state) {
  352. $form['title'] = array(
  353. '#type' => 'textfield',
  354. '#title' => 'Title',
  355. '#required' => TRUE,
  356. );
  357. $form['test'] = array(
  358. '#title' => 'Test',
  359. '#type' => 'textfield',
  360. '#element_validate' => array('form_test_limit_validation_errors_element_validate_test'),
  361. );
  362. $form['test_numeric_index'] = array(
  363. '#tree' => TRUE,
  364. );
  365. $form['test_numeric_index'][0] = array(
  366. '#title' => 'Test (numeric index)',
  367. '#type' => 'textfield',
  368. '#element_validate' => array('form_test_limit_validation_errors_element_validate_test'),
  369. );
  370. $form['test_substring'] = array(
  371. '#tree' => TRUE,
  372. );
  373. $form['test_substring']['foo'] = array(
  374. '#title' => 'Test (substring) foo',
  375. '#type' => 'textfield',
  376. '#element_validate' => array('form_test_limit_validation_errors_element_validate_test'),
  377. );
  378. $form['test_substring']['foobar'] = array(
  379. '#title' => 'Test (substring) foobar',
  380. '#type' => 'textfield',
  381. '#element_validate' => array('form_test_limit_validation_errors_element_validate_test'),
  382. );
  383. $form['actions']['partial'] = array(
  384. '#type' => 'submit',
  385. '#limit_validation_errors' => array(array('test')),
  386. '#submit' => array('form_test_limit_validation_errors_form_partial_submit'),
  387. '#value' => t('Partial validate'),
  388. );
  389. $form['actions']['partial_numeric_index'] = array(
  390. '#type' => 'submit',
  391. '#limit_validation_errors' => array(array('test_numeric_index', 0)),
  392. '#submit' => array('form_test_limit_validation_errors_form_partial_submit'),
  393. '#value' => t('Partial validate (numeric index)'),
  394. );
  395. $form['actions']['substring'] = array(
  396. '#type' => 'submit',
  397. '#limit_validation_errors' => array(array('test_substring', 'foo')),
  398. '#submit' => array('form_test_limit_validation_errors_form_partial_submit'),
  399. '#value' => t('Partial validate (substring)'),
  400. );
  401. $form['actions']['full'] = array(
  402. '#type' => 'submit',
  403. '#value' => t('Full validate'),
  404. );
  405. return $form;
  406. }
  407. /**
  408. * Form element validation handler for the 'test' element.
  409. */
  410. function form_test_limit_validation_errors_element_validate_test(&$element, &$form_state) {
  411. if ($element['#value'] == 'invalid') {
  412. form_error($element, t('@label element is invalid', array('@label' => $element['#title'])));
  413. }
  414. }
  415. /**
  416. * Form submit handler for the partial validation submit button.
  417. */
  418. function form_test_limit_validation_errors_form_partial_submit($form, $form_state) {
  419. // The title has not been validated, thus its value - in case of the test case
  420. // an empty string - may not be set.
  421. if (!isset($form_state['values']['title']) && isset($form_state['values']['test'])) {
  422. drupal_set_message('Only validated values appear in the form values.');
  423. }
  424. }
  425. /**
  426. * Create a header and options array. Helper function for callbacks.
  427. */
  428. function _form_test_tableselect_get_data() {
  429. $header = array(
  430. 'one' => t('One'),
  431. 'two' => t('Two'),
  432. 'three' => t('Three'),
  433. 'four' => t('Four'),
  434. );
  435. $options['row1'] = array(
  436. 'one' => 'row1col1',
  437. 'two' => t('row1col2'),
  438. 'three' => t('row1col3'),
  439. 'four' => t('row1col4'),
  440. );
  441. $options['row2'] = array(
  442. 'one' => 'row2col1',
  443. 'two' => t('row2col2'),
  444. 'three' => t('row2col3'),
  445. 'four' => t('row2col4'),
  446. );
  447. $options['row3'] = array(
  448. 'one' => 'row3col1',
  449. 'two' => t('row3col2'),
  450. 'three' => t('row3col3'),
  451. 'four' => t('row3col4'),
  452. );
  453. return array($header, $options);
  454. }
  455. /**
  456. * Build a form to test the tableselect element.
  457. *
  458. * @param $form_state
  459. * The form_state
  460. * @param $element_properties
  461. * An array of element properties for the tableselect element.
  462. *
  463. * @return
  464. * A form with a tableselect element and a submit button.
  465. */
  466. function _form_test_tableselect_form_builder($form, $form_state, $element_properties) {
  467. list($header, $options) = _form_test_tableselect_get_data();
  468. $form['tableselect'] = $element_properties;
  469. $form['tableselect'] += array(
  470. '#type' => 'tableselect',
  471. '#header' => $header,
  472. '#options' => $options,
  473. '#multiple' => FALSE,
  474. '#empty' => t('Empty text.'),
  475. );
  476. $form['submit'] = array(
  477. '#type' => 'submit',
  478. '#value' => t('Submit'),
  479. );
  480. return $form;
  481. }
  482. /**
  483. * Test the tableselect #multiple = TRUE functionality.
  484. */
  485. function _form_test_tableselect_multiple_true_form($form, $form_state) {
  486. return _form_test_tableselect_form_builder($form, $form_state, array('#multiple' => TRUE));
  487. }
  488. /**
  489. * Process the tableselect #multiple = TRUE submitted values.
  490. */
  491. function _form_test_tableselect_multiple_true_form_submit($form, &$form_state) {
  492. $selected = $form_state['values']['tableselect'];
  493. foreach ($selected as $key => $value) {
  494. drupal_set_message(t('Submitted: @key = @value', array('@key' => $key, '@value' => $value)));
  495. }
  496. }
  497. /**
  498. * Test the tableselect #multiple = FALSE functionality.
  499. */
  500. function _form_test_tableselect_multiple_false_form($form, $form_state) {
  501. return _form_test_tableselect_form_builder($form, $form_state, array('#multiple' => FALSE));
  502. }
  503. /**
  504. * Process the tableselect #multiple = FALSE submitted values.
  505. */
  506. function _form_test_tableselect_multiple_false_form_submit($form, &$form_state) {
  507. drupal_set_message(t('Submitted: @value', array('@value' => $form_state['values']['tableselect'])));
  508. }
  509. /**
  510. * Test functionality of the tableselect #empty property.
  511. */
  512. function _form_test_tableselect_empty_form($form, $form_state) {
  513. return _form_test_tableselect_form_builder($form, $form_state, array('#options' => array()));
  514. }
  515. /**
  516. * Test functionality of the tableselect #js_select property.
  517. */
  518. function _form_test_tableselect_js_select_form($form, $form_state, $action) {
  519. switch ($action) {
  520. case 'multiple-true-default':
  521. $options = array('#multiple' => TRUE);
  522. break;
  523. case 'multiple-false-default':
  524. $options = array('#multiple' => FALSE);
  525. break;
  526. case 'multiple-true-no-advanced-select':
  527. $options = array('#multiple' => TRUE, '#js_select' => FALSE);
  528. break;
  529. case 'multiple-false-advanced-select':
  530. $options = array('#multiple' => FALSE, '#js_select' => TRUE);
  531. break;
  532. }
  533. return _form_test_tableselect_form_builder($form, $form_state, $options);
  534. }
  535. /**
  536. * Tests functionality of vertical tabs.
  537. */
  538. function _form_test_vertical_tabs_form($form, &$form_state) {
  539. $form['vertical_tabs'] = array(
  540. '#type' => 'vertical_tabs',
  541. );
  542. $form['tab1'] = array(
  543. '#type' => 'fieldset',
  544. '#title' => t('Tab 1'),
  545. '#collapsible' => TRUE,
  546. '#group' => 'vertical_tabs',
  547. );
  548. $form['tab1']['field1'] = array(
  549. '#title' => t('Field 1'),
  550. '#type' => 'textfield',
  551. );
  552. $form['tab2'] = array(
  553. '#type' => 'fieldset',
  554. '#title' => t('Tab 2'),
  555. '#collapsible' => TRUE,
  556. '#group' => 'vertical_tabs',
  557. );
  558. $form['tab2']['field2'] = array(
  559. '#title' => t('Field 2'),
  560. '#type' => 'textfield',
  561. );
  562. return $form;
  563. }
  564. /**
  565. * A multistep form for testing the form storage.
  566. *
  567. * It uses two steps for editing a virtual "thing". Any changes to it are saved
  568. * in the form storage and have to be present during any step. By setting the
  569. * request parameter "cache" the form can be tested with caching enabled, as
  570. * it would be the case, if the form would contain some #ajax callbacks.
  571. *
  572. * @see form_test_storage_form_submit()
  573. */
  574. function form_test_storage_form($form, &$form_state) {
  575. if ($form_state['rebuild']) {
  576. $form_state['input'] = array();
  577. }
  578. // Initialize
  579. if (empty($form_state['storage'])) {
  580. if (empty($form_state['input'])) {
  581. $_SESSION['constructions'] = 0;
  582. }
  583. // Put the initial thing into the storage
  584. $form_state['storage'] = array(
  585. 'thing' => array(
  586. 'title' => 'none',
  587. 'value' => '',
  588. ),
  589. );
  590. }
  591. // Count how often the form is constructed.
  592. $_SESSION['constructions']++;
  593. drupal_set_message("Form constructions: " . $_SESSION['constructions']);
  594. $form['title'] = array(
  595. '#type' => 'textfield',
  596. '#title' => 'Title',
  597. '#default_value' => $form_state['storage']['thing']['title'],
  598. '#required' => TRUE,
  599. );
  600. $form['value'] = array(
  601. '#type' => 'textfield',
  602. '#title' => 'Value',
  603. '#default_value' => $form_state['storage']['thing']['value'],
  604. '#element_validate' => array('form_test_storage_element_validate_value_cached'),
  605. );
  606. $form['continue_button'] = array(
  607. '#type' => 'button',
  608. '#value' => 'Reset',
  609. // Rebuilds the form without keeping the values.
  610. );
  611. $form['continue_submit'] = array(
  612. '#type' => 'submit',
  613. '#value' => 'Continue submit',
  614. '#submit' => array('form_storage_test_form_continue_submit'),
  615. );
  616. $form['submit'] = array(
  617. '#type' => 'submit',
  618. '#value' => 'Save',
  619. );
  620. if (isset($_REQUEST['cache'])) {
  621. // Manually activate caching, so we can test that the storage keeps working
  622. // when it's enabled.
  623. $form_state['cache'] = TRUE;
  624. }
  625. return $form;
  626. }
  627. /**
  628. * Form element validation handler for 'value' element in form_test_storage_form().
  629. *
  630. * Tests updating of cached form storage during validation.
  631. */
  632. function form_test_storage_element_validate_value_cached($element, &$form_state) {
  633. // If caching is enabled and we receive a certain value, change the storage.
  634. // This presumes that another submitted form value triggers a validation error
  635. // elsewhere in the form. Form API should still update the cached form storage
  636. // though.
  637. if (isset($_REQUEST['cache']) && $form_state['values']['value'] == 'change_title') {
  638. $form_state['storage']['thing']['changed'] = TRUE;
  639. }
  640. }
  641. /**
  642. * Form submit handler to continue multi-step form.
  643. */
  644. function form_storage_test_form_continue_submit($form, &$form_state) {
  645. $form_state['storage']['thing']['title'] = $form_state['values']['title'];
  646. $form_state['storage']['thing']['value'] = $form_state['values']['value'];
  647. $form_state['rebuild'] = TRUE;
  648. }
  649. /**
  650. * Form submit handler to finish multi-step form.
  651. */
  652. function form_test_storage_form_submit($form, &$form_state) {
  653. drupal_set_message("Title: " . check_plain($form_state['values']['title']));
  654. drupal_set_message("Form constructions: " . $_SESSION['constructions']);
  655. if (isset($form_state['storage']['thing']['changed'])) {
  656. drupal_set_message("The thing has been changed.");
  657. }
  658. $form_state['redirect'] = 'node';
  659. }
  660. /**
  661. * A form for testing form labels and required marks.
  662. */
  663. function form_label_test_form() {
  664. $form['form_checkboxes_test'] = array(
  665. '#type' => 'checkboxes',
  666. '#title' => t('Checkboxes test'),
  667. '#options' => array(
  668. 'first-checkbox' => t('First checkbox'),
  669. 'second-checkbox' => t('Second checkbox'),
  670. 'third-checkbox' => t('Third checkbox'),
  671. '0' => t('0'),
  672. ),
  673. );
  674. $form['form_radios_test'] = array(
  675. '#type' => 'radios',
  676. '#title' => t('Radios test'),
  677. '#options' => array(
  678. 'first-radio' => t('First radio'),
  679. 'second-radio' => t('Second radio'),
  680. 'third-radio' => t('Third radio'),
  681. '0' => t('0'),
  682. ),
  683. // Test #field_prefix and #field_suffix placement.
  684. '#field_prefix' => '<span id="form-test-radios-field-prefix">' . t('Radios #field_prefix element') . '</span>',
  685. '#field_suffix' => '<span id="form-test-radios-field-suffix">' . t('Radios #field_suffix element') . '</span>',
  686. );
  687. $form['form_checkbox_test'] = array(
  688. '#type' => 'checkbox',
  689. '#title' => t('Checkbox test'),
  690. );
  691. $form['form_textfield_test_title_and_required'] = array(
  692. '#type' => 'textfield',
  693. '#title' => t('Textfield test for required with title'),
  694. '#required' => TRUE,
  695. );
  696. $form['form_textfield_test_no_title_required'] = array(
  697. '#type' => 'textfield',
  698. // We use an empty title, since not setting #title suppresses the label
  699. // and required marker.
  700. '#title' => '',
  701. '#required' => TRUE,
  702. );
  703. $form['form_textfield_test_title'] = array(
  704. '#type' => 'textfield',
  705. '#title' => t('Textfield test for title only'),
  706. // Not required.
  707. // Test #prefix and #suffix placement.
  708. '#prefix' => '<div id="form-test-textfield-title-prefix">' . t('Textfield #prefix element') . '</div>',
  709. '#suffix' => '<div id="form-test-textfield-title-suffix">' . t('Textfield #suffix element') . '</div>',
  710. );
  711. $form['form_textfield_test_title_after'] = array(
  712. '#type' => 'textfield',
  713. '#title' => t('Textfield test for title after element'),
  714. '#title_display' => 'after',
  715. );
  716. $form['form_textfield_test_title_invisible'] = array(
  717. '#type' => 'textfield',
  718. '#title' => t('Textfield test for invisible title'),
  719. '#title_display' => 'invisible',
  720. );
  721. // Textfield test for title set not to display.
  722. $form['form_textfield_test_title_no_show'] = array(
  723. '#type' => 'textfield',
  724. );
  725. // Checkboxes & radios with title as attribute.
  726. $form['form_checkboxes_title_attribute'] = array(
  727. '#type' => 'checkboxes',
  728. '#title' => 'Checkboxes test',
  729. '#options' => array(
  730. 'first-checkbox' => 'First checkbox',
  731. 'second-checkbox' => 'Second checkbox',
  732. ),
  733. '#title_display' => 'attribute',
  734. '#required' => TRUE,
  735. );
  736. $form['form_radios_title_attribute'] = array(
  737. '#type' => 'radios',
  738. '#title' => 'Radios test',
  739. '#options' => array(
  740. 'first-radio' => 'First radio',
  741. 'second-radio' => 'Second radio',
  742. ),
  743. '#title_display' => 'attribute',
  744. '#required' => TRUE,
  745. );
  746. return $form;
  747. }
  748. /**
  749. * Menu callback; Invokes a form builder function with a wrapper callback.
  750. */
  751. function form_test_wrapper_callback($form_id) {
  752. $form_state = array(
  753. 'build_info' => array('args' => array()),
  754. 'wrapper_callback' => 'form_test_wrapper_callback_wrapper',
  755. );
  756. return drupal_build_form($form_id, $form_state);
  757. }
  758. /**
  759. * Form wrapper for form_test_wrapper_callback_form().
  760. */
  761. function form_test_wrapper_callback_wrapper($form, &$form_state) {
  762. $form['wrapper'] = array('#markup' => 'Form wrapper callback element output.');
  763. return $form;
  764. }
  765. /**
  766. * Form builder for form wrapper callback test.
  767. */
  768. function form_test_wrapper_callback_form($form, &$form_state) {
  769. $form['builder'] = array('#markup' => 'Form builder element output.');
  770. return $form;
  771. }
  772. /**
  773. * Form builder for form_state_values_clean() test.
  774. */
  775. function form_test_form_state_values_clean_form($form, &$form_state) {
  776. // Build an example form containing multiple submit and button elements; not
  777. // only on the top-level.
  778. $form = array('#tree' => TRUE);
  779. $form['foo'] = array('#type' => 'submit', '#value' => t('Submit'));
  780. $form['bar'] = array('#type' => 'submit', '#value' => t('Submit'));
  781. $form['beer'] = array('#type' => 'value', '#value' => 1000);
  782. $form['baz']['foo'] = array('#type' => 'button', '#value' => t('Submit'));
  783. $form['baz']['baz'] = array('#type' => 'submit', '#value' => t('Submit'));
  784. $form['baz']['beer'] = array('#type' => 'value', '#value' => 2000);
  785. return $form;
  786. }
  787. /**
  788. * Form submit handler for form_state_values_clean() test form.
  789. */
  790. function form_test_form_state_values_clean_form_submit($form, &$form_state) {
  791. form_state_values_clean($form_state);
  792. drupal_json_output($form_state['values']);
  793. exit;
  794. }
  795. /**
  796. * Build a form to test a checkbox.
  797. */
  798. function _form_test_checkbox($form, &$form_state) {
  799. // A required checkbox.
  800. $form['required_checkbox'] = array(
  801. '#type' => 'checkbox',
  802. '#required' => TRUE,
  803. '#title' => 'required_checkbox',
  804. );
  805. // A disabled checkbox should get its default value back.
  806. $form['disabled_checkbox_on'] = array(
  807. '#type' => 'checkbox',
  808. '#disabled' => TRUE,
  809. '#return_value' => 'disabled_checkbox_on',
  810. '#default_value' => 'disabled_checkbox_on',
  811. '#title' => 'disabled_checkbox_on',
  812. );
  813. $form['disabled_checkbox_off'] = array(
  814. '#type' => 'checkbox',
  815. '#disabled' => TRUE,
  816. '#return_value' => 'disabled_checkbox_off',
  817. '#default_value' => NULL,
  818. '#title' => 'disabled_checkbox_off',
  819. );
  820. // A checkbox is active when #default_value == #return_value.
  821. $form['checkbox_on'] = array(
  822. '#type' => 'checkbox',
  823. '#return_value' => 'checkbox_on',
  824. '#default_value' => 'checkbox_on',
  825. '#title' => 'checkbox_on',
  826. );
  827. // But inactive in any other case.
  828. $form['checkbox_off'] = array(
  829. '#type' => 'checkbox',
  830. '#return_value' => 'checkbox_off',
  831. '#default_value' => 'checkbox_on',
  832. '#title' => 'checkbox_off',
  833. );
  834. // Checkboxes with a #return_value of '0' are supported.
  835. $form['zero_checkbox_on'] = array(
  836. '#type' => 'checkbox',
  837. '#return_value' => '0',
  838. '#default_value' => '0',
  839. '#title' => 'zero_checkbox_on',
  840. );
  841. // In that case, passing a #default_value != '0' means that the checkbox is off.
  842. $form['zero_checkbox_off'] = array(
  843. '#type' => 'checkbox',
  844. '#return_value' => '0',
  845. '#default_value' => '1',
  846. '#title' => 'zero_checkbox_off',
  847. );
  848. $form['submit'] = array(
  849. '#type' => 'submit',
  850. '#value' => t('Submit')
  851. );
  852. return $form;
  853. }
  854. /**
  855. * Return the form values via JSON.
  856. */
  857. function _form_test_checkbox_submit($form, &$form_state) {
  858. drupal_json_output($form_state['values']);
  859. exit();
  860. }
  861. /**
  862. * Builds a form to test #type 'select' validation.
  863. */
  864. function form_test_select($form, &$form_state) {
  865. $base = array(
  866. '#type' => 'select',
  867. '#options' => drupal_map_assoc(array('one', 'two', 'three')),
  868. );
  869. $form['select'] = $base + array(
  870. '#title' => '#default_value one',
  871. '#default_value' => 'one',
  872. );
  873. $form['select_required'] = $base + array(
  874. '#title' => '#default_value one, #required',
  875. '#required' => TRUE,
  876. '#default_value' => 'one',
  877. );
  878. $form['select_optional'] = $base + array(
  879. '#title' => '#default_value one, not #required',
  880. '#required' => FALSE,
  881. '#default_value' => 'one',
  882. );
  883. $form['empty_value'] = $base + array(
  884. '#title' => '#default_value one, #required, #empty_value 0',
  885. '#required' => TRUE,
  886. '#default_value' => 'one',
  887. '#empty_value' => 0,
  888. );
  889. $form['empty_value_one'] = $base + array(
  890. '#title' => '#default_value = #empty_value, #required',
  891. '#required' => TRUE,
  892. '#default_value' => 'one',
  893. '#empty_value' => 'one',
  894. );
  895. $form['no_default'] = $base + array(
  896. '#title' => 'No #default_value, #required',
  897. '#required' => TRUE,
  898. );
  899. $form['no_default_optional'] = $base + array(
  900. '#title' => 'No #default_value, not #required',
  901. '#required' => FALSE,
  902. '#description' => 'Should result in "one", because it is not required and there is no #empty_value requested, so default browser behavior of preselecting first option is in effect.',
  903. );
  904. $form['no_default_optional_empty_value'] = $base + array(
  905. '#title' => 'No #default_value, not #required, #empty_value empty string',
  906. '#empty_value' => '',
  907. '#required' => FALSE,
  908. '#description' => 'Should result in an empty string (due to #empty_value), because it is optional.',
  909. );
  910. $form['no_default_empty_option'] = $base + array(
  911. '#title' => 'No #default_value, #required, #empty_option',
  912. '#required' => TRUE,
  913. '#empty_option' => '- Choose -',
  914. );
  915. $form['no_default_empty_option_optional'] = $base + array(
  916. '#title' => 'No #default_value, not #required, #empty_option',
  917. '#empty_option' => '- Dismiss -',
  918. '#description' => 'Should result in an empty string (default of #empty_value), because it is optional.',
  919. );
  920. $form['no_default_empty_value'] = $base + array(
  921. '#title' => 'No #default_value, #required, #empty_value 0',
  922. '#required' => TRUE,
  923. '#empty_value' => 0,
  924. '#description' => 'Should never result in 0.',
  925. );
  926. $form['no_default_empty_value_one'] = $base + array(
  927. '#title' => 'No #default_value, #required, #empty_value one',
  928. '#required' => TRUE,
  929. '#empty_value' => 'one',
  930. '#description' => 'A mistakenly assigned #empty_value contained in #options should not be valid.',
  931. );
  932. $form['no_default_empty_value_optional'] = $base + array(
  933. '#title' => 'No #default_value, not #required, #empty_value 0',
  934. '#required' => FALSE,
  935. '#empty_value' => 0,
  936. '#description' => 'Should result in 0, because it is optional.',
  937. );
  938. $form['multiple'] = $base + array(
  939. '#title' => '#multiple, #default_value two',
  940. '#default_value' => array('two'),
  941. '#multiple' => TRUE,
  942. );
  943. $form['multiple_no_default'] = $base + array(
  944. '#title' => '#multiple, no #default_value',
  945. '#multiple' => TRUE,
  946. );
  947. $form['multiple_no_default_required'] = $base + array(
  948. '#title' => '#multiple, #required, no #default_value',
  949. '#required' => TRUE,
  950. '#multiple' => TRUE,
  951. );
  952. $form['submit'] = array('#type' => 'submit', '#value' => 'Submit');
  953. return $form;
  954. }
  955. /**
  956. * Form submit handler for form_test_select().
  957. */
  958. function form_test_select_submit($form, &$form_state) {
  959. drupal_json_output($form_state['values']);
  960. exit();
  961. }
  962. /**
  963. * Form constructor to test expansion of #type checkboxes and radios.
  964. */
  965. function form_test_checkboxes_radios($form, &$form_state, $customize = FALSE) {
  966. $form['#submit'] = array('_form_test_submit_values_json');
  967. // Expand #type checkboxes, setting custom element properties for some but not
  968. // all options.
  969. $form['checkboxes'] = array(
  970. '#type' => 'checkboxes',
  971. '#title' => 'Checkboxes',
  972. '#options' => array(
  973. 0 => 'Zero',
  974. 'foo' => 'Foo',
  975. 1 => 'One',
  976. 'bar' => 'Bar',
  977. '>' => 'Special Char',
  978. ),
  979. );
  980. if ($customize) {
  981. $form['checkboxes'] += array(
  982. 'foo' => array(
  983. '#description' => 'Enable to foo.',
  984. ),
  985. 1 => array(
  986. '#weight' => 10,
  987. ),
  988. );
  989. }
  990. // Expand #type radios, setting custom element properties for some but not
  991. // all options.
  992. $form['radios'] = array(
  993. '#type' => 'radios',
  994. '#title' => 'Radios',
  995. '#options' => array(
  996. 0 => 'Zero',
  997. 'foo' => 'Foo',
  998. 1 => 'One',
  999. 'bar' => 'Bar',
  1000. '>' => 'Special Char',
  1001. ),
  1002. );
  1003. if ($customize) {
  1004. $form['radios'] += array(
  1005. 'foo' => array(
  1006. '#description' => 'Enable to foo.',
  1007. ),
  1008. 1 => array(
  1009. '#weight' => 10,
  1010. ),
  1011. );
  1012. }
  1013. $form['submit'] = array('#type' => 'submit', '#value' => 'Submit');
  1014. return $form;
  1015. }
  1016. /**
  1017. * Build a form to test disabled elements.
  1018. */
  1019. function _form_test_disabled_elements($form, &$form_state) {
  1020. // Elements that take a simple default value.
  1021. foreach (array('textfield', 'textarea', 'hidden') as $type) {
  1022. $form[$type] = array(
  1023. '#type' => $type,
  1024. '#title' => $type,
  1025. '#default_value' => $type,
  1026. '#test_hijack_value' => 'HIJACK',
  1027. '#disabled' => TRUE,
  1028. );
  1029. }
  1030. // Multiple values option elements.
  1031. foreach (array('checkboxes', 'select') as $type) {
  1032. $form[$type . '_multiple'] = array(
  1033. '#type' => $type,
  1034. '#title' => $type . ' (multiple)',
  1035. '#options' => array(
  1036. 'test_1' => 'Test 1',
  1037. 'test_2' => 'Test 2',
  1038. ),
  1039. '#multiple' => TRUE,
  1040. '#default_value' => array('test_2' => 'test_2'),
  1041. // The keys of #test_hijack_value need to match the #name of the control.
  1042. // @see FormsTestCase::testDisabledElements()
  1043. '#test_hijack_value' => $type == 'select' ? array('' => 'test_1') : array('test_1' => 'test_1'),
  1044. '#disabled' => TRUE,
  1045. );
  1046. }
  1047. // Single values option elements.
  1048. foreach (array('radios', 'select') as $type) {
  1049. $form[$type . '_single'] = array(
  1050. '#type' => $type,
  1051. '#title' => $type . ' (single)',
  1052. '#options' => array(
  1053. 'test_1' => 'Test 1',
  1054. 'test_2' => 'Test 2',
  1055. ),
  1056. '#multiple' => FALSE,
  1057. '#default_value' => 'test_2',
  1058. '#test_hijack_value' => 'test_1',
  1059. '#disabled' => TRUE,
  1060. );
  1061. }
  1062. // Checkbox and radio.
  1063. foreach (array('checkbox', 'radio') as $type) {
  1064. $form[$type . '_unchecked'] = array(
  1065. '#type' => $type,
  1066. '#title' => $type . ' (unchecked)',
  1067. '#return_value' => 1,
  1068. '#default_value' => 0,
  1069. '#test_hijack_value' => 1,
  1070. '#disabled' => TRUE,
  1071. );
  1072. $form[$type . '_checked'] = array(
  1073. '#type' => $type,
  1074. '#title' => $type . ' (checked)',
  1075. '#return_value' => 1,
  1076. '#default_value' => 1,
  1077. '#test_hijack_value' => NULL,
  1078. '#disabled' => TRUE,
  1079. );
  1080. }
  1081. // Weight.
  1082. $form['weight'] = array(
  1083. '#type' => 'weight',
  1084. '#title' => 'weight',
  1085. '#default_value' => 10,
  1086. '#test_hijack_value' => 5,
  1087. '#disabled' => TRUE,
  1088. );
  1089. // Date.
  1090. $form['date'] = array(
  1091. '#type' => 'date',
  1092. '#title' => 'date',
  1093. '#disabled' => TRUE,
  1094. '#default_value' => array(
  1095. 'day' => 19,
  1096. 'month' => 11,
  1097. 'year' => 1978,
  1098. ),
  1099. '#test_hijack_value' => array(
  1100. 'day' => 20,
  1101. 'month' => 12,
  1102. 'year' => 1979,
  1103. ),
  1104. );
  1105. // The #disabled state should propagate to children.
  1106. $form['disabled_container'] = array(
  1107. '#disabled' => TRUE,
  1108. );
  1109. foreach (array('textfield', 'textarea', 'hidden') as $type) {
  1110. $form['disabled_container']['disabled_container_' . $type] = array(
  1111. '#type' => $type,
  1112. '#title' => $type,
  1113. '#default_value' => $type,
  1114. '#test_hijack_value' => 'HIJACK',
  1115. );
  1116. }
  1117. // Text format.
  1118. $form['text_format'] = array(
  1119. '#type' => 'text_format',
  1120. '#title' => 'Text format',
  1121. '#disabled' => TRUE,
  1122. '#default_value' => 'Text value',
  1123. '#format' => 'plain_text',
  1124. '#expected_value' => array(
  1125. 'value' => 'Text value',
  1126. 'format' => 'plain_text',
  1127. ),
  1128. '#test_hijack_value' => array(
  1129. 'value' => 'HIJACK',
  1130. 'format' => 'filtered_html',
  1131. ),
  1132. );
  1133. // Password fields.
  1134. $form['password'] = array(
  1135. '#type' => 'password',
  1136. '#title' => 'Password',
  1137. '#disabled' => TRUE,
  1138. );
  1139. $form['password_confirm'] = array(
  1140. '#type' => 'password_confirm',
  1141. '#title' => 'Password confirm',
  1142. '#disabled' => TRUE,
  1143. );
  1144. // Files.
  1145. $form['file'] = array(
  1146. '#type' => 'file',
  1147. '#title' => 'File',
  1148. '#disabled' => TRUE,
  1149. );
  1150. $form['managed_file'] = array(
  1151. '#type' => 'managed_file',
  1152. '#title' => 'Managed file',
  1153. '#disabled' => TRUE,
  1154. );
  1155. // Buttons.
  1156. $form['image_button'] = array(
  1157. '#type' => 'image_button',
  1158. '#value' => 'Image button',
  1159. '#disabled' => TRUE,
  1160. );
  1161. $form['button'] = array(
  1162. '#type' => 'button',
  1163. '#value' => 'Button',
  1164. '#disabled' => TRUE,
  1165. );
  1166. $form['submit_disabled'] = array(
  1167. '#type' => 'submit',
  1168. '#value' => 'Submit',
  1169. '#disabled' => TRUE,
  1170. );
  1171. $form['submit'] = array(
  1172. '#type' => 'submit',
  1173. '#value' => t('Submit'),
  1174. );
  1175. return $form;
  1176. }
  1177. /**
  1178. * Return the form values via JSON.
  1179. */
  1180. function _form_test_disabled_elements_submit($form, &$form_state) {
  1181. drupal_json_output($form_state['values']);
  1182. exit();
  1183. }
  1184. /**
  1185. * Build a form to test input forgery of enabled elements.
  1186. */
  1187. function _form_test_input_forgery($form, &$form_state) {
  1188. // For testing that a user can't submit a value not matching one of the
  1189. // allowed options.
  1190. $form['checkboxes'] = array(
  1191. '#type' => 'checkboxes',
  1192. '#options' => array(
  1193. 'one' => 'One',
  1194. 'two' => 'Two',
  1195. ),
  1196. );
  1197. $form['submit'] = array(
  1198. '#type' => 'submit',
  1199. '#value' => t('Submit'),
  1200. );
  1201. return $form;
  1202. }
  1203. /**
  1204. * Return the form values via JSON.
  1205. */
  1206. function _form_test_input_forgery_submit($form, &$form_state) {
  1207. drupal_json_output($form_state['values']);
  1208. exit();
  1209. }
  1210. /**
  1211. * Form builder for testing preservation of values during a rebuild.
  1212. */
  1213. function form_test_form_rebuild_preserve_values_form($form, &$form_state) {
  1214. // Start the form with two checkboxes, to test different defaults, and a
  1215. // textfield, to test more than one element type.
  1216. $form = array(
  1217. 'checkbox_1_default_off' => array(
  1218. '#type' => 'checkbox',
  1219. '#title' => t('This checkbox defaults to unchecked.'),
  1220. '#default_value' => FALSE,
  1221. ),
  1222. 'checkbox_1_default_on' => array(
  1223. '#type' => 'checkbox',
  1224. '#title' => t('This checkbox defaults to checked.'),
  1225. '#default_value' => TRUE,
  1226. ),
  1227. 'text_1' => array(
  1228. '#type' => 'textfield',
  1229. '#title' => t('This textfield has a non-empty default value.'),
  1230. '#default_value' => 'DEFAULT 1',
  1231. ),
  1232. );
  1233. // Provide an 'add more' button that rebuilds the form with an additional two
  1234. // checkboxes and a textfield. The test is to make sure that the rebuild
  1235. // triggered by this button preserves the user input values for the initial
  1236. // elements and initializes the new elements with the correct default values.
  1237. if (empty($form_state['storage']['add_more'])) {
  1238. $form['add_more'] = array(
  1239. '#type' => 'submit',
  1240. '#value' => 'Add more',
  1241. '#submit' => array('form_test_form_rebuild_preserve_values_form_add_more'),
  1242. );
  1243. }
  1244. else {
  1245. $form += array(
  1246. 'checkbox_2_default_off' => array(
  1247. '#type' => 'checkbox',
  1248. '#title' => t('This checkbox defaults to unchecked.'),
  1249. '#default_value' => FALSE,
  1250. ),
  1251. 'checkbox_2_default_on' => array(
  1252. '#type' => 'checkbox',
  1253. '#title' => t('This checkbox defaults to checked.'),
  1254. '#default_value' => TRUE,
  1255. ),
  1256. 'text_2' => array(
  1257. '#type' => 'textfield',
  1258. '#title' => t('This textfield has a non-empty default value.'),
  1259. '#default_value' => 'DEFAULT 2',
  1260. ),
  1261. );
  1262. }
  1263. // A submit button that finishes the form workflow (does not rebuild).
  1264. $form['submit'] = array(
  1265. '#type' => 'submit',
  1266. '#value' => 'Submit',
  1267. );
  1268. return $form;
  1269. }
  1270. /**
  1271. * Button submit handler for form_test_form_rebuild_preserve_values_form().
  1272. */
  1273. function form_test_form_rebuild_preserve_values_form_add_more($form, &$form_state) {
  1274. // Rebuild, to test preservation of input values.
  1275. $form_state['storage']['add_more'] = TRUE;
  1276. $form_state['rebuild'] = TRUE;
  1277. }
  1278. /**
  1279. * Form submit handler for form_test_form_rebuild_preserve_values_form().
  1280. */
  1281. function form_test_form_rebuild_preserve_values_form_submit($form, &$form_state) {
  1282. // Finish the workflow. Do not rebuild.
  1283. drupal_set_message(t('Form values: %values', array('%values' => var_export($form_state['values'], TRUE))));
  1284. }
  1285. /**
  1286. * Form constructor for testing form state persistence.
  1287. */
  1288. function form_test_state_persist($form, &$form_state) {
  1289. $form['title'] = array(
  1290. '#type' => 'textfield',
  1291. '#title' => 'title',
  1292. '#default_value' => 'DEFAULT',
  1293. '#required' => TRUE,
  1294. );
  1295. $form_state['value'] = 'State persisted.';
  1296. $form['submit'] = array(
  1297. '#type' => 'submit',
  1298. '#value' => t('Submit'),
  1299. );
  1300. return $form;
  1301. }
  1302. /**
  1303. * Submit handler.
  1304. *
  1305. * @see form_test_state_persist()
  1306. */
  1307. function form_test_state_persist_submit($form, &$form_state) {
  1308. drupal_set_message($form_state['value']);
  1309. $form_state['rebuild'] = TRUE;
  1310. }
  1311. /**
  1312. * Implements hook_form_FORM_ID_alter().
  1313. *
  1314. * @see form_test_state_persist()
  1315. */
  1316. function form_test_form_form_test_state_persist_alter(&$form, &$form_state) {
  1317. // Simulate a form alter implementation inserting form elements that enable
  1318. // caching of the form, e.g. elements having #ajax.
  1319. if (!empty($_REQUEST['cache'])) {
  1320. $form_state['cache'] = TRUE;
  1321. }
  1322. }
  1323. /**
  1324. * Form builder to test programmatic form submissions.
  1325. */
  1326. function form_test_programmatic_form($form, &$form_state) {
  1327. $form['textfield'] = array(
  1328. '#title' => 'Textfield',
  1329. '#type' => 'textfield',
  1330. );
  1331. $form['checkboxes'] = array(
  1332. '#type' => 'checkboxes',
  1333. '#options' => array(
  1334. 1 => 'First checkbox',
  1335. 2 => 'Second checkbox',
  1336. ),
  1337. // Both checkboxes are selected by default so that we can test the ability
  1338. // of programmatic form submissions to uncheck them.
  1339. '#default_value' => array(1, 2),
  1340. );
  1341. $form['field_to_validate'] = array(
  1342. '#type' => 'radios',
  1343. '#title' => 'Field to validate (in the case of limited validation)',
  1344. '#description' => 'If the form is submitted by clicking the "Submit with limited validation" button, then validation can be limited based on the value of this radio button.',
  1345. '#options' => array(
  1346. 'all' => 'Validate all fields',
  1347. 'textfield' => 'Validate the "Textfield" field',
  1348. 'field_to_validate' => 'Validate the "Field to validate" field',
  1349. ),
  1350. '#default_value' => 'all',
  1351. );
  1352. // The main submit button for the form.
  1353. $form['submit'] = array(
  1354. '#type' => 'submit',
  1355. '#value' => 'Submit',
  1356. );
  1357. // A secondary submit button that allows validation to be limited based on
  1358. // the value of the above radio selector.
  1359. $form['submit_limit_validation'] = array(
  1360. '#type' => 'submit',
  1361. '#value' => 'Submit with limited validation',
  1362. // Use the same submit handler for this button as for the form itself.
  1363. // (This must be set explicitly or otherwise the form API will ignore the
  1364. // #limit_validation_errors property.)
  1365. '#submit' => array('form_test_programmatic_form_submit'),
  1366. );
  1367. if (!empty($form_state['input']['field_to_validate']) && $form_state['input']['field_to_validate'] != 'all') {
  1368. $form['submit_limit_validation']['#limit_validation_errors'] = array(
  1369. array($form_state['input']['field_to_validate']),
  1370. );
  1371. }
  1372. return $form;
  1373. }
  1374. /**
  1375. * Form validation handler for programmatic form submissions.
  1376. *
  1377. * To test that the validation handler is correctly executed, the field value is
  1378. * explicitly required here.
  1379. */
  1380. function form_test_programmatic_form_validate($form, &$form_state) {
  1381. if (empty($form_state['values']['textfield'])) {
  1382. form_set_error('textfield', t('Textfield is required.'));
  1383. }
  1384. }
  1385. /**
  1386. * Form submit handler for programmatic form submissions.
  1387. *
  1388. * To test that the submission handler is correctly executed, we store the
  1389. * submitted values in a place we can access from the caller context.
  1390. */
  1391. function form_test_programmatic_form_submit($form, &$form_state) {
  1392. $form_state['storage']['programmatic_form_submit'] = $form_state['values'];
  1393. }
  1394. /**
  1395. * Form builder to test button click detection.
  1396. */
  1397. function form_test_clicked_button($form, &$form_state) {
  1398. // A single text field. In IE, when a form has only one non-button input field
  1399. // and the ENTER key is pressed while that field has focus, the form is
  1400. // submitted without any information identifying the button responsible for
  1401. // the submission. In other browsers, the form is submitted as though the
  1402. // first button were clicked.
  1403. $form['text'] = array(
  1404. '#title' => 'Text',
  1405. '#type' => 'textfield',
  1406. );
  1407. // Loop through each path argument, addding buttons based on the information
  1408. // in the argument. For example, if the path is
  1409. // form-test/clicked-button/s/i/rb, then 3 buttons are added: a 'submit', an
  1410. // 'image_button', and a 'button' with #access=FALSE. This enables form.test
  1411. // to test a variety of combinations.
  1412. $i=0;
  1413. $args = array_slice(arg(), 2);
  1414. foreach ($args as $arg) {
  1415. $name = 'button' . ++$i;
  1416. // 's', 'b', or 'i' in the argument define the button type wanted.
  1417. if (strpos($arg, 's') !== FALSE) {
  1418. $type = 'submit';
  1419. }
  1420. elseif (strpos($arg, 'b') !== FALSE) {
  1421. $type = 'button';
  1422. }
  1423. elseif (strpos($arg, 'i') !== FALSE) {
  1424. $type = 'image_button';
  1425. }
  1426. else {
  1427. $type = NULL;
  1428. }
  1429. if (isset($type)) {
  1430. $form[$name] = array(
  1431. '#type' => $type,
  1432. '#name' => $name,
  1433. );
  1434. // Image buttons need a #src; the others need a #value.
  1435. if ($type == 'image_button') {
  1436. $form[$name]['#src'] = 'misc/druplicon.png';
  1437. }
  1438. else {
  1439. $form[$name]['#value'] = $name;
  1440. }
  1441. // 'r' for restricted, so we can test that button click detection code
  1442. // correctly takes #access security into account.
  1443. if (strpos($arg, 'r') !== FALSE) {
  1444. $form[$name]['#access'] = FALSE;
  1445. }
  1446. }
  1447. }
  1448. return $form;
  1449. }
  1450. /**
  1451. * Form validation handler for the form_test_clicked_button() form.
  1452. */
  1453. function form_test_clicked_button_validate($form, &$form_state) {
  1454. if (isset($form_state['triggering_element'])) {
  1455. drupal_set_message(t('The clicked button is %name.', array('%name' => $form_state['triggering_element']['#name'])));
  1456. }
  1457. else {
  1458. drupal_set_message('There is no clicked button.');
  1459. }
  1460. }
  1461. /**
  1462. * Form submit handler for the form_test_clicked_button() form.
  1463. */
  1464. function form_test_clicked_button_submit($form, &$form_state) {
  1465. drupal_set_message('Submit handler for form_test_clicked_button executed.');
  1466. }
  1467. /**
  1468. * Implements hook_form_FORM_ID_alter() for the registration form.
  1469. */
  1470. function form_test_form_user_register_form_alter(&$form, &$form_state) {
  1471. $form['test_rebuild'] = array(
  1472. '#type' => 'submit',
  1473. '#value' => t('Rebuild'),
  1474. '#submit' => array('form_test_user_register_form_rebuild'),
  1475. );
  1476. // If requested, add the test field by attaching the node page form.
  1477. if (!empty($_REQUEST['field'])) {
  1478. $node = (object)array('type' => 'page');
  1479. field_attach_form('node', $node, $form, $form_state);
  1480. }
  1481. }
  1482. /**
  1483. * Submit callback that just lets the form rebuild.
  1484. */
  1485. function form_test_user_register_form_rebuild($form, &$form_state) {
  1486. drupal_set_message('Form rebuilt.');
  1487. $form_state['rebuild'] = TRUE;
  1488. }
  1489. /**
  1490. * Menu callback that returns two instances of the node form.
  1491. */
  1492. function form_test_two_instances() {
  1493. global $user;
  1494. $node1 = (object) array(
  1495. 'uid' => $user->uid,
  1496. 'name' => (isset($user->name) ? $user->name : ''),
  1497. 'type' => 'page',
  1498. 'language' => LANGUAGE_NONE,
  1499. );
  1500. $node2 = clone($node1);
  1501. $return['node_form_1'] = drupal_get_form('page_node_form', $node1);
  1502. $return['node_form_2'] = drupal_get_form('page_node_form', $node2);
  1503. return $return;
  1504. }
  1505. /**
  1506. * Menu callback for testing custom form includes.
  1507. */
  1508. function form_test_load_include_custom($form, &$form_state) {
  1509. $form['button'] = array(
  1510. '#type' => 'submit',
  1511. '#value' => t('Save'),
  1512. '#submit' => array('form_test_load_include_submit'),
  1513. );
  1514. // Specify the include file and enable form caching. That way the form is
  1515. // cached when it is submitted, but needs to find the specified submit handler
  1516. // in the include.
  1517. // Filename is a bit weird here: modules/simpletest/tests/form_test.file.inc
  1518. form_load_include($form_state, 'inc', 'form_test', 'form_test.file');
  1519. $form_state['cache'] = TRUE;
  1520. return $form;
  1521. }
  1522. function form_test_checkbox_type_juggling($form, $form_state, $default_value, $return_value) {
  1523. $form['checkbox'] = array(
  1524. '#type' => 'checkbox',
  1525. '#return_value' => $return_value,
  1526. '#default_value' => $default_value,
  1527. );
  1528. return $form;
  1529. }
  1530. function form_test_checkboxes_zero($form, &$form_state, $json = TRUE) {
  1531. $form['checkbox_off'] = array(
  1532. '#type' => 'checkboxes',
  1533. '#options' => array('foo', 'bar', 'baz'),
  1534. );
  1535. $form['checkbox_zero_default'] = array(
  1536. '#type' => 'checkboxes',
  1537. '#options' => array('foo', 'bar', 'baz'),
  1538. '#default_value' => array(0),
  1539. );
  1540. $form['checkbox_string_zero_default'] = array(
  1541. '#type' => 'checkboxes',
  1542. '#options' => array('foo', 'bar', 'baz'),
  1543. '#default_value' => array('0'),
  1544. );
  1545. $form['submit'] = array(
  1546. '#type' => 'submit',
  1547. '#value' => 'Save',
  1548. );
  1549. if ($json) {
  1550. $form['#submit'][] = '_form_test_checkbox_submit';
  1551. }
  1552. else {
  1553. $form['#submit'][] = '_form_test_checkboxes_zero_no_redirect';
  1554. }
  1555. return $form;
  1556. }
  1557. function _form_test_checkboxes_zero_no_redirect($form, &$form_state) {
  1558. $form_state['redirect'] = FALSE;
  1559. }
Login or register to post comments