Development

/branches/1.0/lib/helper/FormHelper.php

You must first sign up to be able to contribute.

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

Revision 23543, 31.9 kB (checked in by fabien, 5 years ago)

[1.0] fixed deprecated use of split for PHP 5.3 (closes #7509)

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