Development

/branches/1.2/lib/helper/FormHelper.php

You must first sign up to be able to contribute.

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

Revision 17858, 34.1 kB (checked in by FabianLange, 5 years ago)

[1.1, 1.2, 1.3] fixed some codeing standards (fixes #6376 - patch from gimler)

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