root/tags/RELEASE_0_9_0a2/patForms.php

Revision 199, 67.5 kB (checked in by schst, 4 years ago)

prepared 0.9.0a2 release

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * patForms form manager class - serialize form elements into any given output format
4  * using element classes, and build the output via renderer classes.
5  *
6  * $Id$
7  *
8  * @package        patForms
9  * @author        Sebastian Mordziol <argh@php-tools.net>
10  * @author        gERD Schaufelberger <gerd@php-tools.net>
11  * @author        Stephan Schmidt <schst@php-tools.net>
12  * @copyright    2003-2004 PHP Application Tools
13  * @license        LGPL
14  * @link        http://www.php-tools.net
15  */
16
17 /**
18  * set the include path
19  */
20 if( !defined( 'PATFORMS_INCLUDE_PATH' ) ) {
21     define( 'PATFORMS_INCLUDE_PATH', dirname( __FILE__ ). '/patForms' );
22 }
23
24 /**
25  * location of global javascripts
26  */
27 define('PATFORMS_SCRIPT_PATH', PATFORMS_INCLUDE_PATH . '/Scripts');
28
29 /**
30  * needs helper methods of patForms_Element
31  */
32 include_once PATFORMS_INCLUDE_PATH . "/Element.php";
33  
34 /**
35  * error definition: renderer base class file (renderers/_base.php) could not
36  * be found.
37  *
38  * @see    patForms::_createModule()
39  */                                   
40 define( "PATFORMS_ERROR_NO_MODULE_BASE_FILE", 1001 );
41
42 /**
43  * error definition: the specified renderer could not be found.
44  *
45  * @see    patForms::_createModule()
46  */                                   
47 define( "PATFORMS_ERROR_MODULE_NOT_FOUND", 1002 );
48
49 /**
50  * error definition: the element added via the {@link patForms::addElement()}
51  * is not an object. Use the {@link patForms::createElement()} method to
52  * create an element object.
53  *
54  * @see    patForms::addElement()
55  * @see    patForms::createElement()
56  */                                   
57 define( "PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT", 1003 );
58
59 /**
60  * error definition: generic unexpected error.
61  */                                   
62 define( "PATFORMS_ERROR_UNEXPECTED_ERROR", 1004 );
63
64 /**
65  * element does not exist
66  */                                   
67 define( "PATFORMS_ERROR_ELEMENT_NOT_FOUND", 1012 );
68
69 /**
70  * renderer object has not been set - if you want to render the form, you have to
71  * set a renderer object via the {@link patForms::setRenderer()} method. To create
72  * a renderer, use the {@link patForms::createRenderer()} method.
73  *
74  * @see    patForms::setRenderer()
75  * @see    patForms::createRenderer()
76  */                                   
77 define( "PATFORMS_ERROR_NO_RENDERER_SET", 1013 );
78
79 /**
80  * invalid renderer
81  *
82  * @see    createRenderer()
83  */                                   
84 define( "PATFORMS_ERROR_INVALID_RENDERER", 1014 );
85
86 /**
87  * invalid method
88  *
89  * @see    setMethod()
90  */                                   
91 define( "PATFORMS_ERROR_INVALID_METHOD", 1015 );
92
93 /**
94  * Given parameter is not a boolean value
95  */                                   
96 define( "PATFORMS_ERROR_PARAMETER_NO_BOOL", 1016 );
97
98 /**
99  * Given Static property does not exist
100  */
101 define( "PATFORMS_ERROR_NO_STATIC_PROPERTY", 1017 );
102
103 /**
104  * Unknown event
105  */
106 define( "PATFORMS_ERROR_UNKNOWN_EVENT", 1018 );
107
108 /**
109  * Invalid event handler
110  */
111 define( "PATFORMS_ERROR_INVALID_HANDLER", 1019 );
112
113 /**
114  * Event exists
115  */
116 define( 'PATFORMS_NOTICE_EVENT_ALREADY_REGISTERED', 1020 );
117
118 /**
119  * Invalid storage container
120  */
121 define( 'PATFORMS_ERROR_INVALID_STORAGE', 1021 );
122
123 define( 'PATFORMS_NOTICE_ARRAY_EXPECTED', 1022 );
124
125 define( 'PATFORMS_NOTICE_ATTRIBUTE_NOT_SUPPORTED', 1023 );
126
127 define( 'PATFORMS_NOTICE_INVALID_OPTION', 1024 );
128
129 define( 'PATFORMS_ERROR_ATTRIBUTE_REQUIRED', 1025 );
130
131 define( 'PATFORMS_ERROR_CAN_NOT_VERIFY_FORMAT', 1026 );
132
133 define( 'PATFORMS_ERROR_METHOD_FOR_MODE_NOT_AVAILABLE', 1027 );
134
135
136 /**
137  * errors apply on translating errors matching current locale settings
138  */
139 define( 'PATFORMS_NOTICE_VALIDATOR_ERROR_LOCALE_UNDEFINED', 1028 );
140 define( 'PATFORMS_WARNING_VALIDATOR_ERROR_UNDEFINED', 1029 );
141
142 /**
143  * Script file could not be loaded
144  */
145 define( 'PATFORMS_WARNING_SCRIPTFILE_NOT_FOUND', 1040 );
146
147 /**
148  * apply the rule before the built-in validation
149  */
150 define( 'PATFORMS_RULE_BEFORE_VALIDATION', 1 );
151  
152 /**
153  * apply the rule after the built-in validation
154  */
155 define( 'PATFORMS_RULE_AFTER_VALIDATION', 2 );
156
157 /**
158  * apply the rule before AND after the built-in validation
159  */
160 define( 'PATFORMS_RULE_BOTH', 3 );
161     
162 /**
163  * attach the observer to the elements
164  */
165 define( 'PATFORMS_OBSERVER_ATTACH_TO_ELEMENTS', 1 );
166
167 /**
168  * attach the observer to the form
169  */
170 define( 'PATFORMS_OBSERVER_ATTACH_TO_FORM', 2 );
171
172 /**
173  * attach the observer to the form and the elements
174  */
175 define( 'PATFORMS_OBSERVER_ATTACH_TO_BOTH', 3 );
176
177 /**
178  * group values should stay nested
179  */
180 define('PATFORMS_VALUES_NESTED', 0);
181
182 /**
183  * group values should be flattened
184  */
185 define('PATFORMS_VALUES_FLATTENED', 1);
186
187 /**
188  * group values should be prefixed
189  */
190 define('PATFORMS_VALUES_PREFIXED', 2);
191
192 /**
193  * Static patForms properties - used to emulate pre-PHP5 static properties.
194  *
195  * @see    setStaticProperty()
196  * @see    getStaticProperty()
197  */
198 $GLOBALS['_patForms']    =    array(
199     'format'            =>    'html',
200     'locale'            =>    'C',
201     'customLocales'        =>    array(),
202     'autoFinalize'        =>    true,
203     'defaultAttributes'    =>    array(),
204     'elementCounter'    =>    0,
205 );
206
207 /**
208  * patForms form manager class - serialize form elements into any given output format
209  * using element classes, and build the output via renderer classes.
210  *
211  * @package        patForms
212  * @author        Sebastian Mordziol <argh@php-tools.net>
213  * @author        gERD Schaufelberger <gerd@php-tools.net>
214  * @author        Stephan Schmidt <schst@php-tools.net>
215  * @copyright    2003-2004 PHP Application Tools
216  * @license        LGPL
217  * @link        http://www.php-tools.net
218  * @version        0.9.0a2
219  * @todo        check the clientside functionality, as that can lead to broken pages
220  */
221 class patForms
222 {
223    /**
224     * javascript that will displayed only once
225     *
226     * @access    private
227     * @var        array
228     */
229     var $globalJavascript    =    array();
230
231    /**
232     * javascript that will be displayed once per instance
233     *
234     * @access    private
235     * @var        array
236     */
237     var $instanceJavascript    =    array();
238
239    /**
240     * stores the mode for the form. It defaults to 'default', and is only overwritten if
241     * set specifically. It is passed on to any elements you create.
242     *
243     * @access    private
244     * @see        setMode()
245     */
246     var $mode    =    'default';
247     
248    /**
249     * XML entities
250     *
251     * @access    private
252     * @see        toXML()
253     * @todo        This is redundant to the Element's xmlEntities property - find a way to keep this in one place
254     */
255     var $xmlEntities = array(
256         "<"    =>    "&lt;",
257         ">"    =>    "&gt;",
258         "&"    =>    "&amp;",
259         "'"    =>    "&apos;",
260         '"'    =>    "&quot;"
261     );
262
263    /**
264     * stores the format for the element. It defaults to 'html', and is only overwritten if
265     * set specifically. It is passed on to any elements you create.
266     *
267     * @access    private
268     * @see        setFormat()
269     */
270     var $format    =    'html';
271     
272    /**
273     * stores the flag telling the form whether it has been submitted - this is passed on to any
274     * elements you create.
275     *
276     * @access    private
277     * @see        setSubmitted()
278     */
279     var $submitted    =    false;
280
281    /**
282     * stores the element objects of this form.
283     * @access    private
284     * @see        addElement()
285     */
286     var $elements    =    array();
287     
288    /**
289     * stores a renderer
290     * @access    private
291     * @see        setRenderer(), renderForm()
292     */
293     var $renderer        =    null;
294     
295    /**
296     * stores the locale to use when adding validation errors for the whole form.
297     *
298     * @access    private
299     * @var        string    $locale
300     * @see        setLocale()
301     */
302     var    $locale        =    'C';
303     
304    /**
305     * stores custom locale
306     *
307     * @access    private
308     * @var        array
309     * @see        setLocale()
310     */
311     var    $customLocales = array();
312
313    /**
314     * stores the element name
315     * @access    private
316     * @see        getElementName()
317     */
318     var $elementName = 'Form';
319     
320    /**
321     * flag to indicate, whether form should be validated automatically
322     * by renderForm()
323     *
324     * @access    private
325     * @var        string
326     * @see        setAutoValidate(), renderForm()
327     */
328     var    $autoValidate    =    false;
329     
330    /**
331     * name of the variable that indicates, whether the form has
332     * been submitted.
333     *
334     * @access    private
335     * @var        string
336     * @see        setAutoValidate()
337     */
338     var    $submitVar    =    null;
339     
340    /**
341     * event handlers
342     *
343     * @access    private
344     * @var        array
345     * @see        registerEventHandler()
346     * @see        registerEvent()
347     */
348     var    $_eventHandler    =    array();
349     
350    /**
351     * events that can be triggered
352     *
353     * @access    private
354     * @var        array
355     * @see        registerEventHandler()
356     * @see        triggerEvent()
357     * @see        registerEvent()
358     */
359     var    $_validEvents    =    array( 'onInit', 'onSubmit', 'onError', 'onSuccess' );
360     
361    /**
362     * Stores whether the current form has been validated
363     *
364     * @access    private
365     */
366     var $validated    =    false;
367     
368    /**
369     * Stores whether the current form is valid or not (after the
370     * validation process)
371     *
372     * @access    private
373     */
374     var $valid    =    null;
375     
376    /**
377     * Stores the names of all static properties that patForms will use as defaults
378     * for the properties with the same name on startup.
379     *
380     * @access    private
381     */
382     var $staticProperties    =    array(
383         'format'        =>    'setFormat',
384         'autoFinalize'    =>    'setAutoFinalize',
385         'locale'        =>    'setLocale',
386     );
387     
388    /**
389     * Stores the flag for the autoFinalize feature
390     *
391     * @access    private
392     */
393     var $autoFinalize    =    true;
394
395    /**
396     * custom validation rules
397     *
398     * @access    private
399     * @var        array
400     */
401     var $_rules            =    array();
402     
403    /**
404     * define error codes an messages for the form
405     *
406     * Will be set by validation rules that have been
407     * added to the form.
408     *
409     * @access private
410     * @var    array    $validatorErrorCodes
411     */
412     var    $validatorErrorCodes  =   array();
413
414    /**
415     * stores any validation errors that can occurr during the
416     * form's validation process.
417     *
418     * @access    private
419     * @var        array    $validationErrors
420     */
421     var    $validationErrors  =   array();
422     
423    /**
424     * next error offset for rules
425     * @access    private
426     * @var        integer
427     */
428     var $nextErrorOffset    =    1000;
429
430    /**
431     * Attributes of the form - needed to generate the form tag
432     *
433     * @access    private
434     * @var        array    $attributes
435     * @see        setAttribute()
436     */
437     var    $attributes    =    array();
438     
439    /**
440     * Attribute definition for the form - defines which attribute the form
441     * itself supports.
442     *
443     * @access    public
444     */
445     var    $attributeDefinition    =    array(   
446             
447         'id' =>    array(   
448             'required'        =>    false,
449             'format'        =>    'string',
450             'outputFormats'    =>    array( 'html' ),
451         ),
452         
453         'name' => array(   
454             'required'        =>    true,
455             'format'        =>    'string',
456             'outputFormats'    =>    array( 'html' ),
457         ),
458         
459         'method' => array(   
460             'required'        =>    true,
461             'format'        =>    'string',
462             'default'        =>    'post',
463             'outputFormats'    =>    array( 'html' ),
464         ),
465
466         'action' => array(   
467             'required'        =>    true,
468             'format'        =>    'string',
469             'outputFormats'    =>    array( 'html' ),
470         ),
471
472         'accept' => array(   
473             'required'        =>    false,
474             'format'        =>    'string',
475             'outputFormats'    =>    array( 'html' ),
476         ),
477
478         'accept-charset' => array(   
479             'required'        =>    false,
480             'format'        =>    'string',
481             'outputFormats'    =>    array( 'html' ),
482         ),
483
484         'enctype' => array(   
485             'required'        =>    false,
486             'format'        =>    'string',
487             'outputFormats'    =>    array( 'html' ),
488         ),
489
490         'onreset' => array(   
491             'required'        =>    false,
492             'format'        =>    'string',
493             'outputFormats'    =>    array( 'html' ),
494         ),
495
496         'onsubmit' => array(   
497             'required'        =>    false,
498             'format'        =>    'string',
499             'outputFormats'    =>    array( 'html' ),
500         ),
501
502         'target' => array(   
503             'required'        =>    false,
504             'format'        =>    'string',
505             'outputFormats'    =>    array( 'html' ),
506         ),
507     );
508     
509    /**
510     * Stores all available patForms options - these are inherited by all elements
511     * and their dependencies, like rules.
512     *
513     * Short option overview:
514     *
515     * - scripts: enable client script integration
516     *
517     * @access    public
518     */
519     var $options    =    array(
520
521         'scripts'    =>    array(
522             'enabled'    =>    false,
523             'params'    =>    array(
524                                     'folder'    => PATFORMS_SCRIPT_PATH,
525                                     'jsInclude' => false
526                                 ),
527         ),
528
529     );
530     
531    /**
532     * observers of the form
533     *
534     * @access    private
535     * @var        array
536     */
537     var    $observers = array();
538
539    /**
540     * Sets the default attributes that will be inherited by any elements you add to the form.
541     *
542     * <b>Note:</b> You have to call this method statically before creating a new form if you use
543     * patForm's automatic element creation feature via the {@link createForm()} method, as the
544     * default attributes cannot be set after an element has been created.
545     *
546     * @static
547     * @access    public
548     * @param    array    $attributes    The list of attributes to set with key => value pairs.
549     */
550     function setDefaultAttributes( $attributes )
551     {
552         patForms::setStaticProperty( 'defaultAttributes', $attributes );
553     }
554     
555    /**
556     * sets the locale (language) to use for the validation error messages of all elements
557     * in the form.
558     *
559     * @access    public
560     * @param    string        language code
561     * @param    string        optional language file
562     * @return    bool        True on success
563     */
564     function setLocale( $locale, $languageFile = null )
565     {
566         if (!is_null($languageFile)) {
567             $languageData   = patForms::parseLocaleFile($languageFile);
568
569             $customLocales = patForms::getStaticProperty('customLocales');
570             $customLocales[$locale] = $languageData;
571             patForms::setStaticProperty('customLocales', $customLocales);
572         }
573
574         if( isset( $this ) && is_a( $this, 'patForms' ) ) {
575             $this->locale = $locale;
576         
577             if( !empty( $this->elements ) ) {
578                 $cnt    =    count( $this->elements );
579                 for( $i=0; $i < $cnt; $i++ ) {
580                     $this->elements[$i]->setLocale( $locale );
581                 }
582             }
583         } else {
584             patForms::setStaticProperty('locale', $locale);
585         }
586         
587         return true;
588     }
589
590    /**
591     * checks, whether a locale is a custom locale
592     *
593     * @static
594     * @access    public
595     * @param    string        locale name
596     * @return    boolean
597     */
598     function isCustomLocale($locale)
599     {
600         $customLocales = patForms::getStaticProperty('customLocales');
601         if (isset($customLocales[$locale])) {
602             return true;
603         }
604         return false;
605     }
606
607    /**
608     * get the custom locale for an element or a rule
609     *
610     * @static
611     * @access    public
612     * @param    string        locale
613     * @param    string        key
614     * @return    array
615     */
616     function getCustomLocale($locale, $key)
617     {
618         $customLocales = patForms::getStaticProperty('customLocales');
619         if (!isset($customLocales[$locale])) {
620             return false;
621         }
622         if (!isset($customLocales[$locale][$key])) {
623             return false;
624         }
625         return $customLocales[$locale][$key];
626     }
627     
628    /**
629     * parses a locale file
630     *
631     * @access    private
632     * @param    string        filename
633     * @return    array        locale information
634     * @todo        add some file checks
635     */
636     function parseLocaleFile($filename)
637     {
638         return parse_ini_file($filename, true);
639     }
640     
641    /**
642     * sets the format of the element - this will be passed on to any elements you create. If you
643     * have already added some elements when you call this method, it will be passed on to them too.
644     *
645     * @access    public
646     * @param    string    $format    The name of the format you have implemented in your element(s).
647     * @return    bool    $result    True on success
648     * @see        setMode()
649     * @see        format
650     * @see        serialize()
651     */
652     function setFormat( $format )
653     {
654         if( isset( $this ) && is_a( $this, 'patForms' ) )
655         {
656             $this->format    =    strtolower( $format );
657             
658             if( !empty( $this->elements ) )
659             {
660                 $cnt    =    count( $this->elements );
661                 for( $i=0; $i < $cnt; $i++ )
662                 {
663                     $this->elements[$i]->setFormat( $format );
664                 }
665             }
666         }
667         else
668         {
669             patForms::setStaticProperty( 'format', $format );
670         }
671         
672         return true;
673     }
674     
675    /**
676     * sets the mode of the form - If you have already added some elements when you call this
677     * method, it will be passed on to them too.
678     *
679     * @access    public
680     * @param    string    $mode    The mode to set the form to: default|readonly or any other mode you have implemented in your element class(es). Default is 'default'.
681     * @see        setMode()
682     * @see        mode
683     * @see        serialize()
684     */
685     function setMode( $mode )
686     {
687         $this->mode    =    strtolower( $mode );
688
689         if( !empty( $this->elements ) )
690         {
691             $cnt    =    count( $this->elements );
692             for( $i=0; $i < $cnt; $i++ )
693             {
694                 $this->elements[$i]->setMode( $mode );
695             }
696         }
697     }
698
699    /**
700     * sets the current submitted state of the form. Set this to true if you want the form
701     * to pick up its submitted data. It will pass on this information to all elements that
702     * have been added so f