FormHelper.php 34 KB

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