Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/mvc/helpers/form

[return to app]
1 <?php
2
/**
3  * Form-related helper tools
4  */
5
class formHelper {
6     
/**
7      * Internal flag to keep track if a form tag has been opened and not yet closed
8      * @var boolean
9      */
10     
private $_formOpen false;
11
12     
/**
13      * Internal form element counter
14      * @var int
15      */
16     
private $_inputCounter = array();
17
18     
/**
19      * Default value for addBreak
20      * @var Boolean Defaults to true
21      */
22     
public $addBreak true;
23
24     
/**
25      * Converts dynamically-assigned array indecies to use an explicitely defined index
26      *
27      * @param string $name
28      * @return string
29      */
30     
protected function _indexDynamicArray($name) {
31         
$dynamicArrayStart strpos($name'[]');
32         if (
$dynamicArrayStart) {
33             
$prefix substr($name0$dynamicArrayStart);
34             if (!isset(
$this->_inputCounter[$prefix])) {
35                 
$this->_inputCounter[$prefix] = -1;
36             }
37             
$name $prefix '[' . ++$this->_inputCounter[$prefix] . substr($name, ($dynamicArrayStart 1));
38         }
39         return 
$name;
40     }
41
42     
/**
43      * Form types that do not change value with user input
44      * @var array
45      */
46     
protected $_staticTypes = array('hidden''submit''button''image');
47
48     
/**
49      * Sets the standard properties available to all input elements in addition to user-defined properties
50      * Standard properties are: name, value, class, style, id
51      *
52      * @param array $args
53      * @param array $propertyNames Optional, an array of user-defined properties
54      * @return array
55      */
56     
protected function _getProperties(array $args, array $propertyNames = array()) {
57         
$method = (isset($this->_formOpen['method']) && $this->_formOpen['method'] == 'get' $_GET $_POST);
58         if (isset(
$args['name']) && (!isset($args['type']) || !in_array($args['type'], $this->_staticTypes))) {
59             
$arrayStart strpos($args['name'], '[');
60             if (!
$arrayStart) {
61                 if (isset(
$method[$args['name']])) {
62                     
$args['value'] = $method[$args['name']];
63                 }
64             } else {
65                 
$name $this->_indexDynamicArray($args['name']);
66                 if (
preg_match_all('/\[(.*)\]/'$name$arrayIndex)) {
67                     
array_shift($arrayIndex); //dump the 0 index element containing full match string
68                 
}
69                 
$name substr($name0$arrayStart);
70                 if (isset(
$method[$name])) {
71                     
$args['value'] = $method[$name];
72                     if (!isset(
$args['type']) || $args['type'] != 'checkbox') {
73                         foreach (
$arrayIndex as $idx) {
74                             if (isset(
$args['value'][current($idx)])) {
75                                 
$args['value'] = $args['value'][current($idx)];
76                             } else {
77                                 unset(
$args['value']);
78                                 break;
79                             }
80                         }
81                     }
82                 }
83             }
84         }
85         
$return = array();
86         
$validProperties array_merge($propertyNames, array('name''value''class''style''id'));
87         foreach (
$validProperties as $propertyName) {
88             if (isset(
$args[$propertyName])) {
89                 
$return[$propertyName] = $args[$propertyName];
90             }
91         }
92         return 
$return;
93     }
94
95     
/**
96      * Begins a form
97      * Includes a safety mechanism to prevent re-opening an already-open form
98      *
99      * @param array $args
100      * @return string
101      */
102     
public function open(array $args = array()) {
103         if (!
$this->_formOpen) {
104             if (!isset(
$args['method'])) {
105                 
$args['method'] = 'post';
106             }
107
108             
$this->_formOpen = array('id' => (isset($args['id']) ? $args['id'] : true),
109                                      
'method' => $args['method']);
110
111             if (!isset(
$args['action'])) {
112                 
$args['action'] = $_SERVER['REQUEST_URI'];
113             }
114             if (isset(
$args['upload']) && $args['upload'] && !isset($args['enctype'])) {
115                 
$args['enctype'] = 'multipart/form-data';
116             }
117             if (isset(
$args['legend'])) {
118                 
$legend $args['legend'];
119                 unset(
$args['legend']);
120                 if (!isset(
$args['title'])) {
121                     
$args['title'] = $legend;
122                 }
123             } else if (isset(
$args['title'])) {
124                 
$legend $args['title'];
125             }
126             if (isset(
$args['alert'])) {
127                 if (
$args['alert']) {
128                     
$alert = (is_array($args['alert']) ? implode('<br />'$args['alert']) : $args['alert']);
129                 }
130                 unset(
$args['alert']);
131             }
132             
$return '<form ' htmlHelper::formatProperties($args) . '>' PHP_EOL '<fieldset>' PHP_EOL;
133             if (isset(
$legend)) {
134                 
$return .= '<legend>' $legend '</legend>' PHP_EOL;
135             }
136             if (isset(
$alert)) {
137                 
$return .= $this->getErrorMessageContainer((isset($args['id']) ? $args['id'] : 'form'), $alert);
138             }
139             return 
$return;
140         } else if (
DEBUG_MODE) {
141             
$errorMsg 'Invalid usage of ' __METHOD__ '() - a form is already open';
142             
trigger_error($errorMsgE_USER_NOTICE);
143         }
144     }
145
146     
/**
147      * Closes a form if one is open
148      *
149      * @return string
150      */
151     
public function close() {
152         if (
$this->_formOpen) {
153             
$this->_formOpen false;
154             return 
'</fieldset>' PHP_EOL '</form>' PHP_EOL;
155         } else if (
DEBUG_MODE) {
156             
$errorMsg 'Invalid usage of ' __METHOD__ '() - there is no open form to close';
157             
trigger_error($errorMsgE_USER_NOTICE);
158         }
159     }
160
161     
/**
162      * Adds label tags to a form element
163      *
164      * @param array $args
165      * @param str $formElement
166      * @return str
167      */
168     
protected function _getLabel(array $args$formElement) {
169         if (!isset(
$args['label']) && isset($args['name'])
170             && (!isset(
$args['type']) || !in_array($args['type'], $this->_staticTypes))) {
171             
$args['label'] = ucfirst($args['name']);
172         }
173
174         if (isset(
$args['label'])) {
175             
$label = (!isset($args['htmlok']) || !$args['htmlok'] ? get::xhtmlentities($args['label']) :
 
$args['label']);
176             if (isset(
$_POST['errors']) && isset($args['name']) && isset($_POST['errors'][$args['name']])) {
177                 
$label .= ' ' $this->getErrorMessageContainer($args['name'], $_POST['errors'][$args['name']]);
178             }
179             
$labelFirst = (!isset($args['labelFirst']) || $args['labelFirst']);
180             if (isset(
$args['id'])) {
181                 
$label '<label for="' $args['id'] . '" id="' $args['id'] . 'label">' $label '</label>';
182             }
183             if (isset(
$args['addBreak']) && $args['addBreak']) {
184                 
$label = ($labelFirst $label '<br />' PHP_EOL '<br />' PHP_EOL $label);
185             }
186             
$formElement = ($labelFirst $label $formElement $formElement $label);
187             if (!isset(
$args['id'])) {
188                 
$formElement '<label>' $formElement '</label>';
189             }
190         }
191         return 
$formElement;
192     }
193
194     
/**
195      * Returns a standardized container to wrap an error message
196      *
197      * @param string $id
198      * @param string $errorMessage Optional, you may want to leave this blank and populate dynamically via
 
JavaScript
199      
* @return string
200      
*/
201     public function 
getErrorMessageContainer($id$errorMessage '') {
202         return 
'<span class="errormessage" id="' $id 'errorwrapper">'
203              
get::xhtmlentities($errorMessage) . '</span>';
204     }
205
206     
/**
207      * Internal counters used by the wysiwygTextarea system
208      * @var int
209      */
210     
protected $_wysiwygTextareaCount 0$_wysiwygTextareaDefaultInitSent 0;
211
212     
/**
213      * Initializes WYSIWYG system
214      * docs at: http://wiki.moxiecode.com/index.php/TinyMCE:Configuration
215      *
216      * @param array $args Optional
217      * @return string
218      */
219     
public function wysiwygTextareaInit(array $args = array()) {
220         
$init = array(
221             
'theme' => 'advanced',
222             
'plugins' => 'spellchecker,xhtmlxtras,searchreplace,advlink,advimage,media,fullscreen',
223             
'mode' => 'specific_textareas',
224             
'editor_selector' => 'wysiwyg',
225             
'theme_advanced_buttons1' => 'bold,italic,|,formatselect,|,'
226                                       
'justifyleft,justifycenter,justifyright,justifyfull,|,'
227                                       
'bullist,numlist,sub,sup,blockquote,cite,abbr,acronym,|,'
228                                       
'indent,outdent,|,link,unlink,|,image,media,hr,charmap,|,code,cleanup,|,'
229                                       
'search,replace,|,spellchecker,|,fullscreen',
230             
'theme_advanced_buttons2' => '',
231             
'theme_advanced_buttons3' => '',
232             
'theme_advanced_blockformats' => 'p,h1,h2,h3,h4',
233             
'theme_advanced_toolbar_location' => 'top',
234             
'skin' => 'o2k7',
235             
'extended_valid_elements' => 'a[name|href|target|title|onclick]',
236             
'relative_urls' => false
237         
);
238         
$html get::helper('html');
239         
$initJsObj $return[] = $html->jsInline('var vorkInitTinyMce = ' json_encode($init));
240         
$init array_merge($args$init);
241         if (!isset(
$args['nocache'])) {
242             
$return[] = $html->js('/js/tinymce/tiny_mce_gzip.js');
243             
$return[] = $html->jsInline('tinyMCE_GZ.init({theme: "' $init['theme']
244                                       . 
'", plugins: "' $init['plugins']
245                                       . 
'", disk_cache: ' . (isset($init['disk_cache'])
246                                                              ? 
$init['disk_cache'] : 'true') . '});');
247
248         }
249         
$return[] = $html->js('/js/tinymce/tiny_mce.js');
250         return 
implode(PHP_EOL$return);
251     }
252
253     
/**
254      * Adds WYSIWYG capabilities to a textarea
255      * This is a simplified interface to $this->createWysiwygTextareaParts() and $this->wysiwygTextareaParts
256      *
257      * @param array $args Optional
258      * @return string
259      */
260     
public function wysiwygTextarea(array $args = array()) {
261         
$return = (!$this->_wysiwygTextareaCount++ ? $this->wysiwygTextareaInit($args) : '');
262         unset(
$args['disk_cache']); //only used in the init gzip
263         
if ($args) {
264             
$jsObj 'vorkTinyMce' $this->_wysiwygTextareaCount;
265             
$js 'var ' $jsObj ' = vorkInitTinyMce;';
266             foreach (
$args as $key => $val) {
267                 
$js .= PHP_EOL $jsObj '.' $key ' = '
268                      
. (!in_array($val, array('true''false')) ? '"' $val '"' $val) . ';';
269             }
270             
$js .= PHP_EOL 'tinyMCE.init(' $jsObj ');';
271             
$return .= get::helper('html')->jsInline($js);
272         } else if (!
$this->_wysiwygTextareaDefaultInitSent++) {
273             
$return .= get::helper('html')->jsInline('tinyMCE.init(vorkInitTinyMce);');
274         }
275         return 
$return;
276     }
277
278     
/**
279      * Sanitizes a string for use as an ID by swapping brackets with underscores
280      *
281      * @param string $str
282      * @return string
283      */
284     
protected function _getValidId($str) {
285         return 
str_replace(array('['']'), '_'$str);
286     }
287
288     
/**
289      * Used for text, textarea (standard and WYSIWYG,) hidden, password, file, button, image and submit
290      *
291      * Valid args are any properties valid within an HTML input as well as label
292      *
293      * @param array $args
294      * @return string
295      */
296     
public function input(array $args) {
297         
$args['type'] = (isset($args['type']) ? $args['type'] : 'text');
298
299         switch (
$args['type']) {
300             case 
'select':
301                 return 
$this->select($args);
302                 break;
303             case 
'checkbox':
304                 return 
$this->checkboxes($args);
305                 break;
306             case 
'radio':
307                 return 
$this->radios($args);
308                 break;
309         }
310
311         if (
$args['type'] == 'textarea' && isset($args['maxlength'])) {
312             if (!isset(
$args['id']) && isset($args['name'])) {
313                 
$args['id'] = $this->_getValidId($args['name']);
314             }
315             if (isset(
$args['id'])) {
316                 
$maxlength $args['maxlength'];
317             }
318             unset(
$args['maxlength']);
319         }
320
321         if (
$args['type'] == 'submit' && !isset($args['class'])) {
322             
$args['class'] = $args['type'];
323         }
324
325         
$takeFocus = (isset($args['focus']) && $args['focus'] && $args['type'] != 'hidden');
326         if (
$takeFocus && !isset($args['id'])) {
327             if (isset(
$args['name'])) {
328                 
$args['id'] = $this->_getValidId($args['name']);
329             } else {
330                 
$takeFocus false;
331                 if (
DEBUG_MODE) {
332                     
$errorMsg 'Either name or id is required to use the focus option on a form input';
333                     
trigger_error($errorMsgE_USER_NOTICE);
334                 }
335             }
336         }
337
338         if (isset(
$args['wysiwyg']) && $args['wysiwyg']) {
339             
$args['class'] = (!isset($args['class']) ? 'wysiwyg' $args['class'] . ' wysiwyg');
340         }
341         
$properties $this->_getProperties($args, array('type''maxlength'));
342
343         if (
$args['type'] == 'image') {
344             
$properties['src'] = $args['src'];
345             
$properties['alt'] = (isset($args['alt']) ? $args['alt'] : '');
346             
$optionalProperties = array('height''width');
347             foreach (
$optionalProperties as $optionalProperty) {
348                 if (isset(
$args[$optionalProperty])) {
349                     
$properties[$optionalProperty] = $args[$optionalProperty];
350                 }
351             }
352         }
353
354         if (!
class_exists('htmlHelper')) {
355             
get::helper('html');
356         }
357         if (
$args['type'] != 'textarea') {
358             
$return[] = '<input ' htmlHelper::formatProperties($properties) . ' />' PHP_EOL;
359         } else {
360             unset(
$properties['type']);
361             if (isset(
$properties['value'])) {
362                 
$value $properties['value'];
363                 unset(
$properties['value']);
364             }
365             if (isset(
$args['preview']) && $args['preview'] && !isset($properties['id'])) {
366                 
$properties['id'] = 'textarea_' rand(100999);
367             }
368             
$properties['rows'] = (isset($args['rows']) ? $args['rows'] : 13);
369             
$properties['cols'] = (isset($args['cols']) ? $args['cols'] : 55);
370             
$return[] = '<textarea ' htmlHelper::formatProperties($properties);
371             if (isset(
$maxlength)) {
372                 
$return[] = ' onkeyup="document.getElementById(\''
373                           
$properties['id'] . 'errorwrapper\').innerHTML = (this.value.length > '
374                           
$maxlength ' ? \'Form content exceeds maximum length of '
375                           
$maxlength ' characters\' : \'Length: \' + this.value.length + \' (maximum: '
376                           
$maxlength ' characters)\')"';
377             }
378             
$return[] = '>';
379             if (isset(
$value)) {
380                 
$return[] = get::htmlentities($valuenullnulltrue); //double-encode allowed
381             
}
382             
$return[] = '</textarea>' PHP_EOL;
383             if (isset(
$args['wysiwyg']) && $args['wysiwyg']) {
384                 if (!
is_array($args['wysiwyg'])) {
385                     
$args['wysiwyg'] = array();
386                 }
387                 
$return[] = $this->wysiwygTextarea($args['wysiwyg']);
388             }
389             if (isset(
$maxlength) && (!isset($args['validatedInput']) || !$args['validatedInput'])) {
390                 
$return[] = $this->getErrorMessageContainer($properties['id']);
391             }
392         }
393         if (!isset(
$args['addBreak'])) {
394             
$args['addBreak'] = $this->addBreak;
395         }
396         if (
$takeFocus) {
397             
$html get::helper('html');
398             
$return[] = $html->jsInline($html->jsTools(true) . 'dom("' $args['id'] . '").focus();');
399         }
400         if (isset(
$args['preview']) && $args['preview']) {
401             
$js 'document.writeln(\'<div class="htmlpreviewlabel">'
402                 
'<label for="livepreview_' $properties['id'] . '">Preview:</label></div>'
403                 
'<div id="livepreview_' $properties['id'] . '" class="htmlpreview"></div>\');' PHP_EOL
404                 
'if (dom("livepreview_' $properties['id'] . '")) {' PHP_EOL
405                 
'    var updateLivePreview_' $properties['id'] . ' = '
406                     
'function() {dom("livepreview_' $properties['id'] . '").innerHTML = '
407                         
'dom("' $properties['id'] . '").value};' PHP_EOL
408                 
'    dom("' $properties['id'] . '").onkeyup = updateLivePreview_' $properties['id'] . ';'
409                 
' updateLivePreview_' $properties['id'] . '();' PHP_EOL
410                 
'}';
411             if (!isset(
$html)) {
412                 
$html get::helper('html');
413             }
414             
$return[] = $html->jsInline($html->jsTools(true) . $js);
415         }
416         return 
$this->_getLabel($argsimplode($return));
417     }
418
419     
/**
420      * Returns an input that is validated using the Validator package
421      *
422      * @param array $args
423      * @return string
424      */
425     
public function validatedInput(array $args) {
426         
$args['validatedInput'] = true;
427         
$errorMessage '';
428         if (isset(
Validator::$errors[$this->_formOpen['id']][$args['id']])) {
429             
$errorMessage Validator::$errors[$this->_formOpen['id']][$args['id']];
430         }
431         return 
$this->input($args) . $this->getErrorMessageContainer($args['id'], $errorMessage);
432     }
433
434     
/**
435      * Returns a form select element
436      *
437      * $args = array(
438      * 'name' => '',
439      * 'multiple' => true,
440      * 'leadingOptions' => array(),
441      * 'optgroups' => array('group 1' => array('label' => 'g1o1', 'value' => 'grp 1 opt 1'),
442      *                      'group 2' => array(),),
443      * 'options' => array('value1' => 'text1', 'value2' => 'text2', 'value3' => 'text3'),
444      * 'value' => array('value2', 'value3') //if (multiple==false) 'value' => (str) 'value3'
445      * );
446      *
447      * @param array $args
448      * @return str
449      */
450     
public function select(array $args) {
451         if (!isset(
$args['id'])) {
452             
$args['id'] = $this->_getValidId($args['name']);
453         }
454         if (isset(
$args['multiple']) && $args['multiple']) {
455             
$args['multiple'] = 'multiple';
456             if (
substr($args['name'], -2) != '[]') {
457                 
$args['name'] .= '[]';
458             }
459         }
460         
$properties $this->_getProperties($args, array('multiple'));
461         
$values = (isset($properties['value']) ? $properties['value'] : null);
462         unset(
$properties['value']);
463         if (!
is_array($values)) {
464             
$values = ($values != '' ? array($values) : array());
465         }
466         
$return '<select ' htmlHelper::formatProperties($properties) . '>' PHP_EOL;
467         if (isset(
$args['prependBlank']) && $args['prependBlank']) {
468             
$return .= '<option value=""></option>' PHP_EOL;
469         }
470
471         if (isset(
$args['leadingOptions'])) {
472             
$useValues = (key($args['leadingOptions']) !== 0
473                           
|| (isset($args['useValue']) && $args['useValue']));
474             foreach (
$args['leadingOptions'] as $value => $text) {
475                 if (!
$useValues) {
476                     
$value $text;
477                 }
478                 
$return .= '<option value="' get::htmlentities($value) . '">'
479                          
get::htmlentities($text) . '</option>' PHP_EOL;
480             }
481         }
482
483         if (isset(
$args['optgroups'])) {
484             foreach (
$args['optgroups'] as $groupLabel => $optgroup) {
485                 
$return .= '<optgroup label="' get::htmlentities($groupLabel) . '">' PHP_EOL;
486                 foreach (
$optgroup as $value => $label) {
487                     
$return .= '<option value="' get::htmlentities($value) . '"';
488                     if (isset(
$label)) {
489                         
$return .= ' label="' get::htmlentities($label) . '"';
490                     }
491                     if (
in_array($value$values)) {
492                         
$return .= ' selected="selected"';
493                     }
494                     
$return .= '>' get::htmlentities($label) . '</option>' PHP_EOL;
495                 }
496                 
$return .= '</optgroup>' PHP_EOL;
497             }
498         }
499
500         if (isset(
$args['options'])) {
501             
$useValues = (key($args['options']) !== || (isset($args['useValue']) && $args['useValue']));
502             foreach (
$args['options'] as $value => $text) {
503                 if (!
$useValues) {
504                     
$value $text;
505                 }
506                 
$return .= '<option value="' get::htmlentities($value) . '"';
507                 if (
in_array($value$values)) {
508                     
$return .= ' selected="selected"';
509                 }
510                 
$return .= '>' get::htmlentities($text) . '</option>' PHP_EOL;
511             }
512         }
513         
$return .= '</select>' PHP_EOL;
514         if (!isset(
$args['addBreak'])) {
515             
$args['addBreak'] = $this->addBreak;
516         }
517         
$return $this->_getLabel($args$return);
518         if (isset(
$args['error'])) {
519              
$return .= $this->getErrorMessageContainer($args['id'], '<br />' $args['error']);
520         }
521         return 
$return;
522     }
523
524     
/**
525      * Cache containing individual radio, checkbox and dateSelect-selector elements in an array
526      * @var array
527      */
528     
public $radios = array(), $checkboxes = array(), $dateSelect = array();
529
530     
/**
531      * Returns a set of radio form elements
532      *
533      * array(
534      * 'name' => '',
535      * 'value' => '',
536      * 'id' => '',
537      * 'legend' => '',
538      * 'options' => array('value1' => 'text1', 'value2' => 'text2', 'value3' => 'text3'), // if just one option
 
exists this can be a string
539      
'options' => array('text1''text2''text3'), //also acceptable (cannot do half this, half above syntax)
540      
* )
541      *
542      * @
param array $args
543      
* @return str
544      
*/
545     public function 
radios(array $args) {
546         
$id = (isset($args['id']) ? $args['id'] : $this->_getValidId($args['name']));
547         
$properties $this->_getProperties($args);
548         if (isset(
$properties['value'])) {
549             
$checked $properties['value'];
550             unset(
$properties['value']);
551         }
552         
$properties['type'] = (isset($args['type']) ? $args['type'] : 'radio');
553         if (!empty(
$args['options']) && !is_array($args['options'])) {
554             
$args['options'] = (isset($args['label']) ? array($args['options'] => $args['label']) :
 
array($args['options']));
555             
$args['addFieldset'] = false;
556         }
557         
$useValues = (key($args['options']) !== || (isset($args['useValue']) && $args['useValue']));
558         foreach (
$args['options'] as $value => $text) {
559             if (!
$useValues) {
560                 
$value $text;
561             }
562             
$properties['id'] = $id '_' $this->_getValidId(preg_replace('/\W/'''$value));
563             
$properties['value'] = $value;
564             if (isset(
$checked) &&
565                 (((
$properties['type'] == 'radio' || !is_array($checked)) && $value == $checked)
566                   || (
$properties['type'] == 'checkbox' && is_array($checked) && in_array($value$checked)))) {
567                 
$properties['checked'] = 'checked';
568                 
$rowClass = (!isset($properties['class']) ? 'checked' $properties['class'] . ' checked');
569             }
570             
$labelFirst = (isset($args['labelFirst']) ? $args['labelFirst'] : false);
571             
$labelArgs = array('label' => $text'id' => $properties['id'], 'labelFirst' => $labelFirst);
572             if (isset(
$args['htmlok'])) {
573                 
$labelArgs['htmlok'] = $args['htmlok'];
574             }
575             
$input '<input ' htmlHelper::formatProperties($properties) . ' />';
576             
$row $this->_getLabel($labelArgs$input);
577             if (isset(
$rowClass)) {
578                 
$row '<span class="' $rowClass '">' $row '</span>';
579             }
580             
$radios[] = $row;
581             unset(
$properties['checked'], $rowClass);
582         }
583         
$this->{$properties['type'] == 'radio' 'radios' 'checkboxes'} = $radios;
584         
$break = (!isset($args['addBreak']) ? '<br />' PHP_EOL $args['addBreak']);
585         
$addFieldset = (isset($args['addFieldset']) ? $args['addFieldset'] : ((isset($args['label']) &&
 
$args['label']) || count($args['options']) > 1));
586         if (
$addFieldset) {
587             
$return '<fieldset id="' $id '">' PHP_EOL;
588             if (isset(
$args['label'])) {
589                 
$return .= '<legend>' get::xhtmlentities($args['label']) . '</legend>' PHP_EOL;
590             }
591             
$return .= implode($break$radios) . '</fieldset>' PHP_EOL;
592         } else {
593             
$return implode($break$radios);
594         }
595         if (isset(
$_POST['errors']) && isset($_POST['errors'][$id])) {
596             
$return $this->getErrorMessageContainer($id$_POST['errors'][$id]) . $return;
597         }
598         return 
$return;
599     }
600
601     
/**
602      * Returns a set of checkbox form elements
603      *
604      * This method essentially extends the getRadios method and uses an identical signature except
605      * that $args['value'] can also accept an array of values to be checked.
606      *
607      * @param array $args
608      * @return str
609      */
610     
public function checkboxes(array $args) {
611         
$args['type'] = 'checkbox';
612         if (isset(
$args['value']) && !is_array($args['value'])) {
613             
$args['value'] = array($args['value']);
614         }
615         
$nameParts explode('['$args['name']);
616         if (!isset(
$args['id'])) {
617             
$args['id'] = $this->_getValidId($nameParts[0]);
618         }
619         if (!isset(
$nameParts[1]) && count($args['options']) > 1) {
620             
$args['name'] .= '[]';
621         }
622         return 
$this->radios($args);
623     }
624
625     
/**
626      * Months of the year in the format commonly used when entering credit cards
627      * @var array
628      */
629     
public $months = array(=> '01 - January''02 - February''03 - March''04 - April',
630                          
'05 - May''06 - June''07 - July''08 - August',
631                          
'09 - September''10 - October''11 - November''12 - December');
632
633     
/**
634      * Creates a Date selection box
635      *
636      * @param array $args
637      * @return string
638      */
639     
public function dateSelect(array $args) {
640         
$includeTime = ((isset($args['time']) && $args['time'])
641                         || isset(
$args['hour']) || isset($args['minute']) || isset($args['mil']));
642         
$includeDate = (!isset($args['date']) || $args['date'] || !$includeTime /* must show something */);
643
644         if (!isset(
$args['addBreak'])) {
645             
$args['addBreak'] = false;
646         }
647
648         
$dateParts = ($includeDate ? array('month' => 'm''day' => 'j''year' => 'Y') : array());
649         if (
$includeTime) {
650             
$dateParts['hour'] = 'h';
651             
$dateParts['minute'] = 'i';
652             
$isMil = (isset($args['mil']) && $args['mil']);
653             if (!isset(
$args['ampm']) && isset($args['pmam'])) {
654                 
$args['ampm'] = $args['pmam'];
655             }
656             if (!
$isMil) {
657                 
$dateParts['ampm'] = 'p';
658             }
659             if (!isset(
$args['hour']['options'])) {
660                 
$args['hour']['options'] = (!$isMil range(112) : range(023));
661             }
662             if (!isset(
$args['minute']['options'])) {
663                 if (isset(
$args['minute']['increment'])) {
664                     switch (
$args['minute']['increment']) {
665                         case 
5:
666                             
$minutes range(10555);
667                             
array_unshift($minutes'00''05');
668                             break;
669                         case 
10:
670                             
$minutes range(105010);
671                             
array_unshift($minutes'00');
672                             break;
673                         case 
15:
674                             
$minutes = array(00153045);
675                             break;
676                         case 
20:
677                             
$minutes = array(002040);
678                             break;
679                         case 
30:
680                             
$minutes = array(0030);
681                             break;
682                     }
683                 } else {
684                     
$minutes range(059);
685                 }
686                 foreach (
$minutes as $x) {
687                     
$args['minute']['options'][] = str_pad($x2'0'STR_PAD_LEFT);
688                 }
689             }
690             if (!isset(
$args['hour']['label'])) {
691                 
$args['hour']['label'] = 'Time';
692             }
693             if (!isset(
$args['minute']['label'])) {
694                 
$args['minute']['label'] = ':';
695             }
696             if (!
$isMil) {
697                 if (!isset(
$args['ampm']['options'])) {
698                     
$args['ampm']['options'] = array('AM''PM');
699                 }
700                 if (!isset(
$args['ampm']['label'])) {
701                     
$args['ampm']['label'] = '';
702                 }
703             }
704             if (isset(
$args['ampm']['value'])) {
705                 
$args['ampm']['value'] = strtoupper($args['ampm']['value']);
706         }
707         }
708
709         if (
$includeDate) {
710         if (!isset(
$args['month']['options'])) {
711             
$selectArgs['month']['options'] = $this->months;
712         }
713
714         
$selectArgs['day']['options'] = range(131);
715
716         
$datePart 'year';
717         if (!isset(
$args[$datePart]['start'])) {
718             
$args[$datePart]['start'] = date($dateParts[$datePart]);
719         }
720         if (!isset(
$args['year']['end'])) {
721             
$args[$datePart]['end'] = ($args[$datePart]['start'] - 100);
722         }
723         
$selectArgs['year']['options'] = range(current($args[$datePart]), next($args[$datePart]));
724         }
725
726         
$method = (isset($this->_formOpen['method']) && $this->_formOpen['method'] == 'get' $_GET $_POST);
727         foreach (
$dateParts as $dateType => $unixCode) {
728             
$selectArgs[$dateType]['name'] = $args['name'] . '[' $dateType ']';
729             
$selectArgs[$dateType]['id'] = $this->_getValidId($args['name']) . '_' $dateType;
730             if (isset(
$args[$dateType])) {
731                 
$selectArgs[$dateType] = array_merge($args[$dateType], $selectArgs[$dateType]);
732             }
733             if (!isset(
$selectArgs[$dateType]['label'])) {
734                 
$selectArgs[$dateType]['label'] = ucfirst($dateType);
735             }
736             if (isset(
$method[$args['name']][$dateType])) {
737                 
$selectArgs[$dateType]['value'] = $method[$args['name']][$dateType];
738             } else if (isset(
$args['value'][$dateType])) {
739                 
$selectArgs[$dateType]['value'] = $args['value'][$dateType];
740             }
741             
$this->dateSelect[] = $this->select(array_merge($args$selectArgs[$dateType]));
742         }
743         
$return '<fieldset class="dateselect';
744         if (isset(
$args['class'])) {
745             
$return .= ' ' $args['class'];
746         }
747         
$return .= '"';
748         if (isset(
$args['id'])) {
749             
$return .= ' id="' $args['id'] . '"';
750         }
751         
$return .= '>';
752         if (isset(
$args['label'])) {
753             
$return .= '<legend>' get::htmlentities($args['label']) . '</legend>' PHP_EOL;
754         }
755         
$return .= implode($this->dateSelect) . '</fieldset>' PHP_EOL;
756         return 
$return;
757     }
758
759     
/**
760      * Opens up shorthand usage of form elements like $form->file() and $form->submit()
761      * The $legacyNames section keeps legacy naming convention working. New applications can safely remove this
 
section.
762      *
763      * @
param string $name
764      
* @param array $args
765      
* @return mixed
766      
*/
767     public function 
__call($name, array $args) {
768         
$inputShorthand = array('text''textarea''password''file''hidden''submit''button''image');
769         if (
in_array($name$inputShorthand)) {
770             if (!
is_array($args[0]) && $args[0]) { //shortcut strings
771                 
$defaultKey 'name';
772                 if (
$name == 'submit' && !isset($args[1])) {
773                     
$defaultKey 'value';
774                 }
775                 
$args[0] = array($defaultKey => $args[0]);
776                 if (isset(
$args[1]) && !is_array($args[1]) && $args[1]) {
777                     
$args[0][$name != 'image' 'value' 'src'] = $args[1];
778                 }
779             }
780             
$args[0]['type'] = $name;
781             return 
$this->input($args[0]);
782         }
783
784         
$legacyNames = array('getFormOpen' => 'open''getFormClose' => 'close',
785                              
'getInput' => 'input''getValidatedInput' => 'validatedInput''getRadios' =>
 
'radios',
786                              
'getSelect' => 'select''getDateSelect' => 'dateSelect''getCheckboxes' =>
 
'checkboxes');
787         if (isset(
$legacyNames[$name])) {
788             return 
call_user_func_array(array($this$legacyNames[$name]), $args);
789         } else {
790             
trigger_error('Call to undefined method ' __CLASS__ '::' $name '()'E_USER_ERROR);
791         }
792     }
793 }