FormHelper.php 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. * (c) 2004 David Heinemeier Hansson
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * FormHelper.
  12. *
  13. * @package symfony
  14. * @subpackage helper
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. * @author David Heinemeier Hansson
  17. * @version SVN: $Id: FormHelper.php 14152 2008-12-17 22:39:33Z FabianLange $
  18. */
  19. /**
  20. * Returns a formatted set of <option> tags based on optional <i>$options</i> array variable.
  21. *
  22. * The options_for_select helper is usually called in conjunction with the select_tag helper, as it is relatively
  23. * useless on its own. By passing an array of <i>$options</i>, the helper will automatically generate <option> tags
  24. * using the array key as the value and the array value as the display title. Additionally the options_for_select tag is
  25. * smart enough to detect nested arrays as <optgroup> tags. If the helper detects that the array value is an array itself,
  26. * it creates an <optgroup> tag with the name of the group being the key and the contents of the <optgroup> being the array.
  27. *
  28. * <b>Options:</b>
  29. * - include_blank - Includes a blank <option> tag at the beginning of the string with an empty value
  30. * - include_custom - Includes an <option> tag with a custom display title at the beginning of the string with an empty value
  31. *
  32. * <b>Examples:</b>
  33. * <code>
  34. * echo select_tag('person', options_for_select(array(1 => 'Larry', 2 => 'Moe', 3 => 'Curly')));
  35. * </code>
  36. *
  37. * <code>
  38. * $card_list = array('VISA' => 'Visa', 'MAST' => 'MasterCard', 'AMEX' => 'American Express', 'DISC' => 'Discover');
  39. * echo select_tag('cc_type', options_for_select($card_list, 'AMEX', array('include_custom' => '-- Select Credit Card Type --')));
  40. * </code>
  41. *
  42. * <code>
  43. * $optgroup_array = array(1 => 'Joe', 2 => 'Sue', 'Group A' => array(3 => 'Mary', 4 => 'Tom'), 'Group B' => array(5 => 'Bill', 6 =>'Andy'));
  44. * echo select_tag('employee', options_for_select($optgroup_array, null, array('include_blank' => true)), array('class' => 'mystyle'));
  45. * </code>
  46. *
  47. * @param array $options dataset to create <option> tags and <optgroup> tags from
  48. * @param string $selected selected option value
  49. * @param array $html_options additional HTML compliant <option> tag parameters
  50. *
  51. * @return string populated with <option> tags derived from the <i>$options</i> array variable
  52. * @see select_tag
  53. */
  54. function options_for_select($options = array(), $selected = '', $html_options = array())
  55. {
  56. $html_options = _parse_attributes($html_options);
  57. if (is_array($selected))
  58. {
  59. $selected = array_map('strval', array_values($selected));
  60. }
  61. $html = '';
  62. if ($value = _get_option($html_options, 'include_custom'))
  63. {
  64. $html .= content_tag('option', $value, array('value' => ''))."\n";
  65. }
  66. else if (_get_option($html_options, 'include_blank'))
  67. {
  68. $html .= content_tag('option', '', array('value' => ''))."\n";
  69. }
  70. foreach ($options as $key => $value)
  71. {
  72. if (is_array($value) || $value instanceof sfOutputEscaperArrayDecorator)
  73. {
  74. $html .= content_tag('optgroup', options_for_select($value, $selected, $html_options), array('label' => $key))."\n";
  75. }
  76. else
  77. {
  78. $option_options = array('value' => $key);
  79. if (
  80. (is_array($selected) && in_array(strval($key), $selected, true))
  81. ||
  82. (strval($key) == strval($selected))
  83. )
  84. {
  85. $option_options['selected'] = 'selected';
  86. }
  87. $html .= content_tag('option', $value, $option_options)."\n";
  88. }
  89. }
  90. return $html;
  91. }
  92. /**
  93. * Returns an HTML <form> tag that points to a valid action, route or URL as defined by <i>$url_for_options</i>.
  94. *
  95. * By default, the form tag is generated in POST format, but can easily be configured along with any additional
  96. * HTML parameters via the optional <i>$options</i> parameter. If you are using file uploads, be sure to set the
  97. * <i>multipart</i> option to true.
  98. *
  99. * <b>Options:</b>
  100. * - multipart - When set to true, enctype is set to "multipart/form-data".
  101. *
  102. * <b>Examples:</b>
  103. * <code><?php echo form_tag('@myroute'); ?></code>
  104. * <code><?php echo form_tag('/module/action', array('name' => 'myformname', 'multipart' => true)); ?></code>
  105. *
  106. * @param string $url_for_options valid action, route or URL
  107. * @param array $options optional HTML parameters for the <form> tag
  108. *
  109. * @return string opening HTML <form> tag with options
  110. */
  111. function form_tag($url_for_options = '', $options = array())
  112. {
  113. $options = _parse_attributes($options);
  114. $html_options = $options;
  115. if (!isset($html_options['method']))
  116. {
  117. $html_options['method'] = 'post';
  118. }
  119. if (_get_option($html_options, 'multipart'))
  120. {
  121. $html_options['enctype'] = 'multipart/form-data';
  122. }
  123. $html_options['action'] = url_for($url_for_options);
  124. return tag('form', $html_options, true);
  125. }
  126. /**
  127. * Returns a <select> tag, optionally comprised of <option> tags.
  128. *
  129. * The select tag does not generate <option> tags by default.
  130. * To do so, you must populate the <i>$option_tags</i> parameter with a string of valid HTML compliant <option> tags.
  131. * Fortunately, Symfony provides a handy helper function to convert an array of data into option tags (see options_for_select).
  132. * If you need to create a "multiple" select tag (ability to select multiple options), set the <i>multiple</i> option to true.
  133. * Doing so will automatically convert the name field to an array type variable (i.e. name="name" becomes name="name[]").
  134. *
  135. * <b>Options:</b>
  136. * - multiple - If set to true, the select tag will allow multiple options to be selected at once.
  137. *
  138. * <b>Examples:</b>
  139. * <code>
  140. * $person_list = array(1 => 'Larry', 2 => 'Moe', 3 => 'Curly');
  141. * echo select_tag('person', options_for_select($person_list, $sf_params->get('person')), array('class' => 'full'));
  142. * </code>
  143. *
  144. * <code>
  145. * echo select_tag('department', options_for_select($department_list), array('multiple' => true));
  146. * </code>
  147. *
  148. * <code>
  149. * echo select_tag('url', options_for_select($url_list), array('onChange' => 'Javascript:this.form.submit();'));
  150. * </code>
  151. *
  152. * @param string $name field name
  153. * @param mixed $option_tags contains a string of valid <option></option> tags, or an array of options that will be passed to options_for_select
  154. * @param array $options additional HTML compliant <select> tag parameters
  155. *
  156. * @return string <select> tag optionally comprised of <option> tags.
  157. * @see options_for_select, content_tag
  158. */
  159. function select_tag($name, $option_tags = null, $options = array())
  160. {
  161. $options = _convert_options($options);
  162. $id = $name;
  163. if (isset($options['multiple']) && $options['multiple'] && substr($name, -2) !== '[]')
  164. {
  165. $name .= '[]';
  166. }
  167. if (is_array($option_tags))
  168. {
  169. $option_tags = options_for_select($option_tags);
  170. }
  171. return content_tag('select', $option_tags, array_merge(array('name' => $name, 'id' => get_id_from_name($id)), $options));
  172. }
  173. /**
  174. * Returns a <select> tag populated with all the countries in the world.
  175. *
  176. * The select_country_tag builds off the traditional select_tag function, and is conveniently populated with
  177. * all the countries in the world (sorted alphabetically). Each option in the list has a two-character country
  178. * code for its value and the country's name as its display title. The country data is retrieved via the sfCultureInfo
  179. * class, which stores a wide variety of i18n and i10n settings for various countries and cultures throughout the world.
  180. * Here's an example of an <option> tag generated by the select_country_tag:
  181. *
  182. * <samp>
  183. * <option value="US">United States</option>
  184. * </samp>
  185. *
  186. * <b>Examples:</b>
  187. * <code>
  188. * echo select_country_tag('country', 'FR');
  189. * </code>
  190. * <code>
  191. * echo select_country_tag('country', 'de', array('countries' => array('US','FR')));
  192. * </code>
  193. *
  194. * @param string $name field name
  195. * @param string $selected selected field value (two-character country code)
  196. * @param array $options additional HTML compliant <select> tag parameters
  197. *
  198. * @return string <select> tag populated with all the countries in the world.
  199. * @see select_tag, options_for_select, sfCultureInfo
  200. */
  201. function select_country_tag($name, $selected = null, $options = array())
  202. {
  203. $c = sfCultureInfo::getInstance(sfContext::getInstance()->getUser()->getCulture());
  204. $countries = $c->getCountries();
  205. if ($country_option = _get_option($options, 'countries'))
  206. {
  207. foreach ($countries as $key => $value)
  208. {
  209. if (!in_array($key, $country_option))
  210. {
  211. unset($countries[$key]);
  212. }
  213. }
  214. }
  215. asort($countries);
  216. $option_tags = options_for_select($countries, $selected, $options);
  217. unset($options['include_blank'], $options['include_custom']);
  218. return select_tag($name, $option_tags, $options);
  219. }
  220. /**
  221. * Returns a <select> tag populated with all the languages in the world (or almost).
  222. *
  223. * The select_language_tag builds off the traditional select_tag function, and is conveniently populated with
  224. * all the languages in the world (sorted alphabetically). Each option in the list has a two or three character
  225. * language/culture code for its value and the language's name as its display title. The country data is
  226. * retrieved via the sfCultureInfo class, which stores a wide variety of i18n and i10n settings for various
  227. * countries and cultures throughout the world. Here's an example of an <option> tag generated by the select_language_tag:
  228. *
  229. * <samp>
  230. * <option value="en">English</option>
  231. * </samp>
  232. *
  233. * <b>Examples:</b>
  234. * <code>
  235. * echo select_language_tag('language', 'de');
  236. * </code>
  237. * <code>
  238. * echo select_language_tag('language', 'de', array('languages' => array('en','fr','fi')));
  239. * </code>
  240. *
  241. * @param string $name field name
  242. * @param string $selected selected field value (two or threecharacter language/culture code)
  243. * @param array $options additional HTML compliant <select> tag parameters
  244. *
  245. * @return string <select> tag populated with all the languages in the world.
  246. * @see select_tag, options_for_select, sfCultureInfo
  247. */
  248. function select_language_tag($name, $selected = null, $options = array())
  249. {
  250. $c = sfCultureInfo::getInstance(sfContext::getInstance()->getUser()->getCulture());
  251. $languages = $c->getLanguages();
  252. if ($language_option = _get_option($options, 'languages'))
  253. {
  254. foreach ($languages as $key => $value)
  255. {
  256. if (!in_array($key, $language_option))
  257. {
  258. unset($languages[$key]);
  259. }
  260. }
  261. }
  262. asort($languages);
  263. $option_tags = options_for_select($languages, $selected, $options);
  264. unset($options['include_blank'], $options['include_custom']);
  265. return select_tag($name, $option_tags, $options);
  266. }
  267. /**
  268. * Returns a <select> tag populated with all the currencies in the world (or almost).
  269. *
  270. * The select_currency_tag builds off the traditional select_tag function, and is conveniently populated with
  271. * all the currencies in the world (sorted alphabetically). Each option in the list has a three character
  272. * currency code for its value and the currency's name as its display title. The currency data is
  273. * retrieved via the sfCultureInfo class, which stores a wide variety of i18n and i10n settings for various
  274. * countries and cultures throughout the world. Here's an example of an <option> tag generated by the select_currency_tag:
  275. *
  276. * <samp>
  277. * <option value="EUR">Euro</option>
  278. * </samp>
  279. *
  280. * <b>Examples:</b>
  281. * <code>
  282. * echo select_currency_tag('currency', 'EUR');
  283. * </code>
  284. * <code>
  285. * echo select_currency_tag('currency', 'EUR', array('currencies' => array('EUR', 'USD'), 'display' => 'symbol'));
  286. * </code>
  287. *
  288. * @param string $name field name
  289. * @param string $selected selected field value (threecharacter currency code)
  290. * @param array $options additional HTML compliant <select> tag parameters
  291. *
  292. * @return string <select> tag populated with all the currencies in the world.
  293. * @see select_tag, options_for_select, sfCultureInfo
  294. */
  295. function select_currency_tag($name, $selected = null, $options = array())
  296. {
  297. $c = sfCultureInfo::getInstance(sfContext::getInstance()->getUser()->getCulture());
  298. $currencies = $c->getCurrencies();
  299. $currency_option = _get_option($options, 'currencies');
  300. $display_option = _get_option($options, 'display');
  301. foreach ($currencies as $key => $value)
  302. {
  303. if ($currency_option && !in_array($key, $currency_option))
  304. {
  305. unset($currencies[$key]);
  306. }
  307. else
  308. {
  309. switch ($display_option)
  310. {
  311. case 'symbol' : $currencies[$key] = $value[0]; break;
  312. case 'code' : $currencies[$key] = $key; break;
  313. default : $currencies[$key] = ucfirst($value[1]); break;
  314. }
  315. }
  316. }
  317. asort($currencies);
  318. $option_tags = options_for_select($currencies, $selected, $options);
  319. unset($options['include_blank'], $options['include_custom']);
  320. return select_tag($name, $option_tags, $options);
  321. }
  322. /**
  323. * Returns an XHTML compliant <input> tag with type="text".
  324. *
  325. * The input_tag helper generates your basic XHTML <input> tag and can utilize any standard <input> tag parameters
  326. * passed in the optional <i>$options</i> parameter.
  327. *
  328. * <b>Examples:</b>
  329. * <code>
  330. * echo input_tag('name');
  331. * </code>
  332. *
  333. * <code>
  334. * echo input_tag('amount', $sf_params->get('amount'), array('size' => 8, 'maxlength' => 8));
  335. * </code>
  336. *
  337. * @param string $name field name
  338. * @param string $value selected field value
  339. * @param array $options additional HTML compliant <input> tag parameters
  340. *
  341. * @return string XHTML compliant <input> tag with type="text"
  342. */
  343. function input_tag($name, $value = null, $options = array())
  344. {
  345. return tag('input', array_merge(array('type' => 'text', 'name' => $name, 'id' => get_id_from_name($name, $value), 'value' => $value), _convert_options($options)));
  346. }
  347. /**
  348. * Returns an XHTML compliant <input> tag with type="number".
  349. *
  350. * The input_tag helper generates your basic XHTML <input> tag and can utilize any standard <input> tag parameters
  351. * passed in the optional <i>$options</i> parameter.
  352. *
  353. * <b>Examples:</b>
  354. * <code>
  355. * echo input_number_tag('name');
  356. * </code>
  357. *
  358. * <code>
  359. * echo input_number_tag('amount', $sf_params->get('amount'), array('size' => 8, 'maxlength' => 8));
  360. * </code>
  361. *
  362. * @param string $name field name
  363. * @param string $value selected field value
  364. * @param array $options additional HTML compliant <input> tag parameters
  365. *
  366. * @return string XHTML compliant <input> tag with type="text"
  367. */
  368. function input_number_tag($name, $value = null, $options = array())
  369. {
  370. return tag('input', array_merge(array('type' => 'number', 'name' => $name, 'id' => get_id_from_name($name, $value), 'value' => $value), _convert_options($options)));
  371. }
  372. /**
  373. * Returns an XHTML compliant <input> tag with type="hidden".
  374. *
  375. * Similar to the input_tag helper, the input_hidden_tag helper generates an XHTML <input> tag and can utilize
  376. * any standard <input> tag parameters passed in the optional <i>$options</i> parameter. The only difference is
  377. * that it creates the tag with type="hidden", meaning that is not visible on the page.
  378. *
  379. * <b>Examples:</b>
  380. * <code>
  381. * echo input_hidden_tag('id', $id);
  382. * </code>
  383. *
  384. * @param string $name field name
  385. * @param string $value populated field value
  386. * @param array $options additional HTML compliant <input> tag parameters
  387. *
  388. * @return string XHTML compliant <input> tag with type="hidden"
  389. */
  390. function input_hidden_tag($name, $value = null, $options = array())
  391. {
  392. $options = _parse_attributes($options);
  393. $options['type'] = 'hidden';
  394. return input_tag($name, $value, $options);
  395. }
  396. /**
  397. * Returns an XHTML compliant <input> tag with type="file".
  398. *
  399. * Similar to the input_tag helper, the input_hidden_tag helper generates your basic XHTML <input> tag and can utilize
  400. * any standard <input> tag parameters passed in the optional <i>$options</i> parameter. The only difference is that it
  401. * creates the tag with type="file", meaning that next to the field will be a "browse" (or similar) button.
  402. * This gives the user the ability to choose a file from there computer to upload to the web server. Remember, if you
  403. * plan to upload files to your website, be sure to set the <i>multipart</i> option form_tag helper function to true
  404. * or your files will not be properly uploaded to the web server.
  405. *
  406. * <b>Examples:</b>
  407. * <code>
  408. * echo input_file_tag('filename', array('size' => 30));
  409. * </code>
  410. *
  411. * @param string $name field name
  412. * @param array $options additional HTML compliant <input> tag parameters
  413. *
  414. * @return string XHTML compliant <input> tag with type="file"
  415. * @see input_tag, form_tag
  416. */
  417. function input_file_tag($name, $options = array())
  418. {
  419. $options = _parse_attributes($options);
  420. $options['type'] = 'file';
  421. return input_tag($name, null, $options);
  422. }
  423. /**
  424. * Returns an XHTML compliant <input> tag with type="password".
  425. *
  426. * Similar to the input_tag helper, the input_hidden_tag helper generates your basic XHTML <input> tag and can utilize
  427. * any standard <input> tag parameters passed in the optional <i>$options</i> parameter. The only difference is that it
  428. * creates the tag with type="password", meaning that the text entered into this field will not be visible to the end user.
  429. * In most cases it is replaced by * * * * * * * *. Even though this text is not readable, it is recommended that you do not
  430. * populate the optional <i>$value</i> option with a plain-text password or any other sensitive information, as this is a
  431. * potential security risk.
  432. *
  433. * <b>Examples:</b>
  434. * <code>
  435. * echo input_password_tag('password');
  436. * echo input_password_tag('password_confirm');
  437. * </code>
  438. *
  439. * @param string $name field name
  440. * @param string $value populated field value
  441. * @param array $options additional HTML compliant <input> tag parameters
  442. *
  443. * @return string XHTML compliant <input> tag with type="password"
  444. * @see input_tag
  445. */
  446. function input_password_tag($name = 'password', $value = null, $options = array())
  447. {
  448. $options = _parse_attributes($options);
  449. $options['type'] = 'password';
  450. return input_tag($name, $value, $options);
  451. }
  452. /**
  453. * Returns a <textarea> tag, optionally wrapped with an inline rich-text JavaScript editor.
  454. *
  455. * The texarea_tag helper generates a standard HTML <textarea> tag and can be manipulated with
  456. * any number of standard HTML parameters via the <i>$options</i> array variable. However, the
  457. * textarea tag also has the unique capability of being transformed into a WYSIWYG rich-text editor
  458. * such as TinyMCE (http://tinymce.moxiecode.com) very easily with the use of some specific options:
  459. *
  460. * <b>Options:</b>
  461. * - rich: A rich text editor class (for example sfRichTextEditorTinyMCE for TinyMCE).
  462. *
  463. * <b>Examples:</b>
  464. * <code>
  465. * echo textarea_tag('notes');
  466. * </code>
  467. *
  468. * <code>
  469. * echo textarea_tag('description', 'This is a description', array('rows' => 10, 'cols' => 50));
  470. * </code>
  471. *
  472. * @param string $name field name
  473. * @param string $content populated field value
  474. * @param array $options additional HTML compliant <textarea> tag parameters
  475. *
  476. * @return string <textarea> tag optionally wrapped with a rich-text WYSIWYG editor
  477. */
  478. function textarea_tag($name, $content = null, $options = array())
  479. {
  480. $options = _parse_attributes($options);
  481. if ($size = _get_option($options, 'size'))
  482. {
  483. list($options['cols'], $options['rows']) = split('x', $size, 2);
  484. }
  485. // rich control?
  486. if ($rich = _get_option($options, 'rich', false))
  487. {
  488. if (true === $rich)
  489. {
  490. $rich = sfConfig::get('sf_rich_text_editor_class', 'TinyMCE');
  491. }
  492. // switch for backward compatibility
  493. switch ($rich)
  494. {
  495. case 'tinymce':
  496. $rich = 'TinyMCE';
  497. break;
  498. case 'fck':
  499. $rich = 'FCK';
  500. break;
  501. }
  502. $editorClass = 'sfRichTextEditor'.$rich;
  503. if (!class_exists($editorClass))
  504. {
  505. throw new sfConfigurationException(sprintf('The rich text editor "%s" does not exist.', $editorClass));
  506. }
  507. $sfEditor = new $editorClass();
  508. if (!in_array('sfRichTextEditor', class_parents($sfEditor)))
  509. {
  510. throw new sfConfigurationException(sprintf('The editor "%s" must extend sfRichTextEditor.', $editorClass));
  511. }
  512. $sfEditor->initialize($name, $content, $options);
  513. return $sfEditor->toHTML();
  514. }
  515. return content_tag('textarea', escape_once((is_object($content)) ? $content->__toString() : $content), array_merge(array('name' => $name, 'id' => get_id_from_name(_get_option($options, 'id', $name), null)), _convert_options($options)));
  516. }
  517. /**
  518. * Returns an XHTML compliant <input> tag with type="checkbox".
  519. *
  520. * When creating multiple checkboxes with the same name, be sure to use an array for the
  521. * <i>$name</i> parameter (i.e. 'name[]'). The checkbox_tag is smart enough to create unique ID's
  522. * based on the <i>$value</i> parameter like so:
  523. *
  524. * <samp>
  525. * <input type="checkbox" name="status[]" id="status_3" value="3" />
  526. * <input type="checkbox" name="status[]" id="status_4" value="4" />
  527. * </samp>
  528. *
  529. * <b>Examples:</b>
  530. * <code>
  531. * echo checkbox_tag('newsletter', 1, $sf_params->get('newsletter'));
  532. * </code>
  533. *
  534. * <code>
  535. * echo checkbox_tag('option_a', 'yes', true, array('class' => 'style_a'));
  536. * </code>
  537. *
  538. * <code>
  539. * // one request variable with an array of checkbox values
  540. * echo checkbox_tag('choice[]', 1);
  541. * echo checkbox_tag('choice[]', 2);
  542. * echo checkbox_tag('choice[]', 3);
  543. * echo checkbox_tag('choice[]', 4);
  544. * </code>
  545. *
  546. * <code>
  547. * // assuming you have Prototype.js enabled, you could do this
  548. * echo checkbox_tag('show_tos', 1, false, array('onclick' => "Element.toggle('tos'); return false;"));
  549. * </code>
  550. *
  551. * @param string $name field name
  552. * @param string $value checkbox value (if checked)
  553. * @param bool $checked is the checkbox checked? (1 or 0)
  554. * @param array $options additional HTML compliant <input> tag parameters
  555. *
  556. * @return string XHTML compliant <input> tag with type="checkbox"
  557. */
  558. function checkbox_tag($name, $value = '1', $checked = false, $options = array())
  559. {
  560. $html_options = array_merge(array('type' => 'checkbox', 'name' => $name, 'id' => get_id_from_name($name, $value), 'value' => $value), _convert_options($options));
  561. if ($checked)
  562. {
  563. $html_options['checked'] = 'checked';
  564. }
  565. return tag('input', $html_options);
  566. }
  567. /**
  568. * Returns an XHTML compliant <input> tag with type="radio".
  569. *
  570. * <b>Examples:</b>
  571. * <code>
  572. * echo ' Yes '.radiobutton_tag('newsletter', 1);
  573. * echo ' No '.radiobutton_tag('newsletter', 0);
  574. * </code>
  575. *
  576. * @param string $name field name
  577. * @param string $value radio button value (if selected)
  578. * @param bool $checked is the radio button selected? (1 or 0)
  579. * @param array $options additional HTML compliant <input> tag parameters
  580. *
  581. * @return string XHTML compliant <input> tag with type="radio"
  582. */
  583. function radiobutton_tag($name, $value, $checked = false, $options = array())
  584. {
  585. $html_options = array_merge(array('type' => 'radio', 'name' => $name, 'id' => get_id_from_name($name.'[]', $value), 'value' => $value), _convert_options($options));
  586. if ($checked)
  587. {
  588. $html_options['checked'] = 'checked';
  589. }
  590. return tag('input', $html_options);
  591. }
  592. /**
  593. * Returns two XHTML compliant <input> tags to be used as a free-text date fields for a date range.
  594. *
  595. * Built on the input_date_tag, the input_date_range_tag combines two input tags that allow the user
  596. * to specify a from and to date.
  597. * You can easily implement a JavaScript calendar by enabling the 'rich' option in the
  598. * <i>$options</i> parameter. This includes a button next to the field that when clicked,
  599. * will open an inline JavaScript calendar. When a date is selected, it will automatically
  600. * populate the <input> tag with the proper date, formatted to the user's culture setting.
  601. *
  602. * <b>Note:</b> The <i>$name</i> parameter will automatically converted to array names.
  603. * For example, a <i>$name</i> of "date" becomes date[from] and date[to]
  604. *
  605. * <b>Options:</b>
  606. * - rich - If set to true, includes an inline JavaScript calendar can auto-populate the date field with the chosen date
  607. * - before - string to be displayed before the input_date_range_tag
  608. * - middle - string to be displayed between the from and to tags
  609. * - after - string to be displayed after the input_date_range_tag
  610. *
  611. * <b>Examples:</b>
  612. * <code>
  613. * $date = array('from' => '2006-05-15', 'to' => '2006-06-15');
  614. * echo input_date_range_tag('date', $date, array('rich' => true));
  615. * </code>
  616. *
  617. * <code>
  618. * echo input_date_range_tag('date', null, array('middle' => ' through ', 'rich' => true));
  619. * </code>
  620. *
  621. * @param string $name field name
  622. * @param array $value dates: $value['from'] and $value['to']
  623. * @param array $options additional HTML compliant <input> tag parameters
  624. *
  625. * @return string XHTML compliant <input> tag with optional JS calendar integration
  626. * @see input_date_tag
  627. */
  628. function input_date_range_tag($name, $value, $options = array())
  629. {
  630. $options = _parse_attributes($options);
  631. $before = _get_option($options, 'before', '');
  632. $middle = _get_option($options, 'middle', '');
  633. $after = _get_option($options, 'after', '');
  634. return $before.
  635. input_date_tag($name.'[from]', isset($value['from']) ? $value['from'] : null, $options).
  636. $middle.
  637. input_date_tag($name.'[to]', isset($value['to']) ? $value['to'] : null, $options).
  638. $after;
  639. }
  640. /**
  641. * Returns an XHTML compliant <input> tag to be used as a free-text date field.
  642. *
  643. * You can easily implement a JavaScript calendar by enabling the 'rich' option in the
  644. * <i>$options</i> parameter. This includes a button next to the field that when clicked,
  645. * will open an inline JavaScript calendar. When a date is selected, it will automatically
  646. * populate the <input> tag with the proper date, formatted to the user's culture setting.
  647. * Symfony also conveniently offers the input_date_range_tag, that allows you to specify a to
  648. * and from date.
  649. *
  650. * <b>Options:</b>
  651. * - rich - If set to true, includes an inline JavaScript calendar can auto-populate the date field with the chosen date
  652. *
  653. * <b>Examples:</b>
  654. * <code>
  655. * echo input_date_tag('date', null, array('rich' => true));
  656. * </code>
  657. *
  658. * @param string $name field name
  659. * @param string $value date
  660. * @param array $options additional HTML compliant <input> tag parameters
  661. *
  662. * @return string XHTML compliant <input> tag with optional JS calendar integration
  663. * @see input_date_range_tag
  664. */
  665. function input_date_tag($name, $value = null, $options = array())
  666. {
  667. $options = _parse_attributes($options);
  668. $context = sfContext::getInstance();
  669. $culture = _get_option($options, 'culture', $context->getUser()->getCulture());
  670. $withTime = _get_option($options, 'withtime', false);
  671. // rich control?
  672. if (!_get_option($options, 'rich', false))
  673. {
  674. use_helper('DateForm');
  675. // set culture for month tag
  676. $options['culture'] = $culture;
  677. if ($withTime)
  678. {
  679. return select_datetime_tag($name, $value, $options, isset($options['html']) ? $options['html'] : array());
  680. }
  681. else
  682. {
  683. return select_date_tag($name, $value, $options, isset($options['html']) ? $options['html'] : array());
  684. }
  685. }
  686. $pattern = _get_option($options, 'format', $withTime ? 'g' : 'd');
  687. $dateFormat = new sfDateFormat($culture);
  688. $pattern = $dateFormat->getInputPattern($pattern);
  689. // parse date
  690. if ($value === null || $value === '')
  691. {
  692. $value = '';
  693. }
  694. else
  695. {
  696. $value = $dateFormat->format($value, $pattern);
  697. }
  698. // register our javascripts and stylesheets
  699. $langFile = sfConfig::get('sf_calendar_web_dir').'/lang/calendar-'.$culture;
  700. if((!is_readable(sfConfig::get('sf_web_dir').'/'.$langFile.'.js')) &&
  701. (!is_readable(sfConfig::get('sf_symfony_lib_dir').'/../data/web/'.$langFile.'.js')) &&
  702. (!is_readable(sfConfig::get('sf_symfony_lib_dir').'/../data/symfony/web/'.$langFile.'.js')))
  703. {
  704. $langFile = sfConfig::get('sf_calendar_web_dir').'/lang/calendar-'.substr($culture,0,2);
  705. if((!is_readable(sfConfig::get('sf_web_dir').'/'.$langFile.'.js')) &&
  706. (!is_readable(sfConfig::get('sf_symfony_lib_dir').'/../data/web/'.$langFile.'.js')) &&
  707. (!is_readable(sfConfig::get('sf_symfony_lib_dir').'/../data/symfony/web/'.$langFile.'.js')))
  708. {
  709. $langFile = sfConfig::get('sf_calendar_web_dir').'/lang/calendar-en';
  710. }
  711. }
  712. $jss = array(
  713. sfConfig::get('sf_calendar_web_dir').'/calendar',
  714. $langFile,
  715. sfConfig::get('sf_calendar_web_dir').'/calendar-setup',
  716. );
  717. foreach ($jss as $js)
  718. {
  719. $context->getResponse()->addJavascript($js);
  720. }
  721. // css
  722. if ($calendar_style = _get_option($options, 'css', 'skins/aqua/theme'))
  723. {
  724. $context->getResponse()->addStylesheet(sfConfig::get('sf_calendar_web_dir').'/'.$calendar_style);
  725. }
  726. // date format
  727. $date_format = $dateFormat->getPattern($pattern);
  728. // calendar date format
  729. $calendar_date_format = $date_format;
  730. $calendar_date_format = strtr($date_format, array('yyyy' => 'Y', 'yy'=>'y', 'MM' => 'm', 'M'=>'m', 'dd'=>'d', 'd'=>'e', 'HH'=>'H', 'H'=>'k', 'hh'=>'I', 'h'=>'l', 'mm'=>'M', 'ss'=>'S', 'a'=>'p'));
  731. $calendar_date_format = preg_replace('/([mdyhklspe])+/i', '%\\1', $calendar_date_format);
  732. $id_inputField = isset($options['id']) ? $options['id'] : get_id_from_name($name);
  733. $id_calendarButton = 'trigger_'.$id_inputField;
  734. $js = '
  735. document.getElementById("'.$id_calendarButton.'").disabled = false;
  736. Calendar.setup({
  737. inputField : "'.$id_inputField.'",
  738. ifFormat : "'.$calendar_date_format.'",
  739. daFormat : "'.$calendar_date_format.'",
  740. button : "'.$id_calendarButton.'"';
  741. if ($withTime)
  742. {
  743. $js .= ",\n showsTime : true";
  744. }
  745. // calendar options
  746. if ($calendar_options = _get_option($options, 'calendar_options'))
  747. {
  748. $js .= ",\n".$calendar_options;
  749. }
  750. $js .= '
  751. });
  752. ';
  753. // calendar button
  754. $calendar_button = '...';
  755. $calendar_button_type = 'txt';
  756. if ($calendar_button_img = _get_option($options, 'calendar_button_img'))
  757. {
  758. $calendar_button = $calendar_button_img;
  759. $calendar_button_type = 'img';
  760. }
  761. else if ($calendar_button_txt = _get_option($options, 'calendar_button_txt'))
  762. {
  763. $calendar_button = $calendar_button_txt;
  764. $calendar_button_type = 'txt';
  765. }
  766. // construct html
  767. if (!isset($options['size']))
  768. {
  769. // educated guess about the size
  770. $options['size'] = strlen($date_format)+2;
  771. }
  772. $html = input_tag($name, $value, $options);
  773. if ($calendar_button_type == 'img')
  774. {
  775. $html .= image_tag($calendar_button, array('id' => $id_calendarButton, 'style' => 'cursor: pointer; vertical-align: middle'));
  776. }
  777. else
  778. {
  779. $html .= content_tag('button', $calendar_button, array('type' => 'button', 'disabled' => 'disabled', 'onclick' => 'return false', 'id' => $id_calendarButton));
  780. }
  781. if (_get_option($options, 'with_format'))
  782. {
  783. $html .= '('.$date_format.')';
  784. }
  785. // add javascript
  786. $html .= content_tag('script', $js, array('type' => 'text/javascript'));
  787. return $html;
  788. }
  789. /**
  790. * Returns an XHTML compliant <input> tag with type="submit".
  791. *
  792. * By default, this helper creates a submit tag with a name of <em>commit</em> to avoid
  793. * conflicts with other parts of the framework. It is recommended that you do not use the name
  794. * "submit" for submit tags unless absolutely necessary. Also, the default <i>$value</i> parameter
  795. * (title of the button) is set to "Save changes", which can be easily overwritten by passing a
  796. * <i>$value</i> parameter.
  797. *
  798. * <b>Examples:</b>
  799. * <code>
  800. * echo submit_tag();
  801. * </code>
  802. *
  803. * <code>
  804. * echo submit_tag('Update Record');
  805. * </code>
  806. *
  807. * @param string $name field value (title of submit button)
  808. * @param array $options additional HTML compliant <input> tag parameters
  809. *
  810. * @return string XHTML compliant <input> tag with type="submit"
  811. */
  812. function submit_tag($value = 'Save changes', $options = array())
  813. {
  814. return tag('input', array_merge(array('type' => 'submit', 'name' => 'commit', 'value' => $value), _convert_options_to_javascript(_convert_options($options))));
  815. }
  816. /**
  817. * Returns an XHTML compliant <input> tag with type="reset".
  818. *
  819. * By default, this helper creates a submit tag with a name of <em>reset</em>. Also, the default
  820. * <i>$value</i> parameter (title of the button) is set to "Reset" which can be easily overwritten
  821. * by passing a <i>$value</i> parameter.
  822. *
  823. * <b>Examples:</b>
  824. * <code>
  825. * echo reset_tag();
  826. * </code>
  827. *
  828. * <code>
  829. * echo reset_tag('Start Over');
  830. * </code>
  831. *
  832. * @param string $name field value (title of reset button)
  833. * @param array $options additional HTML compliant <input> tag parameters
  834. *
  835. * @return string XHTML compliant <input> tag with type="reset"
  836. */
  837. function reset_tag($value = 'Reset', $options = array())
  838. {
  839. return tag('input', array_merge(array('type' => 'reset', 'name' => 'reset', 'value' => $value), _convert_options($options)));
  840. }
  841. /**
  842. * Returns an XHTML compliant <input> tag with type="image".
  843. *
  844. * The submit_image_tag is very similar to the submit_tag, the only difference being that it uses an image
  845. * for the submit button instead of the browser-generated default button. The image is defined by the
  846. * <i>$source</i> parameter and must be a valid image, either local or remote (URL). By default, this
  847. * helper creates a submit tag with a name of <em>commit</em> to avoid conflicts with other parts of the
  848. * framework. It is recommended that you do not use the name "submit" for submit tags unless absolutely necessary.
  849. *
  850. * <b>Examples:</b>
  851. * <code>
  852. * // Assuming your image is in the /web/images/ directory
  853. * echo submit_image_tag('my_submit_button.gif');
  854. * </code>
  855. *
  856. * <code>
  857. * echo submit_image_tag('http://mydomain.com/my_submit_button.gif');
  858. * </code>
  859. *
  860. * @param string $source path to image file
  861. * @param array $options additional HTML compliant <input> tag parameters
  862. *
  863. * @return string XHTML compliant <input> tag with type="image"
  864. */
  865. function submit_image_tag($source, $options = array())
  866. {
  867. if (!isset($options['alt']))
  868. {
  869. $path_pos = strrpos($source, '/');
  870. $dot_pos = strrpos($source, '.');
  871. $begin = $path_pos ? $path_pos + 1 : 0;
  872. $nb_str = ($dot_pos ? $dot_pos : strlen($source)) - $begin;
  873. $options['alt'] = ucfirst(substr($source, $begin, $nb_str));
  874. }
  875. return tag('input', array_merge(array('type' => 'image', 'name' => 'commit', 'src' => image_path($source)), _convert_options_to_javascript(_convert_options($options))));
  876. }
  877. /**
  878. * Returns a <label> tag with <i>$label</i> for the specified <i>$id</i> parameter.
  879. *
  880. * @param string $id id
  881. * @param string $label label or title
  882. * @param array $options additional HTML compliant <label> tag parameters
  883. *
  884. * @return string <label> tag with <i>$label</i> for the specified <i>$id</i> parameter.
  885. */
  886. function label_for($id, $label, $options = array())
  887. {
  888. $options = _parse_attributes($options);
  889. if (is_object($label) && method_exists($label, '__toString'))
  890. {
  891. $label = $label->__toString();
  892. }
  893. return content_tag('label', $label, array_merge(array('for' => get_id_from_name($id, null)), $options));
  894. }
  895. function _convert_include_custom_for_select($options, &$select_options)
  896. {
  897. if (_get_option($options, 'include_blank'))
  898. {
  899. $select_options[''] = '';
  900. }
  901. else if ($include_custom = _get_option($options, 'include_custom'))
  902. {
  903. $select_options[''] = $include_custom;
  904. }
  905. }