form_example_tutorial.inc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. <?php
  2. /**
  3. * @file
  4. * This is the Form API Tutorial from the handbook.
  5. *
  6. * It goes through several form examples of increasing complexity to demonstrate
  7. * Drupal 7 Form API.
  8. *
  9. * Links are provided inline for the related handbook pages.
  10. *
  11. * @see http://drupal.org/node/262422
  12. */
  13. /**
  14. * Main Form tutorial page.
  15. *
  16. * @see form_example_tutorial_1()
  17. * @see form_example_tutorial_2()
  18. * @see form_example_tutorial_3()
  19. * @see form_example_tutorial_4()
  20. * @see form_example_tutorial_5()
  21. * @see form_example_tutorial_6()
  22. * @see form_example_tutorial_7()
  23. * @see form_example_tutorial_8()
  24. * @see form_example_tutorial_9()
  25. * @see form_example_tutorial_10()
  26. *
  27. * @ingroup form_example
  28. */
  29. function form_example_tutorial() {
  30. return t('This is a set of form tutorials tied to the <a href="http://drupal.org/node/262422">Drupal handbook</a>.');
  31. }
  32. /**
  33. * Tutorial Example 1.
  34. *
  35. * This first form function is from the
  36. * @link http://drupal.org/node/717722 Form Tutorial handbook page @endlink
  37. *
  38. * It just creates a very basic form with a textfield.
  39. *
  40. * This function is called the "form constructor function". It builds the form.
  41. * It takes a two arguments, $form and $form_state, but if drupal_get_form()
  42. * sends additional arguments, they will be provided after $form_state.
  43. *
  44. * @ingroup form_example
  45. */
  46. function form_example_tutorial_1($form, &$form_state) {
  47. $form['description'] = array(
  48. '#type' => 'item',
  49. '#title' => t('A form with nothing but a textfield'),
  50. );
  51. // This is the first form element. It's a textfield with a label, "Name"
  52. $form['name'] = array(
  53. '#type' => 'textfield',
  54. '#title' => t('Name'),
  55. );
  56. return $form;
  57. }
  58. /**
  59. * This is Example 2, a basic form with a submit button.
  60. *
  61. * @see http://drupal.org/node/717726
  62. * @ingroup form_example
  63. */
  64. function form_example_tutorial_2($form, &$form_state) {
  65. $form['description'] = array(
  66. '#type' => 'item',
  67. '#title' => t('A simple form with a submit button'),
  68. );
  69. $form['name'] = array(
  70. '#type' => 'textfield',
  71. '#title' => t('Name'),
  72. );
  73. // Adds a simple submit button that refreshes the form and clears its
  74. // contents. This is the default behavior for forms.
  75. $form['submit'] = array(
  76. '#type' => 'submit',
  77. '#value' => 'Submit',
  78. );
  79. return $form;
  80. }
  81. /**
  82. * Example 3: A basic form with fieldsets.
  83. *
  84. * We establish a fieldset element and then place two text fields within
  85. * it, one for a first name and one for a last name. This helps us group
  86. * related content.
  87. *
  88. * Study the code below and you'll notice that we renamed the array of the first
  89. * and last name fields by placing them under the $form['name']
  90. * array. This tells Form API these fields belong to the $form['name'] fieldset.
  91. *
  92. * @ingroup form_example
  93. */
  94. function form_example_tutorial_3($form, &$form_state) {
  95. $form['description'] = array(
  96. '#type' => 'item',
  97. '#title' => t('A form with a fieldset'),
  98. );
  99. $form['name'] = array(
  100. '#type' => 'fieldset',
  101. '#title' => t('Name'),
  102. );
  103. $form['name']['first'] = array(
  104. '#type' => 'textfield',
  105. '#title' => t('First name'),
  106. );
  107. $form['name']['last'] = array(
  108. '#type' => 'textfield',
  109. '#title' => t('Last name'),
  110. );
  111. $form['submit'] = array(
  112. '#type' => 'submit',
  113. '#value' => 'Submit',
  114. );
  115. return $form;
  116. }
  117. /**
  118. * Example 4: Basic form with required fields.
  119. *
  120. * @ingroup form_example
  121. */
  122. function form_example_tutorial_4($form, &$form_state) {
  123. $form['description'] = array(
  124. '#type' => 'item',
  125. '#title' => t('A form with required fields'),
  126. );
  127. $form['name'] = array(
  128. '#type' => 'fieldset',
  129. '#title' => t('Name'),
  130. // Make the fieldset collapsible.
  131. '#collapsible' => TRUE,
  132. '#collapsed' => FALSE,
  133. );
  134. // Make these fields required.
  135. $form['name']['first'] = array(
  136. '#type' => 'textfield',
  137. '#title' => t('First name'),
  138. '#required' => TRUE,
  139. );
  140. $form['name']['last'] = array(
  141. '#type' => 'textfield',
  142. '#title' => t('Last name'),
  143. '#required' => TRUE,
  144. );
  145. $form['submit'] = array(
  146. '#type' => 'submit',
  147. '#value' => 'Submit',
  148. );
  149. return $form;
  150. }
  151. /**
  152. * Example 5: Basic form with additional element attributes.
  153. *
  154. * This demonstrates additional attributes of text form fields.
  155. *
  156. * See the
  157. * @link http://api.drupal.org/api/file/developer/topics/forms_api.html complete form reference @endlink
  158. *
  159. * @ingroup form_example
  160. */
  161. function form_example_tutorial_5($form, &$form_state) {
  162. $form['description'] = array(
  163. '#type' => 'item',
  164. '#title' => t('A form with additional attributes'),
  165. '#description' => t('This one adds #default_value and #description'),
  166. );
  167. $form['name'] = array(
  168. '#type' => 'fieldset',
  169. '#title' => t('Name'),
  170. '#collapsible' => TRUE,
  171. '#collapsed' => FALSE,
  172. );
  173. $form['name']['first'] = array(
  174. '#type' => 'textfield',
  175. '#title' => t('First name'),
  176. '#required' => TRUE,
  177. '#default_value' => "First name",
  178. '#description' => "Please enter your first name.",
  179. '#size' => 20,
  180. '#maxlength' => 20,
  181. );
  182. $form['name']['last'] = array(
  183. '#type' => 'textfield',
  184. '#title' => t('Last name'),
  185. '#required' => TRUE,
  186. );
  187. $form['submit'] = array(
  188. '#type' => 'submit',
  189. '#value' => 'Submit',
  190. );
  191. return $form;
  192. }
  193. /**
  194. * Example 6: A basic form with a validate handler.
  195. *
  196. * From http://drupal.org/node/717736
  197. * @see form_example_tutorial_6_validate()
  198. *
  199. * @ingroup form_example
  200. */
  201. function form_example_tutorial_6($form, &$form_state) {
  202. $form['description'] = array(
  203. '#type' => 'item',
  204. '#title' => t('A form with a validation handler'),
  205. );
  206. $form['name'] = array(
  207. '#type' => 'fieldset',
  208. '#title' => t('Name'),
  209. '#collapsible' => TRUE,
  210. '#collapsed' => FALSE,
  211. );
  212. $form['name']['first'] = array(
  213. '#type' => 'textfield',
  214. '#title' => t('First name'),
  215. '#required' => TRUE,
  216. '#default_value' => "First name",
  217. '#description' => "Please enter your first name.",
  218. '#size' => 20,
  219. '#maxlength' => 20,
  220. );
  221. $form['name']['last'] = array(
  222. '#type' => 'textfield',
  223. '#title' => t('Last name'),
  224. '#required' => TRUE,
  225. );
  226. // New form field added to permit entry of year of birth.
  227. // The data entered into this field will be validated with
  228. // the default validation function.
  229. $form['year_of_birth'] = array(
  230. '#type' => 'textfield',
  231. '#title' => "Year of birth",
  232. '#description' => 'Format is "YYYY"',
  233. );
  234. $form['submit'] = array(
  235. '#type' => 'submit',
  236. '#value' => 'Submit',
  237. );
  238. return $form;
  239. }
  240. /**
  241. * Validation handler for Tutorial 6.
  242. *
  243. * Now we add a handler/function to validate the data entered into the
  244. * "year of birth" field to make sure it's between the values of 1900
  245. * and 2000. If not, it displays an error. The value report is
  246. * $form_state['values'] (see http://drupal.org/node/144132#form-state).
  247. *
  248. * Notice the name of the function. It is simply the name of the form
  249. * followed by '_validate'. This is always the name of the default validation
  250. * function. An alternate list of validation functions could have been provided
  251. * in $form['#validate'].
  252. *
  253. * @see form_example_tutorial_6()
  254. *
  255. * @ingroup form_example
  256. */
  257. function form_example_tutorial_6_validate($form, &$form_state) {
  258. $year_of_birth = $form_state['values']['year_of_birth'];
  259. if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) {
  260. form_set_error('year_of_birth', t('Enter a year between 1900 and 2000.'));
  261. }
  262. }
  263. /**
  264. * Example 7: With a submit handler.
  265. *
  266. * From the handbook page:
  267. * http://drupal.org/node/717740
  268. *
  269. * @see form_example_tutorial_7_validate()
  270. * @see form_example_tutorial_7_submit()
  271. *
  272. * @ingroup form_example
  273. */
  274. function form_example_tutorial_7($form, &$form_state) {
  275. $form['description'] = array(
  276. '#type' => 'item',
  277. '#title' => t('A form with a submit handler'),
  278. );
  279. $form['name'] = array(
  280. '#type' => 'fieldset',
  281. '#title' => t('Name'),
  282. '#collapsible' => TRUE,
  283. '#collapsed' => FALSE,
  284. );
  285. $form['name']['first'] = array(
  286. '#type' => 'textfield',
  287. '#title' => t('First name'),
  288. '#required' => TRUE,
  289. '#default_value' => "First name",
  290. '#description' => "Please enter your first name.",
  291. '#size' => 20,
  292. '#maxlength' => 20,
  293. );
  294. $form['name']['last'] = array(
  295. '#type' => 'textfield',
  296. '#title' => t('Last name'),
  297. '#required' => TRUE,
  298. );
  299. $form['year_of_birth'] = array(
  300. '#type' => 'textfield',
  301. '#title' => "Year of birth",
  302. '#description' => 'Format is "YYYY"',
  303. );
  304. $form['submit'] = array(
  305. '#type' => 'submit',
  306. '#value' => 'Submit',
  307. );
  308. return $form;
  309. }
  310. /**
  311. * Validation function for form_example_tutorial_7().
  312. *
  313. * @ingroup form_example
  314. */
  315. function form_example_tutorial_7_validate($form, &$form_state) {
  316. $year_of_birth = $form_state['values']['year_of_birth'];
  317. if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) {
  318. form_set_error('year_of_birth', t('Enter a year between 1900 and 2000.'));
  319. }
  320. }
  321. /**
  322. * Submit function for form_example_tutorial_7().
  323. *
  324. * Adds a submit handler/function to our form to send a successful
  325. * completion message to the screen.
  326. *
  327. * @ingroup form_example
  328. */
  329. function form_example_tutorial_7_submit($form, &$form_state) {
  330. drupal_set_message(t('The form has been submitted. name="@first @last", year of birth=@year_of_birth',
  331. array(
  332. '@first' => $form_state['values']['first'],
  333. '@last' => $form_state['values']['last'],
  334. '@year_of_birth' => $form_state['values']['year_of_birth'],
  335. )
  336. ));
  337. }
  338. /**
  339. * Example 8: A simple multistep form with a Next and a Back button.
  340. *
  341. * Handbook page: http://drupal.org/node/717750.
  342. *
  343. * For more extensive multistep forms, see
  344. * @link form_example_wizard.inc form_example_wizard.inc @endlink
  345. *
  346. *
  347. * Adds logic to our form builder to give it two pages.
  348. * The @link ajax_example_wizard AJAX Example's Wizard Example @endlink
  349. * gives an AJAX version of this same idea.
  350. *
  351. * @see form_example_tutorial_8_page_two()
  352. * @see form_example_tutorial_8_page_two_back()
  353. * @see form_example_tutorial_8_page_two_submit()
  354. * @see form_example_tutorial_8_next_submit()
  355. * @see form_example_tutorial.inc
  356. *
  357. * @ingroup form_example
  358. */
  359. function form_example_tutorial_8($form, &$form_state) {
  360. // Display page 2 if $form_state['page_num'] == 2
  361. if (!empty($form_state['page_num']) && $form_state['page_num'] == 2) {
  362. return form_example_tutorial_8_page_two($form, $form_state);
  363. }
  364. // Otherwise we build page 1.
  365. $form_state['page_num'] = 1;
  366. $form['description'] = array(
  367. '#type' => 'item',
  368. '#title' => t('A basic multistep form (page 1)'),
  369. );
  370. $form['first'] = array(
  371. '#type' => 'textfield',
  372. '#title' => t('First name'),
  373. '#description' => "Please enter your first name.",
  374. '#size' => 20,
  375. '#maxlength' => 20,
  376. '#required' => TRUE,
  377. '#default_value' => !empty($form_state['values']['first']) ? $form_state['values']['first'] : '',
  378. );
  379. $form['last'] = array(
  380. '#type' => 'textfield',
  381. '#title' => t('Last name'),
  382. '#default_value' => !empty($form_state['values']['last']) ? $form_state['values']['last'] : '',
  383. );
  384. $form['year_of_birth'] = array(
  385. '#type' => 'textfield',
  386. '#title' => "Year of birth",
  387. '#description' => 'Format is "YYYY"',
  388. '#default_value' => !empty($form_state['values']['year_of_birth']) ? $form_state['values']['year_of_birth'] : '',
  389. );
  390. $form['next'] = array(
  391. '#type' => 'submit',
  392. '#value' => 'Next >>',
  393. '#submit' => array('form_example_tutorial_8_next_submit'),
  394. '#validate' => array('form_example_tutorial_8_next_validate'),
  395. );
  396. return $form;
  397. }
  398. /**
  399. * Returns the form for the second page of form_example_tutorial_8().
  400. *
  401. * @ingroup form_example
  402. */
  403. function form_example_tutorial_8_page_two($form, &$form_state) {
  404. $form['description'] = array(
  405. '#type' => 'item',
  406. '#title' => t('A basic multistep form (page 2)'),
  407. );
  408. $form['color'] = array(
  409. '#type' => 'textfield',
  410. '#title' => t('Favorite color'),
  411. '#required' => TRUE,
  412. '#default_value' => !empty($form_state['values']['color']) ? $form_state['values']['color'] : '',
  413. );
  414. $form['submit'] = array(
  415. '#type' => 'submit',
  416. '#value' => t('Submit'),
  417. '#submit' => array('form_example_tutorial_8_page_two_submit'),
  418. );
  419. $form['back'] = array(
  420. '#type' => 'submit',
  421. '#value' => t('<< Back'),
  422. '#submit' => array('form_example_tutorial_8_page_two_back'),
  423. // We won't bother validating the required 'color' field, since they
  424. // have to come back to this page to submit anyway.
  425. '#limit_validation_errors' => array(),
  426. );
  427. return $form;
  428. }
  429. /**
  430. * Validate handler for the next button on first page.
  431. *
  432. * @ingroup form_example
  433. */
  434. function form_example_tutorial_8_next_validate($form, &$form_state) {
  435. $year_of_birth = $form_state['values']['year_of_birth'];
  436. if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) {
  437. form_set_error('year_of_birth', t('Enter a year between 1900 and 2000.'));
  438. }
  439. }
  440. /**
  441. * Submit handler for form_example_tutorial_8() next button.
  442. *
  443. * Capture the values from page one and store them away so they can be used
  444. * at final submit time.
  445. *
  446. * @ingroup form_example
  447. */
  448. function form_example_tutorial_8_next_submit($form, &$form_state) {
  449. // Values are saved for each page.
  450. // to carry forward to subsequent pages in the form.
  451. // and we tell FAPI to rebuild the form.
  452. $form_state['page_values'][1] = $form_state['values'];
  453. if (!empty($form_state['page_values'][2])) {
  454. $form_state['values'] = $form_state['page_values'][2];
  455. }
  456. // When form rebuilds, it will look at this to figure which page to build.
  457. $form_state['page_num'] = 2;
  458. $form_state['rebuild'] = TRUE;
  459. }
  460. /**
  461. * Back button handler submit handler.
  462. *
  463. * Since #limit_validation_errors = array() is set, values from page 2
  464. * will be discarded. We load the page 1 values instead.
  465. *
  466. * @ingroup form_example
  467. */
  468. function form_example_tutorial_8_page_two_back($form, &$form_state) {
  469. $form_state['values'] = $form_state['page_values'][1];
  470. $form_state['page_num'] = 1;
  471. $form_state['rebuild'] = TRUE;
  472. }
  473. /**
  474. * The page 2 submit handler.
  475. *
  476. * This is the final submit handler. Gather all the data together and output
  477. * it in a drupal_set_message().
  478. *
  479. * @ingroup form_example
  480. */
  481. function form_example_tutorial_8_page_two_submit($form, &$form_state) {
  482. // Normally, some code would go here to alter the database with the data
  483. // collected from the form. Instead sets a message with drupal_set_message()
  484. // to validate that the code worked.
  485. $page_one_values = $form_state['page_values'][1];
  486. drupal_set_message(t('The form has been submitted. name="@first @last", year of birth=@year_of_birth',
  487. array(
  488. '@first' => $page_one_values['first'],
  489. '@last' => $page_one_values['last'],
  490. '@year_of_birth' => $page_one_values['year_of_birth'],
  491. )
  492. ));
  493. if (!empty($page_one_values['first2'])) {
  494. drupal_set_message(t('Second name: name="@first @last", year of birth=@year_of_birth',
  495. array(
  496. '@first' => $page_one_values['first2'],
  497. '@last' => $page_one_values['last2'],
  498. '@year_of_birth' => $page_one_values['year_of_birth2'],
  499. )
  500. ));
  501. }
  502. drupal_set_message(t('And the favorite color is @color', array('@color' => $form_state['values']['color'])));
  503. // If we wanted to redirect on submission, set $form_state['redirect']. For
  504. // simple redirects, the value can be a string of the path to redirect to. For
  505. // example, to redirect to /node, one would specify the following:
  506. //
  507. // $form_state['redirect'] = 'node';
  508. //
  509. // For more complex redirects, this value can be set to an array of options to
  510. // pass to drupal_goto(). For example, to redirect to /foo?bar=1#baz, one
  511. // would specify the following:
  512. //
  513. // @code
  514. // $form_state['redirect'] = array(
  515. // 'foo',
  516. // array(
  517. // 'query' => array('bar' => 1),
  518. // 'fragment' => 'baz',
  519. // ),
  520. // );
  521. // @endcode
  522. //
  523. // The first element in the array is the path to redirect to, and the second
  524. // element in the array is the array of options. For more information on the
  525. // available options, see http://api.drupal.org/url.
  526. }
  527. /**
  528. * Example 9: A form with a dynamically added new fields.
  529. *
  530. * This example adds default values so that when the form is rebuilt,
  531. * the form will by default have the previously-entered values.
  532. *
  533. * From handbook page http://drupal.org/node/717746.
  534. *
  535. * @see form_example_tutorial_9_add_name()
  536. * @see form_example_tutorial_9_remove_name()
  537. * @see form_example_tutorial_9_submit()
  538. * @see form_example_tutorial_9_validate()
  539. *
  540. * @ingroup form_example
  541. */
  542. function form_example_tutorial_9($form, &$form_state) {
  543. // We will have many fields with the same name, so we need to be able to
  544. // access the form hierarchically.
  545. $form['#tree'] = TRUE;
  546. $form['description'] = array(
  547. '#type' => 'item',
  548. '#title' => t('A form with dynamically added new fields'),
  549. );
  550. if (empty($form_state['num_names'])) {
  551. $form_state['num_names'] = 1;
  552. }
  553. // Build the number of name fieldsets indicated by $form_state['num_names']
  554. for ($i = 1; $i <= $form_state['num_names']; $i++) {
  555. $form['name'][$i] = array(
  556. '#type' => 'fieldset',
  557. '#title' => t('Name #@num', array('@num' => $i)),
  558. '#collapsible' => TRUE,
  559. '#collapsed' => FALSE,
  560. );
  561. $form['name'][$i]['first'] = array(
  562. '#type' => 'textfield',
  563. '#title' => t('First name'),
  564. '#description' => t("Enter first name."),
  565. '#size' => 20,
  566. '#maxlength' => 20,
  567. '#required' => TRUE,
  568. );
  569. $form['name'][$i]['last'] = array(
  570. '#type' => 'textfield',
  571. '#title' => t('Enter Last name'),
  572. '#required' => TRUE,
  573. );
  574. $form['name'][$i]['year_of_birth'] = array(
  575. '#type' => 'textfield',
  576. '#title' => t("Year of birth"),
  577. '#description' => t('Format is "YYYY"'),
  578. );
  579. }
  580. $form['submit'] = array(
  581. '#type' => 'submit',
  582. '#value' => 'Submit',
  583. );
  584. // Adds "Add another name" button.
  585. $form['add_name'] = array(
  586. '#type' => 'submit',
  587. '#value' => t('Add another name'),
  588. '#submit' => array('form_example_tutorial_9_add_name'),
  589. );
  590. // If we have more than one name, this button allows removal of the
  591. // last name.
  592. if ($form_state['num_names'] > 1) {
  593. $form['remove_name'] = array(
  594. '#type' => 'submit',
  595. '#value' => t('Remove latest name'),
  596. '#submit' => array('form_example_tutorial_9_remove_name'),
  597. // Since we are removing a name, don't validate until later.
  598. '#limit_validation_errors' => array(),
  599. );
  600. }
  601. return $form;
  602. }
  603. /**
  604. * Submit handler for "Add another name" button on form_example_tutorial_9().
  605. *
  606. * $form_state['num_names'] tells the form builder function how many name
  607. * fieldsets to build, so here we increment it.
  608. *
  609. * All elements of $form_state are persisted, so there's no need to use a
  610. * particular key, like the old $form_state['storage']. We can just use
  611. * $form_state['num_names'].
  612. *
  613. * @ingroup form_example
  614. */
  615. function form_example_tutorial_9_add_name($form, &$form_state) {
  616. // Everything in $form_state is persistent, so we'll just use
  617. // $form_state['add_name']
  618. $form_state['num_names']++;
  619. // Setting $form_state['rebuild'] = TRUE causes the form to be rebuilt again.
  620. $form_state['rebuild'] = TRUE;
  621. }
  622. /**
  623. * Submit handler for "Remove name" button on form_example_tutorial_9().
  624. *
  625. * @ingroup form_example
  626. */
  627. function form_example_tutorial_9_remove_name($form, &$form_state) {
  628. if ($form_state['num_names'] > 1) {
  629. $form_state['num_names']--;
  630. }
  631. // Setting $form_state['rebuild'] = TRUE causes the form to be rebuilt again.
  632. $form_state['rebuild'] = TRUE;
  633. }
  634. /**
  635. * Validate function for form_example_tutorial_9().
  636. *
  637. * Adds logic to validate the form to check the validity of the new fields,
  638. * if they exist.
  639. *
  640. * @ingroup form_example
  641. */
  642. function form_example_tutorial_9_validate($form, &$form_state) {
  643. for ($i = 1; $i <= $form_state['num_names']; $i++) {
  644. $year_of_birth = $form_state['values']['name'][$i]['year_of_birth'];
  645. if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) {
  646. form_set_error("name][$i][year_of_birth", t('Enter a year between 1900 and 2000.'));
  647. }
  648. }
  649. }
  650. /**
  651. * Submit function for form_example_tutorial_9().
  652. *
  653. * @ingroup form_example
  654. */
  655. function form_example_tutorial_9_submit($form, &$form_state) {
  656. $output = t("Form 9 has been submitted.");
  657. for ($i = 1; $i <= $form_state['num_names']; $i++) {
  658. $output .= t("@num: @first @last (@date)...",
  659. array(
  660. '@num' => $i,
  661. '@first' => $form_state['values']['name'][$i]['first'],
  662. '@last' => $form_state['values']['name'][$i]['last'],
  663. '@date' => $form_state['values']['name'][$i]['year_of_birth'],
  664. )
  665. ) . ' ';
  666. }
  667. drupal_set_message($output);
  668. }
  669. /**
  670. * Example 10: A form with a file upload field.
  671. *
  672. * This example allows the user to upload a file to Drupal which is stored
  673. * physically and with a reference in the database.
  674. *
  675. * @see form_example_tutorial_10_submit()
  676. * @see form_example_tutorial_10_validate()
  677. *
  678. * @ingroup form_example
  679. */
  680. function form_example_tutorial_10($form_state) {
  681. // If you are familiar with how browsers handle files, you know that
  682. // enctype="multipart/form-data" is required. Drupal takes care of that, so
  683. // you don't need to include it yourself.
  684. $form['file'] = array(
  685. '#type' => 'file',
  686. '#title' => t('Image'),
  687. '#description' => t('Upload a file, allowed extensions: jpg, jpeg, png, gif'),
  688. );
  689. $form['submit'] = array(
  690. '#type' => 'submit',
  691. '#value' => t('Submit'),
  692. );
  693. return $form;
  694. }
  695. /**
  696. * Validate handler for form_example_tutorial_10().
  697. *
  698. * @ingroup form_example
  699. */
  700. function form_example_tutorial_10_validate($form, &$form_state) {
  701. $file = file_save_upload('file', array(
  702. // Validates file is really an image.
  703. 'file_validate_is_image' => array(),
  704. // Validate extensions.
  705. 'file_validate_extensions' => array('png gif jpg jpeg'),
  706. ));
  707. // If the file passed validation:
  708. if ($file) {
  709. // Move the file into the Drupal file system.
  710. if ($file = file_move($file, 'public://')) {
  711. // Save the file for use in the submit handler.
  712. $form_state['storage']['file'] = $file;
  713. }
  714. else {
  715. form_set_error('file', t("Failed to write the uploaded file to the site's file folder."));
  716. }
  717. }
  718. else {
  719. form_set_error('file', t('No file was uploaded.'));
  720. }
  721. }
  722. /**
  723. * Submit handler for form_example_tutorial_10().
  724. *
  725. * @ingroup form_example
  726. */
  727. function form_example_tutorial_10_submit($form, &$form_state) {
  728. $file = $form_state['storage']['file'];
  729. // We are done with the file, remove it from storage.
  730. unset($form_state['storage']['file']);
  731. // Make the storage of the file permanent.
  732. $file->status = FILE_STATUS_PERMANENT;
  733. // Save file status.
  734. file_save($file);
  735. // Set a response to the user.
  736. drupal_set_message(t('The form has been submitted and the image has been saved, filename: @filename.', array('@filename' => $file->filename)));
  737. }
  738. /**
  739. * Example 11: adding a confirmation form.
  740. *
  741. * This example generates a simple form that, when submitted, directs
  742. * the user to a confirmation form generated using the confirm_form function.
  743. * It asks the user to verify that the name they input was correct
  744. *
  745. * @see form_example_tutorial_11_submit()
  746. *
  747. * @ingroup form_example
  748. */
  749. function form_example_tutorial_11($form, &$form_state) {
  750. // This form is identical to the one in example 2 except for one thing: We are
  751. // adding an #action tag to direct the form submission to a confirmation page.
  752. $form['description'] = array(
  753. '#type' => 'item',
  754. '#title' => t('A set of two forms that demonstrate the confirm_form function. This form has an explicit action to direct the form to a confirmation page'),
  755. );
  756. $form['name'] = array(
  757. '#type' => 'textfield',
  758. '#title' => t('Name'),
  759. '#required' => TRUE,
  760. );
  761. $form['submit'] = array(
  762. '#type' => 'submit',
  763. '#value' => 'Submit',
  764. );
  765. return $form;
  766. }
  767. /**
  768. * Submit function for form_example_tutorial_11().
  769. *
  770. * Adds a submit handler/function to our form to redirect
  771. * the user to a confirmation page.
  772. *
  773. * @ingroup form_example
  774. */
  775. function form_example_tutorial_11_submit($form, &$form_state) {
  776. // Simple submit function that changes the redirect of the form based on the
  777. // value of the name field.
  778. $name = $form_state['values']['name'];
  779. $form_state['redirect'] = 'examples/form_example/tutorial/11/confirm/' . urlencode($name);
  780. }
  781. /**
  782. * Example 11: A form generated with confirm_form().
  783. *
  784. * This function generates the confirmation form using the confirm_form()
  785. * function. If confirmed, it sets a drupal message to demonstrate it's success.
  786. *
  787. * @param string $name
  788. * The urlencoded name entered by the user.
  789. *
  790. * @see form_example_tutorial_11_confirm_name_submit()
  791. *
  792. * @ingroup form_example
  793. */
  794. function form_example_tutorial_11_confirm_name($form, $form_state, $name) {
  795. // confirm_form() returns a complete form array for confirming an action.
  796. // It has 7 arguments: $form, $question, $path, $description, $yes, $no, and
  797. // $name.
  798. // - $form: Additional elements to add to the form that will be available in
  799. // the submit handler.
  800. // - $question: What is the user confirming? This will be the title of the
  801. // page.
  802. // - $path: Where should the page go if the user hits cancel?
  803. // - $description = NULL: Additional text to display.
  804. // - $yes = NULL: Anchor text for the confirmation button. Defaults to
  805. // t('Confirm').
  806. // - $no = NULL: Anchor text for the cancel link. Defaults to t('Cancel').
  807. // - $name = 'confirm': The internal name used to refer to the confirmation
  808. // item.
  809. // First we make a textfield for our user's name. confirm_form() allows us to
  810. // Add form elements to the confirmation form, so we'll take advangage of
  811. // that.
  812. $user_name_text_field = array(
  813. 'name' => array(
  814. '#type' => 'textfield',
  815. // We don't want the user to be able to edit their name here.
  816. '#disabled' => TRUE,
  817. '#title' => t('Your name:'),
  818. '#value' => urldecode($name),
  819. ),
  820. );
  821. // The question to ask the user.
  822. $confirmation_question = t('Is this really your name?');
  823. // If the user clicks 'no,' they're sent to this path.
  824. $cancel_path = 'examples/form_example/tutorial/11';
  825. // Some helpful descriptive text.
  826. $description = t('Please verify whether or not you have input your name correctly. If you verify you will be sent back to the form and a message will be set. Otherwise you will be sent to the same page but with no message.');
  827. // These are the text for our yes and no buttons.
  828. $yes_button = t('This is my name');
  829. $no_button = t('Nope, not my name');
  830. // The name Form API will use to refer to our confirmation form.
  831. $confirm_name = 'confirm_example';
  832. // Finally, call confirm_form() with our information, and then return the form
  833. // array it gives us.
  834. return confirm_form(
  835. $user_name_text_field,
  836. $confirmation_question,
  837. $cancel_path,
  838. $description,
  839. $yes_button,
  840. $no_button,
  841. $confirm_name
  842. );
  843. }
  844. /**
  845. * Submit function for form_example_tutorial_11_confirm_form().
  846. *
  847. * Adds a submit handler/function to the confirmation form
  848. * if this point is reached the submission has been confirmed
  849. * so we will set a message to demonstrate the success.
  850. *
  851. * @ingroup form_example
  852. */
  853. function form_example_tutorial_11_confirm_name_submit($form, &$form_state) {
  854. drupal_set_message(t("Confirmation form submission recieved. According to your submission your name is '@name'", array("@name" => $form_state['values']['name'])));
  855. $form_state['redirect'] = 'examples/form_example/tutorial/11';
  856. }