source: trunk/patForms/Element/Combobox.php @ 258

Revision 258, 14.0 KB checked in by sfuchs, 8 years ago (diff)

changed patForms, patForms_Element and several element subclasses to support "form-namespaces"
closing ticket #129

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2/**
3 * Combobox
4 *
5 * $Id$
6 *
7 * @access      protected
8 * @package     patForms
9 * @subpackage  Element
10 */
11
12/**
13 * Error: no default value has been set
14 */
15define( 'PATFORMS_ELEMENT_COMBO_NOTICE_NO_DEFAULT_VALUE_AVAILABLE', 'patForms:Element:Combo:01');
16
17/**
18 * Warning: no values to fill the list with
19 */
20define( 'PATFORMS_ELEMENT_Combo_WARNING_NO_VALUES', 'patForms:Element:Combo:02' );
21
22/**
23 * Combobox
24 *
25 * $Id$
26 *
27 * @access      protected
28 * @package     patForms
29 * @subpackage  Element
30 * @author      Stephan Schmidt <schst@php-tools.net>
31 * @license     LGPL, see license.txt for details
32 */
33class patForms_Element_Combobox extends patForms_Element
34{
35   /**
36    * Stores the name of the element - this is used mainly by the patForms
37    * error management and should be set in every element class.
38    * @access   public
39    */
40    var $elementName = 'Combobox';
41
42   /**
43    * javascript that will be displayed only once
44    *
45    * @access   private
46    * @var      array
47    */
48    var $globalJavascript   =   array(
49                                        'html' => null
50                                    );
51
52   /**
53    * javascript that will be displayed once per instance
54    *
55    * @access   private
56    * @var      array
57    */
58    var $instanceJavascript =   array(
59                                        'html' => "var pfe_[ELEMENT::NAME] = new pFEC_Combo( '[ELEMENT::ID]' );\n"
60                                    );
61
62   /**
63    * the type of the element - set this to the type of element you are creating
64    * if you want to use the {@link patForms_Element::element2html()} method to
65    * create the final HTML tag for your element.
66    *
67    * @access   public
68    * @see      patForms_Element::element2html()
69    */
70    var $elementType    =   array(  "html"  =>  "select",
71                                );
72
73   /**
74    * set here which attributes you want to include in the element if you want to use
75    * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
76    * convert the values from your element definition into element attributes.
77    *
78    * @access   protected
79    * @see      patForms_Element::convertDefinition2Attribute()
80    */
81    var $attributeDefinition    =   array(
82
83            'id'            =>  array(  'required'      =>  false,
84                                        'format'        =>  'string',
85                                        'outputFormats' =>  array( 'html' ),
86                                    ),
87            'name'          =>  array(  'required'      =>  true,
88                                        'format'        =>  'string',
89                                        'outputFormats' =>  array( 'html' ),
90                                    ),
91            'title'         =>  array(  'required'      =>  false,
92                                        'format'        =>  'string',
93                                        'outputFormats' =>  array( 'html' ),
94                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
95                                    ),
96            'description'   =>  array(  'required'      =>  false,
97                                        'format'        =>  'string',
98                                        'outputFormats' =>  array(),
99                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
100                                    ),
101            'default'       =>  array(  'required'      =>  false,
102                                        'format'        =>  'string',
103                                        'outputFormats' =>  array(),
104                                    ),
105            'label'         =>  array(  'required'      =>  false,
106                                        'format'        =>  'string',
107                                        'outputFormats' =>  array(),
108                                    ),
109            'display'       =>  array(  'required'      =>  false,
110                                        'format'        =>  'string',
111                                        'default'       =>  'yes',
112                                        'outputFormats' =>  array(),
113                                    ),
114            'edit'          =>  array(  'required'      =>  false,
115                                        'format'        =>  'string',
116                                        'default'       =>  'yes',
117                                        'outputFormats' =>  array(),
118                                    ),
119            'required'      =>  array(  'required'      =>  false,
120                                        'format'        =>  'string',
121                                        'default'       =>  'yes',
122                                        'outputFormats' =>  array(),
123                                    ),
124            'value'         =>  array(  'required'      =>  false,
125                                        'format'        =>  'string',
126                                        'outputFormats' =>  array(),
127                                    ),
128            'style'         =>  array(  'required'      =>  false,
129                                        'outputFormats' =>  array( 'html' ),
130                                        'format'        =>  'string',
131                                    ),
132            'class'         =>  array(  'required'      =>  false,
133                                        'outputFormats' =>  array( 'html' ),
134                                        'format'        =>  'string',
135                                    ),
136            'onchange'      =>  array(  'required'      =>  false,
137                                        'format'        =>  'string',
138                                        'outputFormats' =>  array( 'html' ),
139                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
140                                    ),
141            'onclick'       =>  array(  'required'      =>  false,
142                                        'format'        =>  'string',
143                                        'outputFormats' =>  array( 'html' ),
144                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
145                                    ),
146            'onfocus'       =>  array(  'required'      =>  false,
147                                        'format'        =>  'string',
148                                        'outputFormats' =>  array( 'html' ),
149                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
150                                    ),
151            'onmouseover'   =>  array(  'required'      =>  false,
152                                        'format'        =>  'string',
153                                        'outputFormats' =>  array( 'html' ),
154                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
155                                    ),
156            'onmouseout'    =>  array(  'required'      =>  false,
157                                        'format'        =>  'string',
158                                        'outputFormats' =>  array( 'html' ),
159                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
160                                    ),
161            'onblur'        =>  array(  'required'      =>  false,
162                                        'format'        =>  'string',
163                                        'outputFormats' =>  array( 'html' ),
164                                        'modifiers'     =>  array( 'insertSpecials' => array() ),
165                                    ),
166            'accesskey'     =>  array(  'required'      =>  false,
167                                        'format'        =>  'string',
168                                        'outputFormats' =>  array( 'html' ),
169                                    ),
170            'position'      =>  array(  'required'      =>  false,
171                                        'format'        =>  'int',
172                                        'outputFormats' =>  array(),
173                                    ),
174            'tabindex'      =>  array(  'required'      =>  false,
175                                        'format'        =>  'int',
176                                        'outputFormats' =>  array( 'html' ),
177                                    ),
178            'values'        =>  array(  'required'      =>  false,
179                                        'format'        =>  'values',
180                                        'outputFormats' =>  array(),
181                                    ),
182            'disabled'      =>  array(  'required'      =>  false,
183                                        'format'        =>  'string',
184                                        'default'       =>  'no',
185                                        'outputFormats' =>  array( 'html' ),
186                                    ),
187            'datasource'    =>  array(  'required'      =>  false,
188                                        'format'        =>  'datasource',
189                                        'outputFormats' =>  array(),
190                                    ),
191        );
192
193    /**
194     *  define error codes an messages for each form element
195     *
196     *  @access private
197     *  @var    array   $validatorErrorCodes
198     */
199    var $validatorErrorCodes  =   array(
200        "C" =>  array(
201            1   =>  "This field is required, please complete it.",
202            2   =>  "The value given for the element does not match any of the possible values.",
203        ),
204        "de" => array(
205            1   =>  "Pflichtfeld. Bitte vervollständigen Sie Ihre Angabe.",
206            2   =>  "Der angegebene Wert stimmt mit keinem der möglichen Werte überein.",
207        ),
208        "fr" => array(
209            1   =>  "Ce champ est obligatoire.",
210            2   =>  "La valeur de ce champ ne correspond à aucune des valeurs admises.",
211        )
212    );
213
214   /**
215    * Stores the value that will be displayed in readonly mode
216    * when no entry has been selected, in the available locales.
217    *
218    * @access   private
219    * @var      array
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   protected
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    * retrieves the values to fill the list with. If a data source object has been set,
251    * tries to retrieve them from there, otherwise takes them from the 'values' attribute.
252    *
253    * @access   public
254    * @return   mixed   $values Array with values, or false if failed.
255    * @see      setDataSource()
256    */
257    function getValues()
258    {
259        $values = array();
260
261        if( isset( $this->attributes["datasource"] ) )
262        {
263            if( is_object( $this->attributes["datasource"] ) )
264            {
265                $values =   $this->attributes["datasource"]->getValues();
266            }
267            else
268            {
269                /**
270                 * if the datasource is no object, it could
271                 * be a callback
272                 *
273                 * The name of the element will be passed to the callback
274                 */
275                if( is_callable( $this->attributes["datasource"], false ) )
276                {
277                    $values = call_user_func( $this->attributes["datasource"], $this->getName() );
278                }
279            }
280        }
281
282        $values = array_merge( $this->attributes["values"], $values );
283        if( empty( $values ) )
284        {
285            return patErrorManager::raiseWarning(
286                PATFORMS_ELEMENT_ENUM_WARNING_NO_VALUES,
287                'No values set to create an Enum field',
288                'The Enum element ['.$this->attributes['name'].'] has no values to create a list from'
289            );
290        }
291
292        return $values;
293    }
294
295   /**
296    * element creation method for the 'HTML' format in the 'default' form mode.
297    *
298    * @access   public
299    * @param    mixed   value of the element
300    * @return   mixed   $element    The element, or false if failed.
301    */
302    function serializeHtmlDefault( $value )
303    {
304        // handle display attribute
305        if ($this->attributes['display'] == 'no') {
306            return $this->createDisplaylessTag( $value );
307        }
308
309        if ($this->attributes['edit'] == 'no') {
310            return $this->serializeHtmlReadonly( $value );
311        }
312
313        $values = $this->getValues();
314        if (patErrorManager::isError($values)) {
315            return $values;
316        }
317
318        $attribs = $this->getAttributesFor($this->getFormat());
319        $attribs['size'] = 1;
320        $element = $this->createTag( 'select', 'opening', $attribs );
321
322        $valueInList = false;
323        foreach( $values as $line => $optionDef ) {
324            $attribs = array( "value" => $optionDef["value"] );
325
326            if ( isset( $optionDef['disabled'] ) && $optionDef['disabled'] == 'yes' ) {
327                $attribs['disabled'] = 'disabled';
328            }
329
330            if( !empty( $optionDef['value'] ) && $optionDef['value'] == $value ) {
331                $attribs['selected'] = 'selected';
332                $valueInList = true;
333            }
334            $element .= $this->createTag( 'option', 'full', $attribs, $optionDef['label'] );
335        }
336
337        $element .= $this->createTag( 'select', 'closing' );
338
339        $attribs = $this->getAttributesFor($this->getFormat());
340        $attribs['name'] .= '__free';
341        $attribs['id']   .= '__free';
342        $attribs['type'] = 'text';
343        if (!$valueInList) {
344            $attribs['value'] = $value;
345        }
346
347        $element .= $this->createTag( 'input', 'empty', $attribs );
348
349        // and return to sender...
350        return $element;
351    }
352
353   /**
354    * element creation method for the 'HTML' format in the 'readonly' form mode.
355    *
356    * @access   public
357    * @param    mixed   value of the element
358    * @return   string  $value  The element's value
359    */
360    function serializeHtmlReadonly( $value )
361    {
362        $element    =   null;
363        $values     =   $this->getValues();
364
365        if( patErrorManager::isError( $values ) )
366        {
367            return $values;
368        }
369
370        $tag = $this->createDisplaylessTag( $value );
371
372        if( $this->attributes['display'] == 'no' )
373        {
374            return $tag;
375        }
376
377        // empty value -> no entry selected - display the readonly
378        // default value instead.
379        if( $value === '' )
380        {
381            return $this->getReadonlyDefaultValue().$tag;
382        }
383
384        foreach( $values as $line => $optionDef )
385        {
386            if( $optionDef["value"] == $value )
387            {
388                $element    =   $optionDef["label"];
389                break;
390            }
391        }
392
393        if( empty( $element ) )
394        {
395            $element = $this->getReadonlyDefaultValue();
396        }
397
398        return $element.$tag;
399    }
400
401   /**
402    * Retrieves the default value to display in the element's readonly mode if the
403    * user has not selected any entry, according to the selected locale
404    *
405    * @access   public
406    * @return   string  $defaultValue   The default readonly value in the needed locale
407    */
408    function getReadonlyDefaultValue()
409    {
410        $lang   =   $this->locale;
411
412        if( !isset( $this->defaultReadonlyValue[$lang] ) )
413        {
414            patErrorManager::raiseNotice(
415                PATFORMS_ELEMENT_ENUM_NOTICE_NO_DEFAULT_VALUE_AVAILABLE,
416                'There is no default readonly value available for the locale "'.$lang.'", using default locale "C" instead.'
417            );
418
419            return $this->defaultReadonlyValue['C'];
420        }
421
422        return $this->defaultReadonlyValue[$lang];
423    }
424
425   /**
426    * validates the element.
427    *
428    * @access   public
429    * @param    mixed   value of the element
430    * @return   bool    $isValid    True if element could be validated, false otherwise.
431    */
432    function validateElement( $value )
433    {
434        $values =   $this->getValues();
435
436        if( $values === false )
437        {
438            $this->valid    =   false;
439            return false;
440        }
441
442        // required & empty
443        if( isset( $this->attributes["required"] ) && $this->attributes["required"] == "yes" && strlen( $value ) == 0 )
444        {
445            $this->addValidationError( 1 );
446            return false;
447        }
448
449        return true;
450    }
451
452   /**
453    * resolves the scope the value of the element may be stored in, and returns it.
454    *
455    * @access   protected
456    * @see      getValue()
457    * @see      value
458    * @todo     parse element name, if it uses the array syntax
459    */
460    function resolveValue()
461    {
462        $varName = $this->attributes['name'];
463
464        if($this->submitted) {
465            if ($this->value = $this->getRequestVar($_POST, $varName)) {
466                return true;
467            }
468            if ($this->value = $this->getRequestVar($_POST, $varName.'__free')) {
469                return true;
470            }
471            if ($this->value = $this->getRequestVar($_GET, $varName)) {
472                return true;
473            }
474            if ($this->value = $this->getRequestVar($_GET, $varName.'__free')) {
475                return true;
476            }
477        }
478
479        if (isset($this->attributes['default'])) {
480            $this->value = $this->attributes['default'];
481            $this->value = $this->_applyFilters( $this->value, 'in', PATFORMS_FILTER_TYPE_PHP );
482
483            return true;
484        }
485        return true;
486    }
487
488   /**
489    * create XML representation of the element
490    *
491    * This can be used when you need to store the structure
492    * of your form in flat files or create form templates that can
493    * be read by patForms_Parser at a later point.
494    *
495    * @access   public
496    * @param    string      namespace
497    * @uses     getElementName()
498    * @see      patForms_Parser
499    */
500    function toXML( $namespace = null )
501    {
502        $tagName    =   $this->getElementName();
503
504        // prepend Namespace
505        if( $namespace != null )
506        {
507            $tagName    =   "$namespace:$tagName";
508            $optName    =   "$namespace:Option";
509        }
510        else
511            $optName    =   "Option";
512
513        // get all attributes
514        $attributes =   $this->getAttributes();
515        $options = $attributes['values'];
516        unset( $attributes['values'] );
517
518        // create valid XML attributes
519        foreach( $attributes as $key => $value )
520        {
521            $attributes[$key]   =   strtr( $value, $this->xmlEntities );
522        }
523
524        $tag = $this->createTag( $tagName, "opening", $attributes );
525        foreach( $options as $opt)
526        {
527            $tag .= $this->createTag( $optName, "empty", $opt );
528        }
529        $tag .= $this->createTag( $tagName, "closing" );
530
531        return $tag;
532    }
533}
534?>
Note: See TracBrowser for help on using the repository browser.