root/trunk/patForms/Element.php

Revision 396, 56.4 kB (checked in by axel, 1 year ago)

Changed the way to calcualte the strlen. If the mb_strlen function is available, this will be used to calcuatle the length.

Added minlength and maxlength in string element example.

Now the patForms_Element_String and patForms_Element_Text classes are using the new way to calcualte the string length.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * base patForms element class with all needed base functionality that each element
4  * should have.
5  *
6  * $Id$
7  *
8  * @package        patForms
9  * @subpackage    Element
10  * @access        protected
11  * @author        Sebastian Mordziol <argh@php-tools.net>
12  * @author        gERD Schaufelberger <gerd@php-tools.net>
13  * @author        Stephan Schmidt <schst@php-tools.net>
14  */
15
16 /**
17  * error definition: the attribute that was set is not supported by this element (it is
18  * not listed in the attributeDefinition property set in the element class).
19  * @see    patForms_Element::attributeDefinition
20  */
21 define( "PATFORMS_ELEMENT_NOTICE_ATTRIBUTE_NOT_SUPPORTED", 1101 );
22
23 /**
24  * error definition: the setAttributes() method expects an array,
25  * but given value was not.
26  * @see    patForms_Element::setAttributes()
27  */
28 define( "PATFORMS_ELEMENT_ERROR_ARRAY_EXPECTED", 1102 );
29
30 /**
31  * error definition: the given attribute could not be set
32  */
33 define( "PATFORMS_ELEMENT_ERROR_ADDING_ATTRIBUTE_FAILED", 1103 );
34
35 /**
36  * error definition: the element method to serialize the element in the given mode is
37  * not implemented.
38  * @see    patForms_Element::serialize()
39  */
40 define( "PATFORMS_ELEMENT_ERROR_METHOD_FOR_MODE_NOT_AVAILABLE", 1104 );
41
42 /**
43  * error definition: the element returned an error
44  */
45 define( "PATFORMS_ELEMENT_ERROR_ERROR_RETURNED", 1105 );
46
47 /**
48  * error definition: the modifier that was set for the element is not an array.
49  * @see    patForms_Element::_applyModifiers()
50  */
51 define( "PATFORMS_ELEMENT_ERROR_MODIFIER_NOT_AN_ARRAY", 1107 );
52
53 /**
54  * error definition: the method for the given modifier does not exist
55  * @see    patForms_Element::_applyModifiers()
56  */
57 define( "PATFORMS_ELEMENT_ERROR_METHOD_FOR_MODIFIER_NOT_FOUND", 1108 );
58
59 /**
60  * error definition: the modifier returned an error, modifications could not be made.
61  * @see    patForms_Element::_applyModifiers()
62  */
63 define( "PATFORMS_ELEMENT_ERROR_MODIFIER_RETURNED_ERROR", 1109 );
64
65 /**
66  * error definition: the given attribute is required for the specified output format.
67  * @see    patForms_Element::getAttributesFor()
68  */
69 define( "PATFORMS_ELEMENT_ERROR_ATTRIBUTE_REQUIRED", 1110 );
70
71 /**
72  * error definition: given modifier could not be applied to specified attribute
73  * @see    patForms_Element::getAttributesFor()
74  */
75 define( "PATFORMS_ELEMENT_ERROR_UNABLE_TO_APPLY_MODIFIER_TO_ATTRIBUTE", 1111 );
76
77 /**
78  * error definition: the given attribute is not available for output in the specified
79  * output format.
80  * @see    patForms_Element::getAttributesFor()
81  */
82 define( "PATFORMS_ELEMENT_ERROR_ATTRIBUTE_NOT_AVAILABLE_FOR_OUTPUT", 1112 );
83
84 /**
85  * error definition: format of the attribute could not be verified
86  * @see    patForms_Element::getAttributesFor()
87  */
88 define( "PATFORMS_ELEMENT_ERROR_CAN_NOT_VERIFY_FORMAT", 1113 );
89
90 /**
91  * error definition: the attribute collection of the element could not be validated.
92  * @see patForms_Element::toHtml()
93  */
94 define( "PATFORMS_ELEMENT_ERROR_CAN_NOT_VALIDATE_ATTRIBUTE_COLLECTION", 1114 );
95
96 /**
97  * error definition: validator undefined
98  */
99 define( "PATFORMS_ELEMENT_ERROR_VALIDATOR_ERROR_UNDEFINED", 1115 );
100
101 /**
102  * error definition: undefined locale for errors output
103  */
104 define( "PATFORMS_ELEMENT_ERROR_VALIDATOR_ERROR_LOCALE_UNDEFINED", 1116 );
105
106 /**
107  * error definition: the html source for the element could not be generated.
108  */
109 define( "PATFORMS_ELEMENT_ERROR_NO_HTML_CONTENT", 1221 );
110
111 /**
112  * error definition: not a valid renderer
113  */
114 define( 'PATFORMS_ELEMENT_ERROR_INVALID_RENDERER', 1222 );
115
116 /**
117  * error definition: this element does not support the use of a renderer
118  */
119 define( 'PATFORMS_ELEMENT_RENDERER_NOT_SUPPORTED', 1223 );
120
121 /**
122  * no values supplied
123  */
124 define('PATFORMS_ELEMENT_WARNING_NO_VALUES',1224);
125
126 /**
127  * error definition: this element type can't be converted to another type
128  */
129 define( 'PATFORMS_ELEMENT_ERROR_TYPE_NOT_CONVERTABLE', 1224 );
130
131 /**
132  * error definition: this element value can't be converted to the requested element type
133  */
134 define( 'PATFORMS_ELEMENT_ERROR_VALUE_NOT_CONVERTABLE', 1225 );
135
136 /**
137  * The filter is invalid
138  */
139 define('PATFORMS_ELEMENT_ERROR_FILTER_INVALID', 1300);
140
141 /**
142  * filter is located between patForms and browser
143  */
144 define( 'PATFORMS_FILTER_TYPE_HTTP', 1 );
145
146 /**
147  * filter is located between patForms and the PHP script
148  */
149 define( 'PATFORMS_FILTER_TYPE_PHP', 2 );
150
151
152
153 /**
154  * base patForms element class with all needed base functionality that each element
155  * should have. Extend this class to create your own elements.
156  *
157  * $Id$
158  *
159  * @abstract
160  * @package        patForms
161  * @subpackage    Element
162  * @access        protected
163  * @author        Sebastian Mordziol <argh@php-tools.net>
164  * @author        gERD Schaufelberger <gerd@php-tools.net>
165  * @author        Stephan Schmidt <schst@php-tools.net>
166  * @license        LGPL, see license.txt for details
167  * @link        http://www.php-tools.net
168  */
169 class patForms_Element
170 {
171    /**
172     * the type of the element, set this in your element class!
173     * @access    protected
174     */
175     var $elementType    =    false;
176
177    /**
178     * javascript that will be displayed only once
179     *
180     * @access    private
181     * @var        array
182     */
183     var $globalJavascript    =    array();
184
185    /**
186     * javascript that will be displayed once per instance
187     *
188     * @access    private
189     * @var        array
190     */
191     var $instanceJavascript    =    array();
192
193    /**
194     * the value of the element
195     * @access    protected
196     */
197     var $value        =    false;
198
199    /**
200     * filters that have been applied
201     * @access    private
202     */
203     var $filters    =    array();
204
205    /**
206     * attribute filters that have been applied
207     * @access   protected
208     */
209     var $attributeFilters    =   array();
210
211    /**
212     * observers that have been attached
213     *
214     * @access    private
215     * @var        array
216     */
217     var $observers    =    array();
218
219    /**
220     * The elementName for the serialized version of the element
221     *
222     * This is needed for the toXML() method and also by the patForms
223     * error management. If it is not set, the element name will be
224     * created by extracting everything after the last underscore in
225     * the classname.
226     *
227     * @access    protected
228     * @see        toXML()
229     */
230     var $elementName    =    null;
231
232    /**
233     * the attribute collection of the element
234     * @access    private
235     * @see        setAttribute()
236     * @see        setAttributes()
237     * @see        getAttribute()
238     * @see        getAttributes()
239     */
240     var $attributes    =    array();
241
242    /**
243     * the configuration for the attributes supported by the element. Overwrite this
244     * in your element class.
245     *
246     * @abstract
247     */
248     var $attributeDefinition    =    array();
249
250    /**
251     * Stores the attribute defaults for the element, that will be used
252     * if the given attributes have not been set by the user.
253     *
254     * @abstract
255     * @access    private
256     * @see        getAttributeDefaults()
257     */
258     var $attributeDefaults    =    array();
259
260    /**
261     * stores the mode for the element. It defaults to 'default', and is only overwritten if
262     * set specifically.
263     *
264     * @access    protected
265     * @see        setMode()
266     */
267     var $mode    =    "default";
268
269    /**
270     * stores the format for the element. It defaults to 'html', and is only overwritten if
271     * set specifically.
272     *
273     * @access    protected
274     * @see        setFormat()
275     */
276     var $format    =    "html";
277
278    /**
279     * stores the locale to use when adding validation errors. The specified locale has
280     * to be set in the validationErrorCodes element class property, otherwise the default
281     * 'C' (as in the programming language C => english) will be used.
282     *
283     * @access    private
284     * @var        string    $locale
285     * @see        setLocale()
286     */
287     var    $locale   =   "C";
288
289    /**
290     * the form's namespace
291     *
292     * @access    private
293     * @var        string
294     */
295     var    $namespace = '';
296
297    /**
298     * stores the flag telling the element whether it has been submitted - this is used by the
299     * getValue() method to determine where to get the element's value from.
300     * @access    protected
301     * @see        getValue()
302     */
303     var $submitted    =    false;
304
305    /**
306     * stores the flag whether the element is valid
307     * @access    protected
308     */
309     var $valid    =    true;
310
311    /**
312     * stores any validation errors that can occurr during the element's validation process.
313     *
314     * @access    private
315     * @var        array    $validationErrors
316     */
317     var    $validationErrors  =   array();
318
319    /**
320     * define error codes an messages for each form element
321     *
322     * @access    protected
323     * @var        array    $validatorErrorCodes
324     */
325     var    $validatorErrorCodes  =   array();
326
327    /**
328     * defines the starting character for the modifier placeholders that can be inserted
329     * in the attributes listed as having modifier support.
330     *
331     * @access    private
332     * @var        string    $modifierStart
333     */
334     var $modifierStart    =    "[";
335
336    /**
337     * defines the starting character for the modifier placeholders that can be inserted
338     * in the attributes listed as having modifier support.
339     *
340     * @access    private
341     * @var        string    $modifierStart
342     */
343     var $modifierEnd    =    "]";
344
345    /**
346     * XML entities
347     *
348     * @access    protected
349     * @see        toXML()
350     */
351     var $xmlEntities    =    array(
352                                     "<"    =>    "&lt;",
353                                     ">"    =>    "&gt;",
354                                     "&"    =>    "&amp;",
355                                     "'"    =>    "&apos;",
356                                     '"'    =>    "&quot;"
357                                 );
358    /**
359     * shortcur to the session variables
360     * If "false", no session will be used, otherwise it stores the session variables for this element
361     *
362     * @access private
363     * @var    mixed    $sessionVar
364     */
365     var    $sessionVar = false;
366
367    /**
368     * custom validation rules
369     *
370     * @access    private
371     * @var        array
372     */
373     var $_rules            =    array();
374
375    /**
376     * next error offset for rules
377     * @access    private
378     * @var        integer
379     */
380     var $nextErrorOffset    =    1000;
381
382    /**
383     * stores whether the element uses a renderer to serialize its content
384     * @access    private
385     * @var        bool
386     */
387     var $usesRenderer        =    false;
388
389    /**
390     * Stores the renderer object that can be set via the setRenderer method
391     * @access    private
392     * @var        object
393     */
394     var $renderer            =    false;
395
396    /**
397     * Stores all element options
398     * @access    private
399     */
400     var $options    =    array();
401
402    /**
403     * flag to indicate, whether the element is a container element
404     *
405     * @access protected
406     * @var    boolean
407     */
408     var $containerElement = false;
409
410    /**
411     * id of the last rule that has been added using the format attribute
412     *
413     * @access protected
414     * @var    string
415     */
416     var $_formatRuleId = null;
417
418    /**
419     * contains the function name for calculating strlen of a string.
420     * Maybe mb_strlen is available so this will be used instead.
421     *
422     * @access protected
423     * @var    string
424     */
425     var $_lenFunc = 'strlen';
426
427    /**
428     * constructor - extend this in your class if you need to do specific operations
429     * on startup. In that case, however, don't forget to call this constructor anyway
430     * so that the thing happening here don't get lost.
431     *
432     * That's easy to do... just add the following line in your constructor:
433     * parent::patForms_Element();
434     *
435     * @access    public
436     * @param    mixed    $mode    Optional: the output format, e.g. 'html'
437     */
438     function __construct( $format = false )
439     {
440         if ($format !== false) {
441             $this->format = $format;
442         }
443
444         if (function_exists('mb_strlen')){
445             $this->_lenFunc = 'mb_strlen';
446         }
447
448         $this->loadAttributeDefaults();
449     }
450
451     /**
452      *    patForms_Element    constructor for php4
453      *
454      *    @access    private
455      *    @param    integer    $id
456      *    @return boolean $result    true on success
457      *    @see    __construct
458      */
459     function patForms_Element( $format = false )
460     {
461         $this->__construct( $format );
462     }
463
464    /**
465     * Add any initialization routines for your element in your element class,
466     * for everythig your element needs to do after it has been instantiated and
467     * the attribute collection has been created.
468     *
469     * @abstract
470     * @access    private
471     * @return    mixed    $success    True on success, a patError object otherwise
472     */
473     function _init()
474     {
475         // your code here
476         return true;
477     }
478
479    /**
480     * sets the format of the element - this defines which method will be called in your
481     * element class, along with the {@link mode} property.
482     *
483     * @access    public
484     * @param    string    $format    The name of the format you have implemented in your element(s). Default is 'html'
485     * @see        setFormat()
486     * @see        format
487     * @see        serialize()
488     */
489     function setFormat($format)
490     {
491         $this->format = strtolower($format);
492     }
493
494    /**
495     * sets the mode of the element that defines which methods will be called in your
496     * element class, along with the {@link format} property.
497     *
498     * @access    public
499     * @param    string    $mode    The mode to set the element to: default|readonly or any other mode you have implemented in your element class(es). Default is 'default'.
500     * @see        setFormat()
501     * @see        mode
502     * @see        serialize()
503     */
504     function setMode( $mode )
505     {
506         $this->mode    =    strtolower( $mode );
507     }
508
509    /**
510     * sets the locale (language) to use for the validation error messages of the form.
511     *
512     * @access    public
513     * @param    string    $lang
514     * @return    bool    $result    True on success
515     * @see        $locale
516     */
517     function setLocale( $lang )
518     {
519         $this->locale = $lang;
520
521         // check, whether this is a custom locale
522         if (patForms::isCustomLocale($lang)) {
523             $errorMessages = patForms::getCustomLocale($lang, 'Element::' . $this->elementName);
524             if (is_array($errorMessages)) {
525                 $this->validatorErrorCodes[$lang] = $errorMessages;
526             }
527         }
528
529         return  true;
530     }
531
532    /**
533     * get the element's namespace
534     *
535     * @access    public
536     * @param    string        namespace
537     * @return    string
538     */
539     function getNamespace()
540     {
541         return $this->namespace;
542     }
543
544    /**
545     * set the element's namespace
546     *
547     * @access    public
548     * @param    string        namespace
549     * @return    null
550     */
551     function setNamespace($namespace)
552     {
553         $this->namespace = $namespace;
554     }
555
556    /**
557     * sets the value of the element, which will be used to fill the element with. If none is
558     * set and the element needs a value, it will load it using the {@link resolveValue()} method.
559     *
560     * This will override user input.
561     *
562     * @access    public
563     * @param    mixed    $value    The value to set
564     * @see        $value
565     * @see        resolveValue()
566     * @see        getValue()
567     */
568     function setValue($value)
569     {
570         $value = $this->_applyFilters($value, 'in', PATFORMS_FILTER_TYPE_PHP);
571         $this->value = $value;
572     }
573
574    /**
575     * sets the default value of the element, which will be used to fill the element with.
576     *
577     * @access    public
578     * @param    mixed    $value    The value to set
579     * @see        $value
580     * @see        resolveValue()
581     * @see        setValue()
582     * @see        getValue()
583     */
584     function setDefaultValue($value)
585     {
586         $value = $this->_applyFilters($value, 'in', PATFORMS_FILTER_TYPE_PHP);
587         $this->setAttribute('default', $value);
588     }
589
590    /**
591     * sets the current submitted state of the element. Set this to true if you want the element
592     * to pick up its submitted data.
593     *
594     * @access    public
595     * @param    bool    $state    True if it has been submitted, false otherwise (default).
596     * @see        getSubmitted()
597     * @see        $submitted
598     */
599     function setSubmitted( $state )
600     {
601         $this->submitted    =    $state;
602     }
603
604    /**
605     * sets the internal ID of the element - this is only used by the {@link patForms} class to
606     * give each element a unique ID that will be added as ID attribute to each element if the
607     * id attribute has not been defined.
608     *
609     * @access    public
610     * @param    string    $id    The id to set for the element
611     * @see        getId()
612     */
613     function setId( $id )
614     {
615         $this->attributes['id']    =    $id;
616     }
617
618    /**
619     * gets the internal ID of the element
620     *
621     * @access    public
622     * @return    string    $id    The id to set for the element
623     * @see        setId()
624     */
625     function getId()
626     {
627         return $this->getAttribute( 'id' );
628     }
629
630    /**
631     * checks whether a given attribute is supported by this element.
632     *
633     * @access    public
634     * @param    string    $attributeName    The name of the attribute to check
635     * @return    bool    $hasAttribute    True if it supports the attribute, false otherwise.
636     */
637     function hasAttribute( $attributeName )
638     {
639         if( isset( $this->attributeDefinition[$attributeName] ) )
640         {
641             return true;
642         }
643
644         return false;
645     }
646
647    /**
648     * adds an attribute to the element's attribut3 collection. If the attribute
649     * already exists, it is overwritten.
650     *
651     * @access    public
652     * @param    string    $attributeName    The name of the attribute to add
653     * @param    string    $attributeValue    The value of the attribute
654     * @return    mixed    $success        True on success, a patError object otherwise
655     */
656     function setAttribute( $attributeName, $attributeValue )
657     {
658         if (!isset($this->attributeDefinition[$attributeName])) {
659             return patErrorManager::raiseNotice(
660                 PATFORMS_ELEMENT_NOTICE_ATTRIBUTE_NOT_SUPPORTED,
661                 'Unknown attribute ['.$attributeName.']',
662                 'Ignored the attribute as the ['.$this->elementName.'] element does not support it.'
663             );
664         }
665
666         if (isset($this->attributeDefinition[$attributeName]['setter'])) {
667             $setter = $this->attributeDefinition[$attributeName]['setter'];
668             call_user_func_array(array(&$this, $setter), array($attributeValue));
669         } else {
670             $result =   $this->_applyAttributeFilters( $attributeName, $attributeValue, 'set');
671             if (patErrorManager::isError($result)) {
672                 return $result;
673             }
674             $this->attributes[$attributeName] = $attributeValue;
675         }
676         return true;
677     }
678
679    /**
680     * adds several attribute at once to the element's attributes collection.
681     * Any existing attributes will be overwritten.
682     *
683     * @access    public
684     * @param    array    $attributes    The attributes to add
685     * @return    mixed    $success    True on success, false otherwise
686     */
687     function setAttributes($attributes)
688     {
689         if (!is_array($attributes)) {
690             return patErrorManager::raiseError(
691                 PATFORMS_ELEMENT_ERROR_ARRAY_EXPECTED,
692                 "Not an array given (setAttributes)"
693             );
694         }
695
696         foreach ($attributes as $attributeName => $attributeValue) {
697             $this->setAttribute($attributeName, $attributeValue);
698         }
699
700         return true;
701     }
702
703    /**
704     * set the value format of the element
705     *
706     * @access public
707     * @param  string    format (=rule) used for validation
708     */
709     function setValueFormat($format)
710     {
711         // remove the previously set rule
712         if ($this->_formatRuleId !== null) {
713             $this->removeRule($this->_formatRuleId);
714         }
715
716         switch (strtolower($format)) {
717             case 'email':
718                 $ruleName = 'Email';
719                 break;
720             case 'url':
721                 $ruleName = 'URL';
722                 break;
723             default:
724                 $ruleName = $format;
725                 break;
726         }
727
728         $rule = &patForms::createRule($ruleName);
729         $this->addRule($rule, PATFORMS_RULE_AFTER_VALIDATION);
730         $this->attributes['format'] = $rule->getRuleName