Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/bennu/iCalendar_components.php
Go to the documentation of this file.
00001 <?php
00002 
00015 class iCalendar_component {
00016     var $name             = NULL;
00017     var $properties       = NULL;
00018     var $components       = NULL;
00019     var $valid_properties = NULL;
00020     var $valid_components = NULL;
00025     var $parser_errors = NULL;
00026 
00027     function __construct() {
00028         // Initialize the components array
00029         if(empty($this->components)) {
00030             $this->components = array();
00031             foreach($this->valid_components as $name) {
00032                 $this->components[$name] = array();
00033             }
00034         }
00035     }
00036 
00037     function get_name() {
00038         return $this->name;
00039     }
00040 
00041     function add_property($name, $value = NULL, $parameters = NULL) {
00042 
00043         // Uppercase first of all
00044         $name = strtoupper($name);
00045 
00046         // Are we trying to add a valid property?
00047         $xname = false;
00048         if(!isset($this->valid_properties[$name])) {
00049             // If not, is it an x-name as per RFC 2445?
00050             if(!rfc2445_is_xname($name)) {
00051                 return false;
00052             }
00053             // Since this is an xname, all components are supposed to allow this property
00054             $xname = true;
00055         }
00056 
00057         // Create a property object of the correct class
00058         if($xname) {
00059             $property = new iCalendar_property_x;
00060             $property->set_name($name);
00061         }
00062         else {
00063             $classname = 'iCalendar_property_'.strtolower(str_replace('-', '_', $name));
00064             $property = new $classname;
00065         }
00066 
00067         // If $value is NULL, then this property must define a default value.
00068         if($value === NULL) {
00069             $value = $property->default_value();
00070             if($value === NULL) {
00071                 return false;
00072             }
00073         }
00074 
00075         // Set this property's parent component to ourselves, because some
00076         // properties behave differently according to what component they apply to.
00077         $property->set_parent_component($this->name);
00078 
00079         // Set parameters before value; this helps with some properties which
00080         // accept a VALUE parameter, and thus change their default value type.
00081 
00082         // The parameters must be valid according to property specifications
00083         if(!empty($parameters)) {
00084             foreach($parameters as $paramname => $paramvalue) {
00085                 if(!$property->set_parameter($paramname, $paramvalue)) {
00086                     return false;
00087                 }
00088             }
00089 
00090             // Some parameters interact among themselves (e.g. ENCODING and VALUE)
00091             // so make sure that after the dust settles, these invariants hold true
00092             if(!$property->invariant_holds()) {
00093                 return false;
00094             }
00095         }
00096 
00097         // $value MUST be valid according to the property data type
00098         if(!$property->set_value($value)) {
00099             return false;
00100         }
00101 
00102         // Check if the property already exists, and is limited to one occurrance,
00103         // DON'T overwrite the value - this can be done explicity with set_value() instead.
00104         if(!$xname && $this->valid_properties[$name] & RFC2445_ONCE && isset($this->properties[$name])) {
00105             return false;
00106         } 
00107                 else {
00108              // Otherwise add it to the instance array for this property
00109             $this->properties[$name][] = $property;
00110         }
00111 
00112         // Finally: after all these, does the component invariant hold?
00113         if(!$this->invariant_holds()) {
00114             // If not, completely undo the property addition
00115             array_pop($this->properties[$name]);
00116             if(empty($this->properties[$name])) {
00117                 unset($this->properties[$name]);
00118             }
00119             return false;
00120         }
00121 
00122         return true;        
00123         
00124     }
00125 
00126     function add_component($component) {
00127 
00128         // With the detailed interface, you can add only components with this function
00129         if(!is_object($component) || !is_subclass_of($component, 'iCalendar_component')) {
00130             return false;
00131         }
00132 
00133         $name = $component->get_name();
00134 
00135         // Only valid components as specified by this component are allowed
00136         if(!in_array($name, $this->valid_components)) {
00137             return false;
00138         }
00139 
00140         // Add it
00141         $this->components[$name][] = $component;
00142 
00143         return true;
00144     }
00145 
00146     function get_property_list($name) {
00147     }
00148 
00149     function invariant_holds() {
00150         return true;
00151     }
00152 
00153     function is_valid() {
00154         // If we have any child components, check that they are all valid
00155         if(!empty($this->components)) {
00156             foreach($this->components as $component => $instances) {
00157                 foreach($instances as $number => $instance) {
00158                     if(!$instance->is_valid()) {
00159                         return false;
00160                     }
00161                 }
00162             }
00163         }
00164 
00165         // Finally, check the valid property list for any mandatory properties
00166         // that have not been set and do not have a default value
00167         foreach($this->valid_properties as $property => $propdata) {
00168             if(($propdata & RFC2445_REQUIRED) && empty($this->properties[$property])) {
00169                 $classname = 'iCalendar_property_'.strtolower(str_replace('-', '_', $property));
00170                 $object    = new $classname;
00171                 if($object->default_value() === NULL) {
00172                     return false;
00173                 }
00174                 unset($object);
00175             }
00176         }
00177 
00178         return true;
00179     }
00180     
00181     function serialize() {
00182         // Check for validity of the object
00183         if(!$this->is_valid()) {
00184             return false;
00185         }
00186 
00187         // Maybe the object is valid, but there are some required properties that
00188         // have not been given explicit values. In that case, set them to defaults.
00189         foreach($this->valid_properties as $property => $propdata) {
00190             if(($propdata & RFC2445_REQUIRED) && empty($this->properties[$property])) {
00191                 $this->add_property($property);
00192             }
00193         }
00194 
00195         // Start tag
00196         $string = rfc2445_fold('BEGIN:'.$this->name) . RFC2445_CRLF;
00197 
00198         // List of properties
00199         if(!empty($this->properties)) {
00200             foreach($this->properties as $name => $properties) {
00201                 foreach($properties as $property) {
00202                     $string .= $property->serialize();
00203                 }
00204             }
00205         }
00206 
00207         // List of components
00208         if(!empty($this->components)) {
00209             foreach($this->components as $name => $components) {
00210                 foreach($components as $component) {
00211                     $string .= $component->serialize();
00212                 }
00213             }
00214         }
00215 
00216         // End tag
00217         $string .= rfc2445_fold('END:'.$this->name) . RFC2445_CRLF;
00218 
00219         return $string;
00220     }
00221     
00233     function unserialize($string) {
00234         $string = rfc2445_unfold($string); // Unfold any long lines
00235         $lines = explode(RFC2445_CRLF, $string); // Create an array of lines
00236         
00237         $components = array(); // Initialise a stack of components
00238         $this->clear_errors();
00239         foreach ($lines as $key => $line) {
00240             // ignore empty lines
00241             if (trim($line) == '') {
00242                 continue;
00243             }
00244 
00245             // Divide the line up into label, parameters and data fields.
00246             if (!preg_match('#^(?P<label>[-[:alnum:]]+)(?P<params>(?:;(?:(?:[-[:alnum:]]+)=(?:[^[:cntrl:]";:,]+|"[^[:cntrl:]"]+")))*):(?P<data>.*)$#', $line, $match)) {
00247                 $this->parser_error('Invalid line: '.$key.', ignoring');
00248                 continue;
00249             }
00250 
00251             // parse parameters
00252             $params = array();
00253             if (preg_match_all('#;(?P<param>[-[:alnum:]]+)=(?P<value>[^[:cntrl:]";:,]+|"[^[:cntrl:]"]+")#', $match['params'], $pmatch)) {
00254                 $params = array_combine($pmatch['param'], $pmatch['value']);
00255             } 
00256             $label = $match['label'];
00257             $data  = $match['data'];
00258             unset($match, $pmatch);
00259 
00260             if ($label == 'BEGIN') {
00261                 // This is the start of a component.
00262                 $current_component = array_pop($components); // Get the current component off the stack so we can check its valid components
00263                 if ($current_component == null) { // If there's nothing on the stack
00264                     $current_component = $this; // use the iCalendar
00265                 }
00266                 if (in_array($data, $current_component->valid_components)) { // Check that the new component is a valid subcomponent of the current one
00267                     if($current_component != $this) {
00268                         array_push($components, $current_component); // We're done with the current component, put it back on the stack.
00269                     }
00270                     if(strpos($data, 'V') === 0) {
00271                         $data = substr($data, 1);
00272                     }
00273                     $cname = 'iCalendar_' . strtolower($data);
00274                     $new_component = new $cname;
00275                     array_push($components, $new_component); // Push a new component onto the stack
00276                 } else {
00277                     if($current_component != $this) {
00278                         array_push($components, $current_component);
00279                         $this->parser_error('Invalid component type on line '.$key);
00280                     }                        
00281                 }
00282                 unset($current_component, $new_component);
00283             } else if ($label == 'END') {
00284                 // It's the END of a component.
00285                 $component = array_pop($components); // Pop the top component off the stack - we're now done with it
00286                 $parent_component = array_pop($components); // Pop the component's conatining component off the stack so we can add this component to it.
00287                 if($parent_component == null) {
00288                     $parent_component = $this; // If there's no components on the stack, use the iCalendar object
00289                 }
00290                 if ($parent_component->add_component($component) === false) {
00291                     $this->parser_error("Failed to add component on line $key");
00292                 }
00293                 if ($parent_component != $this) { // If we're not using the iCalendar
00294                         array_push($components, $parent_component); // Put the component back on the stack
00295                 }
00296                 unset($parent_component, $component);
00297             } else {
00298                 
00299                 $component = array_pop($components); // Get the component off the stack so we can add properties to it
00300                 if ($component == null) { // If there's nothing on the stack
00301                     $component = $this; // use the iCalendar
00302                 }
00303 
00304                 if ($component->add_property($label, $data, $params) === false) {
00305                     $this->parser_error("Failed to add property '$label' on line $key");
00306                 }
00307 
00308                 if($component != $this) { // If we're not using the iCalendar
00309                     array_push($components, $component); // Put the component back on the stack
00310                 }
00311                 unset($component);
00312             }
00313 
00314         }
00315         
00316     }
00317 
00318     function clear_errors() {
00319         $this->parser_errors = array();
00320     }
00321 
00322     function parser_error($error) {
00323         $this->parser_errors[] = $error;
00324     }
00325 
00326 }
00327 
00328 class iCalendar extends iCalendar_component {
00329     var $name = 'VCALENDAR';
00330 
00331     function __construct() {
00332         $this->valid_properties = array(
00333             'CALSCALE'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00334             'METHOD'      => RFC2445_OPTIONAL | RFC2445_ONCE,
00335             'PRODID'      => RFC2445_REQUIRED | RFC2445_ONCE,
00336             'VERSION'     => RFC2445_REQUIRED | RFC2445_ONCE,
00337             RFC2445_XNAME => RFC2445_OPTIONAL 
00338         );
00339 
00340         $this->valid_components = array(
00341             'VEVENT', 'VTODO', 'VJOURNAL', 'VFREEBUSY', 'VTIMEZONE', 'VALARM'
00342         );
00343         parent::__construct();
00344     }
00345 
00346 }
00347 
00348 class iCalendar_event extends iCalendar_component {
00349 
00350     var $name       = 'VEVENT';
00351     var $properties;
00352     
00353     function __construct() {
00354         
00355         $this->valid_components = array('VALARM');
00356 
00357         $this->valid_properties = array(
00358             'CLASS'          => RFC2445_OPTIONAL | RFC2445_ONCE,
00359             'CREATED'        => RFC2445_OPTIONAL | RFC2445_ONCE,
00360             'DESCRIPTION'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00361             // Standard ambiguous here: in 4.6.1 it says that DTSTAMP in optional,
00362             // while in 4.8.7.2 it says it's REQUIRED. Go with REQUIRED.
00363             'DTSTAMP'        => RFC2445_REQUIRED | RFC2445_ONCE,
00364             // Standard ambiguous here: in 4.6.1 it says that DTSTART in optional,
00365             // while in 4.8.2.4 it says it's REQUIRED. Go with REQUIRED.
00366             'DTSTART'        => RFC2445_REQUIRED | RFC2445_ONCE,
00367             'GEO'            => RFC2445_OPTIONAL | RFC2445_ONCE,
00368             'LAST-MODIFIED'  => RFC2445_OPTIONAL | RFC2445_ONCE,
00369             'LOCATION'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00370             'ORGANIZER'      => RFC2445_OPTIONAL | RFC2445_ONCE,
00371             'PRIORITY'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00372             'SEQUENCE'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00373             'STATUS'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00374             'SUMMARY'        => RFC2445_OPTIONAL | RFC2445_ONCE,
00375             'TRANSP'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00376             // Standard ambiguous here: in 4.6.1 it says that UID in optional,
00377             // while in 4.8.4.7 it says it's REQUIRED. Go with REQUIRED.
00378             'UID'            => RFC2445_REQUIRED | RFC2445_ONCE,
00379             'URL'            => RFC2445_OPTIONAL | RFC2445_ONCE,
00380             'RECURRENCE-ID'  => RFC2445_OPTIONAL | RFC2445_ONCE,
00381             'DTEND'          => RFC2445_OPTIONAL | RFC2445_ONCE,
00382             'DURATION'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00383             'ATTACH'         => RFC2445_OPTIONAL,
00384             'ATTENDEE'       => RFC2445_OPTIONAL,
00385             'CATEGORIES'     => RFC2445_OPTIONAL,
00386             'COMMENT'        => RFC2445_OPTIONAL,
00387             'CONTACT'        => RFC2445_OPTIONAL,
00388             'EXDATE'         => RFC2445_OPTIONAL,
00389             'EXRULE'         => RFC2445_OPTIONAL,
00390             'REQUEST-STATUS' => RFC2445_OPTIONAL,
00391             'RELATED-TO'     => RFC2445_OPTIONAL,
00392             'RESOURCES'      => RFC2445_OPTIONAL,
00393             'RDATE'          => RFC2445_OPTIONAL,
00394             'RRULE'          => RFC2445_OPTIONAL,
00395             RFC2445_XNAME    => RFC2445_OPTIONAL
00396         );
00397 
00398         parent::__construct();
00399     }
00400 
00401     function invariant_holds() {
00402         // DTEND and DURATION must not appear together
00403         if(isset($this->properties['DTEND']) && isset($this->properties['DURATION'])) {
00404             return false;
00405         }
00406 
00407         
00408         if(isset($this->properties['DTEND']) && isset($this->properties['DTSTART'])) {
00409             // DTEND must be later than DTSTART
00410             // The standard is not clear on how to hande different value types though
00411             // TODO: handle this correctly even if the value types are different
00412             if($this->properties['DTEND'][0]->value <= $this->properties['DTSTART'][0]->value) {
00413                 return false;
00414             }
00415 
00416             // DTEND and DTSTART must have the same value type
00417             if($this->properties['DTEND'][0]->val_type != $this->properties['DTSTART'][0]->val_type) {
00418                 return false;
00419             }
00420 
00421         }
00422         return true;
00423     }
00424 
00425 }
00426 
00427 class iCalendar_todo extends iCalendar_component {
00428     var $name       = 'VTODO';
00429     var $properties;
00430 
00431     function __construct() {
00432         
00433         $this->valid_components = array('VALARM');
00434 
00435         $this->valid_properties = array(
00436             'CLASS'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00437             'COMPLETED'   => RFC2445_OPTIONAL | RFC2445_ONCE,
00438             'CREATED'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00439             'DESCRIPTION' => RFC2445_OPTIONAL | RFC2445_ONCE,
00440             'DTSTAMP'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00441             'DTSTAP'      => RFC2445_OPTIONAL | RFC2445_ONCE,
00442             'GEO'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00443             'LAST-MODIFIED' => RFC2445_OPTIONAL | RFC2445_ONCE,
00444             'LOCATION'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00445             'ORGANIZER'   => RFC2445_OPTIONAL | RFC2445_ONCE,
00446             'PERCENT'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00447             'PRIORITY'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00448             'RECURID'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00449             'SEQUENCE'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00450             'STATUS'      => RFC2445_OPTIONAL | RFC2445_ONCE,
00451             'SUMMARY'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00452             'UID'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00453             'URL'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00454             'DUE'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00455             'DURATION'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00456             'ATTACH'      => RFC2445_OPTIONAL,
00457             'ATTENDEE'    => RFC2445_OPTIONAL,
00458             'CATEGORIES'  => RFC2445_OPTIONAL,
00459             'COMMENT'     => RFC2445_OPTIONAL,
00460             'CONTACT'     => RFC2445_OPTIONAL,
00461             'EXDATE'      => RFC2445_OPTIONAL,
00462             'EXRULE'      => RFC2445_OPTIONAL,
00463             'RSTATUS'     => RFC2445_OPTIONAL,
00464             'RELATED'     => RFC2445_OPTIONAL,
00465             'RESOURCES'   => RFC2445_OPTIONAL,
00466             'RDATE'       => RFC2445_OPTIONAL,
00467             'RRULE'       => RFC2445_OPTIONAL,
00468             RFC2445_XNAME => RFC2445_OPTIONAL
00469         );
00470 
00471         parent::__construct();
00472     }
00473     
00474     function invariant_holds() {
00475         // DTEND and DURATION must not appear together
00476         if(isset($this->properties['DTEND']) && isset($this->properties['DURATION'])) {
00477             return false;
00478         }
00479 
00480         
00481         if(isset($this->properties['DTEND']) && isset($this->properties['DTSTART'])) {
00482             // DTEND must be later than DTSTART
00483             // The standard is not clear on how to hande different value types though
00484             // TODO: handle this correctly even if the value types are different
00485             if($this->properties['DTEND'][0]->value <= $this->properties['DTSTART'][0]->value) {
00486                 return false;
00487             }
00488 
00489             // DTEND and DTSTART must have the same value type
00490             if($this->properties['DTEND'][0]->val_type != $this->properties['DTSTART'][0]->val_type) {
00491                 return false;
00492             }
00493 
00494         }
00495         
00496         if(isset($this->properties['DUE']) && isset($this->properties['DTSTART'])) {
00497             if($this->properties['DUE'][0]->value <= $this->properties['DTSTART'][0]->value) {
00498                 return false;
00499             }   
00500         }
00501         
00502         return true;
00503     }
00504     
00505 }
00506 
00507 class iCalendar_journal extends iCalendar_component {
00508     var $name = 'VJOURNAL';
00509     var $properties;
00510     
00511     function __construct() {
00512         
00513         $this->valid_properties = array(
00514             'CLASS'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00515             'CREATED'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00516             'DESCRIPTION'   => RFC2445_OPTIONAL | RFC2445_ONCE,
00517             'DTSTART'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00518             'DTSTAMP'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00519             'LAST-MODIFIED' => RFC2445_OPTIONAL | RFC2445_ONCE,
00520             'ORGANIZER'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00521             'RECURRANCE-ID' => RFC2445_OPTIONAL | RFC2445_ONCE,
00522             'SEQUENCE'      => RFC2445_OPTIONAL | RFC2445_ONCE,
00523             'STATUS'        => RFC2445_OPTIONAL | RFC2445_ONCE,
00524             'SUMMARY'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00525             'UID'           => RFC2445_OPTIONAL | RFC2445_ONCE,
00526             'URL'           => RFC2445_OPTIONAL | RFC2445_ONCE,
00527             'ATTACH'        => RFC2445_OPTIONAL,
00528             'ATTENDEE'      => RFC2445_OPTIONAL,
00529             'CATEGORIES'    => RFC2445_OPTIONAL,
00530             'COMMENT'       => RFC2445_OPTIONAL,
00531             'CONTACT'       => RFC2445_OPTIONAL,
00532             'EXDATE'        => RFC2445_OPTIONAL,
00533             'EXRULE'        => RFC2445_OPTIONAL,
00534             'RELATED-TO'    => RFC2445_OPTIONAL,
00535             'RDATE'         => RFC2445_OPTIONAL,
00536             'RRULE'         => RFC2445_OPTIONAL,
00537             RFC2445_XNAME   => RFC2445_OPTIONAL            
00538         );
00539         
00540          parent::__construct();
00541         
00542     }
00543 }
00544 
00545 class iCalendar_freebusy extends iCalendar_component {
00546     var $name       = 'VFREEBUSY';
00547     var $properties;
00548 
00549     function __construct() {
00550         $this->valid_components = array();
00551         $this->valid_properties = array(
00552             'CONTACT'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00553             'DTSTART'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00554             'DTEND'         => RFC2445_OPTIONAL | RFC2445_ONCE,
00555             'DURATION'      => RFC2445_OPTIONAL | RFC2445_ONCE,
00556             'DTSTAMP'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00557             'ORGANIZER'     => RFC2445_OPTIONAL | RFC2445_ONCE,
00558             'UID'           => RFC2445_OPTIONAL | RFC2445_ONCE,
00559             'URL'           => RFC2445_OPTIONAL | RFC2445_ONCE,
00560             // TODO: the next two are components of their own!
00561             'ATTENDEE'      => RFC2445_OPTIONAL,
00562             'COMMENT'       => RFC2445_OPTIONAL,
00563             'FREEBUSY'      => RFC2445_OPTIONAL,
00564             'RSTATUS'       => RFC2445_OPTIONAL,
00565             RFC2445_XNAME   => RFC2445_OPTIONAL
00566         );
00567         
00568         parent::__construct();
00569     }
00570     
00571     function invariant_holds() {
00572         // DTEND and DURATION must not appear together
00573         if(isset($this->properties['DTEND']) && isset($this->properties['DURATION'])) {
00574             return false;
00575         }
00576 
00577         
00578         if(isset($this->properties['DTEND']) && isset($this->properties['DTSTART'])) {
00579             // DTEND must be later than DTSTART
00580             // The standard is not clear on how to hande different value types though
00581             // TODO: handle this correctly even if the value types are different
00582             if($this->properties['DTEND'][0]->value <= $this->properties['DTSTART'][0]->value) {
00583                 return false;
00584             }
00585 
00586             // DTEND and DTSTART must have the same value type
00587             if($this->properties['DTEND'][0]->val_type != $this->properties['DTSTART'][0]->val_type) {
00588                 return false;
00589             }
00590 
00591         }
00592         return true;
00593     }
00594 }
00595 
00596 class iCalendar_alarm extends iCalendar_component {
00597     var $name       = 'VALARM';
00598     var $properties;
00599 
00600     function __construct() {
00601         $this->valid_components = array();
00602         $this->valid_properties = array(
00603             'ACTION'    => RFC2445_REQUIRED | RFC2445_ONCE,
00604             'TRIGGER'   => RFC2445_REQUIRED | RFC2445_ONCE,
00605             // If one of these 2 occurs, so must the other.
00606             'DURATION'  => RFC2445_OPTIONAL | RFC2445_ONCE,
00607             'REPEAT'    => RFC2445_OPTIONAL | RFC2445_ONCE, 
00608             // The following is required if action == "PROCEDURE" | "AUDIO"           
00609             'ATTACH'    => RFC2445_OPTIONAL,
00610             // The following is required if trigger == "EMAIL" | "DISPLAY" 
00611             'DESCRIPTION'  => RFC2445_OPTIONAL | RFC2445_ONCE,
00612             // The following are required if action == "EMAIL"
00613             'SUMMARY'   => RFC2445_OPTIONAL | RFC2445_ONCE,
00614             'ATTENDEE'  => RFC2445_OPTIONAL,
00615             RFC2445_XNAME   => RFC2445_OPTIONAL
00616         );
00617      
00618         parent::__construct();
00619     }
00620         
00621     function invariant_holds() {
00622         // DTEND and DURATION must not appear together
00623         if(isset($this->properties['ACTION'])) {
00624             switch ($this->properties['ACTION'][0]->value) {
00625                 case 'AUDIO':
00626                     if (!isset($this->properties['ATTACH'])) {
00627                         return false;
00628                     }
00629                     break;
00630                 case 'DISPLAY':
00631                     if (!isset($this->properties['DESCRIPTION'])) {
00632                         return false;
00633                     }
00634                     break;
00635                 case 'EMAIL':
00636                     if (!isset($this->properties['DESCRIPTION']) || !isset($this->properties['SUMMARY']) || !isset($this->properties['ATTACH'])) {
00637                         return false;
00638                     }
00639                     break;
00640                 case 'PROCEDURE':
00641                     if (!isset($this->properties['ATTACH']) || count($this->properties['ATTACH']) > 1) {
00642                         return false;
00643                     }
00644                     break;
00645             }
00646         }
00647         return true;
00648     }
00649         
00650         
00651 }
00652 
00653 class iCalendar_timezone extends iCalendar_component {
00654     var $name       = 'VTIMEZONE';
00655     var $properties;
00656 
00657     function __construct() {
00658 
00659         $this->valid_components = array('STANDARD', 'DAYLIGHT');
00660 
00661         $this->valid_properties = array(
00662             'TZID'        => RFC2445_REQUIRED | RFC2445_ONCE,
00663             'LAST-MODIFIED'    => RFC2445_OPTIONAL | RFC2445_ONCE,
00664             'TZURL'       => RFC2445_OPTIONAL | RFC2445_ONCE,
00665             RFC2445_XNAME => RFC2445_OPTIONAL
00666         );
00667         
00668         parent::__construct();
00669     }
00670 
00671 }
00672 
00673 class iCalendar_standard extends iCalendar_component {
00674     var $name       = 'STANDARD';
00675     var $properties;
00676     
00677     function __construct() {
00678         $this->valid_components = array();
00679         $this->valid_properties = array(
00680             'DTSTART'   =>  RFC2445_REQUIRED | RFC2445_ONCE,
00681             'TZOFFSETTO'    =>  RFC2445_REQUIRED | RFC2445_ONCE,
00682             'TZOFFSETFROM'  =>  RFC2445_REQUIRED | RFC2445_ONCE,
00683             'COMMENT'   =>  RFC2445_OPTIONAL,
00684             'RDATE'   =>  RFC2445_OPTIONAL,
00685             'RRULE'   =>  RFC2445_OPTIONAL,
00686             'TZNAME'   =>  RFC2445_OPTIONAL,
00687             RFC2445_XNAME   =>  RFC2445_OPTIONAL,
00688         ); 
00689         parent::__construct();
00690     }
00691 }
00692 
00693 class iCalendar_daylight extends iCalendar_standard {
00694     var $name   =   'DAYLIGHT';
00695 }
00696 
00697 // REMINDER: DTEND must be later than DTSTART for all components which support both
00698 // REMINDER: DUE must be later than DTSTART for all components which support both
00699 
 All Data Structures Namespaces Files Functions Variables Enumerations