root/trunk/patForms/Element/Group.php

Revision 322, 15.6 kB (checked in by schst, 3 years ago)

Removed obsolete @todo (exists as ticket), ignore some generated files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * Group element that can be used as a container for elements.
4  *
5  * $Id$
6  *
7  * @package        patForms
8  * @subpackage    Element
9  */
10
11 /**
12  * Group element that can be used as a container for elements.
13  *
14  * $Id$
15  *
16  * @access        public
17  * @package        patForms
18  * @subpackage    Element
19  * @author        Stephan Schmidt <schst@php-tools.net>
20  * @license        LGPL
21  */
22 class patForms_Element_Group extends patForms_Element
23 {
24    /**
25     * Stores the name of the element - this is used mainly by the patForms
26     * error management and should be set in every element class.
27     * @access    public
28     */
29     var $elementName    =    'Group';
30
31    /**
32     * The radio element uses a renderer to serialize its content, so we set the flag
33     * to true here
34     *
35     * @access    private
36     * @var        array
37     */
38     var $usesRenderer    =    true;
39
40    /**
41     * set here which attributes you want to include in the element if you want to use
42     * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
43     * convert the values from your element definition into element attributes.
44     *
45     * @access    protected
46     * @see        patForms_Element::convertDefinition2Attribute()
47     */
48     var    $attributeDefinition    =    array(
49
50         'id' => array(
51             'required'        =>    false,
52             'format'        =>    'string',
53             'outputFormats'    =>    array( 'html' ),
54         ),
55         'name' => array(
56             'required'        =>    true,
57             'format'        =>    'string',
58             'outputFormats'    =>    array( 'html' ),
59             'modifiers'        =>    array( 'insertSpecials' => array() ),
60         ),
61         'title' => array(
62             'required'        =>    false,
63             'format'        =>    'string',
64             'outputFormats'    =>    array( 'html' ),
65             'modifiers'        =>    array( 'insertSpecials' => array() ),
66         ),
67         'description' => array(
68             'required'        =>    false,
69             'format'        =>    'string',
70             'outputFormats'    =>    array(),
71             'modifiers'        =>    array( 'insertSpecials' => array() ),
72         ),
73         'label' => array(
74             'required'        =>    false,
75             'format'        =>    'string',
76             'outputFormats'    =>    array(),
77         ),
78         'display' => array(
79             'required'        =>    false,
80             'format'        =>    'string',
81             'default'        =>    'yes',
82             'outputFormats'    =>    array(),
83         ),
84         'edit' => array(
85             'required'        =>    false,
86             'format'        =>    'string',
87             'default'        =>    'yes',
88             'outputFormats'    =>    array(),
89         ),
90         'style' => array(
91             'required'        =>    false,
92             'outputFormats'    =>    array( 'html' ),
93             'format'        =>    'string',
94         ),
95         'class' => array(
96             'required'        =>    false,
97             'outputFormats'    =>    array( 'html' ),
98             'format'        =>    'string',
99         ),
100         'position' => array(
101             'required'        =>    false,
102             'format'        =>    'int',
103             'outputFormats'    =>    array(),
104         ),
105         'disabled' => array(
106              'required'        =>    false,
107             'format'        =>    'string',
108             'default'        =>    'no',
109             'outputFormats'    =>    array( 'html' )
110         )
111     );
112
113    /**
114     * stores the element objects of this form.
115     * @access    protected
116     * @see        addElement()
117     */
118     var $elements    =    array();
119
120    /**
121     * stores a renderer
122     * @access    protected
123     * @see        setRenderer()
124     */
125     var $renderer        =    null;
126
127     /**
128      *    define error codes an messages for each form element
129      *
130      *  @access private
131      *  @var    array    $validatorErrorCodes
132      */
133     var    $validatorErrorCodes  =   array(
134                                         "C"    =>    array(
135                                                         ),
136                                         "de" =>    array(
137                                                     )
138                                         );
139
140    /**
141     * stores the current element count for this form, used to generate the ids for each element
142     * @access    protected
143     * @see        getElementId()
144     */
145     var $elementCounter    =    0;
146
147    /**
148     * flag to indicate, whether the element is a container element
149     *
150     * @access private
151     * @var    boolean
152     */
153     var $containerElement = false;
154     
155    /**
156     * sets the locale (language) to use for the validation error messages of the form.
157     *
158     * @access    public
159     * @param    string    $lang
160     * @return    bool    $result    True on success
161     * @see        $locale
162     */
163     function setLocale( $lang )
164     {
165         $this->locale = $lang;
166         $cnt = count($this->elements);
167         for ($i = 0; $i < $cnt; $i++) {
168             $this->elements[$i]->setLocale($lang);
169         }
170         return  true;
171     }
172
173    /**
174     * sets the format of the element - this defines which method will be called in your
175     * element class, along with the {@link mode} property.
176     *
177     * @access    public
178     * @param    string    $format    The name of the format you have implemented in your element(s). Default is 'html'
179     * @see        setFormat()
180     * @see        format
181     * @see        serialize()
182     */
183     function setFormat( $format )
184     {
185         $this->format = strtolower($format);
186         $cnt = count($this->elements);
187         for ($i = 0; $i < $cnt; $i++) {
188             $this->elements[$i]->setFormat($format);
189         }
190     }
191
192    /**
193     * sets the mode of the element that defines which methods will be called in your
194     * element class, along with the {@link format} property.
195     *
196     * @access    public
197     * @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'.
198     * @see        setFormat()
199     * @see        mode
200     * @see        serialize()
201     */
202     function setMode( $mode )
203     {
204         $this->mode    = strtolower( $mode );
205         $cnt = count($this->elements);
206         for ($i = 0; $i < $cnt; $i++) {
207             $this->elements[$i]->setMode($mode);
208         }
209     }
210
211    /**
212     * set the element's namespace
213     *
214     * @static
215     * @access    public
216     * @param    string        namespace
217     * @return    null
218     */
219     function setNamespace($namespace)
220     {
221         $this->namespace = $namespace;
222         $cnt = count($this->elements);
223         for ($i = 0; $i < $cnt; $i++) {
224             $this->elements[$i]->setNamespace($namespace);
225         }
226     }
227
228    /**
229     * sets a renderer object that will be used to render
230     * the form.
231     *
232     * @access    public
233     * @param    object    renderer object
234     * @see        renderForm()
235     */
236     function setRenderer( &$renderer )
237     {
238         if (!is_object($renderer)) {
239             return patErrorManager::raiseError(
240                 PATFORMS_ERROR_INVALID_RENDERER,
241                 "No patForms_Renderer object supplied"
242             );
243         }
244
245         $this->renderer = &$renderer;
246     }
247
248    /**
249     * adds an observer to the element
250     *
251     * @access    public
252     * @param    object patForms_Observer    observer
253     * @return    boolean                        currently always true
254     */
255     function attachObserver( &$observer )
256     {
257         $this->observers[] = &$observer;
258         $cnt = count($this->elements);
259         for ($i = 0; $i < $cnt; $i++) {
260             $this->elements[$i]->attachObserver($observer);
261         }
262         return true;
263     }
264
265    /**
266     * adds an element to the form - has to be a patForms_Element object. Use the {@link createElement()}
267     * method to create a new element object. Also takes care of passing on the form's configuration
268     * including the mode, format and submitted flags to the element.
269     *
270     * @access    public
271     * @param    object    &$element    The patForms_Element object to add to this form.
272     * @return    bool    $success    True if everythng went well, false otherwise.
273     * @see        patForms_Element
274     * @see        createElement()
275     */
276     function addElement(&$element)
277     {
278         if (!is_object($element)) {
279             return patErrorManager::raiseError(
280                 PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT,
281                 "Given element is not an object"
282             );
283         }
284
285         if (patErrorManager::isError($element)) {
286             return patErrorManager::raiseError(
287                 PATFORMS_ERROR_UNEXPECTED_ERROR,
288                 "Unexpected Error Object!"
289             );
290         }
291
292         if (!$element->getId()) {
293             $element->setId($this->getElementId());
294         }
295         $element->setMode($this->getMode());
296         $element->setFormat($this->getFormat());
297         $element->setSubmitted($this->getSubmitted());
298         $element->setNamespace($this->getNamespace());
299
300         $this->elements[] = &$element;
301         return true;
302     }
303
304    /**
305     * retreives a new element id, used to give each added element a unique id for this
306     * form (id can be overwritten by setting the id attribute specifically).
307     *
308     * @access    private
309     * @return    int    $elementId    The new element id.
310     */
311     function getElementId()
312     {
313         $this->elementCounter++;
314         return "pfo" . $this->getName() . $this->elementCounter;
315     }
316
317    /**
318     * element creation method for the 'HTML' format in the 'default' form mode.
319     *
320     * @access    public
321     * @param    mixed    value of the element
322     * @return    mixed    $element    The element, or false if failed.
323     */
324     function serializeHtmlDefault( $value )
325     {
326         // manage display attribute. If set, only the needed hidden
327         // elements for the subelements will be created.
328         if( $this->attributes['display'] == 'no' )
329         {
330             return $this->createDisplaylessTag( $value );
331         }
332
333         if( $this->renderer === null )
334         {
335             return patErrorManager::raiseError(
336                 PATFORMS_ERROR_NO_RENDERER_SET,
337                 "No renderer has been set."
338             );
339         }
340
341         // edit attribute is inherited by all subelements
342         if( $this->attributes['edit'] == 'no' )
343         {
344             $cnt = count( $this->elements );
345
346             for( $i=0; $i < $cnt; $i++ )
347             {
348                 $this->elements[$i]->setAttribute( 'edit', 'no' );
349             }
350         }
351
352         return $this->renderer->render( $this );
353     }
354
355    /**
356     * rewritten for the speciality of the group - creates a collection
357     * of hidden elements for all subelements of the group.
358     *
359     * @access    public
360     * @param    mixed    value of the element
361     * @return    string    $value    The element's value
362     */
363     function createDisplaylessTag( $value )
364     {
365         $this->getAttributesFor( $this->getFormat() );
366
367         $tag = '';
368         $cnt = count( $this->elements );
369
370         for( $i=0; $i < $cnt; $i++ )
371         {
372             $this->elements[$i]->setAttribute( 'display', 'no' );
373             $tag .= $this->elements[$i]->serialize();
374         }
375
376         return $tag;
377     }
378
379    /**
380     * element creation method for the 'HTML' format in the 'readonly' form mode.
381     * Very simple; just returns the stored element value.
382     *
383     * @access    public
384     * @param    mixed    value of the element
385     * @return    string    $value    The element's value
386     */
387     function serializeHtmlReadonly( $value )
388     {
389         // manage display attribute.
390         if( $this->attributes['display'] == 'no' )
391         {
392             return $this->createDisplaylessTag( $value );
393         }
394
395         return $this->renderer->render( $this );
396     }
397
398    /**
399     * validates the element.
400     *
401     * @access    public
402     * @param    mixed    value of the element
403     * @return    bool    $isValid    True if element could be validated, false otherwise.
404     */
405     function validateElement( $value )
406     {
407         $valid = true;
408
409         $cnt = count($this->elements);
410         for ($i = 0; $i < $cnt; ++$i) {
411             if (!$this->elements[$i]->validate()) {
412                 $valid = false;
413             }
414         }
415         return $valid;
416     }
417
418    /**
419     * Get an element by its name.
420     *
421     * @access    public
422     * @param    string    $name    name of the element
423     * @return    mixed            either a patForms element or an array containing patForms elements
424     * @see        getElementById()
425     */
426     function &getElementByName( $name )
427     {
428         if( $name == '__form' ) {
429             return $this;
430         }
431
432         $elements = array();
433         $cnt      = count( $this->elements );
434         for ($i = 0; $i < $cnt; $i++) {
435             if ($this->elements[$i]->getName() == $name) {
436                 $elements[]    = &$this->elements[$i];
437                 continue;
438             }
439             if (method_exists($this->elements[$i], 'getElementById')) {
440                 patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
441                 $result = &$this->elements[$i]->getElementByName($name);
442                 patErrorManager::popExpect();
443                 if (!patErrorManager::isError($result)) {
444                     if (is_array($result)) {
445                         $cnt2 = count( $result );
446                         for ($j = 0; $j < $cnt2; $j++) {
447                             $elements[]    = &$result[$j];
448                         }
449                     } else {
450                         $elements[]    = &$result;
451                     }
452                 }
453             }
454         }
455
456         switch( count( $elements ) )
457         {
458             case    0:
459                 return patErrorManager::raiseError(
460                     PATFORMS_ERROR_ELEMENT_NOT_FOUND,
461                     'Element '.$name.' could not be found.'
462                 );
463                 break;
464             case    1:
465                 return    $elements[0];
466                 break;
467             default:
468                 return    $elements;
469                 break;
470         }
471     }
472
473    /**
474     * Get an element by its id.
475     *
476     * @access    public
477     * @param    string    $id        id of the element
478     * @return    object            patForms element
479     */
480     function &getElementById( $id )
481     {
482         $cnt    =    count( $this->elements );
483         for( $i = 0; $i < $cnt; $i++ )
484         {
485             if( $this->elements[$i]->getId() == $id ) {
486                 return $this->elements[$i];
487             }
488             if (method_exists($this->elements[$i], 'getElementById')) {
489                 patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
490                 $result = &$this->elements[$i]->getElementById($id);
491                 patErrorManager::popExpect();
492                 if (!patErrorManager::isError($result)) {
493                     return $result;
494                 }
495             }
496         }
497         return patErrorManager::raiseError(
498             PATFORMS_ERROR_ELEMENT_NOT_FOUND,
499             'Element '.$name.' could not be found.'
500         );
501     }
502
503    /**
504     * Get all elements of the group
505     *
506     * @access    public
507     * @return    array    all elements of the group
508     */
509     function &getElements()
510     {
511         return    $this->elements;
512     }
513
514    /**
515     * serialize start of group
516     *
517     * @return    null
518     */
519     function serializeStart()
520     {
521         return null;
522     }
523
524    /**
525     * serialize end of group
526     *
527     * @return    null
528     */
529     function serializeEnd()
530     {
531         return null;
532     }
533
534     /**
535     * getValidationErrors
536     *
537     * @access    public
538     * @return     array    errors that occured during the validation
539     */
540     function getValidationErrors()
541     {
542         $this->validationErrors = array();
543         foreach ($this->elements as $element) {
544             $childErrors = $element->getValidationErrors();
545             $this->validationErrors = array_merge($this->validationErrors, $childErrors);
546         }
547         return parent::getValidationErrors();
548     }
549
550    /**
551     * sets the current submitted state of the element. Set this to true if you want the element
552     * to pick up its submitted data.
553     *
554     * @access    public
555     * @param    bool    $state    True if it has been submitted, false otherwise (default).
556     * @see        getSubmitted()
557     * @see        $submitted
558     */
559     function setSubmitted( $state )
560     {
561         $this->submitted = $state;
562         $cnt = count($this->elements);
563         for ($i = 0; $i < $cnt; $i++) {
564             $this->elements[$i]->setSubmitted($state);
565         }
566     }
567
568    /**
569     * retrieves the current value of the element. If none is set, will try to retrieve the
570     * value from submitted form data.
571     *
572     * @access    public
573     * @param    boolean        Determines whether the method is used from an external script
574     * @return    mixed        The value, or an empty string if none found.
575     * @see        setValue()
576     * @see        value
577     * @see        resolveValue()
578     */
579     function getValue($external = true)
580     {
581         $value = array();
582         $cnt = count($this->elements);
583         for ($i = 0; $i < $cnt; $i++) {
584             $elName = $this->elements[$i]->getName();
585             $elVal  = $this->