root/trunk/patForms/Element/RadioGroup.php

Revision 381, 14.4 kB (checked in by gerd, 2 years ago)

added missing initialisation of attributes (allows to apply modifier)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * simple radiobutton patForms element that builds and validates radio buttons, with the
4  * particularity that it does not generate a fully serialized element, but an array with
5  * serialized subelements.
6  *
7  * $Id$
8  *
9  * @access        protected
10  * @package        patForms
11  * @subpackage    Element
12  */
13
14 /**
15  * Error: no default value available for the element
16  */
17  define( 'PATFORMS_ERROR_RADIOGROUP_NO_DEFAULT_VALUE_AVAILABLE', 9001 );
18
19 /**
20  * simple radiobutton patForms element that builds and validates radio buttons, with the
21  * particularity that it does not generate a fully serialized element, but an array with
22  * serialized subelements.
23  *
24  * $Id$
25  *
26  * @access        protected
27  * @package        patForms
28  * @subpackage    Element
29  * @author        Sebastian Mordziol <argh@php-tools.net>
30  * @license        LGPL, see license.txt for details
31  */
32 class patForms_Element_RadioGroup extends patForms_Element
33 {
34    /**
35     * Stores the name of the element - this is used mainly by the patForms
36     * error management and should be set in every element class.
37     * @access    public
38     */
39     var $elementName    =    'RadioGroup';
40
41    /**
42     * the type of the element - set this to the type of element you are creating
43     * if you want to use the {@link patForms_Element::element2html()} method to
44     * create the final HTML tag for your element.
45     *
46     * @access    public
47     * @see        patForms_Element::element2html()
48     */
49     var $elementType    =    array(    "html"    =>    "input",
50                                 );
51
52    /**
53     * The radio element uses a renderer to serialize its content, so we set the flag
54     * to true here
55     *
56     * @access    private
57     * @var        array
58     */
59     var $usesRenderer    =    true;
60
61    /**
62     * set here which attributes you want to include in the element if you want to use
63     * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
64     * convert the values from your element definition into element attributes.
65     *
66     * @access    protected
67     * @see        patForms_Element::convertDefinition2Attribute()
68     */
69     var    $attributeDefinition    =    array(
70
71             "id"            =>    array(    "required"        =>    false,
72                                         "format"        =>    "string",
73                                         "outputFormats"    =>    array( "html" ),
74                                     ),
75             "name"            =>    array(    "required"        =>    true,
76                                         "format"        =>    "string",
77                                         "outputFormats"    =>    array( "html" ),
78                                     ),
79             "title"            =>    array(    "required"        =>    false,
80                                         "format"        =>    "string",
81                                         "outputFormats"    =>    array( "html" ),
82                                         "modifiers"        =>    array( "insertSpecials" => array() ),
83                                     ),
84             "description"    =>    array(    "required"        =>    false,
85                                         "format"        =>    "string",
86                                         "outputFormats"    =>    array(),
87                                         "modifiers"        =>    array( "insertSpecials" => array() ),
88                                     ),
89             "default"        =>    array(    "required"        =>    false,
90                                         "format"        =>    "string",
91                                         "outputFormats"    =>    array(),
92                                     ),
93             "label"            =>    array(    "required"        =>    false,
94                                         "format"        =>    "string",
95                                         "outputFormats"    =>    array(),
96                                     ),
97             "display"        =>    array(    "required"        =>    false,
98                                         "format"        =>    "string",
99                                         "default"        =>    "yes",
100                                         "outputFormats"    =>    array(),
101                                     ),
102             "edit"            =>    array(    "required"        =>    false,
103                                         "format"        =>    "string",
104                                         "default"        =>    "yes",
105                                         "outputFormats"    =>    array(),
106                                     ),
107             "required"        =>    array(    "required"        =>    false,
108                                         "format"        =>    "string",
109                                         "default"        =>    "yes",
110                                         "outputFormats"    =>    array(),
111                                     ),
112             "value"            =>    array(    "required"        =>    false,
113                                         "format"        =>    "string",
114                                         "outputFormats"    =>    array(),
115                                     ),
116             "style"            =>    array(    "required"        =>    false,
117                                         "outputFormats"    =>    array( "html" ),
118                                         "format"        =>    "string",
119                                     ),
120             "class"            =>    array(    "required"        =>    false,
121                                         "outputFormats"    =>    array( "html" ),
122                                         "format"        =>    "string",
123                                     ),
124             "onchange"        =>    array(    "required"        =>    false,
125                                         "format"        =>    "string",
126                                         "outputFormats"    =>    array( "html" ),
127                                         "modifiers"        =>    array( "insertSpecials" => array() ),
128                                     ),
129             "onclick"        =>    array(    "required"        =>    false,
130                                         "format"        =>    "string",
131                                         "outputFormats"    =>    array( "html" ),
132                                         "modifiers"        =>    array( "insertSpecials" => array() ),
133                                     ),
134             "onfocus"        =>    array(    "required"        =>    false,
135                                         "format"        =>    "string",
136                                         "outputFormats"    =>    array( "html" ),
137                                         "modifiers"        =>    array( "insertSpecials" => array() ),
138                                     ),
139             "onmouseover"    =>    array(    "required"        =>    false,
140                                         "format"        =>    "string",
141                                         "outputFormats"    =>    array( "html" ),
142                                         "modifiers"        =>    array( "insertSpecials" => array() ),
143                                     ),
144             "onmouseout"    =>    array(    "required"        =>    false,
145                                         "format"        =>    "string",
146                                         "outputFormats"    =>    array( "html" ),
147                                         "modifiers"        =>    array( "insertSpecials" => array() ),
148                                     ),
149             "onblur"        =>    array(    "required"        =>    false,
150                                         "format"        =>    "string",
151                                         "outputFormats"    =>    array( "html" ),
152                                         "modifiers"        =>    array( "insertSpecials" => array() ),
153                                     ),
154             "position"        =>    array(    "required"        =>    false,
155                                         "format"        =>    "int",
156                                         "outputFormats"    =>    array(),
157                                     ),
158             "values"        =>    array(    "required"        =>    false,
159                                         "format"        =>    "values",
160                                         "outputFormats"    =>    array(),
161                                     ),
162             "disabled"        =>    array(    "required"        =>    false,
163                                         "format"        =>    "string",
164                                         "default"        =>    "no",
165                                         "outputFormats"    =>    array( "html" ),
166                                     ),
167             "datasource"    =>    array(    "required"        =>    false,
168                                         "format"        =>    "datasource",
169                                         "outputFormats"    =>    array(),
170                                     ),
171             "clicklabel"    =>    array(    "required"        =>    false,
172                                         "format"        =>    "string",
173                                         "outputFormats"    =>    array(),
174                                     ),
175         );
176
177    /**
178     * elements of the radio group as patForms elements
179     * @var        array
180     * @access    private
181     */
182     var $elements    =    array();
183
184    /**
185     * The amount of elements in the radio group
186     * @var        int
187     * @access    private
188     */
189     var $elementCounter = 0;
190
191     /**
192      *    define error codes an messages for each form element
193      *
194      *  @access private
195      *  @var    array    $validatorErrorCodes
196      */
197     var    $validatorErrorCodes  =   array(
198         "C"    =>    array(
199             1    =>    "A choice is required, please select an option from the list.",
200             2    =>    "The value given for the element does not match any of the possible values.",
201         ),
202         "de" =>    array(
203             1    =>    "Pflichtfeld. Bitte wᅵlen Sie einen Punkt aus der Liste.",
204             2    =>    "Der angegebene Wert stimmt mit keinem der mᅵlichen Werte berein.",
205         ),
206         "fr" =>    array(
207             1    =>    "Ce champ est obligatoire. Veuillez sᅵectionner un ᅵᅵent dans la liste.",
208             2    =>    "La valeur de ce champ ne correspond ᅵaucune des valeurs admises.",
209         )
210     );
211
212    /**
213     * default value in the readonly mode
214     * @var    string
215     */
216     var    $defaultReadonlyValue  =   array(
217         "C"    =>    "No selection",
218         "de" =>    "Keine Angabe",
219         "fr" =>    "Pas de sᅵection.",
220     );
221
222    /**
223     * sets the data source for this element. If you set a data source object, the element will
224     * ignore the 'values' attribute and request the values from the data source object. The
225     * data source object only needs to implement the getValues() method.
226     *
227     * @access    public
228     * @param    object    &$dataSource    The data source to use.
229     * @see        dataSource
230     */
231     function setDataSource( &$dataSource )
232     {
233         $this->attributes["datasource"]    =&    $dataSource;
234     }
235
236    /**
237     * set the element's namespace
238     *
239     * @static
240     * @access    public
241     * @param    string        namespace
242     * @return    null
243     */
244     function setNamespace($namespace)
245     {
246         $this->namespace = $namespace;
247         $cnt = count($this->elements);
248         for ($i = 0; $i < $cnt; $i++) {
249             $this->elements[$i]->setNamespace($namespace);
250         }
251     }
252
253    /**
254     * retrieves the values to fill the list with. If a data source object has been set,
255     * tries to retrieve them from there, otherwise takes them from the 'values' attribute.
256     *
257     * @access    public
258     * @return    mixed    $values    Array with values, or false if failed.
259     * @see        setDataSource()
260     */
261     function getValues()
262     {
263         $values = array();
264
265         if( isset( $this->attributes["datasource"] ) ) {
266             if (is_object( $this->attributes["datasource"])) {
267                 $values    =    $this->attributes["datasource"]->getValues($this);
268             } else {
269                 /**
270                  * if the datasource is no object, it could
271                  * be a callback
272                  *
273                  * The element will be passed to the callback
274                  */
275                 if (is_callable( $this->attributes["datasource"], false)) {
276                     $values    = call_user_func( $this->attributes["datasource"], $this);
277                 }
278             }
279         }
280
281         if (isset($this->attributes["values"])) {
282             $values = array_merge( $this->attributes["values"], $values );
283         }
284         if (empty($values)) {
285             return patErrorManager::raiseWarning(
286                 PATFORMS_ELEMENT_WARNING_NO_VALUES,
287                 'No values set to create a RadioGroup field',
288                 'The RadioGroup element ['.$this->attributes['name'].'] has no values to create a list from'
289             );
290         }
291         return $values;
292     }
293
294    /**
295     * element creation method for the 'HTML' format in the 'default' form mode.
296     *
297     * @access    public
298     * @param    mixed    value of the element
299     * @return    mixed    $element    The element, or false if failed.
300     */
301     function serializeHtmlDefault( $value )
302     {
303         if( $this->attributes['display'] == 'no' )
304         {
305             return $this->createDisplaylessTag( $value );
306         }
307
308         $success = $this->createElementCollection( $value );
309         if( patErrorManager::isError( $success ) )
310         {
311             return $success;
312         }
313
314         // a renderer has been set, use that to generate the content.
315         if( is_object( $this->renderer ) )
316         {
317             return $this->renderer->render( $this );
318         }
319
320         // call this to initialize all attributes
321         $this->getAttributesFor( $this->getFormat() );
322
323         // no renderer set, create standard code
324         $divAtts = array(
325             'id'    =>    $this->getAttribute( 'id' ).'Container',
326         );
327
328         $html = $this->createTag( 'div', 'opening', $divAtts );
329
330         $cnt = count( $this->elements );
331         for( $i=0; $i < $cnt; $i++ )
332         {
333             $html .= '<div>'.$this->elements[$i]->serialize().' '.$this->elements[$i]->getAttribute( 'label' ).'</div>';
334         }
335
336         $html .= '</div>';
337
338         return $html;
339     }
340
341    /**
342     * Creates the element collection based on the values list of the
343     * radio group element.
344     *
345     * @access    private
346     * @return    mixed    $success    True on success, a patError object otherwise.
347     */
348     function createElementCollection( $value )
349     {
350         // don't redo it if this is called again
351         if( !empty( $this->elements ) )
352             return true;
353
354         // get the value list from which to generate the list of elements
355         $values = $this->getValues();
356         if( patErrorManager::isError( $values ) )
357         {
358             return $values;
359         }
360
361         $name = $this->getAttribute( 'name' );
362
363         foreach( $values as $line => $optionDef )
364         {
365             // compute the element id
366             if( !isset( $optionDef['id'] ) )
367             {
368                 $optionDef['id'] = $name.'el'.$this->elementCounter;
369             }
370
371             // needed additional attributes for each radio button
372             $attribs    =    array(
373                 'required'        =>    'no',
374                 'id'            =>    $optionDef['id'],
375                 'value'            =>    $optionDef['value'],
376                 'label'            =>    $optionDef['label'],
377                 'clicklabel'    =>    $this->getAttribute( 'clicklabel' ),
378             );
379
380             if ( isset( $optionDef['disabled'] ) && $optionDef['disabled'] == 'yes' )
381             {
382                 $attribs['disabled'] = 'disabled';
383             }
384
385             // add checked attribute to active subelement
386             if( !empty( $optionDef['value'] ) && $optionDef['value'] == $value )
387             {
388                 $attribs['checked']    =    'checked';
389             }
390
391             // add any additional info as attrributes if they are valid attributes
392             foreach( $this->attributeDefinition as $attribute => $def )
393             {
394                 $keys = array_keys( $optionDef );
395
396                 if( in_array( $attribute, $keys ) )
397                     $attribs[$attribute] = $optionDef[$attribute];
398             }
399
400             $this->addElement(patForms::createElement( $name, 'Radio', $attribs ));
401
402             $this->elementCounter++;
403         }
404
405         return true;
406     }
407
408    /**
409     * Gets the elements of a radiogroup.
410     *
411     * A radiogroup consists of several elements and thus can
412     * be renderered using any renderer.
413     *
414     * @access    public
415     * @return    array
416     */
417     function &getElements()
418     {
419         return $this->elements;
420     }
421
422    /**
423     * Adds a patForms element object to the radio group's element collection.
424     *
425     * @access    public
426     * @param    object    &$element    The element to add.
427     * @see        $elements
428     */
429     function addElement( &$element )
430     {
431         $element->setNamespace($this->getNamespace());
432
433         $this->elementCounter++;
434         $this->elements[] = &$element;
435     }
436
437    /**
438     * element creation method for the 'HTML' format in the 'readonly' form mode.
439     *
440     * @access    public
441     * @param    mixed    value of the element
442     * @return    string    $value    The element's value
443     */
444     function serializeHtmlReadonly( $value )
445     {
446         $values        =    $this->getValues();
447         $element    =    null;
448
449         if( patErrorManager::isError( $values ) )
450         {
451             return $values;
452         }
453
454         $tag = $this->createDisplaylessTag( $value );
455
456         if( $this->attributes['display'] == 'no' )
457         {
458             return $tag;
459         }
460
461         // empty value -> no entry selected - display the readonly
462         // default value instead.
463         if( $value === '' )
464         {
465             return $this->getReadonlyDefaultValue().$tag;
466         }
467
468         foreach( $values as $line => $optionDef )
469         {
470             if( $optionDef["value"] == $value )
471             {
472                 $element    =    $optionDef["label"];
473                 break;
474             }
475         }
476
477         if( empty( $element ) )
478         {
479             $element = $this->getReadonlyDefaultValue();
480         }
481
482         return $element.$tag;
483     }
484
485    /**
486     * Retrieves the default value to display in the element's readonly mode if the
487     * user has not selected any entry, according to the selected locale
488     *
489     * @access    public
490     * @return    string    $defaultValue    The default readonly value in the needed locale
491     */
492     function getReadonlyDefaultValue()
493     {
494         $lang    =    $this->locale;
495
496         if( !isset( $this->defaultReadonlyValue[$lang] ) )
497         {
498             patErrorManager::raiseWarning(
499                 PATFORMS_ERROR_RADIOGROUP_NO_DEFAULT_VALUE_AVAILABLE,
500                 'There is no default readonly value available for the locale "'.$lang.'", using default locale "C" instead.'
501             );
502             return $this->defaultReadonlyValue['C'];
503         }
504
505         return $this->defaultReadonlyValue[$lang];
506     }
507
508    /**
509     * validates the element.
510     *
511     * @access    public
512     * @param    mixed    value of the element
513     * @return    bool    $isValid    True if element could be validated, false otherwise.
514     */
515     function validateElement($value)
516     {
517         $values = $this