source: trunk/patForms/Element/Date.php @ 238

Revision 238, 24.7 KB checked in by sfuchs, 8 years ago (diff)
  • added initial version of patForms value namespaces
  • added method patForms::getOptionParameter()
  • added methods patForms_Element::optionEnabled(), getOptionParameters() and getOptionParameter()
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2/**
3 * patForms Date element
4 *
5 * Powerful date element with a very flexible date parser that enables
6 * very intuitive usage of date input uses.
7 *
8 * $Id$
9 *
10 * @access      public
11 * @package     patForms
12 * @subpackage  patForms_Element
13 * @author      Sebastian 'The Argh' Mordziol <argh@php-tools.net>
14 */
15
16/**
17 * Stores the path to the element's folder - needed to include the subclasses
18 */
19 define( 'PATFORMS_ELEMENT_DATE_INSTALL_DIR', dirname( __FILE__ ) );
20
21/**
22 * Notice: could not use the date set as default for the element, as it does not match
23 *         the specified date format string.
24 */
25 define( 'PATFORMS_ELEMENT_DATE_NOTICE_DATE_PARSE_ERROR', 'patForms:Element:Date:01' );
26
27/**
28 * Notice: the date string ended unexpectedly - it is too short according to the format.
29 */
30 define( 'PATFORMS_ELEMENT_DATE_NOTICE_DATE_UNEXPECTED_END', 'patForms:Element:Date:02' );
31
32/**
33 * Error: the specified date string is not a valid strtotime date string.
34 */
35 define( 'PATFORMS_ELEMENT_DATE_ERROR_INVALID_DATE_DEFINITION', 'patForms:Element:Date:04' );
36
37/**
38 * Error: the specified date string is not a valid strtotime date string.
39 */
40 define( 'PATFORMS_ELEMENT_DATE_ERROR_PEAR_DATE_NEEDED', 'patForms:Element:Date:05' );
41 @include_once 'Date.php';
42 if( !class_exists( 'Date' ) ) {
43    patErrorManager::raiseError(
44        PATFORMS_ELEMENT_DATE_ERROR_PEAR_DATE_NEEDED,
45        'Date class not found',
46        'The patForms Date element needs the PEAR::Date class to function, but it could not be found.'
47    );
48 }
49
50/**
51 * Subelement class file, always needed.
52 */
53 require_once PATFORMS_ELEMENT_DATE_INSTALL_DIR.'/Date/Element.php';
54
55/**
56 * patForms Date element
57 *
58 * Powerful date element with a very flexible date parser that enables
59 * very intuitive usage of date input uses.
60 *
61 * $Id$
62 *
63 * @access      public
64 * @package     patForms
65 * @subpackage  patForms_Element
66 * @author      Sebastian 'The Argh' Mordziol <argh@php-tools.net>
67 * @license     LGPL
68 */
69class patForms_Element_Date extends patForms_Element
70{
71   /**
72    * Stores the name of the element - this is used mainly by the patForms
73    * error management and should be set in every element class.
74    * @access   public
75    */
76    var $elementName    =   'Date';
77
78   /**
79    * set here which attributes you want to include in the element if you want to use
80    * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
81    * convert the values from your element definition into element attributes.
82    *
83    * @access   protected
84    * @see      patForms_Element::convertDefinition2Attribute()
85    */
86    var $attributeDefinition    =   array(
87
88        'id' => array(
89            'required'      =>  false,
90            'format'        =>  'string',
91            'outputFormats' =>  array( 'html' ),
92        ),
93        'name' => array(
94            'required'      =>  true,
95            'format'        =>  'string',
96            'outputFormats' =>  array( 'html' ),
97            'modifiers'     =>  array( 'insertSpecials' => array() ),
98        ),
99        'type' => array(
100            'required'      =>  false,
101            'format'        =>  'string',
102            'default'       =>  'text',
103            'outputFormats' =>  array( 'html' ),
104        ),
105        'title' => array(
106            'required'      =>  false,
107            'format'        =>  'string',
108            'outputFormats' =>  array( 'html' ),
109            'modifiers'     =>  array( 'insertSpecials' => array() ),
110        ),
111        'description' => array(
112            'required'      =>  false,
113            'format'        =>  'string',
114            'outputFormats' =>  array(),
115            'modifiers'     =>  array( 'insertSpecials' => array() ),
116        ),
117        'default' => array(
118            'required'      =>  false,
119            'format'        =>  'string',
120            'outputFormats' =>  array(),
121        ),
122        'label' => array(
123            'required'      =>  false,
124            'format'        =>  'string',
125            'outputFormats' =>  array(),
126        ),
127        'edit' => array(
128            'required'      =>  false,
129            'format'        =>  'string',
130            'default'       =>  'yes',
131            'outputFormats' =>  array(),
132        ),
133        'display' => array(
134            'required'      =>  false,
135            'format'        =>  'string',
136            'default'       =>  'yes',
137            'outputFormats' =>  array(),
138        ),
139        'required' => array(
140            'required'      =>  false,
141            'format'        =>  'string',
142            'default'       =>  'yes',
143            'outputFormats' =>  array(),
144        ),
145        'value' => array(
146            'required'      =>  false,
147            'format'        =>  'string',
148            'outputFormats' =>  array( 'html' ),
149        ),
150        'style' => array(
151            'required'      =>  false,
152            'outputFormats' =>  array( 'html' ),
153            'format'        =>  'string',
154        ),
155        'class' => array(
156            'required'      =>  false,
157            'outputFormats' =>  array( 'html' ),
158            'format'        =>  'string',
159        ),
160        'onchange' => array(
161            'required'      =>  false,
162            'format'        =>  'string',
163            'outputFormats' =>  array( 'html' ),
164            'modifiers'     =>  array( 'insertSpecials' => array() ),
165        ),
166        'onclick' => array(
167            'required'      =>  false,
168            'format'        =>  'string',
169            'outputFormats' =>  array( 'html' ),
170            'modifiers'     =>  array( 'insertSpecials' => array() ),
171        ),
172        'onfocus' => array(
173            'required'      =>  false,
174            'format'        =>  'string',
175            'outputFormats' =>  array( 'html' ),
176            'modifiers'     =>  array( 'insertSpecials' => array() ),
177        ),
178        'onmouseover' => array(
179            'required'      =>  false,
180            'format'        =>  'string',
181            'outputFormats' =>  array( 'html' ),
182            'modifiers'     =>  array( 'insertSpecials' => array() ),
183        ),
184        'onmouseout' => array(
185            'required'      =>  false,
186            'format'        =>  'string',
187            'outputFormats' =>  array( 'html' ),
188            'modifiers'     =>  array( 'insertSpecials' => array() ),
189        ),
190        'onblur' => array(
191            'required'      =>  false,
192            'format'        =>  'string',
193            'outputFormats' =>  array( 'html' ),
194            'modifiers'     =>  array( 'insertSpecials' => array() ),
195        ),
196        'accesskey' => array(
197            'required'      =>  false,
198            'format'        =>  'string',
199            'outputFormats' =>  array( 'html' ),
200        ),
201        'position' => array(
202            'required'      =>  false,
203            'format'        =>  'int',
204            'outputFormats' =>  array(),
205        ),
206        'tabindex' => array(
207            'required'      =>  false,
208            'format'        =>  'int',
209            'outputFormats' =>  array( 'html' ),
210        ),
211        'max' => array(
212            'required'      =>  false,
213            'format'        =>  'datetime',
214            'outputFormats' =>  array(),
215        ),
216        'min' => array(
217            'required'      =>  false,
218            'format'        =>  'datetime',
219            'outputFormats' =>  array(),
220        ),
221        'format' => array(
222            'required'      =>  false,
223            'format'        =>  'datetime',
224            'outputFormats' =>  array(),
225        ),
226        'dateformat' => array(
227            'required'      =>  false,
228            'format'        =>  'string',
229            'default'       =>  'Y.m.d H:i:s',
230            'outputFormats' =>  array(),
231        ),
232        'presets' => array(
233            'required'      =>  false,
234            'format'        =>  'string',
235            'default'       =>  'yes',
236            'outputFormats' =>  array(),
237        ),
238        'disabled' => array(
239            'required'      =>  false,
240            'format'        =>  'string',
241            'default'       =>  'no',
242            'outputFormats' =>  array( 'html' ),
243        ),
244        'returnformat' => array(
245            'required'      =>  false,
246            'format'        =>  'string',
247            'default'       =>  'datestring',
248            'outputFormats' =>  array(),
249        ),
250    );
251
252   /**
253    * define error codes and messages for each form element
254    *
255    * @access private
256    * @var  array   $validatorErrorCodes
257    */
258    var $validatorErrorCodes  =   array(
259        'C' =>  array(
260            1   =>  'This field is required, please complete it.',
261            2   =>  'Value must be after \'[MINDATE]\'!',
262            3   =>  'Value must be before \'[MAXDATE]\'!',
263            4   =>  'Incorrect date',
264
265        ),
266        'de' => array(
267            1   =>  'Pflichtfeld. Bitte vervollständigen Sie Ihre Angabe.',
268            2   =>  'Der Wert muss nach \'[MINDATE]\' sein.',
269            3   =>  'Der Wert muss vor \'[MAXDATE]\' sein.',
270            4   =>  'Falsches Datum',
271        ),
272        'fr' => array(
273            1   =>  'Ce champ est obligatoire.',
274            2   =>  'La date doit être après le \'[MINDATE]\'.',
275            3   =>  'La date doit être avant le \'[MAXDATE]\'.',
276            4   =>  'Date incorrecte',
277        ),
278    );
279
280   /**
281    * the type of the element - set this to the type of element you are creating
282    * if you want to use the {@link patForms_Element::element2html()} method to
283    * create the final HTML tag for your element.
284    *
285    * @access   public
286    * @see      patForms_Element::element2html()
287    */
288    var $elementType    =   array(  "html"  =>  "input" );
289
290   /**
291    * Stores a subelement counter used for the automatic ID generation for each of
292    * the date element's sub elements.
293    *
294    * @access   private
295    * @var      int
296    */
297    var $elCount = 0;
298
299   /**
300    * Stores an index of all date tokens the date element supports, and the
301    * corresponding subelement that handles the token.
302    *
303    * @access   private
304    * @var      array
305    * @see      $tokens
306    */
307    var $tokensIndex = array(
308        'Y' =>  'Year',
309        'y' =>  'Year',
310        'd' =>  'Day',
311        'j' =>  'Day',
312        'F' =>  'Month',
313        'm' =>  'Month',
314        'M' =>  'Month',
315        'n' =>  'Month',
316        'i' =>  'Minute',
317        'a' =>  'Meridiem',
318        'A' =>  'Meridiem',
319        'g' =>  'Hour',
320        'G' =>  'Hour',
321        'h' =>  'Hour',
322        'H' =>  'Hour',
323        's' =>  'Second',
324    );
325
326   /**
327    * Stores a list of date tokens for which the min and max attributes
328    * have to be set when in 'presets' mode.
329    *
330    * @access   private
331    * @var      array
332    */
333    var $minmaxTokens = array(
334        'Y',
335        'y'
336    );
337
338   /**
339    * Similar to the {@link $tokensIndex} property, only without the subelements
340    * information - only the tokens, as an indexed array so it is easier to check
341    * whether a token is available.
342    *
343    * @access   private
344    * @var      array
345    */
346    var $tokens = array();
347
348   /**
349    * Stores a list of all tokens the current date format string uses. Needed by some
350    * subelements like the Meridiem subelement to check whether the related tokens are
351    * present.
352    *
353    * @access   private
354    * @var      array
355    * @see      tokenUsed()
356    */
357    var $usedTokens = array();
358
359   /**
360    * Stores a collection of all the elements the current date format uses. Built on
361    * startup by the _init() method.
362    *
363    * @access   private
364    * @var      array
365    * @see      _init()
366    */
367    var $dateElements = array();
368
369   /**
370    * Stores all date element objects needed for the current date format string. Created
371    * automatically on startup by the _init() method.
372    *
373    * @access   private
374    * @var      array
375    * @see      _init()
376    */
377    var $elements = array();
378
379   /**
380    * Stores a list of characters contained in the date format string that will be transformed
381    * when serializing to HTML to ensure the output stays correct.
382    *
383    * @access   private
384    * @var      array
385    */
386    var $transformTable = array(
387        ' ' =>  '&#160;'
388    );
389
390   /**
391    * Stores a list of attributes that all subelements will inherit from the date element
392    *
393    * @access   private
394    * @var      array
395    */
396    var $inheritableAttributes = array(
397        'edit',
398        'display',
399        'required',
400        'style',
401        'class'
402    );
403
404   /**
405    * Stores an index of all elements for easy element name handling
406    *
407    * @access   private
408    * @var      array
409    */
410    var $elementsIndex = array();
411
412   /**
413    * Stores the current date object (the value of the element)
414    *
415    * @access   private
416    * @var      object
417    */
418    var $date = null;
419
420   /**
421    * Stores the default date object
422    *
423    * @access   private
424    * @var      object
425    */
426    var $defaultDate = null;
427
428   /**
429    * Stores the max date object
430    *
431    * @access   private
432    * @var      object
433    */
434    var $maxDate = null;
435
436   /**
437    * Stores the min date object
438    *
439    * @access   private
440    * @var      object
441    */
442    var $minDate = null;
443
444   /**
445    * Stores attributes for which there are special setter methods
446    * which need to be called. This is mainly for date attributes
447    * that need to be converted to date objects internally.
448    *
449    * @access   private
450    * @var      array
451    */
452    var $setterAttribs = array(
453        'default',
454        'max',
455        'min'
456    );
457
458   /**
459    * Runs all needed tasks that the date element needs to run - this
460    * includes parsing the date format string and generating the date
461    * subelements collection. Also sets any default values and max/min
462    * directives as required.
463    *
464    * @access   private
465    * @return   bool    $success    Always returns true. Errors occurring on parsing the default date are ignored and the default date ignored as well in that case.
466    * @see      $dateElements
467    * @see      $elements
468    */
469    function _init()
470    {
471        parent::_init();
472
473        // presets mode? check the attribute collection
474        if( $this->attributes['presets'] == 'yes' ) {
475            $this->checkMinMaxAttribs();
476        }
477
478        $this->tokens = array_keys( $this->tokensIndex );
479
480        // now parse the format string to create the
481        // elements collection. This fills the dateElements
482        // property as well as the elements property.
483        $cnt = strlen( $this->attributes["dateformat"] );
484        for( $i=0; $i < $cnt; $i++ )
485        {
486            $char = $this->attributes["dateformat"][$i];
487
488            if( in_array( $char, $this->tokens ) ){
489
490                $elementID = $this->tokensIndex[$char];
491
492                $this->elements[$elementID] =& $this->createElement( $elementID );
493                $this->elements[$elementID]->setToken( $char );
494
495                $element = array(
496                    'type'      =>  'token',
497                    'elementID' =>  $elementID,
498                );
499
500                if( !in_array( $char, $this->usedTokens ) ) {
501                    array_push( $this->usedTokens, $char );
502                }
503            } else {
504                $element = array(
505                    'type'      => 'cdata',
506                    'content'   =>  $char
507                );
508            }
509
510            array_push( $this->dateElements, $element );
511        }
512
513        $this->elementsIndex = array_keys( $this->elements );
514
515        // inherit any inheritable attributes
516        foreach( $this->inheritableAttributes as $attribute ) {
517            if( !isset( $this->attributes[$attribute] ) ) {
518                continue;
519            }
520            $this->inheritAttribute( $attribute, $this->attributes[$attribute] );
521        }
522
523        // special attributes which have their own setter methods
524        foreach( $this->setterAttribs as $attributeName ) {
525            if( isset( $this->attributes[$attributeName] ) ) {
526                $setterMethod = 'set'.ucfirst( $attributeName );
527                $this->$setterMethod( $this->attributes[$attributeName] );
528            }
529        }
530
531        // submitted state
532        foreach( $this->elementsIndex as $elementID ) {
533            $this->elements[$elementID]->setSubmitted( $this->submitted );
534        }
535
536        foreach( $this->elementsIndex as $elementID ) {
537            $this->elements[$elementID]->init();
538        }
539
540        return true;
541    }
542
543   /**
544    * Wrapper for the main element function, with added functionality to
545    * inherit the submitted state to all subelements.
546    *
547    * @access   public
548    * @param    bool    $state  True if it has been submitted, false otherwise (default).
549    */
550    function setSubmitted( $state )
551    {
552        $this->submitted = $state;
553
554        foreach( $this->elementsIndex as $elementID ) {
555            $this->elements[$elementID]->setSubmitted( $this->submitted );
556        }
557    }
558
559   /**
560    * Some date tokens require the min and max attributes to be set when
561    * in presets mode, as these dates are used to create the span with
562    * which the date selectors are filled. This method checks if all is
563    * set.
564    *
565    * @access   private
566    * @return   mixed   $success    True if OK, a patError object otherwise
567    */
568    function checkMinMaxAttribs()
569    {
570        $found = false;
571        foreach( $this->minmaxTokens as $minmaxToken ) {
572            if( strstr( $this->attributes['dateformat'], $minmaxToken ) ) {
573                $found = true;
574                break;
575            }
576        }
577
578        if( !$found ) {
579            return true;
580        }
581
582        if( !isset( $this->attributes['min'] ) ) {
583            if( !is_null( $this->defaultDate ) ) {
584                $minDate =& new Date( $this->defaultDate );
585            } else {
586                $minDate =& new Date();
587            }
588
589            $this->attributes['min'] = $minDate->getDate();
590        }
591
592        if( !isset( $this->attributes['max'] ) ) {
593            if( !is_null( $this->defaultDate ) ) {
594                $maxDate =& new Date( $this->defaultDate );
595            } else {
596                $maxDate =& new Date();
597            }
598
599            // add 5 years
600            $maxDate->addSeconds( 157680000 );
601
602            $this->attributes['max'] = $maxDate->getDate();
603        }
604
605        return true;
606    }
607
608    function setDefault( $date )
609    {
610        $this->defaultDate =& $this->getDate( $date );
611        if( patErrorManager::isError( $this->defaultDate ) ) {
612            return $this->defaultDate;
613        }
614
615        foreach( $this->elementsIndex as $elementID ) {
616            $this->elements[$elementID]->setDefault( $this->defaultDate );
617        }
618    }
619
620    function setMax( $date )
621    {
622        $this->maxDate = $this->getDate( $date );
623        if( patErrorManager::isError( $this->maxDate ) ) {
624            return $this->maxDate;
625        }
626
627        foreach( $this->elementsIndex as $elementID ) {
628            $this->elements[$elementID]->setMax( $this->maxDate );
629        }
630    }
631
632    function setMin( $date )
633    {
634        $this->minDate =& $this->getDate( $date );
635        if( patErrorManager::isError( $this->minDate ) ) {
636            return $this->minDate;
637        }
638
639        foreach( $this->elementsIndex as $elementID ) {
640            $this->elements[$elementID]->setMin( $this->minDate );
641        }
642    }
643
644   /**
645    * Converts a strtotime-compatible date string that is used to define
646    * the default date, as well as the max/min dates into a date string
647    * according to the given format so the internal date parser can handle
648    * it.
649    *
650    * @access   private
651    * @param    string  $dateElement    A date string/object
652    * @return   mixed   $date   The converted, internal parsing engine compatible date string or a patError object if failed.
653    * @todo     Under windows, the strtotime function does not return the time, only the date in its timestamp. Check a solution for this problem.
654    */
655    function &getDate( $dateElement )
656    {
657        if( !is_object( $dateElement ) ) {
658            // check if it is a strtotime-compatible date string
659            $stamp = strtotime( $dateElement );
660            if( $stamp !== -1 ) {
661                $dateElement = $stamp;
662            }
663        }
664
665        $date =& new Date( $dateElement );
666
667        // if there is no year, the date object could not convert the
668        // date string ot a valid date.
669        if( $date->getYear() == 0 ) {
670            return patErrorManager::raiseError(
671                PATFORMS_ELEMENT_DATE_ERROR_INVALID_DATE_DEFINITION,
672                'Invalid date',
673                '['.$dateElement.'] seems not to be a valid date. Please check your date syntax.'
674            );
675        }
676
677        return $date;
678    }
679
680   /**
681    * Sets the element's value. In the date element's case, this means parsing the
682    * date string or timestamp, and set the according values for all subelements.
683    *
684    * @access   public
685    * @param    string  $value  The date to set. Has to be a timestamp or strtotime compatible string
686    */
687    function setValue( $value )
688    {
689        $this->date =& $this->getDate( $value );
690        if( patErrorManager::isError( $this->date ) ) {
691            return $this->date;
692        }
693
694        foreach( $this->elementsIndex as $elementID ) {
695            $this->elements[$elementID]->setValue( $this->date );
696        }
697    }
698
699   /**
700    * Checks whether a token has been used in the current date format string.
701    * Used by some subelements to check whether the related tokens have been set
702    * or not.
703    *
704    * @access   private
705    * @param    string  $token  The token to check
706    * @return   bool    $used   True if used, false otherwise.
707    * @see      $usedTokens
708    */
709    function tokenUsed( $token )
710    {
711        if( in_array( $token, $this->usedTokens ) ) {
712            return true;
713        }
714
715        return false;
716    }
717
718   /**
719    * Creates a date subelement from the corresponding class file, instantiates and
720    * configures it, and returns it.
721    *
722    * @access   private
723    * @param    string  $role       The role of the element, i.e. its name
724    * @return   object  $element    The requested element object
725    */
726    function &createElement( $role )
727    {
728        $file = PATFORMS_ELEMENT_DATE_INSTALL_DIR.'/Date/Element/'.$role.'.php';
729        $elClassName = 'patForms_Element_Date_Element_'.$role;
730
731        $this->elCount++;
732
733        include_once $file;
734
735        $el =& new $elClassName();
736        $el->setID( $this->elCount );
737        $el->setParentName( $this->attributes['name'] );
738        $el->setParentID( $this->attributes['id'] );
739        $el->setParent( $this );
740        $el->setLocale( $this->locale );
741
742        if( $this->attributes['presets'] == 'yes' ) {
743            $el->setMode( 'presets' );
744        }
745
746        return $el;
747    }
748
749   /**
750    * element creation method for the 'HTML' format in the 'default' form mode.
751    *
752    * @access   public
753    * @param    mixed   value of the element
754    * @return   mixed   $element    The element, or false if failed.
755    */
756    function serializeHtmlDefault( $value )
757    {
758        // handle display attribute
759        if( $this->attributes['display'] == 'no' )
760        {
761            return $this->createDisplaylessTag( $value );
762        }
763
764        $content    =   '<table cellpadding="0" cellspacing="0" border="0">'
765                    .   '   <tr>';
766
767        foreach( $this->dateElements as $row => $element )
768        {
769            $content .= '<td>';
770
771            switch( $element['type'] ) {
772                case 'token':
773                    $content .= $this->elements[$element['elementID']]->serialize();
774                    break;
775
776                default:
777                    if( isset( $this->transformTable[$element['content']] ) ) {
778                        $content .= $this->transformTable[$element['content']];
779                    } else {
780                        $content .= $element['content'];
781                    }
782                    break;
783            }
784
785            $content .= '</td>';
786        }
787
788        $content    .=  '   </tr>'
789                    .   '</table>';
790
791        return $content;
792    }
793
794   /**
795    * Special implementation of the common method to gather the subelement's
796    * displayless tags and use them as displayless content.
797    *
798    * @access   private
799    * @param    mixed   $value  Unused - the value of the element
800    * @return   mixed   $content    The element content, or a patError object if failed.
801    */
802    function createDisplaylessTag( $value )
803    {
804        $content = '';
805
806        $this->inheritAttribute( 'display', 'no' );
807
808        foreach( $this->elements as $elementID => $element ) {
809            $serialized = $element->serialize();
810            if( patErrorManager::isError( $serialized ) ) {
811                return $serialized;
812            }
813
814            $content .= $serialized;
815        }
816
817        return $content;
818    }
819
820   /**
821    * Retrieves a format string for use with the date() function,
822    * in the ISO 8601 format. Use this if you are too lazy to
823    * remember it by yourself.
824    *
825    * @access   public
826    * @return   string  $formatString   The format string
827    */
828    function getISOFormat()
829    {
830        return 'Y-m-d H:i:s';
831    }
832
833   /**
834    * Makes an attribute of the date element be inherited by the subelements.
835    *
836    * @access   public
837    * @param    string  $attribute  The name of the attribute
838    * @param    mixed   $value      The value of the attribute
839    */
840    function inheritAttribute( $attribute, $value )
841    {
842        if( !in_array( $attribute, $this->inheritableAttributes ) ) {
843            return true;
844        }
845
846        foreach( $this->elementsIndex as $elementID ) {
847            $this->elements[$elementID]->inheritAttribute( $attribute, $value );
848        }
849
850        return true;
851    }
852
853   /**
854    * element creation method for the 'HTML' format in the 'readonly' form mode.
855    * Very simple; just returns the stored element value.
856    *
857    * @access   public
858    * @param    mixed   value of the element
859    * @return   string  $value  The element's value
860    * @todo     check wether the call to getAttributesFor() is needed
861    */
862    function serializeHtmlReadonly( $value )
863    {
864        $tag = $this->createDisplaylessTag( $value );
865
866        // handle display attribute
867        if( $this->attributes['display'] == 'no' )
868        {
869            return $tag;
870        }
871
872        return $value.$tag;
873    }
874
875   /**
876    * Retrieve a dte string according to the specified dateformat. Use
877    * this if you need the selected date in that format, which is
878    * otherwise solely used for layout.
879    *
880    * @access   public
881    * @return   string  $formattedDate  The formatted date
882    */
883    function getFormattedDate()
884    {
885        // resolve the current date
886        $this->resolveValue();
887
888        return date( $this->attributes['dateformat'], $this->date->getTime() );
889    }
890
891   /**
892    * resolves the scope the value of the element may be stored in, and returns it.
893    *
894    * @access   protected
895    * @see      getValue()
896    * @see      value
897    * @todo     parse element name, if it uses the array syntax
898    */
899    function resolveValue()
900    {
901        $returnformat = 'isodate';
902        if( $this->attributes['returnformat'] != $returnformat ) {
903            $returnformat = $this->attributes['returnformat'];
904        }
905
906        // resolve date object to use
907        if( is_null( $this->date ) ) {
908            if( !is_null( $this->defaultDate ) ) {
909                $this->date = $this->defaultDate;
910            } else {
911                $this->date =& new Date();
912            }
913        }
914
915        $valid = true;
916
917        // now set the needed parts of the date element
918        foreach( $this->elementsIndex as $elementID ) {
919            $methodName = $this->elements[$elementID]->setterMethod();
920            $value = $this->elements[$elementID]->getValue();
921
922            if( is_null( $value ) ) {
923                $valid = false;
924                continue;
925            }
926
927            $this->date->$methodName( $value );
928        }
929
930        if( !$valid ) {
931            $this->value = null;
932            return true;
933        }
934
935        switch( $returnformat ) {
936            case 'timestamp':
937                $this->value = $this->date->getTime();
938            break;
939
940            case 'isodate':
941            default:
942                $this->value = $this->date->getDate();
943                break;
944        }
945
946        $this->value = $this->_applyFilters( $this->value, 'in', PATFORMS_FILTER_TYPE_PHP );
947
948        return true;
949    }
950
951   /**
952    * validates the element.
953    *
954    * @access   public
955    * @param    mixed   value of the element
956    * @return   bool    $isValid    True if element could be validated, false otherwise.
957    * @todo     The required check should go through each subelement and generate an error message according to the subelement(s) that have errors
958    */
959    function validateElement( $value )
960    {
961        $required   =   false;
962
963        // store the required flag for easy access
964        if( $this->attributes['required'] == "yes" ) {
965            $required = true;
966        }
967
968        if( $required && is_null( $value ) )
969        {
970            $this->addValidationError( 1 );
971            return false;
972        }
973
974        foreach( $this->elementsIndex as $elementID ) {
975            if( !$this->elements[$elementID]->validate() ) {
976                $this->addValidationError( 4 );
977                return false;
978            }
979        }
980
981        if( !is_null( $this->minDate ) && $this->date->before( $this->minDate ) ) {
982            $this->addValidationError( 2, array( 'mindate' => $this->minDate->getDate() ) );
983        }
984
985        if( !is_null( $this->maxDate ) && $this->date->after( $this->maxDate ) ) {
986            $this->addValidationError( 3, array( 'maxdate' => $this->maxDate->getDate() ) );
987        }
988
989        // validate input
990        return true;
991    }
992
993   /**
994    * Wrapper for the normal element setAttribute method, which handles
995    * inheriting the attributes to all its children
996    *
997    * @access   public
998    * @param    string  $attributeName  The name of the attribute to add
999    * @param    string  $attributeValue The value of the attribute
1000    * @return   mixed   $success        True on success, a patError object otherwise
1001    */
1002    function setAttribute( $attributeName, $attributeValue )
1003    {
1004        // set the attribute normally
1005        $success = parent::setAttribute( $attributeName, $attributeValue );
1006        if( patErrorManager::isError( $success ) ) {
1007            return $success;
1008        }
1009
1010        // special attributes that have their own setter method
1011        if( in_array( $attributeName, $this->setterAttribs ) ) {
1012            $setterMethod = 'set'.ucfirst( $attributeName );
1013            $this->$setterMethod( $attributeValue );
1014        }
1015
1016        return $this->inheritAttribute( $attributeName, $attributeValue );
1017    }
1018
1019}
1020?>
Note: See TracBrowser for help on using the repository browser.