source: trunk/patForms/Element/RadioGroup.php @ 261

Revision 261, 14.6 KB checked in by sfuchs, 8 years ago (diff)

minor fixes to the new namespace stuff

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