Development

/branches/1.1/lib/helper/FormHelper.php

You must first sign up to be able to contribute.

root/branches/1.1/lib/helper/FormHelper.php

Revision 14152, 34.0 kB (checked in by FabianLange, 6 years ago)

[1.1] fixed input_date_tag to work correctly in pear installations. fixes #4229

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