dokeos
[ class tree: dokeos ] [ index: dokeos ] [ all elements ]

Source for file iCalcreator.class.php

Documentation is available at iCalcreator.class.php

  1. <?php
  2. /*********************************************************************************/
  3. /**
  4.  * iCalcreator class v2.4.3
  5.  * copyright (c) 2007-2008 Kjell-Inge Gustafsson kigkonsult
  6.  * www.kigkonsult.se/iCalcreator/index.php
  7.  * ical@kigkonsult.se
  8.  *
  9.  * Description:
  10.  * This file is a PHP implementation of RFC 2445.
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Lesser General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2.1 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Lesser General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Lesser General Public
  23.  * License along with this library; if not, write to the Free Software
  24.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  25.  */
  26. /*********************************************************************************/
  27. /*********************************************************************************/
  28. /*         A little setup                                                        */
  29. /*********************************************************************************/
  30.             /* your local language code */
  31. // define( 'ICAL_LANG', 'sv' );
  32.             // alt. autosetting
  33. /*
  34. $langstr     = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
  35. $pos         = strpos( $langstr, ';' );
  36. if ($pos   !== false) {
  37.   $langstr   = substr( $langstr, 0, $pos );
  38.   $pos       = strpos( $langstr, ',' );
  39.   if ($pos !== false) {
  40.     $pos     = strpos( $langstr, ',' );
  41.     $langstr = substr( $langstr, 0, $pos );
  42.   }
  43.   define( 'ICAL_LANG', $langstr );
  44. }
  45. */
  46.             /* only for phpversion 5.x, date management, default timezone setting */
  47. ifsubstrphpversion()01>= '5' // && ( 'UTC' == date_default_timezone_get() )) {
  48.   date_default_timezone_set'Europe/Stockholm' );
  49.             /* version string, do NOT remove!! */
  50. define'ICALCREATOR_VERSION''iCalcreator 2.4.3' );
  51. /*********************************************************************************/
  52. /*********************************************************************************/
  53. /**
  54.  * vcalendar class
  55.  *
  56.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  57.  * @since 2.2.13 - 2007-12-30
  58.  */
  59. class vcalendar {
  60.             //  calendar property variables
  61.   var $calscale;
  62.   var $method;
  63.   var $prodid;
  64.   var $version;
  65.   var $xprop;
  66.             //  container for calendar components
  67.   var $components;
  68.             //  component config variables
  69.   var $allowEmpty;
  70.   var $unique_id;
  71.   var $language;
  72.   var $directory;
  73.   var $filename;
  74.   var $url;
  75.   var $delimiter;
  76.   var $nl;
  77.   var $format;
  78.             //  component internal variables
  79.   var $valueInit;
  80.             //  component xCal declaration container
  81.   var $xcaldecl;
  82. /*
  83.  * constructor for calendar object
  84.  *
  85.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  86.  * @since 2.2.13 - 2007-12-30
  87.  * @return void
  88.  */
  89.   function vcalendar ({
  90.     $this->_makeVersion();
  91.     $this->calscale   = null;
  92.     $this->method     = null;
  93.     $this->_makeUnique_id();
  94.     $this->prodid     = null;
  95.     $this->xprop      = array();
  96. /**
  97.  *   language = <Text identifying a language, as defined in [RFC 1766]>
  98.  */
  99.     ifdefined'ICAL_LANG' ))
  100.       $this->setConfig'language'ICAL_LANG );
  101.     $this->setConfig'allowEmpty'TRUE );
  102.     $this->setConfig'nl',         "\n" );
  103.     $this->setConfig'format',     'iCal');
  104.     $this->directory  = null;
  105.     $this->filename   = null;
  106.     $this->url        = null;
  107.     $this->setConfig'delimiter',  DIRECTORY_SEPARATOR );
  108.     $this->xcaldecl   = array();
  109.     $this->components = array();
  110.   }
  111. /*********************************************************************************/
  112. /**
  113.  * Property Name: CALSCALE
  114.  */
  115. /**
  116.  * creates formatted output for calendar property calscale
  117.  *
  118.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  119.  * @since 0.9.7 - 2006-11-20
  120.  * @return string 
  121.  */
  122.   function createCalscale({
  123.     if!isset$this->calscale ))
  124.       return;
  125.     switch$this->format {
  126.       case 'xcal':
  127.         return ' calscale="'.$this->calscale.'"'.$this->nl;
  128.         break;
  129.       default:
  130.         return 'CALSCALE:'.$this->calscale.$this->nl;
  131.         break;
  132.     }
  133.   }
  134. /**
  135.  * set calendar property calscale
  136.  *
  137.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  138.  * @since 0.3.0 - 2006-08-13
  139.  * @param string $value 
  140.  * @return void 
  141.  */
  142.   function setCalscale$value {
  143.     $this->calscale = $value;
  144.   }
  145. /*********************************************************************************/
  146. /**
  147.  * Property Name: METHOD
  148.  */
  149. /**
  150.  * creates formatted output for calendar property method
  151.  *
  152.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  153.  * @since 0.9.7 - 2006-11-20
  154.  * @return string 
  155.  */
  156.   function createMethod({
  157.     if!isset$this->method ))
  158.       return;
  159.     switch$this->format {
  160.       case 'xcal':
  161.         return ' method="'.$this->method.'"'.$this->nl;
  162.         break;
  163.       default:
  164.         return 'METHOD:'.$this->method.$this->nl;
  165.         break;
  166.     }
  167.   }
  168. /**
  169.  * set calendar property method
  170.  *
  171.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  172.  * @since 0.3.0 - 2006-08-13
  173.  * @param string $method 
  174.  * @return void 
  175.  */
  176.   function setMethod$method {
  177.     $this->method = $method;
  178.   }
  179. /*********************************************************************************/
  180. /**
  181.  * Property Name: PRODID
  182.  *
  183.  *  The identifier is RECOMMENDED to be the identical syntax to the
  184.  * [RFC 822] addr-spec. A good method to assure uniqueness is to put the
  185.  * domain name or a domain literal IP address of the host on which.. .
  186.  */
  187. /**
  188.  * creates formatted output for calendar property prodid
  189.  *
  190.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  191.  * @since 0.9.7 - 2006-11-20
  192.  * @return string 
  193.  */
  194.   function createProdid({
  195.     if!isset$this->prodid ))
  196.       $this->_makeProdid();
  197.     switch$this->format {
  198.       case 'xcal':
  199.         return ' prodid="'.$this->prodid.'"'.$this->nl;
  200.         break;
  201.       default:
  202.         return 'PRODID:'.$this->prodid.$this->nl;
  203.         break;
  204.     }
  205.   }
  206. /**
  207.  * make default value for calendar prodid
  208.  *
  209.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  210.  * @since 0.3.0 - 2006-08-10
  211.  * @return void 
  212.  */
  213.   function _makeProdid({
  214.     $this->prodid  = '-//'.$this->unique_id.'//NONSGML '.ICALCREATOR_VERSION.'//'.strtoupper$this->language );
  215.   }
  216. /**
  217.  * Conformance: The property MUST be specified once in an iCalendar object.
  218.  * Description: The vendor of the implementation SHOULD assure that this
  219.  * is a globally unique identifier; using some technique such as an FPI
  220.  * value, as defined in [ISO 9070].
  221.  */
  222. /**
  223.  * make default unique_id for calendar prodid
  224.  *
  225.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  226.  * @since 0.3.0 - 2006-08-10
  227.  * @return void 
  228.  
  229.  */
  230.   function _makeUnique_id({
  231.     $this->unique_id  = gethostbyname$_SERVER['SERVER_NAME');
  232.   }
  233. /*********************************************************************************/
  234. /**
  235.  * Property Name: VERSION
  236.  *
  237.  * Description: A value of "2.0" corresponds to this memo.
  238.  */
  239. /**
  240.  * creates formatted output for calendar property version
  241.  
  242.  *
  243.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  244.  * @since 0.9.7 - 2006-11-20
  245.  * @return string 
  246.  */
  247.   function createVersion({
  248.     if!isset$this->version ))
  249.       $this->_makeVersion();
  250.     switch$this->format {
  251.       case 'xcal':
  252.         return ' version="'.$this->version.'"'.$this->nl;
  253.         break;
  254.       default:
  255.         return 'VERSION:'.$this->version.$this->nl;
  256.         break;
  257.     }
  258.   }
  259. /**
  260.  * set default calendar version
  261.  *
  262.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  263.  * @since 0.3.0 - 2006-08-10
  264.  * @return void 
  265.  */
  266.   function _makeVersion({
  267.     $this->version = '2.0';
  268.   }
  269. /**
  270.  * set calendar version
  271.  *
  272.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  273.  * @since 0.3.0 - 2006-08-10
  274.  * @param string version
  275.  * @return void 
  276.  */
  277.   function setVersion$version {
  278.     $this->version = $version;
  279.   }
  280. /*********************************************************************************/
  281. /**
  282.  * Property Name: x-prop
  283.  */
  284. /**
  285.  * creates formatted output for calendar property x-prop, iCal format only
  286.  *
  287.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  288.  * @since 2.3.2 - 2007-11-25
  289.  * @return string 
  290.  */
  291.   function createXprop({
  292.     if'xcal' == $this->format )
  293.       return false;
  294.     if>= count$this->xprop ))
  295.       return;
  296.     $xprop null;
  297.     $toolbox new calendarComponent();
  298.     $toolbox->setConfig'language'$this->getConfig'language' ));
  299.     $toolbox->setConfig'nl',       $this->getConfig'nl' ));
  300.     $toolbox->_createFormat(         $this->getConfig'format' ));
  301.     foreach$this->xprop as $label => $xpropPart {
  302.       $attributes $toolbox->_createParams$xpropPart['params']array'LANGUAGE' ));
  303.       ifis_array$xpropPart['value')) {
  304.         foreach$xpropPart['value'as $pix => $theXpart )
  305.           $xpropPart['value'][$pix$toolbox->_strrep$theXpart );
  306.         $xpropPart['value']  implode','$xpropPart['value');
  307.       }
  308.       else
  309.         $xpropPart['value'$toolbox->_strrep$xpropPart['value');
  310.       $xprop   .= $toolbox->_createElementstrtoupper$label )$attributes$xpropPart['value');
  311.     }
  312.     return $xprop;
  313.   }
  314. /**
  315.  * set calendar property x-prop
  316.  *
  317.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  318.  * @since 2.0.7 - 2007-06-21
  319.  * @param string $label 
  320.  * @param string $value 
  321.  * @param array $params optional
  322.  * @return void 
  323.  */
  324.   function setXprop$label$value$params=FALSE {
  325.     ifempty$label || empty$value ))
  326.       return;
  327.     $xprop array'value' => $value );
  328.     $toolbox new calendarComponent();
  329.     $xprop['params'$toolbox->_setParams$params );
  330.     $this->xprop[$label$xprop;
  331.   }
  332. /*********************************************************************************/
  333. /**
  334.  * delete calendar property value
  335.  *
  336.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  337.  * @since 2.2.15 - 2007-10-29
  338.  * @param string $propName 
  339.  * @param int @propix, optional, if specific property is wanted in case of multiply occurences
  340.  * @return bool, if successfull delete
  341.  */
  342.   function deleteProperty$propName$propix=FALSE {
  343.     $propName $propName strtoupper$propName 'X-PROP';
  344.     if!$propix )
  345.       $propix isset$this->propdelix[$propName)) $this->propdelix[$propName1;
  346.     $this->propdelix[$propName= --$propix;
  347.     $return FALSE;
  348.     switch$propName {
  349.       case 'CALSCALE':
  350.         $this->calscale = null;
  351.         $return TRUE;
  352.         break;
  353.       case 'METHOD':
  354.         $this->method   = null;
  355.         $return TRUE;
  356.         break;
  357.       default:
  358.         if$propName != 'X-PROP' {
  359.           if!isset$this->xprop[$propName)) return FALSE;
  360.           unset$this->xprop[$propName);
  361.           $return TRUE;
  362.         }
  363.         else {
  364.           ifcount$this->xprop <= $propix )  return FALSE;
  365.           $xpropno 0;
  366.           foreach$this->xprop as $xpropkey => $xpropvalue {
  367.             if$propix == $xpropno {
  368.               unset$this->xprop[$xpropkey);
  369.               $return TRUE;
  370.               break 2;
  371.             }
  372.             else
  373.               $xpropno++;
  374.           }
  375.         }
  376.     }
  377.     return $return;
  378.   }
  379. /**
  380.  * get calendar property value/params
  381.  *
  382.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  383.  * @since 2.0.8 - 2007-07-07
  384.  * @param string $propName, optional
  385.  * @param int @propix, optional, if specific property is wanted in case of multiply occurences
  386.  * @param bool $inclParam=FALSE 
  387.  * @return mixed 
  388.  */
  389.   function getProperty$propName=FALSE$propix=FALSE$inclParam=FALSE {
  390.     $propName $propName strtoupper$propName 'X-PROP';
  391.     if!$propix )
  392.       $propix isset$this->propix[$propName)) $this->propix[$propName1;
  393.     $this->propix[$propName= --$propix;
  394.     switch$propName {
  395.       case 'CALSCALE':
  396.         if$propix return FALSE;
  397.         return !empty$this->calscale )) $this->calscale : null;
  398.         break;
  399.       case 'METHOD':
  400.         if$propix return FALSE;
  401.         return !empty$this->method )) $this->method : null;
  402.         break;
  403.       case 'PRODID':
  404.         if$propix return FALSE;
  405.         ifempty$this->prodid ))
  406.           $this->_makeProdid();
  407.         return $this->prodid;
  408.         break;
  409.       case 'VERSION':
  410.         if$propix return FALSE;
  411.         return !empty$this->version )) $this->version : null;
  412.         break;
  413.       default:
  414.         if$propName != 'X-PROP' {
  415.           if!isset$this->xprop[$propName)) return FALSE;
  416.           return $inclParam array$propName$this->xprop[$propName)
  417.                                 : array$propName$this->xprop[$propName]['value');
  418.         }
  419.         else {
  420.           ifcount$this->xprop <= $propix )  return FALSE;
  421.           $xpropno 0;
  422.           foreach$this->xprop as $xpropkey => $xpropvalue {
  423.             if$propix == $xpropno )
  424.               return $inclParam array$xpropkey$this->xprop[$xpropkey)
  425.                                     : array$xpropkey$this->xprop[$xpropkey]['value');
  426.             else
  427.               $xpropno++;
  428.           }
  429.           return FALSE// not found ??
  430.         }
  431.     }
  432.     return FALSE;
  433.   }
  434. /**
  435.  * general vcalendar property setting
  436.  *
  437.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  438.  * @since 2.2.13 - 2007-10-23
  439.  * @param mixed $args variable number of function arguments,
  440.  *                     first argument is ALWAYS component name,
  441.  *                     second ALWAYS component value!
  442.  * @return void 
  443.  */
  444.   function setProperty ({
  445.     $numargs    func_num_args();
  446.     if>= $numargs )
  447.       return FALSE;
  448.     $arglist    func_get_args();
  449.     if!$this->getConfig'allowEmpty' && !isset$arglist[1|| empty$arglist[1)))
  450.       return;
  451.     $arglist[0strtoupper$arglist[0);
  452.     for$argix=$numargs$argix 3$argix++ {
  453.       if!isset$arglist[$argix))
  454.         $arglist[$argixnull;
  455.     }
  456.     switch$arglist[0{
  457.       case 'CALSCALE':
  458.         $this->setCalscale$arglist[1);
  459.         break;
  460.       case 'METHOD':
  461.         $this->setMethod$arglist[1);
  462.         break;
  463.       case 'VERSION':
  464.         $this->setVersion$arglist[1);
  465.         break;
  466.       default:
  467.         $this->setXprop$arglist[0]$arglist[1]$arglist[2);
  468.         break;
  469.     }
  470.   }
  471. /*********************************************************************************/
  472. /**
  473.  * get vcalendar config values or * calendar components
  474.  *
  475.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  476.  * @since 2.2.13 - 2007-12-30
  477.  * @param string $config 
  478.  * @return value 
  479.  */
  480.   function getConfig$config {
  481.     switchstrtoupper$config )) {
  482.       case 'ALLOWEMPTY':
  483.         return $this->allowEmpty;
  484.         break;
  485.       case 'COMPSINFO':
  486.         unset$this->compix );
  487.         $info array();
  488.         foreach$this->components as $cix => $component {
  489.           unset$component->propix );
  490.           $info[$cix]['ordno'$cix 1;
  491.           $info[$cix]['type']  $component->objName;
  492.           $info[$cix]['uid']   $component->getProperty'uid' );
  493.           $info[$cix]['props'$component->getConfig'propinfo' );
  494.           $info[$cix]['sub']   $component->getConfig'compsinfo' );
  495.           unset$component->propix );
  496.         }
  497.         return $info;
  498.         break;
  499.       case 'DELIMITER':
  500.         return $this->delimiter;
  501.         break;
  502.       case 'DIRECTORY':
  503.         ifempty$this->directory ))
  504.           $this->directory = '.';
  505.         return $this->directory;
  506.         break;
  507.       case 'DIRFILE':
  508.         return $this->getConfig'directory' ).$this->getConfig'delimiter' ).$this->getConfig'filename' );
  509.         break;
  510.       case 'FILEINFO':
  511.         return array$this->getConfig'directory' )
  512.                     $this->getConfig'filename' )
  513.                     $this->getConfig'filesize' ));
  514.         break;
  515.       case 'FILENAME':
  516.         ifempty$this->filename )) {
  517.           if'xcal' == $this->format )
  518.             $this->filename = date'YmdHis' ).'.xml'// recommended xcs.. .
  519.           else
  520.             $this->filename = date'YmdHis' ).'.ics';
  521.         }
  522.         return $this->filename;
  523.         break;
  524.       case 'FILESIZE':
  525.         $size    0;
  526.         ifempty$this->url )) {
  527.           $dirfile $this->getConfig'dirfile' );
  528.           ifFALSE === $size filesize$dirfile )))
  529.             $size 0;
  530.           clearstatcache();
  531.         }
  532.         return $size;
  533.         break;
  534.       case 'FORMAT':
  535.         return $this->format;
  536.         break;
  537.       case 'LANGUAGE':
  538.          /* get language for calendar component as defined in [RFC 1766] */
  539.         return $this->language;
  540.         break;
  541.       case 'NL':
  542.       case 'NEWLINECHAR':
  543.         return $this->nl;
  544.         break;
  545.       case 'UNIQUE_ID':
  546.         return $this->unique_id;
  547.         break;
  548.       case 'URL':
  549.         if!empty$this->url ))
  550.           return $this->url;
  551.         else
  552.           return FALSE;
  553.         break;
  554.     }
  555.   }
  556. /**
  557.  * general vcalendar config setting
  558.  *
  559.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  560.  * @since 2.2.13 - 2007-12-30
  561.  * @param string $config 
  562.  * @param string $value 
  563.  * @return void 
  564.  */
  565.   function setConfig$config$value {
  566.     switchstrtoupper$config )) {
  567.       case 'ALLOWEMPTY':
  568.         $this->allowEmpty = $value;
  569.         break;
  570.       case 'DELIMITER':
  571.         $this->delimiter = $value;
  572.         break;
  573.       case 'DIRECTORY':
  574.         $value   trim$value );
  575.         $nl      $this->getConfig('delimiter');
  576.         if$nl == substr$valuestrlen$nl ))))
  577.           $value substr$value0strlen$value strlen$nl )));
  578.         ifis_dir$value )) {
  579.             /* local directory */
  580.           clearstatcache();
  581.           $this->directory = $value;
  582.           $this->url       = null;
  583.           return TRUE;
  584.         }
  585.         else
  586.           return FALSE;
  587.         break;
  588.       case 'FILENAME':
  589.         $value   trim$value );
  590.         if!empty$this->url )) {
  591.             /* remote directory+file - URL */
  592.           $this->filename = $value;
  593.           return TRUE;
  594.         }
  595.         $dirfile $this->getConfig'directory' ).$this->getConfig'delimiter' ).$value;
  596.         iffile_exists$dirfile )) {
  597.             /* local existing file */
  598.           ifis_readable$dirfile || is_writable$dirfile )) {
  599.             clearstatcache();
  600.             $this->filename = $value;
  601.             return TRUE;
  602.           }
  603.           else
  604.             return FALSE;
  605.         }
  606.         elseifFALSE !== touch$dirfile )) {
  607.             /* new local file created */
  608.           $this->filename = $value;
  609.           return TRUE;
  610.         }
  611.         else
  612.           return FALSE;
  613.         break;
  614.       case 'FORMAT':
  615.         $value   trim$value );
  616.         if'xcal' == strtolower$value )) {
  617.           $this->format             = 'xcal';
  618.           $this->attributeDelimiter = $this->nl;
  619.           $this->valueInit          = null;
  620.         }
  621.         else {
  622.           $this->format             = null;
  623.           $this->attributeDelimiter = ';';
  624.           $this->valueInit          = ':';
  625.         }
  626.         break;
  627.       case 'LANGUAGE':
  628.          // set language for calendar component as defined in [RFC 1766]
  629.         $value   trim$value );
  630.         $this->language = $value;
  631.         break;
  632.       case 'NL':
  633.       case 'NEWLINECHAR':
  634.         $this->nl = $value;
  635.         break;
  636.       case 'UNIQUE_ID':
  637.         $value   trim$value );
  638.         $this->unique_id = $value;
  639.         break;
  640.       case 'URL':
  641.             /* remote file - URL */
  642.         $value     trim$value );
  643.         $value     str_replace'HTTP://',   'http://'$value );
  644.         $value     str_replace'WEBCAL://''http://'$value );
  645.         $value     str_replace'webcal://''http://'$value );
  646.         $this->url = $value;
  647.         $this->directory = null;
  648.         $parts     pathinfo$value );
  649.         return $this->setConfig'filename',  $parts['basename');
  650.         break;
  651.     }
  652.   }
  653. /*********************************************************************************/
  654. /**
  655.  * validDate
  656.  *
  657.  * convert input parameters to (valid) iCalcreator date in array format (or FALSE)
  658.  * if $utc=TRUE and $tz = utc offset ([[+/]-]HHmm) input (local) date array + UTC offset
  659.  * returns ouput in UTC format date
  660.  *
  661.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  662.  * @since 2.2.2 - 2007-07-29
  663.  * @param mixed $year 
  664.  * @param mixed $month optional
  665.  * @param int $day optional
  666.  * @param int $hour optional
  667.  * @param int $min optional
  668.  * @param int $sec optional
  669.  * @param mixed $tz optional
  670.  * @param bool $utc optional
  671.  * @return bool false / array $date
  672.  */
  673.   function validDate$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$tz=FALSE$utc=FALSE {
  674.     $input   array();
  675.     $toolbox new calendarComponent();
  676.     $parno   null;
  677.     ifis_array$year && isset$year['timestamp')) {
  678.       $input        $toolbox->_date_time_stringdate'Y-m-d H:i:s'$year['timestamp'));
  679.       $input['tz']  isset$year['tz')) $year['tz'null;
  680.       $utc TRUE === $month TRUE FALSE;
  681.     }
  682.     elseifis_array$year && in_arraycount$year )array346)))) {
  683.       ifisset$year['tz'|| == count$year )) || == count$year )))
  684.         $parno 7;
  685.       elseifisset$year['hour'|| isset$year['min'|| isset$year['sec'||
  686.             == count$year )))
  687.         $parno 6;
  688.       else
  689.         $parno 3;
  690.       $input $toolbox->_date_time_array$year$parno );
  691.       $utc TRUE === $month TRUE FALSE;
  692.     }
  693.     elseif<= strlentrim$year ))) // ex. 2006-08-03 10:12:18
  694.       $input $toolbox->_date_time_string$year );
  695.       $utc TRUE === $month TRUE FALSE;
  696.     }
  697.     elseif(( $year !== FALSE && $month !== FALSE && $day !== FALSE )) {
  698.       if(( > (int) $year || (2100 < (int) $year ))
  699.         return FALSE;
  700.       $month = (int) $month;
  701.       if(( $month || 12 $month ))
  702.         return FALSE;
  703.       $day   = (int) $day;
  704.       if(( $day || 31 $day ))
  705.         return FALSE;
  706.       $input['year']   $year;
  707.       $input['month']  $month;
  708.       $input['day']    $day;
  709.       if(( $hour !== FALSE || $min !== FALSE || $sec !== FALSE )) {
  710.         $parno 6;
  711.         if$hour !== FALSE )
  712.           $input['hour'$hour;
  713.         if$min !== FALSE )
  714.           $input['min']  $min;
  715.         if$sec !== FALSE )
  716.           $input['sec']  $sec;
  717.       }
  718.       if$tz !== FALSE {
  719.         $parno 7;
  720.         $input['tz']  $tz;
  721.       }
  722.       elseif!$parno )
  723.         $parno 3;
  724.       $input $toolbox->_date_time_array$input$parno );
  725.     }
  726.     else
  727.       return FALSE;
  728.     if!checkdate $input['month']$input['day']$input['year'))
  729.       return FALSE;
  730.     ifisset$input['hour'&&
  731.         (( $input['hour'|| 23 $input['hour')))
  732.       return FALSE;
  733.     ifisset$input['min'&&
  734.         (( $input['min'|| 59 $input['min')))
  735.       return FALSE;
  736.     ifisset$input['sec'&&
  737.         (( $input['sec'|| 59 $input['sec')))
  738.       return FALSE;
  739.     ifisset$input['tz'&& '' trim $input['tz'))) {
  740.       $input['tz'= (string) trim$input['tz');
  741.       ifctype_digit$input['tz']{1)) // only numeric tz=offset
  742.         $offset 0;
  743.         ifctype_digit$input['tz']{0))
  744.           $input['tz''+'.$input['tz'];
  745.         $offset $toolbox->_tz2offset$input['tz');
  746.         if!= $offset{
  747.           if!isset$input['hour'))
  748.             $input['hour'0;
  749.           if!isset$input['min'))
  750.             $input['min'0;
  751.           if!isset$input['sec'))
  752.             $input['sec'0;
  753.           $input date('Y-m-d H:i:s\Z'mktime$input['hour']
  754.                                                 $input['min']
  755.                                                 $input['sec'$offset
  756.                                                 $input['month']
  757.                                                 $input['day']
  758.                                                 $input['year']));
  759.           $parno $utc ;
  760.           $input $toolbox->_date_time_string$input$parno );
  761.           if!$utc && isset$input['tz'&& 'Z' == $input['tz'))
  762.             unset$input['tz');
  763.         }
  764.       }
  765.     }
  766.     return $input;
  767.   }
  768. /*********************************************************************************/
  769. /**
  770.  * add calendar component to container
  771.  *
  772.  * alias to setComponent
  773.  *
  774.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  775.  * @since 1.x.x - 2007-04-24
  776.  * @param object $component calendar component
  777.  * @return void 
  778.  */
  779.   function addComponent$component {
  780.     $this->setComponent$component );
  781.   }
  782. /**
  783.  * delete calendar component from container
  784.  *
  785.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  786.  * @since 2.0.4 - 2007-06-14
  787.  * @param mixed $arg1 ordno / component type / component uid
  788.  * @param mixed $arg2 optional, ordno if arg1 = component type
  789.  * @return void 
  790.  */
  791.   function deleteComponent$arg1$arg2=FALSE  {
  792.     $argType $index null;
  793.     if ctype_digit(string) $arg1 )) {
  794.       $argType 'INDEX';
  795.       $index   = (int) $arg1 1;
  796.     }
  797.     elseif(( strlen$arg1 <= strlen'vfreebusy' )) && FALSE === strpos$arg1'@' ))) {
  798.       $argType strtolower$arg1 );
  799.       $index   !empty$arg2 && ctype_digit(string) $arg2 )) (( int ) $arg2 1;
  800.     }
  801.     $cix1dC 0;
  802.     foreach $this->components as $cix => $component{
  803.       unset$component->propix );
  804.       if(( 'INDEX' == $argType && $index == $cix )) {
  805.         unset$this->components[$cix);
  806.         return TRUE;
  807.       }
  808.       elseif$argType == $component->objName {
  809.         if$index == $cix1dC {
  810.           unset$this->components[$cix);
  811.           return TRUE;
  812.         }
  813.         $cix1dC++;
  814.       }
  815.       elseif!$argType && ($arg1 == $component->getProperty'uid' ))) {
  816.         unset$this->components[$cix);
  817.         return TRUE;
  818.       }
  819.     }
  820.     return FALSE;
  821.   }
  822. /**
  823.  * get calendar component from container
  824.  *
  825.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  826.  * @since 2.2.16 - 2007-11-11
  827.  * @param mixed $arg1 optional, ordno/component type/ component uid
  828.  * @param mixed $arg2 optional, ordno if arg1 = component type
  829.  * @return object 
  830.  */
  831.   function getComponent$arg1=FALSE$arg2=FALSE {
  832.     $index $argType null;
  833.     if !$arg1 {
  834.       $argType 'INDEX';
  835.       $index   $this->compix['INDEX'=
  836.         isset$this->compix['INDEX')) $this->compix['INDEX'1;
  837.     }
  838.     elseif ctype_digit(string) $arg1 )) {
  839.       $argType 'INDEX';
  840.       $index   = (int) $arg1;
  841.       unset$this->compix );
  842.     }
  843.     elseif(( strlen$arg1 <= strlen'vfreebusy' )) && FALSE === strpos$arg1'@' ))) {
  844.       unset$this->compix['INDEX');
  845.       $argType strtolower$arg1 );
  846.       if!$arg2 )
  847.         $index $this->compix[$argType=
  848.         isset$this->compix[$argType)) $this->compix[$argType1;
  849.       else
  850.         $index = (int) $arg2;
  851.     }
  852.     $index  -= 1;
  853.     $ckeys =  array_keys$this->components );
  854.     if!empty$index&& $index end(  $ckeys )))
  855.       return FALSE;
  856.     $cix1gC 0;
  857.     foreach $this->components as $cix => $component{
  858.       unset$component->propix );
  859.       if(( 'INDEX' == $argType && $index == $cix ))
  860.         return $component->copy();
  861.       elseif$argType == $component->objName {
  862.          if$index == $cix1gC )
  863.            return $component->copy();
  864.          $cix1gC++;
  865.       }
  866.       elseif!$argType && ($arg1 == $component->getProperty'uid' ))) {
  867.         unset$component->propix );
  868.         return $component->copy();
  869.       }
  870.     }
  871.             /* not found.. . */
  872.     unset$this->compix );
  873.     return false;
  874.   }
  875. /**
  876.  * select components from calendar on date basis
  877.  *
  878.  * Ensure DTSTART is set for every component.
  879.  * No date controls occurs.
  880.  *
  881.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  882.  * @since 2.4.1 - 2008-02-05
  883.  * @param int $startY optional,  start Year, default current Year
  884.  * @param int $startM optional,  start Month, default current Month
  885.  * @param int $startD optional,  start Day, default current Day
  886.  * @param int $endY optional,    end Year, default $startY
  887.  * @param int $endY optional,    end Month, default $startM
  888.  * @param int $endY optional,    end Day, default $startD
  889.  * @param mixed $cType optional, calendar component type(-s), default FALSE=all else string/array type(-s)
  890.  * @param bool $flat optional,   FALSE (default) => output : array[Year][Month][Day][]
  891.  *                                TRUE => output : array[] (ignores split)
  892.  * @param bool $any optional,    TRUE (default) - select component that take place within period
  893.  *                                FALSE - only components that starts within period
  894.  * @param bool $split optional,  TRUE (default) - one component copy every day it take place during the
  895.  *                                        period (implies flat=FALSE)
  896.  *                                FALSE - one occurance of component only in output array</tr>
  897.  * @return array or FALSE
  898.  */
  899.   function selectComponents$startY=FALSE$startM=FALSE$startD=FALSE$endY=FALSE$endM=FALSE$endD=FALSE$cType=FALSE$flat=FALSE$any=TRUE$split=TRUE {
  900.             /* check  if empty calendar */
  901.     if>= count$this->components ))
  902.       return FALSE;
  903.             /* check default dates */
  904.     if!$startY $startY date'Y' );
  905.     if!$startM $startM date'm' );
  906.     if!$startD $startD date'd' );
  907.     $startDate mktime000$startM$startD$startY );
  908.     if!$endY )   $endY   $startY;
  909.     if!$endM )   $endM   $startM;
  910.     if!$endD )   $endD   $startD;
  911.     $endDate   mktime235959$endM$endD$endY );
  912.             /* check component types */
  913.     $validTypes array('vevent''vtodo''vjournal''vfreebusy' );
  914.     ifis_array$cType )) {
  915.       foreach$cType as $cix => $theType {
  916.         $cType[$cix$theType strtolower$theType );
  917.         if!in_array$theType$validTypes ))
  918.           $cType[$cix'vevent';
  919.       }
  920.       $cType array_unique$cType );
  921.     }
  922.     elseif!empty$cType )) {
  923.       $cType strtolower$cType );
  924.       if!in_array$cType$validTypes ))
  925.         $cType array'vevent' );
  926.       else
  927.         $cType array$cType );
  928.     }
  929.     else
  930.       $cType $validTypes;
  931.     if>= count$cType ))
  932.       $cType $validTypes;
  933.             /* iterate components */
  934.     $result array();
  935.     foreach $this->components as $cix => $component {
  936.       unset$component->propix$start );
  937.             /* deselect unvalid type components */
  938.       if!in_array$component->objName$cType ))
  939.         continue;
  940.             /* deselect components without dtstart set */
  941.       ifFALSE === $start $component->getProperty'dtstart' )))
  942.         continue;
  943.       $dtendExist $dueExist FALSE;
  944.       unset$end$startWdate$endWdate$rdurWsecs$rdur$exdatelist$workstart$workend )// clean up
  945.       $startWdate $component->_date2timestamp$start );
  946.             /* get end date from dtend/due/duration properties */
  947.       $end $component->getProperty'dtend' );
  948.       if!empty$end ))
  949.         $dtendExist TRUE;
  950.       //if( !empty($end))  echo 'selectComponents 1 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
  951.       ifempty($end&& $component->objName == 'vtodo' )) {
  952.         $end $component->getProperty'due' );
  953.         if!empty$end ))
  954.           $dueExist TRUE;
  955.         //if( !empty($end))  echo 'selectComponents 2 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
  956.       }
  957.       elseif!empty($end&& !isset$end['hour')) {
  958.           /* a DTEND without time part regards an event that ends the day before,
  959.              for an all-day event DTSTART=20071201 DTEND=20071202 (taking place 20071201!!! */
  960.         $end array'year' => $end['year']'month' => $end['month']'day' => ($end['day'1)'hour' => 23'min' => 59'sec' => 59 );
  961.         //if( !empty($end))  echo 'selectComponents 3 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
  962.       }
  963.       ifempty$end )) {
  964.         $end $component->getProperty'duration'FALSEFALSETRUE );// in dtend (array) format
  965.         //if( !empty($end))  echo 'selectComponents 4 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
  966.       }
  967.       ifempty$end )) // assume one day duration if missing end date
  968.         $end array'year' => $start['year']'month' => $start['month']'day' => $start['day']'hour' => 23'min' => 59'sec' => 59 );
  969.         //if( isset($end))  echo 'selectComponents 5 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
  970.       }
  971.       $endWdate $component->_date2timestamp$end );
  972.       if$endWdate $startWdate // MUST be after start date!!
  973.         $end array'year' => $start['year']'month' => $start['month']'day' => $start['day']'hour' => 23'min' => 59'sec' => 59 );
  974.         $endWdate $component->_date2timestamp$end );
  975.       }
  976.       $rdurWsecs  $endWdate $startWdate// compute component duration in seconds
  977.       $rdur       $component->_date2duration$start$end )// compute component duration, array
  978.             /* make a list of optional exclude dates for component occurence, exrule, exdate */
  979.       $exdatelist array();
  980.       $workstart  $component->_date_time_stringdate('Y-m-d H:i:s'$startDate $rdurWsecs ))6);
  981.       $workend    $component->_date_time_stringdate('Y-m-d H:i:s'$endDate $rdurWsecs ))6);
  982.       whileFALSE !== $exrule $component->getProperty'exrule' )))
  983.         $component->_recur2date$exdatelist$exrule$start$workstart$workend );
  984.       whileFALSE !== $exdate $component->getProperty'exdate' ))) {
  985.         foreach$exdate as $theExdate {
  986.           $exWdate $component->_date2timestamp$theExdate );
  987.           if((( $startDate $rdurWsecs <= $exWdate && $endDate >= $exWdate ))
  988.             $exdatelist[$exWdateTRUE;
  989.         }
  990.       }
  991.             /* if 'any' components, check repeating components, removing all excluding dates */
  992.       ifTRUE === $any {
  993.             /* make a list of optional repeating dates for component occurence, rrule, rdate */
  994.         $recurlist array();
  995.         whileFALSE !== $rrule $component->getProperty'rrule' )))    // check rrule
  996.           $component->_recur2date$recurlist$rrule$start$workstart$workend );
  997.         foreach$recurlist as $recurkey => $recurvalue // key=match date as timestamp
  998.           $recurlist[$recurkey$rdurWsecs// add duration in seconds
  999.         whileFALSE !== $rdate $component->getProperty'rdate' ))) {  // check rdate
  1000.           foreach$rdate as $theRdate {
  1001.             ifis_array$theRdate && == count$theRdate )) &&  // PERIOD
  1002.                    array_key_exists'0'$theRdate &&  array_key_exists'1'$theRdate )) {
  1003.               $rstart $component->_date2timestamp$theRdate[0);
  1004.               if(( $rstart $startDate $rdurWsecs )) || $rstart $endDate ))
  1005.                 continue;
  1006.               ifisset$theRdate[1]['year')) // date-date period
  1007.                 $rend $component->_date2timestamp$theRdate[1);
  1008.               else {                             // date-duration period
  1009.                 $rend $component->duration2date$theRdate[0]$theRdate[1);
  1010.                 $rend $component->_date2timestamp$rend );
  1011.               }
  1012.               if((( $startDate $rdurWsecs <= $rstart && $endDate >= $rstart ))
  1013.                 $recurlist[$rstart$rstart $rend )// set start date + rdate duration in seconds
  1014.             }
  1015.             else // single date
  1016.               $theRdate $component->_date2timestamp$theRdate );
  1017.               if((( $startDate $rdurWsecs <= $theRdate && $endDate >= $theRdate ))
  1018.                 $recurlist[$theRdate$rdurWsecs// set start date + event duration in seconds
  1019.             }
  1020.           }
  1021.         }
  1022.         ifcount$recurlist )) {
  1023.           ksort$recurlist );
  1024.           foreach$recurlist as $recurkey => $durvalue {
  1025.             if((( $startDate $rdurWsecs $recurkey || $endDate $recurkey )) // not within period
  1026.               continue;
  1027.             ifisset$exdatelist[$recurkey)) // check excluded dates
  1028.               continue;
  1029.             if$startWdate >= $recurkey // exclude component start date
  1030.               continue;
  1031.             $component2 $component->copy();
  1032.             $rstart     $component2->_date_time_stringdate('Y-m-d H:i:s'$recurkey )6);
  1033.             $datevalue  $rstart['month'].'/'.$rstart['day'].'/'.$rstart['year'];
  1034.             $dateformat 'Y-m-d';
  1035.             ifisset$start['hour'|| isset$start['min'|| isset$start['sec')) {
  1036.               $datevalue  .= isset$rstart['hour')) ' '.$rstart['hour'' 00';
  1037.               $datevalue  .= isset$rstart['min'))  ':'.$rstart['min']  ':00';
  1038.               $datevalue  .= isset$rstart['sec'))  ':'.$rstart['sec']  ':00';
  1039.               $dateformat .= ' H:i:s';
  1040.             }
  1041.             $datestring date$dateformatstrtotime$datevalue ));
  1042.             ifisset$start['tz'))
  1043.               $datestring .= ' '.$start['tz'];
  1044.             $component2->setProperty'x-current-dtstart'$datestring );
  1045.             $rend   $component2->_date_time_stringdate('Y-m-d H:i:s'$recurkey $durvalue ))6);
  1046.             ifisset$datevalue && $dtendExist || $dueExist )) {
  1047.               $datevalue  $rend['month'].'/'.$rend['day'].'/'.$rend['year'];
  1048.               $dateformat 'Y-m-d';
  1049.               ifisset$end['hour'|| isset$end['min'|| isset$end['sec')) {
  1050.                 $datevalue  .= isset$rend['hour')) ' '.$rend['hour'' 00';
  1051.                 $datevalue  .= isset$rend['min'))  ':'.$rend['min']  ':00';
  1052.                 $datevalue  .= isset$rend['sec'))  ':'.$rend['sec']  ':00';
  1053.                 $dateformat .= ' H:i:s';
  1054.               }
  1055.               $datestring date$dateformatstrtotime$datevalue ));
  1056.               ifisset$end['tz'))
  1057.                 $datestring .= ' '.$end['tz'];
  1058.               if$dtendExist )
  1059.                 $component2->setProperty'x-current-dtend'$datestring );
  1060.               else
  1061.                 $component2->setProperty'x-current-due'$datestring );
  1062.             }
  1063.             $rend   $component2->_date2timestamp$rend );
  1064.             $rstart $recurkey;
  1065.             /* add repeating components within valid dates to output array, only start date */
  1066.             if$flat )
  1067.               $result[$component2// copy to output
  1068.             elseif$split {
  1069.               if$rend $endDate )
  1070.                 $rend $endDate;
  1071.               while$rstart <= $rend // iterate
  1072.                 $wd getdate$rstart );
  1073. //                if(( $rstart >= $startDate ) &&     // date within period
  1074.                 if(( $rstart $startDate &&     // date after dtstart
  1075.                     !isset$exdatelist[$rstart)) // check exclude date
  1076.                   $result[$wd['year']][$wd['mon']][$wd['mday']][$component2->copy()// copy to output
  1077.                 $rstart += 24*60*60 )// step one day
  1078.               }
  1079.             }
  1080.             elseif(( $rstart >= $startDate &&     // date within period
  1081.                   !isset$exdatelist[$rstart)) // check exclude date
  1082.               $wd getdate$rstart );
  1083.               $result[$wd['year']][$wd['mon']][$wd['mday']][$component2->copy()// copy to output
  1084.             }
  1085.           }
  1086.         }
  1087.             /* deselect components with startdate/enddate not within period */
  1088.         if(( $endWdate $startDate || $startWdate $endDate ))
  1089.           continue;
  1090.       }
  1091.             /* deselect components with startdate not within period */
  1092.       elseif(( $startWdate $startDate || $startWdate $endDate ))
  1093.         continue;
  1094.             /* add selected components within valid dates to output array */
  1095.       if$flat {
  1096.         $result[$component->copy()// copy to output;
  1097.       }
  1098.       elseif$split {
  1099.         if$endWdate $endDate )
  1100.           $endWdate $endDate;     // use period end date
  1101.         if!isset$exdatelist[$startWdate))  // check excluded dates
  1102.           if$startWdate $startDate )
  1103.             $startWdate $startDate// use period start date
  1104.           while$startWdate <= $endWdate // iterate
  1105.             $wd getdate$startWdate );
  1106.             $result[$wd['year']][$wd['mon']][$wd['mday']][$component->copy()// copy to output
  1107.             $startWdate += 24*60*60 )// step one day
  1108.           }
  1109.         }
  1110.       // use component date
  1111.       elseif!isset$exdatelist[$startWdate&&   // check excluded dates
  1112.             $startWdate >= $startDate )) {         // within period
  1113.         $wd getdate$startWdate );
  1114.         $result[$wd['year']][$wd['mon']][$wd['mday']][$component->copy()// copy to output
  1115.       }
  1116.     }
  1117.     if>= count$result ))
  1118.       return FALSE;
  1119.    elseif!$flat {
  1120.       foreach$result as $y => $yeararr {
  1121.         foreach$yeararr as $m => $montharr {
  1122.           ksort$result[$y][$m);
  1123.         }
  1124.         ksort$result[$y);
  1125.       }
  1126.       ksort$result );
  1127.     }
  1128.     return $result;
  1129.   }
  1130. /**
  1131.  * add calendar component to container
  1132.  *
  1133.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1134.  * @since 2.2.16 - 2007-11-11
  1135.  * @param object $component calendar component
  1136.  * @param mixed $arg1 optional, ordno/component type/ component uid
  1137.  * @param mixed $arg2 optional, ordno if arg1 = component type
  1138.  * @return void 
  1139.  */
  1140.   function setComponent$component$arg1=FALSE$arg2=FALSE  {
  1141.     if'' >= $component->getConfig'language'))
  1142.       $component->setConfig'language',  $this->getConfig'language' ));
  1143.     $component->setConfig'allowEmpty',  $this->getConfig'allowEmpty' ));
  1144.     $component->setConfig'nl',          $this->getConfig'nl' ));
  1145.     $component->setConfig'unique_id',   $this->getConfig'unique_id' ));
  1146.     $component->setConfig'format',      $this->getConfig'format' ));
  1147.     if!in_array$component->objNamearray'valarm''vtimezone' ))) {
  1148.       unset$component->propix );
  1149.             /* make sure dtstamp and uid is set */
  1150.       $dummy $component->getProperty'dtstamp' );
  1151.       $dummy $component->getProperty'uid' );
  1152.     }
  1153.     if!$arg1 {
  1154.       $this->components[$component->copy();
  1155.       return TRUE;
  1156.     }
  1157.     $argType $index null;
  1158.     if ctype_digit(string) $arg1 )) {
  1159.       $argType 'INDEX';
  1160.       $index   = (int) $arg1 1;
  1161.     }
  1162.     elseif(( strlen$arg1 <= strlen'vfreebusy' )) && FALSE === strpos$arg1'@' ))) {
  1163.       $argType strtolower$arg1 );
  1164.       $index ctype_digit(string) $arg2 )) ((int) $arg20;
  1165.     }
  1166.     $cix1sC 0;
  1167.     foreach $this->components as $cix => $component2{
  1168.       unset$component2->propix );
  1169.       if(( 'INDEX' == $argType && $index == $cix )) {
  1170.         $this->components[$cix$component->copy();
  1171.         return TRUE;
  1172.       }
  1173.       elseif$argType == $component2->objName {
  1174.         if$index == $cix1sC {
  1175.           $this->components[$cix$component->copy();
  1176.           return TRUE;
  1177.         }
  1178.         $cix1sC++;
  1179.       }
  1180.       elseif!$argType && $arg1 == $component2->getProperty'uid' ))) {
  1181.         $this->components[$cix$component->copy();
  1182.         return TRUE;
  1183.       }
  1184.     }
  1185.             /* not found.. . insert last in chain anyway .. .*/
  1186.     $this->components[$component->copy();
  1187.   }
  1188. /**
  1189.  * sort iCal compoments, only local date sort
  1190.  *
  1191.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1192.  * @since 2.2.9 - 2007-10-02
  1193.  * @return sort param
  1194.  *
  1195.  */
  1196.   function _cmpfcn$a$b {
  1197.     if(  'vtimezone' == $a->objName)                   return -1;
  1198.     if(  'vtimezone' == $b->objName)                   return  1;
  1199.     if(          isset$a->dtstart['value'||
  1200.                  isset$b->dtstart['value')) {
  1201.       foreach$this->_sortkeys as $key {
  1202.         if(     !isset$a->dtstart['value'][$key))  return -1;
  1203.         elseif!isset$b->dtstart['value'][$key))  return  1;
  1204.         if    (         $a->dtstart['value'][$key]
  1205.                      == $b->dtstart['value'][$key)
  1206.           continue;
  1207.         if    ((  (int) $a->dtstart['value'][$key<
  1208.                (  (int) $b->dtstart['value'][$key))  return -1;
  1209.         elseif((  (int) $a->dtstart['value'][$key>
  1210.                (  (int) $b->dtstart['value'][$key))  return  1;
  1211.       }
  1212.     }
  1213.     ifisset$a->dtend['value'))
  1214.       $c $a->dtend['value'];
  1215.     if(     empty$c && !empty$a->due['value'))
  1216.       $c $a->due['value'];
  1217.     if(     empty$c && !empty$a->duration['value'))
  1218.       $c $a->duration2date();
  1219.     ifisset$b->dtend['value'))
  1220.       $d $b->dtend['value'];
  1221.     if(     empty$d && !empty$b->due['value'))
  1222.       $d $b->due['value'];
  1223.     if(     empty$d && !empty$b->duration['value'))
  1224.       $d $b->duration2date();
  1225.     if(          isset$c ||   isset$d )) {
  1226.       if(       !isset$c &&   isset$d ))         return -1;
  1227.       if(        isset$c &&  !isset$d ))         return  1;
  1228.       foreach$this->_sortkeys as $key {
  1229.         if    !isset$c[$key))                    return -1;
  1230.         elseif!isset$d[$key))                    return  1;
  1231.         if    (         $c[$key]
  1232.                      == $d[$key)
  1233.           continue;
  1234.         if    ((  (int) $c[$key<
  1235.                (  (int) $d[$key))                    return -1;
  1236.         elseif((  (int) $c[$key>
  1237.                (  (int) $d[$key))                    return  1;
  1238.       }
  1239.     }
  1240.     $c isset$a->created['value')) $a->created['value'$a->dtstamp['value'];
  1241.     $d isset$b->created['value')) $b->created['value'$b->dtstamp['value'];
  1242.     foreach$this->_sortkeys as $key {
  1243.       if(       !isset$a->created['value'][$key))  return -1;
  1244.       elseif(   !isset$b->created['value'][$key))  return  1;
  1245.       if    (           $a->created['value'][$key]
  1246.                      == $b->created['value'][$key)
  1247.         continue;
  1248.       if    ((    (int) $a->created['value'][$key<
  1249.              (    (int) $b->created['value'][$key))  return -1;
  1250.       elseif((    (int) $a->created['value'][$key>
  1251.              (    (int) $b->created['value'][$key))  return  1;
  1252.     }
  1253.     if    ((            $a->uid['value'<
  1254.            (            $b->uid['value'))            return -1;
  1255.     elseif((            $a->uid['value'>
  1256.            (            $b->uid['value'))            return  1;
  1257.     return 0;
  1258.   }
  1259.   function sort({
  1260.     ifis_array$this->components )) {
  1261.       $this->_sortkeys array'year''month''day''hour''min''sec' );
  1262.       usort$this->componentsarray$this'_cmpfcn' ));
  1263.     }
  1264.   }
  1265. /**
  1266.  * parse iCal file into vcalendar, components, properties and parameters
  1267.  *
  1268.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1269.  * @since 2.4.3 - 2008-02-13
  1270.  * @param string $filename optional filname (incl. opt. directory/path) or URL
  1271.  * @return bool FALSE if error occurs during parsing
  1272.  *
  1273.  */
  1274.   function parse$filename=FALSE {
  1275.     if!$filename {
  1276.             /* directory/filename previous set via setConfig directory+filename / url */
  1277.       ifFALSE === $filename $this->getConfig'url' )))
  1278.         $filename $this->getConfig'dirfile' );
  1279.     }
  1280.     elseif(( 'http://'   == strtolowersubstr$filename0))) ||
  1281.            'webcal://' == strtolowersubstr$filename0))))  {
  1282.             /* remote file - URL */
  1283.       $this->setConfig'URL'$filename );
  1284.       if!$filename $this->getConfig'url' ))
  1285.         return FALSE;                 /* err 2 */
  1286.     }
  1287.     else {
  1288.             /* local directory/filename */
  1289.       $parts pathinfo$filename );
  1290.       if!empty$parts['dirname'&& '.' != $parts['dirname')) {
  1291.         if!$this->setConfig'directory'$parts['dirname'))
  1292.           return FALSE;               /* err 3 */
  1293.       }
  1294.       if!$this->setConfig'filename'$parts['basename'))
  1295.         return FALSE;                 /* err 4 */
  1296.     }
  1297.     if'http://' != substr$filename0)) {
  1298.             /* local file error tests */
  1299.       if!is_file$filename ))      /* err 5 */
  1300.         return FALSE;
  1301.       if!is_readable$filename ))
  1302.         return FALSE;                 /* err 6 */
  1303.       if!filesize$filename ))
  1304.         return FALSE;                 /* err 7 */
  1305.       clearstatcache();
  1306.     }
  1307.             /* READ FILE */
  1308.     ifFALSE === $rows file$filename )))
  1309.       return FALSE;                   /* err 1 */
  1310.             /* identify BEGIN:VCALENDAR, MUST be first row */
  1311.     if'BEGIN:VCALENDAR' != strtouppertrim$rows[0)))
  1312.       return FALSE;                   /* err 8 */
  1313.             /* remove empty trailing lines */
  1314.     while'' == trim$rows[count$rows 1)) {
  1315.       unset$rows[count$rows 1);
  1316.       $rows  array_values$rows );
  1317.     }
  1318.             /* identify ending END:VCALENDAR row */
  1319.     if'END:VCALENDAR'   != strtouppertrim$rows[count$rows 1))) {
  1320.       return FALSE;                   /* err 9 */
  1321.     }
  1322.     ifcount$rows ))
  1323.       return FALSE;                   /* err 10 */
  1324.     $comp    $subcomp null;
  1325.     $actcomp $this;
  1326.     $nl      $this->getConfig'nl' );
  1327.     $calsync 0;
  1328.             /* identify components and update unparsed data within component */
  1329.     foreach$rows as $line {
  1330.       if'' == trim$line ))
  1331.         continue;
  1332.       if$nl == substr$linestrlen$nl )))
  1333.         $line substr$line0strlen$line strlen$nl ))).'\n';
  1334.       if'BEGIN:VCALENDAR' == strtouppersubstr$line015 ))) {
  1335.         $calsync++;
  1336.         continue;
  1337.       }
  1338.       elseif'END:VCALENDAR' == strtouppersubstr$line013 ))) {
  1339.         $calsync--;
  1340.         continue;
  1341.       }
  1342.       elseif!= $calsync )
  1343.         return FALSE;                 /* err 20 */
  1344.       if'END:' == strtouppersubstr$line0))) {
  1345.         ifnull != $subcomp {
  1346.           $comp->setComponent$subcomp );
  1347.           $subcomp null;
  1348.         }
  1349.         else {
  1350.           $this->setComponent$comp );
  1351.           $comp null;
  1352.         }
  1353.         $actcomp null;
  1354.         continue;
  1355.       // end - if ( 'END:' ==.. .
  1356.       elseif'BEGIN:' == strtouppersubstr$line0))) {
  1357.         $line str_replace'\n'''$line );
  1358.         $compname trim (strtouppersubstr$line)));
  1359.         ifnull != $comp {
  1360.           if'VALARM' == $compname )
  1361.             $subcomp new valarm();
  1362.           elseif'STANDARD' == $compname )
  1363.             $subcomp new vtimezone'STANDARD' );
  1364.           elseif'DAYLIGHT' == $compname )
  1365.             $subcomp new vtimezone'DAYLIGHT' );
  1366.           else
  1367.             return FALSE/* err 6 */
  1368.           $actcomp $subcomp;
  1369.         }
  1370.         else {
  1371.           switch$compname {
  1372.             case 'VALARM':
  1373.               $comp new valarm();
  1374.               break;
  1375.             case 'VEVENT':
  1376.               $comp new vevent();
  1377.               break;
  1378.             case 'VFREEBUSY';
  1379.               $comp new vfreebusy();
  1380.               break;
  1381.             case 'VJOURNAL':
  1382.               $comp new vjournal();
  1383.               break;
  1384.             case 'VTODO':
  1385.               $comp new vtodo();
  1386.               break;
  1387.             case 'VTIMEZONE':
  1388.               $comp new vtimezone();
  1389.               break;
  1390.             default:
  1391.               return FALSE// err 7
  1392.               break;
  1393.           // end - switch
  1394.           $actcomp $comp;
  1395.         }
  1396.         continue;
  1397.       // end - elsif ( 'BEGIN:'.. .
  1398.             /* update selected component with unparsed data */
  1399.       $actcomp->unparsed[$line;
  1400.     // end - foreach( rows.. .
  1401.             /* parse data for calendar (this) object */
  1402.     ifis_array$this->unparsed && count$this->unparsed ))) {
  1403.             /* concatenate property values spread over several lines */
  1404.       $lastix    = -1;
  1405.       $propnames array'calscale','method','prodid','version','x-' );
  1406.       $proprows  array();
  1407.       foreach$this->unparsed as $line {
  1408.         $newProp FALSE;
  1409.         foreach $propnames as $propname {
  1410.           if$propname == strtolowersubstr$line0strlen$propname )))) {
  1411.             $newProp TRUE;
  1412.             break;
  1413.           }
  1414.         }
  1415.         if$newProp {
  1416.           $newProp FALSE;
  1417.           $lastix++;
  1418.           $proprows[$lastix]  $line;
  1419.         }
  1420.         else {
  1421.             /* remove line breaks */
  1422.           if(( '\n' == substr$proprows[$lastix]-)) &&
  1423.              (  ' ' == substr$line0))) {
  1424.             $proprows[$lastixsubstr$proprows[$lastix]0strlen$proprows[$lastix);
  1425.             $line substr$line);
  1426.           }
  1427.           $proprows[$lastix.= $line;
  1428.         }
  1429.       }
  1430.       $toolbox new calendarComponent();
  1431.       foreach$proprows as $line {
  1432.         if'\n' == substr$line-))
  1433.           $line substr$line0strlen$line );
  1434.             /* get propname */
  1435.         $cix $propname null;
  1436.         for$cix=0$cix strlen$line )$cix++ {
  1437.           ifin_array$line{$cix}array':'';' )))
  1438.             break;
  1439.           else
  1440.             $propname .= $line{$cix};
  1441.         }
  1442.             /* ignore version/prodid properties */
  1443.         ifin_arraystrtoupper$propname )array'VERSION''PRODID' )))
  1444.           continue;
  1445.         $line substr$line$cix);
  1446.             /* separate attributes from value */
  1447.         $attr   array();
  1448.         $attrix = -1;
  1449.         $strlen strlen$line );
  1450.         for$cix=0$cix $strlen$cix++ {
  1451.           if((       ':'   == $line{$cix)             &&
  1452.                    '://' != substr$line$cix)) &&
  1453.              'mailto:'   != strtolowersubstr$line$cix 6)))) {
  1454.             $attrEnd TRUE;
  1455.             if(( $cix $strlen )) &&
  1456.                  ctype_digitsubstr$line$cix+1))) // an URI with a (4pos) portnr??
  1457.               for$c2ix $cix$c2ix$c2ix-- {
  1458.                 if'://' == substr$line$c2ix 2)) {
  1459.                   $attrEnd FALSE;
  1460.                   break// an URI with a portnr!!
  1461.                 }
  1462.               }
  1463.             }
  1464.             if$attrEnd{
  1465.               $line substr$line$cix );
  1466.               break;
  1467.             }
  1468.           }
  1469.           if';' == $line{$cix)
  1470.             $attr[++$attrixnull;
  1471.           else
  1472.             $attr[$attrix.= $line{$cix};
  1473.         }
  1474.  
  1475.             /* make attributes in array format */
  1476.         $propattr array();
  1477.         foreach$attr as $attribute {
  1478.           $attrsplit explode'='$attribute);
  1479.           ifcount$attrsplit ))
  1480.             $propattr[$attrsplit[0]] $attrsplit[1];
  1481.           else
  1482.             $propattr[$attribute;
  1483.         }
  1484.             /* update Property */
  1485.         ifFALSE !== strpos$line',' )) {
  1486.           $content  explode','$line );
  1487.           $clen     count$content );
  1488.           for$cix 0$cix $clen$cix++ {
  1489.             if"\\" == substr$content[$cix]-)) {
  1490.               $content[$cix.= ','.$content[$cix 1];
  1491.               unset$content[$cix 1);
  1492.               $cix++;
  1493.             }
  1494.           }
  1495.           ifcount$content )) {
  1496.             foreach$content as $cix => $contentPart )
  1497.               $content[$cix$toolbox->_strunrep$contentPart );
  1498.             $this->setProperty$propname$content$propattr );
  1499.             continue;
  1500.           }
  1501.           else
  1502.             $line reset$content );
  1503.           $line $toolbox->_strunrep$line );
  1504.         }
  1505.         $this->setProperty$propnametrim$line )$propattr );
  1506.       // end - foreach( $this->unparsed.. .
  1507.     // end - if( is_array( $this->unparsed.. .
  1508.             /* parse Components */
  1509.     ifis_array$this->components && count$this->components ))) {
  1510.       for$six 0$six count$this->components )$six++ )
  1511.         $this->components[$six]->parse();
  1512.     }
  1513.     else
  1514.       return FALSE;                   /* err 91 or something.. . */
  1515.   }
  1516. /*********************************************************************************/
  1517. /**
  1518.  * creates formatted output for calendar object instance
  1519.  *
  1520.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1521.  * @since 2.2.13 - 2007-10-25
  1522.  * @return string 
  1523.  */
  1524.   function createCalendar({
  1525.     $calendarInit1 $calendarInit2 $calendarxCaldecl $calendarStart $calendar null;
  1526.     switch$this->format {
  1527.       case 'xcal':
  1528.         $calendarInit1 '<?xml version="1.0" encoding="UTF-8"?>'.$this->nl.
  1529.                          '<!DOCTYPE iCalendar PUBLIC "-//IETF//DTD XCAL/iCalendar XML//EN"'.$this->nl.
  1530.                          '"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-01.txt"';
  1531.         $calendarInit2 '>'.$this->nl;
  1532.         $calendarStart '<vcalendar';
  1533.         break;
  1534.       default:
  1535.         $calendarStart 'BEGIN:VCALENDAR'.$this->nl;
  1536.         break;
  1537.     }
  1538.     $calendarStart .= $this->createCalscale();
  1539.     $calendarStart .= $this->createMethod();
  1540.     $calendarStart .= $this->createProdid();
  1541.     $calendarStart .= $this->createVersion();
  1542.     switch$this->format {
  1543.       case 'xcal':
  1544.         $nlstrlen strlen$this->nl );
  1545.         if$this->nl == substr$calendarStart$nlstrlen )))
  1546.           $calendarStart substr$calendarStart0strlen$calendarStart $nlstrlen ));
  1547.         $calendarStart .= '>'.$this->nl;
  1548.         break;
  1549.       default:
  1550.         break;
  1551.     }
  1552.     $calendar .= $this->createXprop();
  1553.     foreach$this->components as $component {
  1554.       if'' >= $component->getConfig'language'))
  1555.         $component->setConfig'language',  $this->getConfig'language' ));
  1556.       $component->setConfig'allowEmpty',  $this->getConfig'allowEmpty' ));
  1557.       $component->setConfig'nl',          $this->getConfig'nl' ));
  1558.       $component->setConfig'unique_id',   $this->getConfig'unique_id' ));
  1559.       $component->setConfig'format',      $this->getConfig'format' ));
  1560.       $calendar .= $component->createComponent$this->xcaldecl );
  1561.     }
  1562.     if(( count$this->xcaldecl )) && 'xcal' == $this->format )) // xCal only
  1563.       $calendarInit1 .= $this->nl.'['.$this->nl;
  1564.       $old_xcaldecl array();
  1565.       foreach$this->xcaldecl as $declix => $declPart {
  1566.         if(( count$old_xcaldecl)) &&
  1567.            in_array$declPart['uri'],      $old_xcaldecl['uri')) &&
  1568.            in_array$declPart['external']$old_xcaldecl['external')))
  1569.           continue// no duplicate uri and ext. references
  1570.         $calendarxCaldecl .= '<!';
  1571.         foreach$declPart as $declKey => $declValue {
  1572.           switch$declKey {                    // index
  1573.             case 'xmldecl':                       // no 1
  1574.               $calendarxCaldecl .= $declValue.' ';
  1575.               break;
  1576.             case 'uri':                           // no 2
  1577.               $calendarxCaldecl .= $declValue.' ';
  1578.               $old_xcaldecl['uri'][$declValue;
  1579.               break;
  1580.             case 'ref':                           // no 3
  1581.               $calendarxCaldecl .= $declValue.' ';
  1582.               break;
  1583.             case 'external':                      // no 4
  1584.               $calendarxCaldecl .= '"'.$declValue.'" ';
  1585.               $old_xcaldecl['external'][$declValue;
  1586.               break;
  1587.             case 'type':                          // no 5
  1588.               $calendarxCaldecl .= $declValue.' ';
  1589.               break;
  1590.             case 'type2':                         // no 6
  1591.               $calendarxCaldecl .= $declValue;
  1592.               break;
  1593.           }
  1594.         }
  1595.         $calendarxCaldecl .= '>'.$this->nl;
  1596.       }
  1597.       $calendarInit2 ']'.$calendarInit2;
  1598.     }
  1599.     switch$this->format {
  1600.       case 'xcal':
  1601.         $calendar .= '</vcalendar>'.$this->nl;
  1602.         break;
  1603.       default:
  1604.         $calendar .= 'END:VCALENDAR'.$this->nl;
  1605.         break;
  1606.     }
  1607.     return $calendarInit1.$calendarxCaldecl.$calendarInit2.$calendarStart.$calendar;
  1608.   }
  1609. /**
  1610.  * a HTTP redirect header is sent with created, updated and/or parsed calendar
  1611.  *
  1612.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1613.  * @since 2.2.12 - 2007-10-23
  1614.  * @return redirect 
  1615.  */
  1616.   function returnCalendar({
  1617.     $filename $this->getConfig'filename' );
  1618.     $output   $this->createCalendar();
  1619.     $filesize strlen$output );
  1620. //    if( headers_sent( $filename, $linenum ))
  1621. //      die( "Headers already sent in $filename on line $linenum\n" );
  1622.     if'xcal' == $this->format )
  1623.       header'Content-Type: application/calendar+xml; charset=utf-8' );
  1624.     else
  1625.       header'Content-Type: text/calendar; charset=utf-8' );
  1626.     header'Content-Length: '.$filesize );
  1627.     header'Content-Disposition: attachment; filename="'.$filename.'"' );
  1628.     header'Cache-Control: max-age=10' );
  1629.     echo $output;
  1630.     die();
  1631.   }
  1632. /**
  1633.  * save content in a file
  1634.  *
  1635.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1636.  * @since 2.2.12 - 2007-12-30
  1637.  * @param string $directory optional
  1638.  * @param string $filename optional
  1639.  * @param string $delimiter optional
  1640.  * @return bool 
  1641.  */
  1642.   function saveCalendar$directory=FALSE$filename=FALSE$delimiter=FALSE {
  1643.     if$directory )
  1644.       $this->setConfig'directory'$directory );
  1645.     if$filename )
  1646.       $this->setConfig'filename',  $filename );
  1647.     if$delimiter && ($delimiter != DIRECTORY_SEPARATOR ))
  1648.       $this->setConfig'delimiter'$delimiter );
  1649.     ifFALSE === $dirfile $this->getConfig'url' )))
  1650.       $dirfile $this->getConfig'dirfile' );
  1651.     $iCalFile @fopen$dirfile'w' );
  1652.     if$iCalFile {
  1653.       ifFALSE === fwrite$iCalFile$this->createCalendar() ))
  1654.         return FALSE;
  1655.       fclose$iCalFile );
  1656.       return TRUE;
  1657.     }
  1658.     else
  1659.       return FALSE;
  1660.   }
  1661. /**
  1662.  * if recent version of calendar file exists (default one hour), an HTTP redirect header is sent
  1663.  * else FALSE is returned
  1664.  *
  1665.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1666.  * @since 2.2.12 - 2007-10-28
  1667.  * @param string $directory optional alt. int timeout
  1668.  * @param string $filename optional
  1669.  * @param string $delimiter optional
  1670.  * @param int timeout optional, default 3600 sec
  1671.  * @return redirect/FALSE 
  1672.  */
  1673.   function useCachedCalendar$directory=FALSE$filename=FALSE$delimiter=FALSE$timeout=3600{
  1674.     if $directory && ctype_digit(string) $directory && !$filename {
  1675.       $timeout   = (int) $directory;
  1676.       $directory FALSE;
  1677.     }
  1678.     if$directory )
  1679.       $this->setConfig'directory'$directory );
  1680.     if$filename )
  1681.       $this->setConfig'filename',  $filename );
  1682.     if$delimiter && $delimiter != DIRECTORY_SEPARATOR ))
  1683.       $this->setConfig'delimiter'$delimiter );
  1684.     $filesize    $this->getConfig'filesize' );
  1685.     if>= $filesize )
  1686.       return FALSE;
  1687.     $dirfile     $this->getConfig'dirfile' );
  1688.     iftime(filemtime$dirfile $timeout{
  1689.       clearstatcache();
  1690.       $dirfile   $this->getConfig'dirfile' );
  1691.       $filename  $this->getConfig'filename' );
  1692. //    if( headers_sent( $filename, $linenum ))
  1693. //      die( "Headers already sent in $filename on line $linenum\n" );
  1694.       if'xcal' == $this->format )
  1695.         header'Content-Type: application/calendar+xml; charset=utf-8' );
  1696.       else
  1697.         header'Content-Type: text/calendar; charset=utf-8' );
  1698.       header'Content-Length: '.$filesize );
  1699.       header'Content-Disposition: attachment; filename="'.$filename.'"' );
  1700.       header'Cache-Control: max-age=10' );
  1701.       $fp @$fopen$dirfile'r' );
  1702.       if$fp {
  1703.         fpassthru$fp );
  1704.         fclose$fp );
  1705.       }
  1706.       die();
  1707.     }
  1708.     else
  1709.       return FALSE;
  1710.   }
  1711. }
  1712. /*********************************************************************************/
  1713. /*********************************************************************************/
  1714. /**
  1715.  *  abstract class for calendar components
  1716.  *
  1717.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1718.  * @since 2.3.1 - 2007-11-19
  1719.  */
  1720.             //  component property variables
  1721.   var $uid;
  1722.   var $dtstamp;
  1723.  
  1724.   var $action;
  1725.   var $attach;
  1726.   var $attendee;
  1727.   var $categories;
  1728.   var $comment;
  1729.   var $completed;
  1730.   var $contact;
  1731.   var $class;
  1732.   var $created;
  1733.   var $description;
  1734.   var $dtend;
  1735.   var $dtstart;
  1736.   var $due;
  1737.   var $duration;
  1738.   var $exdate;
  1739.   var $exrule;
  1740.   var $freebusy;
  1741.   var $geo;
  1742.   var $lastmodified;
  1743.   var $location;
  1744.   var $organizer;
  1745.   var $priority;
  1746.   var $rdate;
  1747.   var $recurrenceid;
  1748.   var $relatedto;
  1749.   var $repeat;
  1750.   var $requeststatus;
  1751.   var $resources;
  1752.   var $rrule;
  1753.   var $sequence;
  1754.   var $status;
  1755.   var $summary;
  1756.   var $transp;
  1757.   var $trigger;
  1758.   var $tzid;
  1759.   var $tzname;
  1760.   var $tzoffsetfrom;
  1761.   var $tzoffsetto;
  1762.   var $tzurl;
  1763.   var $url;
  1764.   var $xprop;
  1765.             //  component subcomponents container
  1766.   var $components;
  1767.             //  component config variables
  1768.   var $allowEmpty;
  1769.   var $language;
  1770.   var $nl;
  1771.   var $unique_id;
  1772.   var $format;
  1773.   var $objName// created automatically at instance creation
  1774.             //  component internal variables
  1775.   var $componentEnd1;
  1776.   var $componentEnd2;
  1777.   var $elementStart1;
  1778.   var $elementStart2;
  1779.   var $elementEnd1;
  1780.   var $elementEnd2;
  1781.   var $valueInit;
  1782.             //  component xCal declaration container
  1783.   var $xcaldecl;
  1784. /**
  1785.  * constructor for calendar component object
  1786.  *
  1787.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1788.  * @since 2.3.1 - 2007-11-19
  1789.  */
  1790.   function calendarComponent({
  1791.     $this->objName         = isset$this->timezonetype )) ?
  1792.                           strtolower$this->timezonetype )  :  get_class $this );
  1793.     $this->uid             = array();
  1794.     $this->dtstamp         = array();
  1795.  
  1796.     $this->action          = array();
  1797.     $this->attach          = array();
  1798.     $this->attendee        = array();
  1799.     $this->categories      = array();
  1800.     $this->class           = array();
  1801.     $this->comment         = array();
  1802.     $this->completed       = array();
  1803.     $this->contact         = array();
  1804.     $this->created         = array();
  1805.     $this->description     = array();
  1806.     $this->dtend           = array();
  1807.     $this->dtstart         = array();
  1808.     $this->due             = array();
  1809.     $this->duration        = array();
  1810.     $this->exdate          = array();
  1811.     $this->exrule          = array();
  1812.     $this->freebusy        = array();
  1813.     $this->geo             = array();
  1814.     $this->lastmodified    = array();
  1815.     $this->location        = array();
  1816.     $this->organizer       = array();
  1817.     $this->percentcomplete = array();
  1818.     $this->priority        = array();
  1819.     $this->rdate           = array();
  1820.     $this->recurrenceid    = array();
  1821.     $this->relatedto       = array();
  1822.     $this->repeat          = array();
  1823.     $this->requeststatus   = array();
  1824.     $this->resources       = array();
  1825.     $this->sequence        = array();
  1826.     $this->rrule           = array();
  1827.     $this->status          = array();
  1828.     $this->summary         = array();
  1829.     $this->transp          = array();
  1830.     $this->trigger         = array();
  1831.     $this->tzid            = array();
  1832.     $this->tzname          = array();
  1833.     $this->tzoffsetfrom    = array();
  1834.     $this->tzoffsetto      = array();
  1835.     $this->tzurl           = array();
  1836.     $this->url             = array();
  1837.     $this->xprop           = array();
  1838.  
  1839.     $this->components      = array();
  1840.  
  1841.     $this->language        = null;
  1842.     $this->nl              = null;
  1843.     $this->unique_id       = null;
  1844.     $this->allowEmpty      = TRUE;
  1845.     $this->xcaldecl        = array();
  1846.  
  1847.     $this->_makeDtstamp();
  1848.   }
  1849. /*********************************************************************************/
  1850. /**
  1851.  * Property Name: ACTION
  1852.  */
  1853. /**
  1854.  * creates formatted output for calendar component property action
  1855.  *
  1856.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1857.  * @since 0.9.7 - 2006-11-20
  1858.  * @return string 
  1859.  */
  1860.   function createAction({
  1861.     if!isset$this->action['value'))
  1862.       return;
  1863.     $attributes $this->_createParams$this->action['params');
  1864.     return $this->_createElement'ACTION'$attributes$this->action['value');
  1865.   }
  1866. /**
  1867.  * set calendar component property action
  1868.  *
  1869.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1870.  * @since 0.9.2 - 2006-11-16
  1871.  * @param string $value  "AUDIO" / "DISPLAY" / "EMAIL" / "PROCEDURE"
  1872.  * @param mixed $params 
  1873.  * @return void 
  1874.  */
  1875.   function setAction$value$params=FALSE {
  1876.     $this->action['value']  $value;
  1877.     $this->action['params'$this->_setParams$params );
  1878.   }
  1879. /*********************************************************************************/
  1880. /**
  1881.  * Property Name: ATTACH
  1882.  */
  1883. /**
  1884.  * creates formatted output for calendar component property attach
  1885.  *
  1886.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1887.  * @since 0.9.7 - 2006-11-20
  1888.  * @return string 
  1889.  */
  1890.   function createAttach({
  1891.     $cnt count$this->attach );
  1892.     if>= $cnt )
  1893.       return;
  1894.     $output    null;
  1895.     foreach$this->attach as $attachPart {
  1896.       $attributes $this->_createParams$attachPart['params');
  1897.       $output    .= $this->_createElement'ATTACH'$attributes$attachPart['value');
  1898.     }
  1899.     return $output;
  1900.   }
  1901. /**
  1902.  * set calendar component property attach
  1903.  *
  1904.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1905.  * @since 0.9.22 - 2007-04-10
  1906.  * @param string $value 
  1907.  * @param string $params 
  1908.  * @return void 
  1909.  */
  1910.   function setAttach$value$params=FALSE{
  1911.     $attach           array();
  1912.     $attach['value']  $value ;
  1913.     $attach['params'$this->_setParams$params );
  1914.     $this->attach[]   $attach;
  1915.   }
  1916. /*********************************************************************************/
  1917. /**
  1918.  * Property Name: ATTENDEE
  1919.  */
  1920. /**
  1921.  * creates formatted output for calendar component property attendee
  1922.  *
  1923.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1924.  * @since 1.x.x - 2007-05-20
  1925.  * @return string 
  1926.  */
  1927.   function createAttendee({
  1928.     $cnt count$this->attendee );
  1929.     if>= $cnt )
  1930.       return;
  1931.     $attendees null;
  1932.     foreach$this->attendee as $attendeePart {                      // start foreach 1
  1933.       $attendee1 $attendee2 $attendeeLANG $attendeeCN null;
  1934.       foreach$attendeePart as $paramlabel => $paramvalue {         // start foreach 2
  1935.         if'value' == $paramlabel {
  1936.           $attendee2  .= 'MAILTO:'.$paramvalue;
  1937.         }
  1938.         elseif(( 'params' == $paramlabel && is_array$paramvalue ))) // start elseif
  1939.           foreach$paramvalue as $optparamlabel => $optparamvalue // start foreach 3
  1940.             $attendee11 $attendee12 null;
  1941.             ifis_int$optparamlabel )) {
  1942.               $attendee1 .= $this->intAttrDelimiter.$optparamvalue;
  1943.               continue;
  1944.             }
  1945.             switch$optparamlabel {                                 // start switch
  1946.               case 'CUTYPE':
  1947.               case 'PARTSTAT':
  1948.               case 'ROLE':
  1949.               case 'RSVP':
  1950.                 $attendee1 .= $this->intAttrDelimiter.$optparamlabel.'="'.$optparamvalue.'"';
  1951.                 break;
  1952.               case 'SENT-BY':
  1953.                 $attendee1 .= $this->intAttrDelimiter.'SENT-BY="MAILTO:'.$optparamvalue.'"';
  1954.                 break;
  1955.               case 'MEMBER':
  1956.                 $attendee11 $this->intAttrDelimiter.'MEMBER=';
  1957.               case 'DELEGATED-TO':
  1958.                 $attendee11 !$attendee11 $this->intAttrDelimiter.'DELEGATED-TO='   $attendee11;
  1959.               case 'DELEGATED-FROM':
  1960.                 $attendee11 !$attendee11 $this->intAttrDelimiter.'DELEGATED-FROM=' $attendee11;
  1961.                 foreach$optparamvalue  as $cix => $calUserAddress {
  1962.                   $attendee12 .= $cix ',' null;
  1963.                   $attendee12 .= '"MAILTO:'.$calUserAddress.'"';
  1964.                 }
  1965.                 $attendee1  .= $attendee11.$attendee12;
  1966.                 break;
  1967.               case 'CN':
  1968.                 $attendeeCN .= $this->intAttrDelimiter.'CN="'.$optparamvalue.'"';
  1969.                 break;
  1970.               case 'DIR':
  1971.                 $attendee1 .= $this->intAttrDelimiter.'DIR="'.$optparamvalue.'"';
  1972.                 break;
  1973.               case 'LANGUAGE':
  1974.                 $attendeeLANG .= $this->intAttrDelimiter.'LANGUAGE='.$optparamvalue;
  1975.                 break;
  1976.               default:
  1977.                 $attendee1 .= $this->intAttrDelimiter."$optparamlabel=$optparamvalue";
  1978.                 break;
  1979.             }    // end switch
  1980.           }      // end foreach 3
  1981.         }        // end elseif
  1982.       }          // end foreach 2
  1983.       $attendees .= $this->_createElement'ATTENDEE'$attendee1.$attendeeLANG.$attendeeCN$attendee2 );
  1984.     }              // end foreach 1
  1985.     return $attendees;
  1986.   }
  1987. /**
  1988.  * set calendar component property attach
  1989.  *
  1990.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  1991.  * @since 1.x.x - 2007-05-24
  1992.  * @param string $value 
  1993.  * @param array $params optional
  1994.  * @return void 
  1995.  */
  1996.   function setAttendee$value$params=FALSE {
  1997.     $value str_replace 'MAILTO:'''$value );
  1998.     $value str_replace 'mailto:'''$value );
  1999.     $attendee array'value' => $value'params' => array() );
  2000.     ifis_array($params )) {
  2001.       $optarrays array();
  2002.       foreach$params as $optparamlabel => $optparamvalue {
  2003.         $optparamlabel strtoupper$optparamlabel );
  2004.         switch$optparamlabel {
  2005.           case 'MEMBER':
  2006.           case 'DELEGATED-TO':
  2007.           case 'DELEGATED-FROM':
  2008.             ifis_array$optparamvalue )) {
  2009.               foreach$optparamvalue as $part {
  2010.                 $part str_replace'MAILTO:'''$part );
  2011.                 $part str_replace'mailto:'''$part );
  2012.                 if(( '"' == $part{0&& '"' == $part{strlen($part)-1))
  2013.                   $part substr$part1strlen($part)-));
  2014.                 $optarrays[$optparamlabel][$part;
  2015.               }
  2016.             }
  2017.             else {
  2018.               $part str_replace'MAILTO:'''$optparamvalue );
  2019.               $part str_replace'mailto:'''$part );
  2020.               if(( '"' == $part{0&& '"' == $part{strlen($part)-1))
  2021.                 $part substr$part1strlen($part)-));
  2022.               $optarrays[$optparamlabel][$part;
  2023.             }
  2024.             break;
  2025.           default:
  2026.             if'SENT-BY' ==  $optparamlabel {
  2027.               $optparamvalue str_replace'MAILTO:'''$optparamvalue );
  2028.               $optparamvalue str_replace'mailto:'''$optparamvalue );
  2029.             }
  2030.             if(( '"' == substr$optparamvalue0)) &&
  2031.                '"' == substr$optparamvalue-)))
  2032.               $optparamvalue substr$optparamvalue1strlen$optparamvalue ));
  2033.             $attendee['params'][$optparamlabel$optparamvalue;
  2034.             break;
  2035.         // end switch( $optparamlabel.. .
  2036.       // end foreach( $optparam.. .
  2037.       foreach$optarrays as $optparamlabel => $optparams )
  2038.         $attendee['params'][$optparamlabel$optparams;
  2039.     }
  2040.         // remove defaults
  2041.     ifisset$attendee['params']['CUTYPE' )  &&
  2042.        strtoupper$attendee['params']['CUTYPE' )  == 'INDIVIDUAL' ))
  2043.       unset$attendee['params']['CUTYPE' );
  2044.     ifisset$attendee['params']['PARTSTAT'&&
  2045.        strtoupper$attendee['params']['PARTSTAT'== 'NEEDS-ACTION' ))
  2046.       unset$attendee['params']['PARTSTAT');
  2047.     ifisset$attendee['params']['ROLE')     &&
  2048.        strtoupper$attendee['params']['ROLE')     == 'REQ-PARTICIPANT' ))
  2049.       unset$attendee['params']['ROLE');
  2050.     ifisset$attendee['params']['RSVP')     &&
  2051.        strtoupper$attendee['params']['RSVP')     == 'FALSE' ))
  2052.       unset$attendee['params']['RSVP');
  2053.         // check language setting
  2054.     ifisset$attendee['params']['CN' )) {
  2055.       $lang $this->getConfig'language' );
  2056.       if!isset$attendee['params']['LANGUAGE' && !empty$lang ))
  2057.         $attendee['params']['LANGUAGE' $lang;
  2058.     }
  2059.     $this->attendee[$attendee;
  2060.   }
  2061. /*********************************************************************************/
  2062. /**
  2063.  * Property Name: CATEGORIES
  2064.  */
  2065. /**
  2066.  * creates formatted output for calendar component property categories
  2067.  *
  2068.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2069.  * @since 2.3.2 - 2007-11-24
  2070.  * @return string 
  2071.  */
  2072.   function createCategories({
  2073.     $cnt count$this->categories );
  2074.     if>= $cnt )
  2075.       return;
  2076.     $output null;
  2077.     foreach$this->categories as $category {
  2078.       $attributes $this->_createParams$category['params']array'LANGUAGE' ));
  2079.       ifis_array$category['value')) {
  2080.         foreach$category['value'as $cix => $categoryPart )
  2081.           $category['value'][$cix$this->_strrep$categoryPart );
  2082.         $content  implode','$category['value');
  2083.       }
  2084.       else
  2085.         $content  $this->_strrep$category['value');
  2086.       $output    .= $this->_createElement'CATEGORIES'$attributes$content );
  2087.     }
  2088.     return $output;
  2089.   }
  2090. /**
  2091.  * set calendar component property categories
  2092.  *
  2093.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2094.  * @since 2.3.2 - 2007-11-24
  2095.  * @param mixed $value 
  2096.  * @param array $params optional
  2097.  * @return void 
  2098.  */
  2099.   function setCategories$value$params=FALSE {
  2100.     $category array();
  2101.     $category['value']  $value;
  2102.     $category['params'$this->_setParams$params );
  2103.     $this->categories[$category;
  2104.   }
  2105. /*********************************************************************************/
  2106. /**
  2107.  * Property Name: CLASS
  2108.  */
  2109. /**
  2110.  * creates formatted output for calendar component property class
  2111.  *
  2112.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2113.  * @since 0.9.7 - 2006-11-20
  2114.  * @return string 
  2115.  */
  2116.   function createClass({
  2117.     $cnt count$this->class );
  2118.     if>= $cnt )
  2119.       return;
  2120.     $attributes $this->_createParams$this->class['params');
  2121.     return $this->_createElement'CLASS'$attributes$this->class['value');
  2122.   }
  2123. /**
  2124.  * set calendar component property class
  2125.  *
  2126.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2127.  * @since 0.9.18 - 2003-03-18
  2128.  * @param string $value "PUBLIC" / "PRIVATE" / "CONFIDENTIAL" / iana-token / x-name
  2129.  * @param array $params optional
  2130.  * @return void 
  2131.  */
  2132.   function setClass$value$params=FALSE {
  2133.     $this->class['value']  $value;
  2134.     $this->class['params'$this->_setParams$params );
  2135.   }
  2136. /*********************************************************************************/
  2137. /**
  2138.  * Property Name: COMMENT
  2139.  */
  2140. /**
  2141.  * creates formatted output for calendar component property comment
  2142.  *
  2143.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2144.  * @since 0.9.7 - 2006-11-20
  2145.  * @return string 
  2146.  */
  2147.   function createComment({
  2148.     $cnt count$this->comment );
  2149.      if>= $cnt )
  2150.       return;
  2151.     $comment null;
  2152.     foreach$this->comment as $commentPart {
  2153.       $attributes $this->_createParams$commentPart['params']array'ALTREP''LANGUAGE' ));
  2154.       $content    $this->_strrep$commentPart['value');
  2155.       $comment   .= $this->_createElement'COMMENT'$attributes$content );
  2156.     }
  2157.     return $comment;
  2158.   }
  2159. /**
  2160.  * set calendar component property comment
  2161.  *
  2162.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2163.  * @since 0.9.18 - 2007-03-18
  2164.  * @param string $value 
  2165.  * @param array $params optional
  2166.  * @return void 
  2167.  */
  2168.   function setComment$value$params=FALSE {
  2169.     $comment['value']  $value;
  2170.     $comment['params'$this->_setParams$params );
  2171.     $this->comment[]   $comment;
  2172.   }
  2173. /*********************************************************************************/
  2174. /**
  2175.  * Property Name: COMPLETED
  2176.  */
  2177. /**
  2178.  * creates formatted output for calendar component property completed
  2179.  *
  2180.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2181.  * @since 0.9.7 - 2006-11-20
  2182.  * @return string 
  2183.  */
  2184.   function createCompleted{
  2185.     if!isset$this->completed['value']['year')  &&
  2186.         !isset$this->completed['value']['month'&&
  2187.         !isset$this->completed['value']['day')   &&
  2188.         !isset$this->completed['value']['hour')  &&
  2189.         !isset$this->completed['value']['min')   &&
  2190.         !isset$this->completed['value']['sec'))
  2191.       return;
  2192.     $formatted  $this->_format_date_time$this->completed['value']);
  2193.     $attributes $this->_createParams$this->completed['params');
  2194.     return $this->_createElement'COMPLETED'$attributes$formatted );
  2195.   }
  2196. /**
  2197.  * set calendar component property completed
  2198.  *
  2199.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2200.  * @since 2.2.2 - 2007-08-02
  2201.  * @param mixed $year 
  2202.  * @param mixed $month optional
  2203.  * @param int $day optional
  2204.  * @param int $hour optional
  2205.  * @param int $min optional
  2206.  * @param int $sec optional
  2207.  * @param array $params optional
  2208.  * @return void 
  2209.  */
  2210.   function setCompleted$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$params=FALSE {
  2211.     $this->completed = $this->_setDate2$year$month$day$hour$min$sec$params );
  2212.   }
  2213. /*********************************************************************************/
  2214. /**
  2215.  * Property Name: CONTACT
  2216.  */
  2217. /**
  2218.  * creates formatted output for calendar component property contact
  2219.  *
  2220.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2221.  * @since 1.x.x - 2007-05-24
  2222.  * @return string 
  2223.  */
  2224.   function createContact({
  2225.     $cnt count$this->contact );
  2226.     if>= $cnt )
  2227.       return;
  2228.     $output null;
  2229.     foreach$this->contact as $contact {
  2230.       $attributes $this->_createParams$contact['params']array'ALTREP''LANGUAGE' ));
  2231.       $content    $this->_strrep$contact['value');
  2232.       $output    .= $this->_createElement'CONTACT'$attributes$content );
  2233.     }
  2234.     return $output;
  2235.   }
  2236. /**
  2237.  * set calendar component property contact
  2238.  *
  2239.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2240.  * @since 2.3.2 - 2007-11-25
  2241.  * @param string $value 
  2242.  * @param array $params optional
  2243.  * @return void 
  2244.  */
  2245.   function setContact$value$params=FALSE {
  2246.     $contact['value']  $value;
  2247.     $contact['params'$this->_setParams$params );
  2248.     $this->contact[$contact;
  2249.   }
  2250. /*********************************************************************************/
  2251. /**
  2252.  * Property Name: CREATED
  2253.  */
  2254. /**
  2255.  * creates formatted output for calendar component property created
  2256.  *
  2257.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2258.  * @since 0.9.7 - 2006-11-20
  2259.  * @return string 
  2260.  */
  2261.   function createCreated({
  2262.     if!isset$this->created['value']['year')  &&
  2263.         !isset$this->created['value']['month'&&
  2264.         !isset$this->created['value']['day')   &&
  2265.         !isset$this->created['value']['hour')  &&
  2266.         !isset$this->created['value']['min')   &&
  2267.         !isset$this->created['value']['sec'))
  2268.       return;
  2269.     $formatted  $this->_format_date_time$this->created['value']);
  2270.     $attributes $this->_createParams$this->created['params');
  2271.     return $this->_createElement'CREATED'$attributes$formatted );
  2272.   }
  2273. /**
  2274.  * set calendar component property created
  2275.  *
  2276.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2277.  * @since 2.2.2 - 2007-08-02
  2278.  * @param mixed $year optional
  2279.  * @param mixed $month optional
  2280.  * @param int $day optional
  2281.  * @param int $hour optional
  2282.  * @param int $min optional
  2283.  * @param int $sec optional
  2284.  * @param mixed $params optional
  2285.  * @return void 
  2286.  */
  2287.   function setCreated$year=FALSE$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$params=FALSE {
  2288.     if!isset$year )) {
  2289.       $year date('Ymd\THis'mktimedate'H' )date'i' )date's' date'Z')date'm' )date'd' )date'Y' )));
  2290.     }
  2291.     $this->created = $this->_setDate2$year$month$day$hour$min$sec$params );
  2292.   }
  2293. /*********************************************************************************/
  2294. /**
  2295.  * Property Name: DESCRIPTION
  2296.  */
  2297. /**
  2298.  * creates formatted output for calendar component property description
  2299.  *
  2300.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2301.  * @since 0.9.7 - 2006-11-20
  2302.  * @return string 
  2303.  */
  2304.   function createDescription({
  2305.     $cnt count$this->description );
  2306.     if>= $cnt )
  2307.       return;
  2308.     $descriptions    null;
  2309.     foreach$this->description as $description {
  2310.       $attributes    $this->_createParams$description['params']array'ALTREP''LANGUAGE' ));
  2311.       $content       $this->_strrep$description['value');
  2312.       $descriptions .= $this->_createElement'DESCRIPTION'$attributes$content );
  2313.     }
  2314.     return $descriptions;
  2315.   }
  2316. /**
  2317.  * set calendar component property description
  2318.  *
  2319.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2320.  * @since 0.9.18 - 2007-03-18
  2321.  * @param string $value 
  2322.  * @param array $params optional
  2323.  * @return void 
  2324.  */
  2325.   function setDescription$value$params=FALSE {
  2326.     $description['value']  $value;
  2327.     $description['params'$this->_setParams$params );
  2328.     $this->description[]   $description;
  2329.   }
  2330. /*********************************************************************************/
  2331. /**
  2332.  * Property Name: DTEND
  2333.  */
  2334. /**
  2335.  * creates formatted output for calendar component property dtend
  2336.  *
  2337.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2338.  * @since 0.9.19 - 2007-03-27
  2339.  * @return string 
  2340.  */
  2341.   function createDtend({
  2342.     if!isset$this->dtend['value']['year')  &&
  2343.         !isset$this->dtend['value']['month'&&
  2344.         !isset$this->dtend['value']['day')   &&
  2345.         !isset$this->dtend['value']['hour')  &&
  2346.         !isset$this->dtend['value']['min')   &&
  2347.         !isset$this->dtend['value']['sec'))
  2348.       return;
  2349.     $formatted  $this->_format_date_time$this->dtend['value');
  2350.     $attributes $this->_createParams$this->dtend['params');
  2351.     return $this->_createElement'DTEND'$attributes$formatted );
  2352.   }
  2353. /**
  2354.  * set calendar component property dtend
  2355.  *
  2356.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2357.  * @since 2.2.2 - 2007-07-29
  2358.  * @param mixed $year 
  2359.  * @param mixed $month optional
  2360.  * @param int $day optional
  2361.  * @param int $hour optional
  2362.  * @param int $min optional
  2363.  * @param int $sec optional
  2364.  * @param string $tz optional
  2365.  * @param array params optional
  2366.  * @return void 
  2367.  */
  2368.   function setDtend$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$tz=FALSE$params=FALSE {
  2369.     $this->dtend = $this->_setDate$year$month$day$hour$min$sec$tz$params );
  2370.   }
  2371. /*********************************************************************************/
  2372. /**
  2373.  * Property Name: DTSTAMP
  2374.  */
  2375. /**
  2376.  * creates formatted output for calendar component property dtstamp
  2377.  *
  2378.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2379.  * @since 2.2.4 - 2007-08-01
  2380.  * @return string 
  2381.  */
  2382.   function createDtstamp({
  2383.     if!isset$htis->dtstamp['value']['year')  &&
  2384.         !isset$this->dtstamp['value']['month'&&
  2385.         !isset$this->dtstamp['value']['day')   &&
  2386.         !isset$this->dtstamp['value']['hour')  &&
  2387.         !isset$this->dtstamp['value']['min')   &&
  2388.         !isset$this->dtstamp['value']['sec'))
  2389.       $this->_makeDtstamp();
  2390.     $formatted  $this->_format_date_time$this->dtstamp['value']);
  2391.     $attributes $this->_createParams$this->dtstamp['params');
  2392.     return $this->_createElement'DTSTAMP'$attributes$formatted );
  2393.   }
  2394. /**
  2395.  * computes datestamp for calendar component object instance dtstamp
  2396.  *
  2397.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2398.  * @since 1.x.x - 2007-05-13
  2399.  * @return void 
  2400.  */
  2401.   function _makeDtstamp({
  2402.     $this->dtstamp['value'array'year'  => date'Y' )
  2403.                                    'month' => date'm' )
  2404.                                    'day'   => date'd' )
  2405.                                    'hour'  => date'H' )
  2406.                                    'min'   => date'i' )
  2407.                                    'sec'   => date's' date'Z' ));
  2408.     $this->dtstamp['params'null;
  2409.   }
  2410. /**
  2411.  * set calendar component property dtstamp
  2412.  *
  2413.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2414.  * @since 2.2.2 - 2007-08-02
  2415.  * @param mixed $year 
  2416.  * @param mixed $month optional
  2417.  * @param int $day optional
  2418.  * @param int $hour optional
  2419.  * @param int $min optional
  2420.  * @param int $sec optional
  2421.  * @param array $params optional
  2422.  * @return void 
  2423.  */
  2424.   function setDtstamp$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$params=FALSE {
  2425.     $this->dtstamp = $this->_setDate2$year$month$day$hour$min$sec$params );
  2426.   }
  2427. /*********************************************************************************/
  2428. /**
  2429.  * Property Name: DTSTART
  2430.  */
  2431. /**
  2432.  * creates formatted output for calendar component property dtstart
  2433.  *
  2434.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2435.  * @since 0.9.7 - 2006-11-20
  2436.  * @param bool $localtime optional, default FALSE
  2437.  * @return string 
  2438.  */
  2439.   function createDtstart$localtime=FALSE {
  2440.     if!isset$this->dtstart['value']['year')  &&
  2441.         !isset$this->dtstart['value']['month'&&
  2442.         !isset$this->dtstart['value']['day')   &&
  2443.         !isset$this->dtstart['value']['hour')  &&
  2444.         !isset$this->dtstart['value']['min')   &&
  2445.         !isset$this->dtstart['value']['sec'))
  2446.       return;
  2447.     if$localtime )
  2448.       unset$this->dtstart['value']['tz');
  2449.     $formatted  $this->_format_date_time$this->dtstart['value');
  2450.     $attributes $this->_createParams$this->dtstart['params');
  2451.     return $this->_createElement'DTSTART'$attributes$formatted );
  2452.   }
  2453. /**
  2454.  * set calendar component property dtstart
  2455.  *
  2456.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2457.  * @since 2.2.2 - 2007-07-29
  2458.  * @param mixed $year 
  2459.  * @param mixed $month optional
  2460.  * @param int $day optional
  2461.  * @param int $hour optional
  2462.  * @param int $min optional
  2463.  * @param int $sec optional
  2464.  * @param string $tz optional
  2465.  * @param array $params optional
  2466.  * @return void 
  2467.  */
  2468.   function setDtstart$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$tz=FALSE$params=FALSE {
  2469.     $this->dtstart = $this->_setDate$year$month$day$hour$min$sec$tz$params );
  2470.   }
  2471. /*********************************************************************************/
  2472. /**
  2473.  * Property Name: DUE
  2474.  */
  2475. /**
  2476.  * creates formatted output for calendar component property due
  2477.  *
  2478.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2479.  * @since 0.9.19 - 2007-03-27
  2480.  * @return string 
  2481.  */
  2482.   function createDue({
  2483.     if!isset$this->due['value']['year')  &&
  2484.         !isset$this->due['value']['month'&&
  2485.         !isset$this->due['value']['day')   &&
  2486.         !isset$this->due['value']['hour')  &&
  2487.         !isset$this->due['value']['min')   &&
  2488.         !isset$this->due['value']['sec'))
  2489.       return;
  2490.     $formatted  $this->_format_date_time$this->due['value');
  2491.     $attributes $this->_createParams$this->due['params');
  2492.     return $this->_createElement'DUE'$attributes$formatted );
  2493.   }
  2494. /**
  2495.  * set calendar component property due
  2496.  *
  2497.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2498.  * @since 2.2.2 - 2007-07-29
  2499.  * @param mixed $year 
  2500.  * @param mixed $month optional
  2501.  * @param int $day optional
  2502.  * @param int $hour optional
  2503.  * @param int $min optional
  2504.  * @param int $sec optional
  2505.  * @param array $params optional
  2506.  * @return void 
  2507.  */
  2508.   function setDue$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$tz=FALSE$params=FALSE {
  2509.     $this->due = $this->_setDate$year$month$day$hour$min$sec$tz$params );
  2510.   }
  2511. /*********************************************************************************/
  2512. /**
  2513.  * Property Name: DURATION
  2514.  */
  2515. /**
  2516.  * creates formatted output for calendar component property duration
  2517.  *
  2518.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2519.  * @since 0.9.7 - 2006-11-20
  2520.  * @return string 
  2521.  */
  2522.   function createDuration({
  2523.     if!isset$this->duration['value']['week'&&
  2524.         !isset$this->duration['value']['day')  &&
  2525.         !isset$this->duration['value']['hour'&&
  2526.         !isset$this->duration['value']['min')  &&
  2527.         !isset$this->duration['value']['sec'))
  2528.       return;
  2529.     $attributes $this->_createParams$this->duration['params');
  2530.     return $this->_createElement'DURATION'$attributes$this->_format_duration$this->duration['value'));
  2531.   }
  2532. /**
  2533.  * set calendar component property duration
  2534.  *
  2535.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2536.  * @since 0.9.18 - 2007-03-18
  2537.  * @param mixed $week 
  2538.  * @param mixed $day optional
  2539.  * @param int $hour optional
  2540.  * @param int $min optional
  2541.  * @param int $sec optional
  2542.  * @param array $params optional
  2543.  * @return void 
  2544.  */
  2545.   function setDuration$week=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$params=FALSE {
  2546.     ifis_array$week ))  {
  2547.       $this->duration['value']  $this->_duration_array$week );
  2548.       $this->duration['params'$this->_setParams$day );
  2549.     }
  2550.     elseifis_string$week && <= strlentrim$week )))) {
  2551.       ifin_arraysubstr$week,0)array'+''-' )))
  2552.         $week substr$week);
  2553.       $this->duration['value']  $this->_duration_string$week );
  2554.       $this->duration['params'$this->_setParams$day );
  2555.     }
  2556.     else {
  2557.       $this->duration['value']  $this->_duration_arrayarray$week$day$hour$min$sec ));
  2558.       $this->duration['params'$this->_setParams$params );
  2559.     }
  2560.   }
  2561. /*********************************************************************************/
  2562. /**
  2563.  * Property Name: EXDATE
  2564.  */
  2565. /**
  2566.  * creates formatted output for calendar component property exdate
  2567.  *
  2568.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2569.  * @since 0.9.7 - 2006-11-20
  2570.  * @return string 
  2571.  */
  2572.   function createExdate({
  2573.     $cnt count$this->exdate );
  2574.     if>= $cnt )
  2575.       return;
  2576.     $output null;
  2577.     foreach$this->exdate as $theExdate {
  2578.       $content $attributes null;
  2579.       foreach$theExdate['value'as $eix => $exdatePart {
  2580.         $formatted $this->_format_date_time$exdatePart );
  2581.         ifisset$theExdate['params']['TZID'))
  2582.           $formatted str_replace'Z'''$formatted);
  2583.         if$eix {
  2584.           ifisset$theExdate['value'][0]['tz'&&
  2585.             ctype_digitsubstr$theExdate['value'][0]['tz']-)) ||
  2586.                 'Z' == $theExdate['value'][0]['tz'))) {
  2587.             if'Z' != substr$formatted-))
  2588.               $formatted .= 'Z';
  2589.           }
  2590.           else
  2591.             $formatted str_replace'Z'''$formatted );
  2592.         }
  2593.         if$eix )
  2594.           $content .= ',';
  2595.         $content .= $formatted;
  2596.       }
  2597.       $attributes .= $this->_createParams$theExdate['params');
  2598.       $output .= $this->_createElement'EXDATE'$attributes$content );
  2599.     }
  2600.     return $output;
  2601.   }
  2602. /**
  2603.  * set calendar component property exdate
  2604.  *
  2605.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2606.  * @since 2.0.5 - 2007-06-22
  2607.  * @param array exdates
  2608.  * @param array $params optional
  2609.  * @return void 
  2610.  */
  2611.   function setExdate$exdates$params=FALSE {
  2612.     $exdate array();
  2613.     $exdate['params'$this->_setParams$paramsarray'VALUE' => 'DATE-TIME' ) );
  2614.     $parno  isset$exdate['params']['TZID')) null;
  2615.     $parno  $this->_existRem$exdate['params']'VALUE''DATE-TIME'7$parno );
  2616.     if!isset$parno )) $parno $this->_existRem$exdate['params']'VALUE''DATE');
  2617.     foreach$exdates as $eix => $theExdate {
  2618.       if(  is_array$theExdate &&
  2619.          in_arraycount$theExdate )array346)))) {
  2620.         ifisset$exdate['params']['TZID'))
  2621.           $theExdate['tz'$exdate['params']['TZID'];
  2622.         if!isset$parno )) {
  2623.           ifcount$theExdate ))
  2624.             $parno 7;
  2625.           else
  2626.             $parno 3;
  2627.         }
  2628.         $exdatea   $this->_date_time_array$theExdate$parno );
  2629.       }
  2630.       elseifis_array$theExdate && isset$theExdate['timestamp')) {
  2631.         ifisset$exdate['params']['TZID'))
  2632.           $theExdate['tz'$exdate['params']['TZID'];
  2633.         $tz        isset$theExdate['tz')) ' '.$theExdate['tz'null;
  2634.         if!isset$parno ))
  2635.           $parno   !empty$tz )) 6;
  2636.         $exdatea   $this->_date_time_stringdate'Y-m-d H:i:s'$theExdate['timestamp').$tz$parno );
  2637.       }
  2638.       elseif<= strlentrim$theExdate ))) // ex. 2006-08-03 10:12:18
  2639.         $exdatea   $this->_date_time_string$theExdate$parno );
  2640.         ifisset$exdate['params']['TZID'))
  2641.           $exdatea['tz'$exdate['params']['TZID'];
  2642.       }
  2643.       if!isset$parno )) {
  2644.         $parno     count$exdatea );
  2645.         if== $parno )
  2646.           $parno   7;
  2647.       }
  2648.       ifisset$exdatea['tz'))
  2649.         $exdatea['tz'= (string) $exdatea['tz'];
  2650.       $exdate['value'][$exdatea;
  2651.     }
  2652.     ifcount$exdate['value')) {
  2653.       if== $parno {
  2654.         $exdate['params']['VALUE''DATE';
  2655.         foreach$exdate['value'as $eix => $exdatea )
  2656.           unset$exdate['value'][$eix]['tz');
  2657.         unset$exdate['params']['TZID');
  2658.       }
  2659.       if!empty$exdate['value'][0]['tz')   &&
  2660.            $exdate['value'][0]['tz'!= 'Z' &&
  2661.         !in_array($exdate['value'][0]['tz']{0}array'+''-' )) &&
  2662.              ctype_digitsubstr$exdate['value'][0]['tz']))) &&
  2663.           !ctype_digit$exdate['value'][0]['tz') ) ) {
  2664.         $exdate['params']['TZID'$exdate['value'][0]['tz'];
  2665.         foreach$exdate['value'as $exix => $exdatea {
  2666.           if!empty$exdate['value'][0]['tz')   &&
  2667.                $exdate['value'][0]['tz'!= 'Z' &&
  2668.             !in_array($exdate['value'][0]['tz']{0}array'+''-' )) &&
  2669.                  ctype_digitsubstr$exdate['value'][0]['tz']))) &&
  2670.               !ctype_digit$exdate['value'][0]['tz') ) )
  2671.             unset$exdate['value'][$exix]['tz');
  2672.         }
  2673.       }
  2674.       elseifisset$exdate['params']['TZID'))
  2675.         unset$exdate['params']['TZID');
  2676.       $this->exdate[$exdate;
  2677.     }
  2678.   }
  2679. /*********************************************************************************/
  2680. /**
  2681.  * Property Name: EXRULE
  2682.  */
  2683. /**
  2684.  * creates formatted output for calendar component property exrule
  2685.  *
  2686.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2687.  * @since 0.7.28 - 2006-09-13
  2688.  * @return string 
  2689.  */
  2690.   function createExrule({
  2691.     $cnt count$this->exrule );
  2692.     if>= $cnt )
  2693.       return;
  2694.     $exrule 'EXRULE';
  2695.     return $this->_format_recur$exrule$this->exrule );
  2696.   }
  2697. /**
  2698.  * set calendar component property exdate
  2699.  *
  2700.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2701.  * @since 0.9.18 - 2007-03-18
  2702.  * @param array $exruleset 
  2703.  * @param array $params optional
  2704.  * @return void 
  2705.  */
  2706.   function setExrule$exruleset$params=FALSE {
  2707.     $exrule array();
  2708.     foreach$exruleset as $exrulelabel => $exrulevalue {
  2709.       $exrulelabel strtoupper$exrulelabel );
  2710.       if'UNTIL'  != $exrulelabel )
  2711.         $exrule['value'][$exrulelabel$exrulevalue;
  2712.       elseifis_array$exrulevalue &&
  2713.             (( == count$exrulevalue )) ||
  2714.              == count$exrulevalue )) ||
  2715.              == count$exrulevalue )) ||
  2716.              array_key_exists'year'$exrulevalue )))) {
  2717.         $parno count$exrulevalue )) ;
  2718.         $date  $this->_date_time_array$exrulevalue$parno );
  2719.         if(( count$date )) && !isset$date['tz'))
  2720.           $date['tz''Z';
  2721.         $exrule['value'][$exrulelabel$date;
  2722.       }
  2723.       elseifis_array$exrulevalue && isset$exrulevalue['timestamp')) {
  2724.         $date  $this->_date_time_stringdate'Y-m-d H:i:s'$exrulevalue['timestamp'));
  2725.         $date['tz''Z';
  2726.         $exrule['value'][$exrulelabel$date;
  2727.       }
  2728.       elseif<= strlentrim$exrulevalue ))) // ex. 2006-08-03 10:12:18
  2729.         $date $this->_date_time_string$exrulevalue );
  2730.         if(( count$date )) && !isset$date['tz'))
  2731.           $date['tz''Z';
  2732.         $exrule['value'][$exrulelabel$date;
  2733.       }
  2734.     }
  2735.     $exrule['params'$this->_setParams$params );
  2736.     $this->exrule[$exrule;
  2737.   }
  2738. /*********************************************************************************/
  2739. /**
  2740.  * Property Name: FREEBUSY
  2741.  */
  2742. /**
  2743.  * creates formatted output for calendar component property freebusy
  2744.  *
  2745.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2746.  * @since 1.x.x - 2007-05-16
  2747.  * @return string 
  2748.  */
  2749.   function createFreebusy({
  2750.     $cnt count$this->freebusy );
  2751.     if>= $cnt )
  2752.       return;
  2753.     $output null;
  2754.     foreach$this->freebusy as $freebusyPart {
  2755.       $attributes $content null;
  2756.       ifisset$freebusyPart['value']['fbtype')) {
  2757.         $attributes .= $this->intAttrDelimiter.'FBTYPE='.$freebusyPart['value']['fbtype'];
  2758.         unset$freebusyPart['value']['fbtype');
  2759.         $freebusyPart['value'array_values$freebusyPart['value');
  2760.       }
  2761.       else
  2762.         $attributes .= $this->intAttrDelimiter.'FBTYPE=BUSY';
  2763.       $attributes .= $this->_createParams$freebusyPart['params');
  2764.       $fno 1;
  2765.       $cnt count$freebusyPart['value']);
  2766.       foreach$freebusyPart['value'as $periodix => $freebusyPeriod {
  2767.         $formatted   $this->_format_date_time$freebusyPeriod[0);
  2768.         $content .= $formatted;
  2769.         $content .= '/';
  2770.         $cnt2 count$freebusyPeriod[1]);
  2771.         ifarray_key_exists'year'$freebusyPeriod[1))      // date-time
  2772.           $cnt2 7;
  2773.         elseifarray_key_exists'week'$freebusyPeriod[1))  // duration
  2774.           $cnt2 5;
  2775.         if(( == $cnt2 )   &&    // period=  -> date-time
  2776.             isset$freebusyPeriod[1]['year')  &&
  2777.             isset$freebusyPeriod[1]['month'&&
  2778.             isset$freebusyPeriod[1]['day')) {
  2779.           $content .= $this->_format_date_time$freebusyPeriod[1);
  2780.         }
  2781.         else {                                  // period=  -> dur-time
  2782.           $content .= $this->_format_duration$freebusyPeriod[1);
  2783.         }
  2784.         if$fno $cnt )
  2785.           $content .= ',';
  2786.         $fno++;
  2787.       }
  2788.       $output .= $this->_createElement'FREEBUSY'$attributes$content );
  2789.     }
  2790.     return $output;
  2791.   }
  2792. /**
  2793.  * set calendar component property freebusy
  2794.  *
  2795.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2796.  * @since 0.9.18 - 2007-03-18
  2797.  * @param string $fbType 
  2798.  * @param array $fbValues 
  2799.  * @param array $params optional
  2800.  * @return void 
  2801.  */
  2802.   function setFreebusy$fbType$fbValues$params=FALSE {
  2803.     $fbType strtoupper$fbType );
  2804.     if(( !in_array$fbTypearray'FREE''BUSY''BUSY-UNAVAILABLE''BUSY-TENTATIVE' ))) &&
  2805.        'X-' != substr$fbType0)))
  2806.       $fbType 'BUSY';
  2807.     $freebusy['value'array'fbtype' => $fbType );
  2808.     foreach$fbValues as $fbPeriod {   // periods => period
  2809.       $freebusyPeriod array();
  2810.       foreach$fbPeriod as $fbMember // pairs => singlepart
  2811.         $freebusyPairMember array();
  2812.         ifis_array$fbMember )) {
  2813.           $cnt count$fbMember );
  2814.           if(( == $cnt || == $cnt || array_key_exists'year'$fbMember ))) // date-time value
  2815.             $date $this->_date_time_array$fbMember);
  2816.             $date['tz'!isset$date['tz')) 'Z' $date['tz'];
  2817.             $freebusyPairMember $date;
  2818.           }
  2819.           elseifarray_key_exists'timestamp'$fbMember )) // timestamp value
  2820.             $tz    isset$fbMember['tz')) ' '.$fbMember['tz'null;
  2821.             $parno !empty$tz )) 6;
  2822.             $date  $this->_date_time_stringdate'Y-m-d H:i:s'$fbMember['timestamp').$tz$parno );
  2823.             $date['tz'!isset$date['tz')) 'Z' $date['tz'];
  2824.             $freebusyPairMember $date;
  2825.           }
  2826.           else {                                         // array format duration
  2827.             $freebusyPairMember $this->_duration_array$fbMember );
  2828.           }
  2829.         }
  2830.         elseif(( <= strlentrim$fbMember ))) &&    // string format duration
  2831.                in_array$fbMember{0}array'P''+''-' )))) {
  2832.           if'P' != $fbMember{0)
  2833.             $fbmember substr$fbMember);
  2834.           $freebusyPairMember $this->_duration_string$fbMember );
  2835.         }
  2836.         elseif<= strlentrim$fbMember ))) // ex. 2006-08-03 10:12:18
  2837.           $date $this->_date_time_string$fbMember);
  2838.           $date['tz'!isset$date['tz')) 'Z' $date['tz'];
  2839.           $freebusyPairMember $date;
  2840.         }
  2841.         $freebusyPeriod[]  $freebusyPairMember;
  2842.       }
  2843.       $freebusy['value'][$freebusyPeriod;
  2844.     }
  2845.     $freebusy['params']    $this->_setParams$params );
  2846.     $this->freebusy[]      $freebusy;
  2847.   }
  2848. /*********************************************************************************/
  2849. /**
  2850.  * Property Name: GEO
  2851.  */
  2852. /**
  2853.  * creates formatted output for calendar component property geo
  2854.  *
  2855.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2856.  * @since 0.9.7 - 2006-11-20
  2857.  * @return string 
  2858.  */
  2859.   function createGeo({
  2860.     $cnt count$this->geo );
  2861.     if>= $cnt )
  2862.       return;
  2863.     $attributes $this->_createParams$this->geo['params');
  2864.     $content    null;
  2865.     $content   .= number_format(float) $this->geo['value']['latitude']6'.''');
  2866.     $content   .= ';';
  2867.     $content   .= number_format(float) $this->geo['value']['longitude']6'.''');
  2868.     return $this->_createElement'GEO'$attributes$content );
  2869.   }
  2870. /**
  2871.  * set calendar component property geo
  2872.  *
  2873.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2874.  * @since 0.9.18 - 2007-03-18
  2875.  * @param float $latitude 
  2876.  * @param float $longitude 
  2877.  * @param array $params optional
  2878.  * @return void 
  2879.  */
  2880.   function setGeo$latitude$longitude$params=FALSE {
  2881.     $this->geo['value']['latitude']  $latitude;
  2882.     $this->geo['value']['longitude'$longitude;
  2883.     $this->geo['params'$this->_setParams$params );
  2884.   }
  2885. /*********************************************************************************/
  2886. /**
  2887.  * Property Name: LAST-MODIFIED
  2888.  */
  2889. /**
  2890.  * creates formatted output for calendar component property last-modified
  2891.  *
  2892.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2893.  * @since 0.9.7 - 2006-11-20
  2894.  * @return string 
  2895.  */
  2896.   function createLastModified({
  2897.     if!isset$this->lastmodified['value']['year')  &&
  2898.         !isset$this->lastmodified['value']['month'&&
  2899.         !isset$this->lastmodified['value']['day')   &&
  2900.         !isset$this->lastmodified['value']['hour')  &&
  2901.         !isset$this->lastmodified['value']['min')   &&
  2902.         !isset$this->lastmodified['value']['sec'))
  2903.       return;
  2904.     $attributes $this->_createParams$this->lastmodified['params');
  2905.     $formatted  $this->_format_date_time$this->lastmodified['value']);
  2906.     return $this->_createElement'LAST-MODIFIED'$attributes$formatted );
  2907.   }
  2908. /**
  2909.  * set calendar component property completed
  2910.  *
  2911.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2912.  * @since 2.2.2 - 2007-08-02
  2913.  * @param mixed $year optional
  2914.  * @param mixed $month optional
  2915.  * @param int $day optional
  2916.  * @param int $hour optional
  2917.  * @param int $min optional
  2918.  * @param int $sec optional
  2919.  * @param array $params optional
  2920.  * @return void 
  2921.  */
  2922.   function setLastModified$year=FALSE$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$params=FALSE {
  2923.     if!isset$year )) {
  2924.       $year date('Ymd\THis'mktimedate'H' )date'i' )date's' date'Z')date'm' )date'd' )date'Y' )));
  2925.     }
  2926.     $this->lastmodified = $this->_setDate2$year$month$day$hour$min$sec$params );
  2927.  
  2928.   }
  2929. /*********************************************************************************/
  2930. /**
  2931.  * Property Name: LOCATION
  2932.  */
  2933. /**
  2934.  * creates formatted output for calendar component property location
  2935.  *
  2936.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2937.  * @since 0.9.7 - 2006-11-20
  2938.  * @return string 
  2939.  */
  2940.   function createLocation({
  2941.     $cnt count$this->location );
  2942.     if>= $cnt )
  2943.       return;
  2944.     $attributes $this->_createParams$this->location['params']array'ALTREP''LANGUAGE' ));
  2945.     $content    $this->_strrep$this->location['value');
  2946.     return $this->_createElement'LOCATION'$attributes$content );
  2947.   }
  2948. /**
  2949.  * set calendar component property location
  2950.  '
  2951.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2952.  * @since 0.9.18 - 2007-03-18
  2953.  * @param string $value 
  2954.  * @param array params optional
  2955.  * @return void 
  2956.  */
  2957.   function setLocation$value$params=FALSE {
  2958.     $this->location['value']  $value;
  2959.     $this->location['params'$this->_setParams$params );
  2960.   }
  2961. /*********************************************************************************/
  2962. /**
  2963.  * Property Name: ORGANIZER
  2964.  */
  2965. /**
  2966.  * creates formatted output for calendar component property organizer
  2967.  *
  2968.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2969.  * @since 0.9.7 - 2006-11-20
  2970.  * @return string 
  2971.  */
  2972.   function createOrganizer({
  2973.     $cnt count$this->organizer );
  2974.     if>= $cnt )
  2975.       return;
  2976.     $attributes $this->_createParams$this->organizer['params']
  2977.                                       array'CN''DIR''LANGUAGE''SENT-BY' ));
  2978.     $content    'MAILTO:'.$this->organizer['value'];
  2979.     return $this->_createElement'ORGANIZER'$attributes$content );
  2980.   }
  2981. /**
  2982.  * set calendar component property organizer
  2983.  *
  2984.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  2985.  * @since 2.0.9 - 2007-06-30
  2986.  * @param string $value 
  2987.  * @param array params optional
  2988.  * @return void 
  2989.  */
  2990.   function setOrganizer$value$params=FALSE {
  2991.     $value str_replace 'MAILTO:'''$value );
  2992.     $value str_replace 'mailto:'''$value );
  2993.     $this->organizer['value']  $value;
  2994.     $this->organizer['params'$this->_setParams$params );
  2995.     ifisset($this->organizer['params']['SENT-BY')) {
  2996.       if'MAILTO' == strtouppersubstr$this->organizer['params']['SENT-BY']0)))
  2997.         $this->organizer['params']['SENT-BY'substr$this->organizer['params']['SENT-BY']);
  2998.     }
  2999.   }
  3000. /*********************************************************************************/
  3001. /**
  3002.  * Property Name: PERCENT-COMPLETE
  3003.  */
  3004. /**
  3005.  * creates formatted output for calendar component property percent-complete
  3006.  *
  3007.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3008.  * @since 0.9.7 - 2006-11-20
  3009.  * @return string 
  3010.  */
  3011.   function createPercentComplete({
  3012.     $cnt count$this->percentcomplete );
  3013.     if>= $cnt )
  3014.       return;
  3015.     $attributes $this->_createParams$this->percentcomplete['params');
  3016.     return $this->_createElement'PERCENT-COMPLETE'$attributes$this->percentcomplete['value');
  3017.   }
  3018. /**
  3019.  * set calendar component property percent-complete
  3020.  *
  3021.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3022.  * @since 0.9.18 - 2007-03-18
  3023.  * @param int $value 
  3024.  * @param array $params optional
  3025.  * @return void 
  3026.  */
  3027.   function setPercentComplete$value$params=FALSE {
  3028.     $this->percentcomplete['value']  $value;
  3029.     $this->percentcomplete['params'$this->_setParams$params );
  3030.   }
  3031. /*********************************************************************************/
  3032. /**
  3033.  * Property Name: PRIORITY
  3034.  */
  3035. /**
  3036.  * creates formatted output for calendar component property priority
  3037.  *
  3038.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3039.  * @since 0.9.7 - 2006-11-20
  3040.  * @return string 
  3041.  */
  3042.   function createPriority({
  3043.     $cnt count$this->priority );
  3044.     if>= $cnt )
  3045.       return;
  3046.     $attributes $this->_createParams$this->priority['params');
  3047.     return $this->_createElement'PRIORITY'$attributes$this->priority['value');
  3048.   }
  3049. /**
  3050.  * set calendar component property priority
  3051.  *
  3052.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3053.  * @since 0.9.18 - 2007-03-18
  3054.  * @param int $value 
  3055.  * @param array $params optional
  3056.  * @return void 
  3057.  */
  3058.   function setPriority$value$params=FALSE  {
  3059.     $this->priority['value']  $value;
  3060.     $this->priority['params'$this->_setParams$params );
  3061.   }
  3062. /*********************************************************************************/
  3063. /**
  3064.  * Property Name: RDATE
  3065.  */
  3066. /**
  3067.  * creates formatted output for calendar component property rdate
  3068.  *
  3069.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3070.  * @since 1.x.x - 2007-05-13
  3071.  * @param bool $localtime optional, default FALSE
  3072.  * @return string 
  3073.  */
  3074.   function createRdate$localtime=FALSE {
  3075.     $cnt count$this->rdate );
  3076.     if>= $cnt )
  3077.       return;
  3078.     $output null;
  3079.     foreach$this->rdate as $theRdate {
  3080.       $attributes $this->_createParams$theRdate['params');
  3081.       $cnt count$theRdate['value');
  3082.       $content null;
  3083.       $rno 1;
  3084.       foreach$theRdate['value'as $rpix =>$rdatePart {
  3085.         $contentPart null;
  3086.         ifis_array$rdatePart &&
  3087.            == count$rdatePart )) &&
  3088.              array_key_exists'0'$rdatePart &&
  3089.              array_key_exists'1'$rdatePart )) // PERIOD
  3090.           if$localtime  )
  3091.             unset$rdatePart[0]['tz');
  3092.           $formatted $this->_format_date_time$rdatePart[0]);
  3093.           ifisset$theRdate['params']['TZID'))
  3094.             $formatted str_replace'Z'''$formatted);
  3095.           if$rpix {
  3096.             ifisset$rdatePart[0]['tz'&&
  3097.                ctype_digitsubstr$rdatePart[0]['tz']-)) ||
  3098.                   'Z' == $rdatePart[0]['tz'))) {
  3099.               if'Z' != substr$formatted-))
  3100.                 $formatted .= 'Z';
  3101.             }
  3102.             else
  3103.               $formatted str_replace'Z'''$formatted );
  3104.           }
  3105.           $contentPart .= $formatted;
  3106.           if== $rno )
  3107.             $attributes .= $this->intAttrDelimiter.'VALUE=PERIOD';
  3108.           $contentPart .= '/';
  3109.           $cnt2 count$rdatePart[1]);
  3110.           ifarray_key_exists'year'$rdatePart[1)) {
  3111.             ifarray_key_exists'hour'$rdatePart[1))
  3112.               $cnt2 7;                                      // date-time
  3113.             else
  3114.               $cnt2 3;                                      // date
  3115.           }
  3116.           elseifarray_key_exists'week'$rdatePart[1))  // duration
  3117.             $cnt2 5;
  3118.           if(( == $cnt2 )   &&    // period=  -> date-time
  3119.               isset$rdatePart[1]['year')  &&
  3120.               isset$rdatePart[1]['month'&&
  3121.               isset$rdatePart[1]['day')) {
  3122.             if$localtime  )
  3123.               unset$rdatePart[1]['tz');
  3124.             $formatted $this->_format_date_time$rdatePart[1);
  3125.             ifisset$theRdate['params']['TZID'))
  3126.               $formatted str_replace'Z'''$formatted);
  3127.             ifisset$rdatePart[0]['tz'&&
  3128.               ctype_digitsubstr$rdatePart[0]['tz']-)) ||
  3129.                   'Z' == $rdatePart[0]['tz'))) {
  3130.               if'Z' != substr$formatted-))
  3131.                 $formatted .= 'Z';
  3132.             }
  3133.             else
  3134.               $formatted str_replace'Z'''$formatted );
  3135.            $contentPart .= $formatted;
  3136.           }
  3137.           else {                                  // period=  -> dur-time
  3138.             $contentPart .= $this->_format_duration$rdatePart[1);
  3139.           }
  3140.         // PERIOD end
  3141.         else // single date start
  3142.           if$localtime  )
  3143.             unset$rdatePart['tz');
  3144.           $formatted $this->_format_date_time$rdatePart);
  3145.           ifisset$theRdate['params']['TZID'))
  3146.             $formatted str_replace'Z'''$formatted);
  3147.           if$rpix {
  3148.             $firstPart == count$theRdate['value'][0))
  3149.                        ? $theRdate['value'][0][0$theRdate['value'][0];
  3150.             ifisset$firstPart['tz'&&
  3151.                ctype_digitsubstr$firstPart['tz']-)) ||
  3152.                   'Z' == $firstPart['tz'))) {
  3153.               if'Z' != substr$formatted-))
  3154.                 $formatted .= 'Z';
  3155.             }
  3156.             else
  3157.               $formatted str_replace'Z'''$formatted );
  3158.           }
  3159.           $contentPart .= $formatted;
  3160.         }
  3161.         $content .= $contentPart;
  3162.         if$rno $cnt )
  3163.           $content .= ',';
  3164.         $rno++;
  3165.       }
  3166.       $output    .= $this->_createElement'RDATE'$attributes$content );
  3167.     }
  3168.     return $output;
  3169.   }
  3170. /**
  3171.  * set calendar component property rdate
  3172.  *
  3173.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3174.  * @since 2.2.14 - 2007-10-30
  3175.  * @param array $rdates 
  3176.  * @param array $params optional
  3177.  * @return void 
  3178.  */
  3179.   function setRdate$rdates$params=FALSE {
  3180.     $input array();
  3181.     $input['params'$this->_setParams$paramsarray'VALUE' => 'DATE-TIME' ));
  3182.     $this->_existRem$input['params']'VALUE''PERIOD' );
  3183.     $parno isset$input['params']['TZID')) null;
  3184.     $parno !$parno $this->_existRem$input['params']'VALUE''DATE-TIME'null;
  3185.     $parno !$parno $this->_existRem$input['params']'VALUE''DATE'6;
  3186.     $this->_existRem$input['params']'VALUE''DATE-TIME' );
  3187.     foreach$rdates as $theRdate {
  3188.  //   echo 'setRdate in '; print_r ( $theRdate ); echo "<br />\n"; // test ##
  3189.       $inputa null;
  3190.       ifis_array$theRdate )) {
  3191.         if(( == count$theRdate )) &&
  3192.              array_key_exists'0'$theRdate &&
  3193.              array_key_exists'1'$theRdate &&
  3194.             !array_key_exists'timestamp'$theRdate )) // PERIOD
  3195.           foreach$theRdate as $rix => $rPeriod {
  3196.  //   echo 'setRdate i2 '; print_r ( $rPeriod ); echo "<br />\n"; // test ##
  3197.             ifis_array$rPeriod )) {
  3198.  //   echo 'setRdate i3 '; print_r ( $rPeriod ); echo "<br />\n"; // test ##
  3199.               if (( == count$rPeriod )) &&
  3200.                   <= strlenreset$rPeriod )))) // text-date
  3201.  //   echo 'setRdate i4 '; print_r ( $rPeriod ); echo "<br />\n"; // test ##
  3202.                 $inputab       $this->_date_time_stringreset$rPeriod )$parno );
  3203.                 if isset$input['params']['TZID'))
  3204.                   $inputab['tz'= (string) $input['params']['TZID'];
  3205.                 elseifisset$inputab['tz'))
  3206.                   $inputab['tz'= (string) $inputab['tz'];
  3207.                 else
  3208.                   unset$inputab['tz');
  3209.                 $parno         !isset$parno )) count$inputab $parno;
  3210.                 if(( == $parno && !isset$inputab['tz'))
  3211.                   $inputab['tz''Z';
  3212.                 ifisset$inputab['tz'))
  3213.                   $inputab['tz'= (string) $inputab['tz'];
  3214.                 $inputa[$inputab;
  3215.               }
  3216.               elseif (((== count$rPeriod )) && $rix )) ||
  3217.                       == count$rPeriod )) ||
  3218.                       == count$rPeriod )) ||
  3219.                       array_key_exists'year'$rPeriod ))) // date[-time] (only 1st rperiod)
  3220.                 if!isset$parno && count$rPeriod ))
  3221.                   $parno 7;
  3222.                 $inputab       $this->_date_time_array$rPeriod$parno );
  3223.                 if isset$input['params']['TZID'))
  3224.                   $inputab['tz'= (string) $input['params']['TZID'];
  3225.                 elseifisset$inputab['tz'))
  3226.                   $inputab['tz'= (string) $inputab['tz'];
  3227.                 else
  3228.                   unset$inputab['tz');
  3229.                 $parno         !isset$parno )) count$inputab $parno;
  3230.                 if(( == $parno && !isset$inputab['tz'))
  3231.                   $inputab['tz''Z';
  3232.                 ifisset$inputab['tz'))
  3233.                   $inputab['tz'= (string) $inputab['tz'];
  3234.                 $inputa[$inputab;
  3235.               }
  3236.               elseifisset$rPeriod['timestamp')) {   // timestamp
  3237.                 $tz    isset$rPeriod['tz'))           ' '.$rPeriod['tz']           null;
  3238.                 $tz    isset$input['params']['TZID')) ' '.$input['params']['TZID'$tz;
  3239.                 if!isset$parno )) $parno !empty$tz )) 6;
  3240.                 $inputab $this->_date_time_stringdate'Y-m-d H:i:s'$rPeriod['timestamp').$tz$parno );
  3241.                 if(( == $parno && !isset$inputab['tz'))
  3242.                   $inputab['tz''Z';
  3243.                 ifisset$inputab['tz'))
  3244.                   $inputab['tz'= (string) $inputab['tz'];
  3245.                 $inputa[$inputab;
  3246.               }
  3247.               else {                                       // array format duration
  3248.                 $inputa[$this->_duration_array$rPeriod );
  3249.               }
  3250.             }
  3251.             elseif(( <= strlentrim$rPeriod ))) &&    // string format duration
  3252.                    in_array$rPeriod{0}array'P''+''-' )))) {
  3253.               if'P' != $rPeriod{0)
  3254.                 $rPeriod substr$rPeriod);
  3255.               $inputa[$this->_duration_string$rPeriod );
  3256.             }
  3257.             elseif<= strlentrim$rPeriod ))) // ex. 2006-08-03 10:12:18
  3258.               $tz    isset$input['params']['TZID')) ' '.$input['params']['TZID''';
  3259.               $inputab       $this->_date_time_string$rPeriod.$tz$parno );
  3260.               if isset$input['params']['TZID'))
  3261.                 $inputab['tz'= (string) $input['params']['TZID'];
  3262.               elseifisset$inputab['tz'))
  3263.                 $inputab['tz'= (string) $inputab['tz'];
  3264.               else
  3265.                 unset$inputab['tz');
  3266.               $inputa[]      $inputab;
  3267.               $parno         !isset$parno )) count$inputab $parno;
  3268.             }
  3269.           }
  3270.         }
  3271.         elseif array_key_exists'timestamp'$theRdate )) {   // timestamp
  3272.           $tz    isset$theRdate['tz'))          ' '.$theRdate['tz']          null;
  3273.           $tz    isset$input['params']['TZID')) ' '.$input['params']['TZID'$tz;
  3274.           if!isset$parno )) $parno !empty$tz )) 6;
  3275.           $inputab $this->_date_time_stringdate'Y-m-d H:i:s'$theRdate['timestamp').$tz$parno );
  3276.           if(( == $parno && !isset$inputab['tz'))
  3277.             $inputab['tz''Z';
  3278.           ifisset$inputab['tz'))
  3279.             $inputab['tz'= (string) $inputab['tz'];
  3280.           $inputa $inputab;
  3281.         }
  3282.         elseif (( in_arraycount$theRdate )array346))) ||
  3283.                 array_key_exists'year'$theRdate ))) {  // date[-time]
  3284.           ifisset$input['params']['TZID'))
  3285.             $theRdate['tz'$input['params']['TZID'];
  3286.           elseif!isset$theRdate['tz')) {
  3287.             if(( == count$theRdate )) && isset$theRdate[6)) {
  3288.               $theRdate['tz'$theRdate[6];
  3289.               unset$theRdate[6);
  3290.             }
  3291.             elseif(( == count$theRdate )) && isset$theRdate[3)) {
  3292.               $theRdate['tz'$theRdate[3];
  3293.               unset$theRdate[3);
  3294.             }
  3295.           }
  3296.           if!isset$parno && count$theRdate ))
  3297.             $parno isset$theRdate['tz')) count$theRdate );
  3298.           elseif!isset$parno ))
  3299.             $parno 3;
  3300.           $inputa $this->_date_time_array$theRdate$parno );
  3301.           if(( == $parno && !isset$inputa['tz'))
  3302.             $inputa['tz''Z';
  3303.           ifisset$inputa['tz'))
  3304.             $inputa['tz'= (string) $inputa['tz'];
  3305.         }
  3306.       }
  3307.       elseif<= strlentrim$theRdate ))) // ex. 2006-08-03 10:12:18
  3308.         $inputa       $this->_date_time_string$theRdate$parno );
  3309.         ifisset$input['params']['TZID'))
  3310.           $inputa['tz'= (string) $input['params']['TZID'];
  3311.         elseifisset$inputa['tz'))
  3312.           $inputa['tz'= (string) $inputa['tz'];
  3313.         else
  3314.           unset$inputa['tz');
  3315.         $parno !isset$parno )) count$inputa $parno;
  3316.         if(( == $parno && !isset$inputa['tz'))
  3317.           $inputa['tz''Z';
  3318.         ifisset$inputa['tz'))
  3319.           $inputa['tz'= (string) $inputa['tz'];
  3320.  //         echo 'setRdate inputa single string '; print_r ( $inputa ); echo "<br />\n"; // test ##
  3321.       }
  3322.       $input['value'][$inputa;
  3323.     }
  3324.     ifcount$input['value')) {
  3325.  //     echo 'setRdate ut 1 '; print_r ( $input ); echo "<br />\n"; // test ##
  3326.       if== $parno {
  3327.         $input['params']['VALUE''DATE';
  3328.         foreach$input['value'as $eix => $inputa )
  3329.           unset$input['value'][$eix]['tz');
  3330.         unset$input['params']['TZID');
  3331.       }
  3332.       ifempty$input['value'][0]['tz'||
  3333.          $input['value'][0]['tz'== 'Z' ))
  3334.         $dummy TRUE;
  3335.       elseifin_array($input['value'][0]['tz']{0}array'+''-' )) &&
  3336.                ctype_digitsubstr$input['value'][0]['tz'])))
  3337.         $dummy TRUE;
  3338.       elseifctype_digit$input['value'][0]['tz'))
  3339.         $dummy TRUE;
  3340.       elseifisset$input['value'][0]['tz')) {
  3341.         $input['params']['TZID'$input['value'][0]['tz'];
  3342.         foreach$input['value'as $eix => $inputa {
  3343.           if!empty$input['value'][0]['tz')   &&
  3344.                $input['value'][0]['tz'!= 'Z' &&
  3345.             !in_array$input['value'][0]['tz']{0}array'+''-' )) &&
  3346.                  ctype_digitsubstr$input['value'][0]['tz']))) &&
  3347.               !ctype_digit$input['value'][0]['tz') ) )
  3348.             unset$input['value'][$eix]['tz');
  3349.         }
  3350.       }
  3351.       elseifisset$input['params']['TZID'))
  3352.         unset$input['params']['TZID');
  3353.  
  3354.       $this->rdate[$input;
  3355.  //    echo 'setRdate ut 2 '; print_r ( $input ); echo "<br />\n"; // test ##
  3356.     }
  3357.   }
  3358. /*********************************************************************************/
  3359. /**
  3360.  * Property Name: RECURRENCE-ID
  3361.  */
  3362. /**
  3363.  * creates formatted output for calendar component property recurrence-id
  3364.  *
  3365.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3366.  * @since 0.9.18 - 2007-03-26
  3367.  * @return string 
  3368.  */
  3369.   function createRecurrenceid({
  3370.     $cnt count$this->recurrenceid );
  3371.     if>= $cnt )
  3372.       return;
  3373.     $formatted  $this->_format_date_time$this->recurrenceid['value');
  3374.     $attributes $this->_createParams$this->recurrenceid['params');
  3375.     return $this->_createElement'RECURRENCE-ID'$attributes$formatted );
  3376.   }
  3377. /**
  3378.  * set calendar component property recurrence-id
  3379.  *
  3380.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3381.  * @since 2.2.2 - 2007-07-29
  3382.  * @param mixed $year 
  3383.  * @param mixed $month optional
  3384.  * @param int $day optional
  3385.  * @param int $hour optional
  3386.  * @param int $min optional
  3387.  * @param int $sec optional
  3388.  * @param array $params optional
  3389.  * @return void 
  3390.  */
  3391.   function setRecurrenceid$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$tz=FALSE$params=FALSE {
  3392.     $this->recurrenceid = $this->_setDate$year$month$day$hour$min$sec$tz$params );
  3393.   }
  3394. /*********************************************************************************/
  3395. /**
  3396.  * Property Name: RELATED-TO
  3397.  */
  3398. /**
  3399.  * creates formatted output for calendar component property related-to
  3400.  *
  3401.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3402.  * @since 2.3.2 - 2007-11-25
  3403.  * @return string 
  3404.  */
  3405.   function createRelatedTo({
  3406.     $cnt count$this->relatedto );
  3407.     if>= $cnt )
  3408.       return;
  3409.     $output null;
  3410.     foreach$this->relatedto as $relation {
  3411.       $attributes $this->_createParams$relation['params');
  3412.       $content    '<'.$this->_strrep$relation['value').'>';
  3413.       $output    .= $this->_createElement'RELATED-TO'$attributes$content );
  3414.     }
  3415.     return $output;
  3416.   }
  3417. /**
  3418.  * set calendar component property related-to
  3419.  *
  3420.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3421.  * @since 1.x.x - 2007-05-24
  3422.  * @param float $relid 
  3423.  * @param array $params optional
  3424.  * @return void 
  3425.  */
  3426.   function setRelatedTo$relid$params=FALSE {
  3427.     $relation           array();
  3428.     if(( '<' == substr$relid0)) &&
  3429.        '>' == substr$relid-)))
  3430.                  $relid substr$relid1strlen$relid ));
  3431.     $relation['value']  $relid;
  3432.     $relation['params'$this->_setParams$params );
  3433.             // remove default
  3434.     ifisset$relation['params']['RELTYPE'&&
  3435.        strtoupper$relation['params']['RELTYPE'== 'PARENT' ))
  3436.       unset$relation['params']['RELTYPE');
  3437.     $this->relatedto[]  $relation;
  3438.   }
  3439. /*********************************************************************************/
  3440. /**
  3441.  * Property Name: REPEAT
  3442.  */
  3443. /**
  3444.  * creates formatted output for calendar component property repeat
  3445.  *
  3446.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3447.  * @since 0.9.7 - 2006-11-20
  3448.  * @return string 
  3449.  */
  3450.   function createRepeat({
  3451.     $cnt count$this->repeat );
  3452.     if>= $cnt )
  3453.       return;
  3454.     $attributes $this->_createParams$this->repeat['params');
  3455.     return $this->_createElement'REPEAT'$attributes$this->repeat['value');
  3456.   }
  3457. /**
  3458.  * set calendar component property transp
  3459.  *
  3460.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3461.  * @since 0.9.18 - 2007-03-18
  3462.  * @param string $value 
  3463.  * @param array $params optional
  3464.  * @return void 
  3465.  */
  3466.   function setRepeat$value$params=FALSE {
  3467.     $this->repeat['value']  $value;
  3468.     $this->repeat['params'$this->_setParams$params );
  3469.   }
  3470. /*********************************************************************************/
  3471. /**
  3472.  * Property Name: REQUEST-STATUS
  3473.  */
  3474. /**
  3475.  * creates formatted output for calendar component property request-status
  3476.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3477.  * @since 1.x.x - 2007-05-16
  3478.  * @return string 
  3479.  */
  3480.   function createRequestStatus({
  3481.     $cnt count$this->requeststatus );
  3482.     if>= $cnt )
  3483.       return;
  3484.     $output null;
  3485.     foreach$this->requeststatus as $rstat {
  3486.       $attributes $this->_createParams$rstat['params']array'LANGUAGE' ));
  3487.       $content    number_format(float) $rstat['value']['statcode']2'.''');
  3488.       $content   .= ';'.$this->_strrep$rstat['value']['text');
  3489.       ifisset$rstat['value']['extdata'))
  3490.         $content .= ';'.$this->_strrep$rstat['value']['extdata');
  3491.       $output    .= $this->_createElement'REQUEST-STATUS'$attributes$content );
  3492.     }
  3493.     return $output;
  3494.   }
  3495. /**
  3496.  * set calendar component property request-status
  3497.  *
  3498.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3499.  * @since 1.x.x - 2007-05-16
  3500.  * @param float $statcode 
  3501.  * @param string $text 
  3502.  * @param string $extdata optional
  3503.  * @param array params optional
  3504.  * @return void 
  3505.  */
  3506.   function setRequestStatus$statcode$text$extdata=FALSE$params=FALSE {
  3507.     $input array();
  3508.     $input['value']['statcode']  $statcode;
  3509.     $input['value']['text']      $text;
  3510.     if$extdata )
  3511.       $input['value']['extdata'$extdata;
  3512.     $input['params']    $this->_setParams$params);
  3513.     $this->requeststatus[$input;
  3514.   }
  3515. /*********************************************************************************/
  3516. /**
  3517.  * Property Name: RESOURCES
  3518.  */
  3519. /**
  3520.  * creates formatted output for calendar component property resources
  3521.  *
  3522.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3523.  * @since 2.3.2 - 2007-11-24
  3524.  * @return string 
  3525.  */
  3526.   function createResources({
  3527.     if>= count$this->resources ))
  3528.       return;
  3529.     $output null;
  3530.     foreach$this->resources as $resource {
  3531.       $attributes $this->_createParams$resource['params']array'ALTREP''LANGUAGE' ));
  3532.       ifis_array$resource['value')) {
  3533.         foreach$resource['value'as $rix => $resourcePart )
  3534.           $resource['value'][$rix$this->_strrep$resourcePart );
  3535.         $content  implode','$resource['value');
  3536.       }
  3537.       else
  3538.         $content  $this->_strrep$resource['value');
  3539.       $output    .= $this->_createElement'RESOURCES'$attributes$content );
  3540.     }
  3541.     return $output;
  3542.   }
  3543. /**
  3544.  * set calendar component property recources
  3545.  *
  3546.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3547.  * @since 2.3.2 - 2007-11-24
  3548.  * @param mixed $value 
  3549.  * @param array params optional
  3550.  * @return void 
  3551.  */
  3552.   function setResources$value$params=FALSE {
  3553.     $input array();
  3554.     $input['value']    $value;
  3555.     $input['params']   $this->_setParams$params );
  3556.     $this->resources[$input;
  3557.   }
  3558. /*********************************************************************************/
  3559. /**
  3560.  * Property Name: RRULE
  3561.  */
  3562. /**
  3563.  * creates formatted output for calendar component property rrule
  3564.  *
  3565.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3566.  * @since 0.7.43 - 2006-09-15
  3567.  * @return string 
  3568.  */
  3569.   function createRrule({
  3570.     $cnt count$this->rrule );
  3571.     if>= $cnt )
  3572.       return;
  3573.     return $this->_format_recur'RRULE'$this->rrule );
  3574.   }
  3575. /**
  3576.  * set calendar component property rrule
  3577.  *
  3578.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3579.  * @since 0.9.18 - 2007-03-18
  3580.  * @param array $rruleset 
  3581.  * @param array $params optional
  3582.  * @return void 
  3583.  */
  3584.   function setRrule$rruleset$params=FALSE {
  3585.     $exrule array();
  3586.     foreach$rruleset as $rrulelabel => $rrulevalue {
  3587.       $rrulelabel strtoupper$rrulelabel );
  3588.       if'UNTIL'  != $rrulelabel )
  3589.         $rrule['value'][$rrulelabel$rrulevalue;
  3590.       elseifis_array$rrulevalue &&
  3591.             (( == count$rrulevalue )) ||
  3592.              == count$rrulevalue )) ||
  3593.              == count$rrulevalue )) ||
  3594.              array_key_exists'year'$rrulevalue )))) {
  3595.         $parno count$rrulevalue )) // datetime / date
  3596.         $date  $this->_date_time_array$rrulevalue$parno );
  3597.         if(( count$date )) && !isset$date['tz'))
  3598.           $date['tz''Z';
  3599.         $rrule['value'][$rrulelabel$date;
  3600.       }
  3601.       elseifis_array$rrulevalue && isset$rrulevalue['timestamp')) {
  3602.         $date  $this->_date_time_stringdate'Y-m-d H:i:s'$rrulevalue['timestamp'));
  3603.         $date['tz''Z';
  3604.         $rrule['value'][$rrulelabel$date;
  3605.       }
  3606.       elseif<= strlentrim$rrulevalue ))) // ex. 2006-08-03 10:12:18
  3607.         $date $this->_date_time_string$rrulevalue );
  3608.         if(( count$date )) && !isset$date['tz'))
  3609.           $date['tz''Z';
  3610.         $rrule['value'][$rrulelabel$date;
  3611.       }
  3612.     }
  3613.     $rrule['params'$this->_setParams$params );
  3614.     $this->rrule[]   $rrule;
  3615.   }
  3616. /*********************************************************************************/
  3617. /**
  3618.  * Property Name: SEQUENCE
  3619.  */
  3620. /**
  3621.  * creates formatted output for calendar component property sequence
  3622.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3623.  * @since 0.9.7 - 2006-11-20
  3624.  * @return string 
  3625.  */
  3626.   function createSequence({
  3627.     $cnt count$this->sequence );
  3628.     if>= $cnt )
  3629.       return;
  3630.     $attributes $this->_createParams$this->sequence['params');
  3631.     return $this->_createElement'SEQUENCE'$attributes$this->sequence['value');
  3632.   }
  3633. /**
  3634.  * set calendar component property sequence
  3635.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3636.  * @since 1.x.x - 2007-04-25
  3637.  * @param int $value optional
  3638.  * @param array $params optional
  3639.  * @return void 
  3640.  */
  3641.   function setSequence$value=FALSE$params=FALSE {
  3642.     if!$value )
  3643.       $value $this->getProperty'sequence' 1;
  3644.     $this->sequence['value']  $value;
  3645.     $this->sequence['params'$this->_setParams$params );
  3646.   }
  3647. /*********************************************************************************/
  3648. /**
  3649.  * Property Name: STATUS
  3650.  */
  3651. /**
  3652.  * creates formatted output for calendar component property status
  3653.  *
  3654.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3655.  * @since 0.9.7 - 2006-11-20
  3656.  * @return string 
  3657.  */
  3658.   function createStatus({
  3659.     $cnt count$this->status );
  3660.     if>= $cnt )
  3661.       return;
  3662.     $attributes $this->_createParams$this->status['params');
  3663.     return $this->_createElement'STATUS'$attributes$this->status['value');
  3664.   }
  3665. /**
  3666.  * set calendar component property status
  3667.  *
  3668.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3669.  * @since 0.9.18 - 2007-03-18
  3670.  * @param string $value 
  3671.  * @param array $params optional
  3672.  * @return void 
  3673.  */
  3674.   function setStatus$value$params=FALSE {
  3675.     $this->status['value']  $value;
  3676.     $this->status['params'$this->_setParams$params );
  3677.   }
  3678. /*********************************************************************************/
  3679. /**
  3680.  * Property Name: SUMMARY
  3681.  */
  3682. /**
  3683.  * creates formatted output for calendar component property summary
  3684.  *
  3685.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3686.  * @since 0.9.7 - 2006-11-20
  3687.  * @return string 
  3688.  */
  3689.   function createSummary({
  3690.     $cnt count$this->summary );
  3691.     if>= $cnt )
  3692.       return;
  3693.     $attributes $this->_createParams$this->summary['params']array'ALTREP''LANGUAGE' ));
  3694.     $content    $this->_strrep$this->summary['value');
  3695.     return $this->_createElement'SUMMARY'$attributes$content );
  3696.   }
  3697. /**
  3698.  * set calendar component property summary
  3699.  *
  3700.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3701.  * @since 0.9.18 - 2007-03-18
  3702.  * @param string $value 
  3703.  * @param string $params optional
  3704.  * @return void 
  3705.  */
  3706.   function setSummary$value$params=FALSE {
  3707.     $this->summary['value']  $value;
  3708.     $this->summary['params'$this->_setParams$params );
  3709.   }
  3710. /*********************************************************************************/
  3711. /**
  3712.  * Property Name: TRANSP
  3713.  */
  3714. /**
  3715.  * creates formatted output for calendar component property transp
  3716.  *
  3717.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3718.  * @since 0.9.7 - 2006-11-20
  3719.  * @return string 
  3720.  */
  3721.   function createTransp({
  3722.     $cnt count$this->transp );
  3723.     if>= $cnt )
  3724.       return;
  3725.     $attributes $this->_createParams$this->transp['params');
  3726.     return $this->_createElement'TRANSP'$attributes$this->transp['value');
  3727.   }
  3728. /**
  3729.  * set calendar component property transp
  3730.  *
  3731.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3732.  * @since 0.9.18 - 2007-03-18
  3733.  * @param string $value 
  3734.  * @param string $params optional
  3735.  * @return void 
  3736.  */
  3737.   function setTransp$value$params=FALSE {
  3738.     $this->transp['value']  $value;
  3739.     $this->transp['params'$this->_setParams$params );
  3740.   }
  3741. /*********************************************************************************/
  3742. /**
  3743.  * Property Name: TRIGGER
  3744.  */
  3745. /**
  3746.  * creates formatted output for calendar component property trigger
  3747.  *
  3748.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3749.  * @since 0.9.19 - 2007-03-27
  3750.  * @return string 
  3751.  */
  3752.   function createTrigger({
  3753.     $cnt count$this->trigger );
  3754.     if>= $cnt )
  3755.       return;
  3756.     $content $attributes null;
  3757.     ifisset$this->trigger['value']['year')   &&
  3758.         isset$this->trigger['value']['month')  &&
  3759.         isset$this->trigger['value']['day'))
  3760.       $content      .= $this->_format_date_time$this->trigger['value');
  3761.     else {
  3762.       ifTRUE !== $this->trigger['value']['relatedstart')
  3763.         $attributes .= $this->intAttrDelimiter.'RELATED=END';
  3764.       if$this->trigger['value']['before')
  3765.         $content    .= '-';
  3766.       $content      .= $this->_format_duration$this->trigger['value');
  3767.     }
  3768.     $attributes     .= $this->_createParams$this->trigger['params');
  3769.     return $this->_createElement'TRIGGER'$attributes$content );
  3770.   }
  3771. /**
  3772.  * set calendar component property trigger
  3773.  *
  3774.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3775.  * @since 2.1.1 - 2007-07-07
  3776.  * @param mixed $year 
  3777.  * @param mixed $month optional
  3778.  * @param int $day optional
  3779.  * @param int $week optional
  3780.  * @param int $hour optional
  3781.  * @param int $min optional
  3782.  * @param int $sec optional
  3783.  * @param bool $relatedEnd optional
  3784.  * @param bool $after optional
  3785.  * @param string $tz optional
  3786.  * @param array $params optional
  3787.  * @return void 
  3788.  * @toto fix is_int
  3789.  */
  3790.   function setTrigger$year=FALSE$month=FALSE$day=FALSE$week=FALSE$hour=FALSE$min=FALSE$sec=FALSE$relatedEnd=FALSE$after=FALSE$tz=FALSE$params=FALSE {
  3791.     ifis_array$year && array_key_exists'timestamp'$year )) // timestamp
  3792.       $params $this->_setParams$month );
  3793.       $this->_existRem$params'VALUE''DATE-TIME' );
  3794.       ifisset$params['TZID')) {
  3795.         $year['tz'$params['TZID'];
  3796.         unset$params['TZID');
  3797.       }
  3798.       $tz     isset$year['tz')) ' '.$year['tz'null;
  3799.       $parno  isset$tz )) 6;
  3800.       $date   $this->_date_time_stringdate'Y-m-d H:i:s'$year['timestamp').$tz$parno );
  3801.       foreach$date as $k => $v )
  3802.         $$k $v;
  3803.     }
  3804.     elseifis_array$year )) {
  3805.       ifarray_key_exists'year',  $year &&
  3806.           array_key_exists'month'$year &&
  3807.           array_key_exists'day',   $year )) {  // date-time
  3808.         $params $this->_setParams$month );
  3809.         ifisset$params['TZID')) {
  3810.           $year['tz'$params['TZID'];
  3811.           unset$params['TZID');
  3812.         }
  3813.       }
  3814.       else // duration
  3815.         $year       $this->_duration_array$year );
  3816.         $relatedEnd $month;
  3817.         $after      $day;
  3818.         $params $this->_setParams$week );
  3819.       }
  3820.       $this->_existRem$params'VALUE''DATE-TIME' );
  3821.       $this->_existRem$params'VALUE''DURATION' );
  3822.       $SSYY  array_key_exists'year',  $year )) $year['year']  null;
  3823.       $month array_key_exists'month'$year )) $year['month'null;
  3824.       $day   array_key_exists'day',   $year )) $year['day']   null;
  3825.       $week  array_key_exists'week',  $year )) $year['week']  null;
  3826.       $hour  array_key_exists'hour',  $year )) $year['hour']  null;
  3827.       $min   array_key_exists'min',   $year )) $year['min']   null;
  3828.       $sec   array_key_exists'sec',   $year )) $year['sec']   null;
  3829.       $tz    array_key_exists'tz',    $year )) $year['tz']    null;
  3830.       $year  $SSYY;
  3831.     }
  3832.     elseifis_string($year&& !ctype_digit(string) $year )) {  // duration or date in a string
  3833.       $params $this->_setParams$month );
  3834.       unset$month );
  3835.       $this->_existRem$params'VALUE''DATE-TIME' );   // ??
  3836.       $this->_existRem$params'VALUE''DURATION' );
  3837.       ifin_array$year{0}array'P''+''-' ))) // duration
  3838.         if'-' == $year{0)
  3839.           $after FALSE;
  3840.         elseif'+' == $year{0)
  3841.           $after TRUE;
  3842.         elseif'P' == $year{0)
  3843.           $after TRUE;
  3844.         if'P' != $year{0)
  3845.           $year  substr$year);
  3846.         $date    $this->_duration_string$year);
  3847.       }
  3848.       else {
  3849.         $date    $this->_date_time_string$year);   // date
  3850.         ifisset$params['TZID')) {
  3851.           $date['tz'$params['TZID'];
  3852.           unset$params['TZID');
  3853.         }
  3854.       }
  3855.       foreach$date as $k => $v )
  3856.         $$k $v;
  3857.     }
  3858.     else
  3859.       $params $this->_setParams$params );
  3860.     if!empty$year && !empty$month && !empty$day ) ) // date
  3861.       $params['VALUE''DATE-TIME';
  3862.       $this->trigger['value'array'year'  => $year
  3863.                                      'month' => $month
  3864.                                      'day'   => $day);
  3865.       $this->trigger['value']['hour']   $hour;
  3866.       $this->trigger['value']['min']    $min;
  3867.       $this->trigger['value']['sec']    $sec;
  3868.       if!empty$tz ))
  3869.         $this->trigger['value']['tz']   $tz;
  3870.       else
  3871.         $this->trigger['value']['tz']   'Z';
  3872.     }
  3873.     else {                                                   // duration
  3874.       $this->_existRem$params'VALUE''DURATION' );
  3875.       if$this->_existRem$params'RELATED''END'TRUE ))
  3876.         $relatedEnd TRUE;
  3877.       elseif$this->_existRem$params'RELATED''START'TRUE ))
  3878.         $relatedEnd FALSE;
  3879.       if!empty$week )) {
  3880.         $this->trigger['value'array'week'         => $week
  3881.                                        'relatedstart' => !$relatedEnd
  3882.                                        'before'       => !$after );
  3883.       }
  3884.       else {
  3885.         $this->trigger['value'array'day'          => $day
  3886.                                        'hour'         => $hour
  3887.                                        'min'          => $min
  3888.                                        'sec'          => $sec
  3889.                                        'relatedstart' => !$relatedEnd
  3890.                                        'before'       => !$after );
  3891.       }
  3892.     }
  3893.     if!isset$this->trigger['value'))
  3894.       return;
  3895.     $this->trigger['params'$params;
  3896.   }
  3897. /*********************************************************************************/
  3898. /**
  3899.  * Property Name: TZID
  3900.  */
  3901. /**
  3902.  * creates formatted output for calendar component property tzid
  3903.  *
  3904.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3905.  * @since 2.3.2 - 2007-11-25
  3906.  * @return string 
  3907.  */
  3908.   function createTzid({
  3909.     $cnt count$this->tzid );
  3910.     if>= $cnt )
  3911.       return;
  3912.     $attributes $this->_createParams$this->tzid['params');
  3913.     return $this->_createElement'TZID'$attributes$this->_strrep$this->tzid['value'));
  3914.   }
  3915. /**
  3916.  * set calendar component property tzid
  3917.  *
  3918.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3919.  * @since 2.3.2 - 2007-11-25
  3920.  * @param string $value 
  3921.  * @param array $params optional
  3922.  * @return void 
  3923.  */
  3924.   function setTzid$value$params=FALSE {
  3925.     ifempty$value ))
  3926.       return;
  3927.     $this->tzid['value']  $value;
  3928.     $this->tzid['params'$this->_setParams$params );
  3929.   }
  3930. /*********************************************************************************/
  3931. /**
  3932.  * .. .
  3933.  * Property Name: TZNAME
  3934.  */
  3935. /**
  3936.  * creates formatted output for calendar component property tzname
  3937.  *
  3938.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3939.  * @since 2.3.2 - 2007-11-25
  3940.  * @return string 
  3941.  */
  3942.   function createTzname({
  3943.     $cnt count$this->tzname );
  3944.     if>= $cnt )
  3945.       return;
  3946.     $output null;
  3947.     foreach$this->tzname as $theName {
  3948.       $attributes $this->_createParams$theName['params']array'LANGUAGE' ));
  3949.       $output    .= $this->_createElement'TZNAME'$attributes$this->_strrep$theName['value'));
  3950.     }
  3951.     return $output;
  3952.   }
  3953. /**
  3954.  * set calendar component property tzname
  3955.  *
  3956.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3957.  * @since 2.3.2 - 2007-11-25
  3958.  * @param string $value 
  3959.  * @param string $params optional
  3960.  * @return void 
  3961.  */
  3962.   function setTzname$value$params=FALSE {
  3963.     ifempty$value ))
  3964.       return;
  3965.     $input['value']  $value;
  3966.     $input['params'$this->_setParams$params );
  3967.     $this->tzname[]  $input;
  3968.   }
  3969. /*********************************************************************************/
  3970. /**
  3971.  * Property Name: TZOFFSETFROM
  3972.  */
  3973. /**
  3974.  * creates formatted output for calendar component property tzoffsetfrom
  3975.  *
  3976.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3977.  * @since 0.9.7 - 2006-11-20
  3978.  * @return string 
  3979.  */
  3980.   function createTzoffsetfrom({
  3981.     $cnt count$this->tzoffsetfrom );
  3982.     if>= $cnt )
  3983.       return;
  3984.     $attributes $this->_createParams$this->tzoffsetfrom['params');
  3985.     return $this->_createElement'TZOFFSETFROM'$attributes$this->tzoffsetfrom['value');
  3986.   }
  3987. /**
  3988.  * set calendar component property tzoffsetfrom
  3989.  *
  3990.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  3991.  * @since 1.x.x - 2007-05-25
  3992.  * @param string $value 
  3993.  * @param string $params optional
  3994.  * @return void 
  3995.  */
  3996.   function setTzoffsetfrom$value$params=FALSE {
  3997.     $this->tzoffsetfrom['value']   $value;
  3998.     ifempty$this->tzoffsetfrom['value'))
  3999.       return;
  4000.     $this->tzoffsetfrom['params'$this->_setParams$params );
  4001.   }
  4002. /*********************************************************************************/
  4003. /**
  4004.  * Property Name: TZOFFSETTO
  4005.  */
  4006. /**
  4007.  * creates formatted output for calendar component property tzoffsetto
  4008.  *
  4009.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4010.  * @since 0.9.7 - 2006-11-20
  4011.  * @return string 
  4012.  */
  4013.   function createTzoffsetto({
  4014.     $cnt count$this->tzoffsetto );
  4015.     if>= $cnt )
  4016.       return;
  4017.     $attributes $this->_createParams$this->tzoffsetto['params');
  4018.     return $this->_createElement'TZOFFSETTO'$attributes$this->tzoffsetto['value');
  4019.   }
  4020. /**
  4021.  * set calendar component property tzoffsetto
  4022.  *
  4023.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4024.  * @since 0.9.18 - 2007-03-18
  4025.  * @param string $value 
  4026.  * @param string $params optional
  4027.  * @return void 
  4028.  */
  4029.   function setTzoffsetto$value$params=FALSE {
  4030.     $this->tzoffsetto['value']  $value;
  4031.     ifempty$this->tzoffsetto['value'))
  4032.       return;
  4033.     $this->tzoffsetto['params'$this->_setParams$params );
  4034.   }
  4035. /*********************************************************************************/
  4036. /**
  4037.  * Property Name: TZURL
  4038.  */
  4039. /**
  4040.  * creates formatted output for calendar component property tzurl
  4041.  *
  4042.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4043.  * @since 0.9.7 - 2006-11-20
  4044.  * @return string 
  4045.  */
  4046.   function createTzurl({
  4047.     $cnt count$this->tzurl );
  4048.     if>= $cnt )
  4049.       return;
  4050.     $attributes $this->_createParams$this->tzurl['params');
  4051.     return $this->_createElement'TZURL'$attributes$this->tzurl['value');
  4052.   }
  4053. /**
  4054.  * set calendar component property tzurl
  4055.  *
  4056.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4057.  * @since 0.9.18 - 2007-03-18
  4058.  * @param string $value 
  4059.  * @param string $params optional
  4060.  * @return void 
  4061.  */
  4062.   function setTzurl$value$params=FALSE {
  4063.     $this->tzurl['value']   $value;
  4064.     ifempty$this->tzurl['value'))
  4065.       return;
  4066.     $this->tzurl['params'$this->_setParams$params );
  4067.   }
  4068. /*********************************************************************************/
  4069. /**
  4070.  * Property Name: UID
  4071.  */
  4072. /**
  4073.  * creates formatted output for calendar component property uid
  4074.  *
  4075.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4076.  * @since 0.9.7 - 2006-11-20
  4077.  * @return string 
  4078.  */
  4079.   function createUid({
  4080.     $cnt count$this->uid );
  4081.     if>= $cnt {
  4082.       $this->_makeuid();
  4083.     }
  4084.     $attributes $this->_createParams$this->uid['params');
  4085.     return $this->_createElement'UID'$attributes$this->uid['value');
  4086.   }
  4087. /**
  4088.  * create an unique id for this calendar component object instance
  4089.  *
  4090.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4091.  * @since 2.2.7 - 2007-09-04
  4092.  * @return void 
  4093.  */
  4094.   function _makeUid({
  4095.     $date   date('Ymd\THisT');
  4096.     $unique substr(microtime()24);
  4097.     $base   'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPrRsStTuUvVxXuUvVwWzZ1234567890';
  4098.     $start  0;
  4099.     $end    strlen$base 1;
  4100.     $length 6;
  4101.     $str    null;
  4102.     for$p 0$p $length$p++ )
  4103.       $unique .= $base{mt_rand$start$end )};
  4104.     $this->uid['value']  $date.'-'.$unique.'@'.$this->getConfig'unique_id' );
  4105.     $this->uid['params'null;
  4106.   }
  4107. /**
  4108.  * set calendar component property uid
  4109.  *
  4110.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4111.  * @since 0.9.18 - 2007-03-18
  4112.  * @param string $value 
  4113.  * @param string $params optional
  4114.  * @return void 
  4115.  */
  4116.   function setUid$value$params=FALSE {
  4117.     $this->uid['value']  $value;
  4118.     ifempty$this->uid['value'))
  4119.       return;
  4120.     $this->uid['params'$this->_setParams$params );
  4121.   }
  4122. /*********************************************************************************/
  4123. /**
  4124.  * Property Name: URL
  4125.  */
  4126. /**
  4127.  * creates formatted output for calendar component property url
  4128.  *
  4129.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4130.  * @since 0.9.7 - 2006-11-20
  4131.  * @return string 
  4132.  */
  4133.   function createUrl({
  4134.     $cnt count$this->url );
  4135.     if>= $cnt )
  4136.       return;
  4137.     $attributes $this->_createParams$this->url['params');
  4138.     return $this->_createElement'URL'$attributes$this->url['value');
  4139.   }
  4140. /**
  4141.  * set calendar component property url
  4142.  *
  4143.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4144.  * @since 0.9.18 - 2007-03-18
  4145.  * @param string $value 
  4146.  * @param string $params optional
  4147.  * @return void 
  4148.  */
  4149.   function setUrl$value$params=FALSE {
  4150.     $this->url['value']   $value;
  4151.     ifempty$this->url['value'))
  4152.       return;
  4153.     $this->url['params'$this->_setParams$params );
  4154.   }
  4155. /*********************************************************************************/
  4156. /**
  4157.  * Property Name: x-prop
  4158.  */
  4159. /**
  4160.  * creates formatted output for calendar component property x-prop
  4161.  *
  4162.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4163.  * @since 2.3.2 - 2007-11-25
  4164.  * @return string 
  4165.  */
  4166.   function createXprop({
  4167.     if>= count$this->xprop ))
  4168.       return;
  4169.     $xprop null;
  4170.     foreach$this->xprop as $label => $xpropPart {
  4171.       $attributes $this->_createParams$xpropPart['params']array'LANGUAGE' ));
  4172.       ifis_array$xpropPart['value')) {
  4173.         foreach$xpropPart['value'as $pix => $theXpart )
  4174.           $xpropPart['value'][$pix$this->_strrep$theXpart );
  4175.         $xpropPart['value']  implode','$xpropPart['value');
  4176.       }
  4177.       else
  4178.         $xpropPart['value'$this->_strrep$xpropPart['value');
  4179.       $xprop .= $this->_createElementstrtoupper$label )$attributes$xpropPart['value');
  4180.     }
  4181.     return $xprop;
  4182.   }
  4183. /**
  4184.  * set calendar component property x-prop
  4185.  *
  4186.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4187.  * @since 2.0.7 - 2007-06-21
  4188.  * @param string $label 
  4189.  * @param mixed $value 
  4190.  * @param array $params optional
  4191.  * @return void 
  4192.  */
  4193.   function setXprop$label$value$params=FALSE {
  4194.     ifempty$label || empty$value ))
  4195.       return;
  4196.     $xprop array'value' => $value );
  4197.     $toolbox new calendarComponent();
  4198.     $xprop['params'$toolbox->_setParams$params );
  4199.     $this->xprop[$label$xprop;
  4200.   }
  4201. /*********************************************************************************/
  4202. /*********************************************************************************/
  4203. /**
  4204.  * create element format parts
  4205.  *
  4206.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4207.  * @since 2.0.6 - 2006-06-20
  4208.  * @return string 
  4209.  */
  4210.   function _createFormat({
  4211.     $objectname                   null;
  4212.     switch$this->format {
  4213.       case 'xcal':
  4214.         $objectname               isset$this->timezonetype )) ?
  4215.                                  strtolower$this->timezonetype )  :  strtolower$this->objName );
  4216.         $this->componentStart1    = $this->elementStart1 = '<';
  4217.         $this->componentStart2    = $this->elementStart2 = '>';
  4218.         $this->componentEnd1      = $this->elementEnd1   = '</';
  4219.         $this->componentEnd2      = $this->elementEnd2   = '>'.$this->nl;
  4220.         $this->intAttrDelimiter   = '<!-- -->';
  4221.         $this->attributeDelimiter = $this->nl;
  4222.         $this->valueInit          = null;
  4223.         break;
  4224.       default:
  4225.         $objectname               isset$this->timezonetype )) ?
  4226.                                  strtoupper$this->timezonetype )  :  strtoupper$this->objName );
  4227.         $this->componentStart1    = 'BEGIN:';
  4228.         $this->componentStart2    = null;
  4229.         $this->componentEnd1      = 'END:';
  4230.         $this->componentEnd2      = $this->nl;
  4231.         $this->elementStart1      = null;
  4232.         $this->elementStart2      = null;
  4233.         $this->elementEnd1        = null;
  4234.         $this->elementEnd2        = $this->nl;
  4235.         $this->intAttrDelimiter   = '<!-- -->';
  4236.         $this->attributeDelimiter = ';';
  4237.         $this->valueInit          = ':';
  4238.         break;
  4239.     }
  4240.     return $objectname;
  4241.   }
  4242. /**
  4243.  * creates formatted output for calendar component property
  4244.  *
  4245.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4246.  * @since 0.9.15 - 2007-01-08
  4247.  * @param string $label property name
  4248.  * @param string $attributes property attributes
  4249.  * @param string $content property content (optional)
  4250.  * @return string 
  4251.  */
  4252.   function _createElement$label$attributes$content=FALSE {
  4253.     $label  $this->_formatPropertyName$label );
  4254.     $output $this->elementStart1.$label;
  4255.     $categoriesAttrLang null;
  4256.     $attachInlineBinary FALSE;
  4257.     $attachfmttype      null;
  4258.     if!empty$attributes ))  {
  4259.       $attributes  trim$attributes );
  4260.       if 'xcal' == $this->format{
  4261.         $attributes2 explode$this->intAttrDelimiter$attributes );
  4262.         $attributes  null;
  4263.         foreach$attributes2 as $attribute {
  4264.           $attrKVarr explode'='$attribute );
  4265.           ifempty$attrKVarr[0))
  4266.             continue;
  4267.           if!isset$attrKVarr[1)) {
  4268.             $attrValue $attrKVarr[0];
  4269.             $attrKey   null;
  4270.           }
  4271.           elseif== count$attrKVarr)) {
  4272.             $attrKey   strtolower$attrKVarr[0);
  4273.             $attrValue $attrKVarr[1];
  4274.           }
  4275.           else {
  4276.             $attrKey   strtolower$attrKVarr[0);
  4277.             unset$attrKVarr[0);
  4278.             $attrValue implode'='$attrKVarr );
  4279.           }
  4280.           if(( 'attach' == $label && in_array$attrKeyarray'fmttype''encoding''value' )))) {
  4281.             $attachInlineBinary TRUE;
  4282.             if'fmttype' == $attrKey )
  4283.               $attachfmttype $attrKey.'='.$attrValue;
  4284.             continue;
  4285.           }
  4286.           elseif(( 'categories' == $label && 'language' == $attrKey ))
  4287.             $categoriesAttrLang $attrKey.'='.$attrValue;
  4288.           else {
  4289.             $attributes .= empty$attributes )) ' ' $this->attributeDelimiter.' ';
  4290.             $attributes .= !empty$attrKey )) $attrKey.'=' null;
  4291.             if(( '"' == substr$attrValue0)) && '"' == substr$attrValue-))) {
  4292.               $attrValue substr$attrValue1strlen$attrValue ));
  4293.               $attrValue str_replace'"'''$attrValue );
  4294.             }
  4295.             $attributes .= '"'.htmlspecialchars$attrValue ).'"';
  4296.           }
  4297.         }
  4298.       }
  4299.       else {
  4300.         $attributes str_replace$this->intAttrDelimiter$this->attributeDelimiter$attributes );
  4301.       }
  4302.     }
  4303.     if(((( 'attach' == $label && !$attachInlineBinary ||
  4304.          in_array$labelarray'tzurl''url' ))))      && 'xcal' == $this->format)) {
  4305.       $pos strrpos($content"/");
  4306.       $docname $pos !== falsesubstr$content(strlen$content $pos )) $content;
  4307.       $this->xcaldecl[array'xmldecl'  => 'ENTITY'
  4308.                                'uri'      => $docname
  4309.                                'ref'      => 'SYSTEM'
  4310.                                'external' => $content
  4311.                                'type'     => 'NDATA'
  4312.                                'type2'    => 'BINERY' );
  4313.       $attributes .= empty$attributes )) ' ' $this->attributeDelimiter.' ';
  4314.       $attributes .= 'uri="'.$docname.'"';
  4315.       $content null;
  4316.       if'attach' == $label {
  4317.         $attributes str_replace$this->attributeDelimiter$this->intAttrDelimiter$attributes );
  4318.         $content $this->_createElement'extref'$attributesnull );
  4319.         $attributes null;
  4320.       }
  4321.     }
  4322.     elseif(( 'attach' == $label && $attachInlineBinary && 'xcal' == $this->format)) {
  4323.       $content $this->nl.$this->_createElement'b64bin'$attachfmttype$content )// max one attribute
  4324.     }
  4325.     $output .= $attributes;
  4326.     if!$content {
  4327.       switch$this->format {
  4328.         case 'xcal':
  4329.           $output .= ' /';
  4330.           $output .= $this->elementStart2;
  4331.           return $output;
  4332.           break;
  4333.         default:
  4334.           $output .= $this->elementStart2;
  4335.           return $this->_size75$output );
  4336.           break;
  4337.       }
  4338.     }
  4339.     $output .= $this->elementStart2;
  4340.     switch$label {
  4341.       case 'categories':
  4342.  //   case 'resources': ??
  4343.         $output  .= $this->nl;
  4344.         $items    explode(','$content);
  4345.         $content  null;
  4346.         foreach$items as $item )
  4347.           $content .= $this->_createElement'item'$categoriesAttrLang$item );  // max one attribute
  4348.         break;
  4349.       case 'geo':
  4350.         $output  .= $this->nl;
  4351.         list($lat$lonexplode(';'$content);
  4352.         $content  null;
  4353.         $content .= $this->_createElement'lat'null$lat );
  4354.         $content .= $this->_createElement'lon'null$lon );
  4355.         break;
  4356.       default:
  4357.         break;
  4358.     }
  4359.     $output .= $this->valueInit.$content;
  4360.     switch$this->format {
  4361.       case 'xcal':
  4362.         return $output.$this->elementEnd1.$label.$this->elementEnd2;
  4363.         break;
  4364.       default:
  4365.         return $this->_size75$output );
  4366.         break;
  4367.     }
  4368.   }
  4369. /**
  4370.  * creates formatted output for calendar component property parameters
  4371.  *
  4372.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4373.  * @since 0.9.22 - 2007-04-10
  4374.  * @param array $params  optional
  4375.  * @param array $ctrKeys optional
  4376.  * @return string 
  4377.  */
  4378.   function _createParams$params=array()$ctrKeys=array() ) {
  4379.     $attrLANG $attr1 $attr2 null;
  4380.     $CNattrKey   in_array'CN',       $ctrKeys )) TRUE FALSE ;
  4381.     $LANGattrKey in_array'LANGUAGE'$ctrKeys )) TRUE FALSE ;
  4382.     $CNattrExist $LANGattrExist FALSE;
  4383.     ifis_array$params )) {
  4384.       foreach$params as $paramKey => $paramValue {
  4385.         ifis_int$paramKey ))
  4386.           $attr2            .= $this->intAttrDelimiter.$paramValue;
  4387.         elseif(( 'LANGUAGE' == $paramKey && $LANGattrKey {
  4388.           $attrLANG         .= $this->intAttrDelimiter."LANGUAGE=$paramValue";
  4389.           $LANGattrExist     TRUE;
  4390.         }
  4391.         elseif(( 'CN'       == $paramKey && $CNattrKey {
  4392.           $attr1             $this->intAttrDelimiter.'CN="'.$paramValue.'"';
  4393.           $CNattrExist       TRUE;
  4394.         }
  4395.         elseif(( 'ALTREP'   == $paramKey && in_array$paramKey$ctrKeys ))
  4396.           $attr2            .= $this->intAttrDelimiter.'ALTREP="'.$paramValue.'"';
  4397.         elseif(( 'DIR'      == $paramKey && in_array$paramKey$ctrKeys ))
  4398.           $attr2            .= $this->intAttrDelimiter.'DIR="'.$paramValue.'"';
  4399.         elseif(( 'SENT-BY'  == $paramKey && in_array$paramKey$ctrKeys ))
  4400.           $attr2            .= $this->intAttrDelimiter.'SENT-BY="MAILTO:'.$paramValue.'"';
  4401.         else
  4402.           $attr2            .= $this->intAttrDelimiter."$paramKey=$paramValue";
  4403.       }
  4404.     }
  4405.     if!$LANGattrExist {
  4406.       $lang $this->getConfig'language' );
  4407.       if(( $CNattrExist || $LANGattrKey && $lang )
  4408.         $attrLANG .= $this->intAttrDelimiter.'LANGUAGE='.$lang;
  4409.     }
  4410.     return $attrLANG.$attr1.$attr2;
  4411.   }
  4412. /**
  4413.  * convert local startdate/enddate (Ymd[His]) to duration
  4414.  *
  4415.  * uses this component dates if missing input dates
  4416.  *
  4417.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4418.  * @since 2.2.11 - 2007-11-03
  4419.  * @param array $startdate, optional
  4420.  * @param array $duration, optional
  4421.  * @return array duration
  4422.  */
  4423.   function _date2duration$startdate=FALSE$enddate=FALSE {
  4424.     if!$startdate || !$enddate {
  4425.       ifFALSE === $startdate $this->getProperty'dtstart' )))
  4426.         return null;
  4427.       ifFALSE === $enddate $this->getProperty'dtend' )))    // vevent/vfreebusy
  4428.         ifFALSE === $enddate $this->getProperty'due' )))      // vtodo
  4429.           return null;
  4430.     }
  4431.     if!$startdate || !$enddate )
  4432.       return null;
  4433.     $startWdate  mktime000$startdate['month']$startdate['day']$startdate['year');
  4434.     $endWdate    mktime000$enddate['month'],   $enddate['day'],   $enddate['year');
  4435.     $wduration   $endWdate $startWdate;
  4436.     $dur         array();
  4437.     $dur['week'= (int) floor$wduration 24 60 60 ));
  4438.     $wduration   =              $wduration 24 60 60 );
  4439.     $dur['day']  = (int) floor$wduration 24 60 60 ));
  4440.     $wduration   =              $wduration 24 60 60 );
  4441.     $dur['hour'= (int) floor$wduration 60 60 ));
  4442.     $wduration   =              $wduration 60 60 );
  4443.     $dur['min']  = (int) floor$wduration 60 ));
  4444.     $dur['sec']  = (int)        $wduration 60 );
  4445.     return $dur;
  4446.   }
  4447. /**
  4448.  * convert date/datetime to timestamp
  4449.  *
  4450.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4451.  * @since 2.2.2 - 2007-07-29
  4452.  * @param array  $datetime  datetime/(date)
  4453.  * @param string $tz        timezone
  4454.  * @return timestamp 
  4455.  */
  4456.   function _date2timestamp$datetime$tz=null {
  4457.     $output null;
  4458.     if!isset$datetime['hour')) $datetime['hour''0';
  4459.     if!isset$datetime['min'))  $datetime['min']  '0';
  4460.     if!isset$datetime['sec'))  $datetime['sec']  '0';
  4461.     foreach$datetime as $dkey => $dvalue {
  4462.       if'tz' != $dkey )
  4463.         $datetime[$dkey= (integer) $dvalue;
  4464.     }
  4465.     if$tz )
  4466.       $datetime['tz'$tz;
  4467.     $offset 0;
  4468.     ifisset$datetime['tz'&& '' trim $datetime['tz')))
  4469.       $offset $this->_tz2offset$datetime['tz');
  4470.     $output          mktime$datetime['hour']
  4471.                              $datetime['min']
  4472.                              $datetime['sec'$offset
  4473.                              $datetime['month']
  4474.                              $datetime['day']
  4475.                              $datetime['year');
  4476.     return $output;
  4477.   }
  4478. /**
  4479.  * ensures internal date-time/date format for input date-time/date in array format
  4480.  *
  4481.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4482.  * @since 0.3.0 - 2006-08-15
  4483.  * @param array $datetime 
  4484.  * @param int $parno optional, default FALSE
  4485.  * @return array 
  4486.  */
  4487.   function _date_time_array$datetime$parno=FALSE {
  4488.     $output array();
  4489.     foreach$datetime as $dateKey => $datePart {
  4490.       switch $dateKey {
  4491.         case '0'case 'year':   $output['year']  $datePartbreak;
  4492.         case '1'case 'month':  $output['month'$datePartbreak;
  4493.         case '2'case 'day':    $output['day']   $datePartbreak;
  4494.       }
  4495.       if!= $parno {
  4496.         switch $dateKey {
  4497.           case '0':
  4498.           case '1':
  4499.           case '2'break;
  4500.           case '3'case 'hour'$output['hour']  $datePartbreak;
  4501.           case '4'case 'min' $output['min']   $datePartbreak;
  4502.           case '5'case 'sec' $output['sec']   $datePartbreak;
  4503.           case '6'case 'tz'  $output['tz']    $datePartbreak;
  4504.         }
  4505.       }
  4506.     }
  4507.     if!= $parno {
  4508.       if!isset$output['hour'))
  4509.         $output['hour'0;
  4510.       if!isset$output['min']  ))
  4511.         $output['min'0;
  4512.       if!isset$output['sec']  ))
  4513.         $output['sec'0;
  4514.     }
  4515.     return $output;
  4516.   }
  4517. /**
  4518.  * ensures internal date-time/date format for input date-time/date in string fromat
  4519.  *
  4520.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4521.  * @since 2.2.10 - 2007-10-19
  4522.  * @param array $datetime 
  4523.  * @param int $parno optional, default FALSE
  4524.  * @return array 
  4525.  */
  4526.   function _date_time_string$datetime$parno=FALSE {
  4527.     $datetime = (string) trim$datetime );
  4528.     $tz  null;
  4529.     $len strlen$datetime 1;
  4530.     if'Z' == substr$datetime-)) {
  4531.       $tz 'Z';
  4532.       $datetime trimsubstr$datetime0$len ));
  4533.     }
  4534.     elseif( ( ctype_digitsubstr$datetime-2))) && // time or date
  4535.                   '-' == substr$datetime-3)) ||
  4536.                   ':' == substr$datetime-3)) ||
  4537.                   '.' == substr$datetime-3))) {
  4538.       $continue TRUE;
  4539.     }
  4540.     elseif( ( ctype_digitsubstr$datetime-4))) && // 4 pos offset
  4541.             ' +' == substr$datetime-6)) ||
  4542.             ' -' == substr$datetime-6))) {
  4543.       $tz substr$datetime-5);
  4544.       $datetime substr$datetime0($len 5));
  4545.     }
  4546.     elseif( ( ctype_digitsubstr$datetime-6))) && // 6 pos offset
  4547.             ' +' == substr$datetime-8)) ||
  4548.             ' -' == substr$datetime-8))) {
  4549.       $tz substr$datetime-7);
  4550.       $datetime substr$datetime0($len 7));
  4551.     }
  4552.     elseif( ( $len && ctype_digitsubstr$datetime-6)))) {
  4553.       $continue TRUE;
  4554.     }
  4555.     elseif'T' ==  substr$datetime-7)) {
  4556.       $continue TRUE;
  4557.     }
  4558.     else {
  4559.        //echo "_date_time_string 1:  $datetime tz=$tz.<br />\n"; // test ###
  4560.       $cx  $tx 0;    //  19970415T133000 US-Eastern
  4561.       for$cx = -1$cx $len )$cx-- {
  4562.         if(( ' ' == substr$datetime$cx)) || ctype_digitsubstr$datetime$cx)))
  4563.           break// if exists, tz ends here.. . ?
  4564.         elseifctype_alphasubstr$datetime$cx)) ||
  4565.              in_arraysubstr$datetime$cx)array'-''/' ))))
  4566.           $tx--// tz length counter
  4567.       }
  4568.       if$tx {
  4569.         $tz substr$datetime$tx );
  4570.         $datetime trimsubstr$datetime0$len $tx ));
  4571.       }
  4572.     }
  4573.       //echo "_date_time_string 1a:  $datetime tz=$tz.<br />\n"; // test ###
  4574.     ifsubstr_count$datetime'-' )) {
  4575.       $datetime str_replace'-''/'$datetime );
  4576.       //echo "_date_time_string 1b:  $datetime tz=$tz.<br />\n"; // test ###
  4577.     }
  4578.     elseifctype_digitsubstr$datetime0)) &&
  4579.            'T' ==      substr$datetime8)) &&
  4580.             ctype_digitsubstr$datetime9))) {
  4581.       $datetime substr$datetime,  4)
  4582.              .'/'.substr$datetime,  6)
  4583.              .'/'.substr$datetime,  0)
  4584.              .' '.substr$datetime,  9)
  4585.              .':'.substr$datetime11)
  4586.              .':'.substr$datetime13);
  4587.       // $datetime = substr( $datetime, 0, 8 ).substr( $datetime, 9 ); // not PHP 4.x compatible
  4588.       //echo "_date_time_string 1c:  $datetime tz=$tz.<br />\n"; // test ###
  4589.     }
  4590.     $datestring date'Y-m-d H:i:s'strtotime$datetime ));
  4591.      // echo "_date_time_string 2:  $datestring tz=$tz. datetime=$datetime<br />\n"; // test ###
  4592.     $tz                trim$tz );
  4593.     $output            array();
  4594.     $output['year']    substr$datestring0);
  4595.     $output['month']   substr$datestring5);
  4596.     $output['day']     substr$datestring8);
  4597.     if(( == $parno || == $parno )) {
  4598.       $output['hour']  substr$datestring11);
  4599.       $output['min']   substr$datestring14);
  4600.       $output['sec']   substr$datestring17);
  4601.       if!empty$tz ))
  4602.         $output['tz']  $tz;
  4603.     }
  4604.     elseif!= $parno {
  4605.       if(( '00' substr$datestring11)) ||
  4606.          '00' substr$datestring14)) ||
  4607.          '00' substr$datestring17))) {
  4608.         $output['hour']  substr$datestring11);
  4609.         $output['min']   substr$datestring14);
  4610.         $output['sec']   substr$datestring17);
  4611.       }
  4612.       if!empty$tz ))
  4613.         $output['tz']  $tz;
  4614.     }
  4615.     return $output;
  4616.   }
  4617. /**
  4618.  * ensures internal duration format for input in array format
  4619.  *
  4620.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4621.  * @since 2.1.1 - 2007-06-24
  4622.  * @param array $duration 
  4623.  * @return array 
  4624.  */
  4625.   function _duration_array$duration {
  4626.     $output array();
  4627.     if(    is_array$duration )        &&
  4628.        == count$duration ))       &&
  4629.               isset$duration['sec'&&
  4630.               60 $duration['sec')) {
  4631.       $durseconds  $duration['sec'];
  4632.       $output['week'floor$durseconds 60 60 24 ));
  4633.       $durseconds  =           $durseconds 60 60 24 );
  4634.       $output['day']  floor$durseconds 60 60 24 ));
  4635.       $durseconds  =           $durseconds 60 60 24 );
  4636.       $output['hour'floor$durseconds 60 60 ));
  4637.       $durseconds  =           $durseconds 60 60 );
  4638.       $output['min']  floor$durseconds 60 ));
  4639.       $output['sec']  =      $durseconds 60 ));
  4640.     }
  4641.     else {
  4642.       foreach$duration as $durKey => $durValue {
  4643.         switch $durKey {
  4644.           case '0'case 'week'$output['week']  $durValuebreak;
  4645.           case '1'case 'day':  $output['day']   $durValuebreak;
  4646.           case '2'case 'hour'$output['hour']  $durValuebreak;
  4647.           case '3'case 'min':  $output['min']   $durValuebreak;
  4648.           case '4'case 'sec':  $output['sec']   $durValuebreak;
  4649.         }
  4650.       }
  4651.     }
  4652.     ifisset$output['week'&& $output['week'))
  4653.       return $output;
  4654.     elseif (( isset$output['hour'&& $output['hour')) ||
  4655.             isset$output['min')  && $output['min']  )) ||
  4656.              (isset$output['sec')  && $output['sec']  ))) {
  4657.       if!isset$output['hour'))
  4658.         $output['hour'0;
  4659.       if!isset$output['min']  ))
  4660.         $output['min']  0;
  4661.       if!isset$output['sec']  ))
  4662.         $output['sec']  0;
  4663.     }
  4664.     return $output;
  4665.   }
  4666. /**
  4667.  * convert duration to date in array format based on dtstart value
  4668.  *
  4669.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4670.  * @since 2.2.11 - 2007-12-02
  4671.  * @param array $startdate, optional
  4672.  * @param array $duration, optional
  4673.  * @return array, date format
  4674.  */
  4675.   function duration2date($startdate=FALSE$duration=FALSE{
  4676.     if$startdate && $duration {
  4677.       $d1               $startdate;
  4678.       $dur              $duration;
  4679.     }
  4680.     elseifisset$this->dtstart['value'&& isset$this->duration['value')) {
  4681.       $d1               $this->dtstart['value'];
  4682.       $dur              $this->duration['value'];
  4683.     }
  4684.     else
  4685.       return null;
  4686.     $dateOnly         isset$d1['hour'|| isset$d1['min'|| isset$d1['sec')) FALSE TRUE;
  4687.     $d1['hour']       isset$d1['hour')) $d1['hour'0;
  4688.     $d1['min']        isset$d1['min'))  $d1['min']  0;
  4689.     $d1['sec']        isset$d1['sec'))  $d1['sec']  0;
  4690.     $dtend mktime$d1['hour']
  4691.                     $d1['min']
  4692.                     $d1['sec']
  4693.                     $d1['month']
  4694.                     $d1['day']
  4695.                     $d1['year');
  4696.     ifisset$dur['week'))
  4697.       $dtend += $dur['week'24 60 60 );
  4698.     ifisset$dur['day'))
  4699.       $dtend += $dur['day'24 60 60 );
  4700.     ifisset$dur['hour'))
  4701.       $dtend += $dur['hour'60 *60 );
  4702.     ifisset$dur['min'))
  4703.       $dtend += $dur['min'60 );
  4704.     ifisset$dur['sec'))
  4705.       $dtend +=   $dur['sec'];
  4706.     $dtend2 array();
  4707.     $dtend2['year']   date('Y'$dtend );
  4708.     $dtend2['month']  date('m'$dtend );
  4709.     $dtend2['day']    date('d'$dtend );
  4710.     $dtend2['hour']   date('H'$dtend );
  4711.     $dtend2['min']    date('i'$dtend );
  4712.     $dtend2['sec']    date('s'$dtend );
  4713.     ifisset$d1['tz'))
  4714.       $dtend2['tz']   $d1['tz'];
  4715.     if$dateOnly && (( == $dtend2['hour'&& == $dtend2['min'&& == $dtend2['sec')))
  4716.       unset$dtend2['hour']$dtend2['min']$dtend2['sec');
  4717.     return $dtend2;
  4718.   }
  4719. /**
  4720.  * ensures internal duration format for input in string format
  4721.  *
  4722.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4723.  * @since 2.0.5 - 2007-03-14
  4724.  * @param string $duration 
  4725.  * @return array 
  4726.  */
  4727.   function _duration_string$duration {
  4728.    $duration = (string) trim$duration );
  4729.    while'P' != strtouppersubstr$duration0))) {
  4730.      ifstrlen$duration ))
  4731.        $duration substr$duration);
  4732.      else
  4733.        return false// no leading P !?!?
  4734.    }
  4735.    $duration substr$duration)// skip P
  4736.    $duration str_replace 't''T'$duration );
  4737.    $duration str_replace 'T'''$duration );
  4738.    $output array();
  4739.    $val    null;
  4740.    for$ix=0$ix strlen$duration )$ix++ {
  4741.      switchstrtoupper$duration{$ix)) {
  4742.       case 'W':
  4743.         $output['week'$val;
  4744.         $val            null;
  4745.         break;
  4746.       case 'D':
  4747.         $output['day']  $val;
  4748.         $val            null;
  4749.         break;
  4750.       case 'H':
  4751.         $output['hour'$val;
  4752.         $val            null;
  4753.         break;
  4754.       case 'M':
  4755.         $output['min']  $val;
  4756.         $val            null;
  4757.         break;
  4758.       case 'S':
  4759.         $output['sec']  $val;
  4760.         $val            null;
  4761.         break;
  4762.       default:
  4763.         if!ctype_digit$duration{$ix))
  4764.           return false// unknown duration controll character  !?!?
  4765.         else
  4766.           $val .= $duration{$ix};
  4767.      }
  4768.    }
  4769.    return $this->_duration_array$output );
  4770.   }
  4771. /**
  4772.  * if exist, remove key with expected value from array and return spec. value
  4773.  *
  4774.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4775.  * @since 0.9.19 - 2007-03-18
  4776.  * @param array $array 
  4777.  * @param string $expkey 
  4778.  * @param string $expval 
  4779.  * @param int $hitval optional
  4780.  * @return int 
  4781.  */
  4782.   function _existRem&$array$expkey$expval=FALSE$hitval=null {
  4783.     if!is_array$array || == count$array )))
  4784.       return null;
  4785.     if!isset$array[$expkey))
  4786.       return null;
  4787.     if!$expval )
  4788.       return $hitval;
  4789.     if$expval != $array[$expkey)
  4790.       return null;
  4791.     unset$array[$expkey);
  4792.     return $hitval;
  4793.   }
  4794. /**
  4795.  * creates formatted output for calendar component property data value type date/date-time
  4796.  *
  4797.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4798.  * @since 2.2.2 - 2007-07-29
  4799.  * @param array   $datetime 
  4800.  * @param int     $parno, optional, default 6
  4801.  * @return string 
  4802.  */
  4803.   function _format_date_time$datetime$parno={
  4804.     if!isset$datetime['year')  &&
  4805.         !isset$datetime['month'&&
  4806.         !isset$datetime['day')   &&
  4807.         !isset$datetime['hour')  &&
  4808.         !isset$datetime['min')   &&
  4809.         !isset$datetime['sec'))
  4810.       return ;
  4811.     $output null;
  4812.     $output date('Ymd'mktime000
  4813.                                  (integer) $datetime['month']
  4814.                                  (integer) $datetime['day']
  4815.                                  (integer) $datetime['year']));
  4816.     ifisset$datetime['hour')  ||
  4817.         isset$datetime['min')   ||
  4818.         isset$datetime['sec')   ||
  4819.         isset$datetime['tz')) {
  4820.       ifisset$datetime['tz')  &&
  4821.          !isset$datetime['hour'))
  4822.         $datetime['hour''0';
  4823.       ifisset$datetime['hour')  &&
  4824.          !isset$datetime['min'))
  4825.         $datetime['min''0';
  4826.       ifisset$datetime['hour')  &&
  4827.           isset$datetime['min')   &&
  4828.          !isset$datetime['sec'))
  4829.         $datetime['sec''0';
  4830.       foreach$datetime as $dkey => $dvalue {
  4831.         if'tz' != $dkey )
  4832.           $datetime[$dkey= (integer) $dvalue;
  4833.       }
  4834.       $output .= date('\THis'mktime$datetime['hour']
  4835.                                       $datetime['min']
  4836.                                       $datetime['sec']
  4837.                                       $datetime['month']
  4838.                                       $datetime['day']
  4839.                                       $datetime['year']));
  4840.       ifisset$datetime['tz'&& '' trim $datetime['tz'))) {
  4841.         $datetime['tz'trim$datetime['tz');
  4842.         if'Z' == $datetime['tz')
  4843.           $output .= 'Z';
  4844.         $offset 0;
  4845.         $offset $this->_tz2offset$datetime['tz');
  4846.         if!= $offset {
  4847.           $output    date('Ymd\THis\Z'mktime$datetime['hour']
  4848.                                                  $datetime['min']
  4849.                                                  $datetime['sec'$offset
  4850.                                                  $datetime['month']
  4851.                                                  $datetime['day']
  4852.                                                  $datetime['year']));
  4853.         }
  4854.       }
  4855.       elseif== $parno )
  4856.         $output .= 'Z';
  4857.     }
  4858.     return $output;
  4859.   }
  4860. /**
  4861.  * creates formatted output for calendar component property data value type duration
  4862.  *
  4863.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4864.  * @since 1.x.x - 2007-05-13
  4865.  * @param array $duration ( week, day, hour, min, sec )
  4866.  * @return string 
  4867.  */
  4868.   function _format_duration$duration {
  4869.     if!isset$duration['week'&&
  4870.         !isset$duration['day')  &&
  4871.         !isset$duration['hour'&&
  4872.         !isset$duration['min')  &&
  4873.         !isset$duration['sec'))
  4874.       return;
  4875.     $output 'P';
  4876.     ifisset$duration['week'&& $duration['week'))
  4877.       $output       .= $duration['week'].'W';
  4878.     else {
  4879.       ifisset($duration['day'&& $duration['day'))
  4880.         $output     .= $duration['day'].'D';
  4881.       if(( isset$duration['hour']&& $duration['hour')) ||
  4882.          isset$duration['min'])  && $duration['min'))  ||
  4883.          isset$duration['sec'])  && $duration['sec'))) {
  4884.         $output     .= 'T';
  4885.         if$duration['hour'{
  4886.           $output   .= $duration['hour'].'H';
  4887.           if$duration['min'{
  4888.             $output .= $duration['min'].'M';
  4889.             if$duration['sec')
  4890.               $output .= $duration['sec'].'S';
  4891.           }
  4892.           elseif$duration['sec')
  4893.             $output .= '0M'.$duration['sec'].'S';
  4894.         }
  4895.         elseif$duration['min'{
  4896.           $output   .= '0H'.$duration['min'].'M';
  4897.           if$duration['sec')
  4898.             $output .= $duration['sec'].'S';
  4899.         }
  4900.         elseif$duration['sec')
  4901.           $output   .= '0H0M'.$duration['sec'].'S';
  4902.       }
  4903.     }
  4904.     return $output;
  4905.   }
  4906. /**
  4907.  * creates formatted output for calendar component property data value type recur
  4908.  *
  4909.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4910.  * @since 0.9.7 - 2006-11-20
  4911.  * @param array $recurlabel 
  4912.  * @param array $recurdata 
  4913.  * @return string 
  4914.  */
  4915.   function _format_recur $recurlabel$recurdata {
  4916.     $recur null;
  4917.     foreach$recurdata as $therule {
  4918.       $attributes isset$therule['params')) $this->_createParams$therule['params'null;
  4919.       $content1  $content2  null;
  4920.       foreach$therule['value'as $rulelabel => $rulevalue {
  4921.         switch$rulelabel {
  4922.           case 'FREQ'{
  4923.             $content1 .= "FREQ=$rulevalue";
  4924.             break;
  4925.           }
  4926.           case 'UNTIL'{
  4927.             $content2 .= ";UNTIL=";
  4928.             $content2 .= $this->_format_date_time$rulevalue );
  4929.             break;
  4930.           }
  4931.           case 'COUNT':
  4932.           case 'INTERVAL':
  4933.           case 'WKST'{
  4934.             $content2 .= ";$rulelabel=$rulevalue";
  4935.             break;
  4936.           }
  4937.           case 'BYSECOND':
  4938.           case 'BYMINUTE':
  4939.           case 'BYHOUR':
  4940.           case 'BYMONTHDAY':
  4941.           case 'BYYEARDAY':
  4942.           case 'BYWEEKNO':
  4943.           case 'BYMONTH':
  4944.           case 'BYSETPOS'{
  4945.             $content2 .= ";$rulelabel=";
  4946.             ifis_array$rulevalue )) {
  4947.               foreach$rulevalue as $vix => $valuePart {
  4948.                 $content2 .= $vix ',' null;
  4949.                 $content2 .= $valuePart;
  4950.               }
  4951.             }
  4952.             else
  4953.              $content2 .= $rulevalue;
  4954.             break;
  4955.           }
  4956.           case 'BYDAY'{
  4957.             $content2 .= ";$rulelabel=";
  4958.             $bydaycnt 0;
  4959.             foreach$rulevalue as $vix => $valuePart {
  4960.               $content21 $content22 null;
  4961.               ifis_array$valuePart )) {
  4962.                 $content2 .= $bydaycnt ',' null;
  4963.                 foreach$valuePart as $vix2 => $valuePart2 {
  4964.                   if'DAY' != strtoupper$vix2 ))
  4965.                       $content21 .= $valuePart2;
  4966.                   else
  4967.                     $content22 .= $valuePart2;
  4968.                 }
  4969.                 $content2 .= $content21.$content22;
  4970.                 $bydaycnt++;
  4971.               }
  4972.               else {
  4973.                 $content2 .= $bydaycnt ',' null;
  4974.                 if'DAY' != strtoupper$vix ))
  4975.                     $content21 .= $valuePart;
  4976.                 else {
  4977.                   $content22 .= $valuePart;
  4978.                   $bydaycnt++;
  4979.                 }
  4980.                 $content2 .= $content21.$content22;
  4981.               }
  4982.             }
  4983.             break;
  4984.           }
  4985.           default{
  4986.             $content2 .= ";$rulelabel=$rulevalue";
  4987.             break;
  4988.           }
  4989.         }
  4990.       }
  4991.       $recur .= $this->_createElement$recurlabel$attributes$content1.$content2 );
  4992.     }
  4993.     return $recur;
  4994.   }
  4995. /**
  4996.  * create property name case - lower/upper
  4997.  *
  4998.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  4999.  * @since 0.9.7 - 2006-11-20
  5000.  * @param string $propertyName 
  5001.  * @return string 
  5002.  */
  5003.   function _formatPropertyName$propertyName {
  5004.     switch$this->format {
  5005.       case 'xcal':
  5006.         return strtolower$propertyName );
  5007.         break;
  5008.       default:
  5009.         return strtoupper$propertyName );
  5010.         break;
  5011.     }
  5012.   }
  5013. /**
  5014.  * remakes a recur pattern to an array of dates
  5015.  *
  5016.  * if missing, UNTIL is set 1 year from startdate (emergency break)
  5017.  *
  5018.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5019.  * @since 2.2.11 - 2007-11-26
  5020.  * @param array $result, array to update, array([timestamp] => timestamp)
  5021.  * @param array $recur, pattern for recurrency (only value part, params ignored)
  5022.  * @param array $wdate, component start date
  5023.  * @param array $startdate, start date
  5024.  * @param array $enddate, optional
  5025.  * @return array of recurrence (start-)dates as index
  5026.  * @todo BYHOUR, BYMINUTE, BYSECOND, ev. BYSETPOS due to ambiguity, WEEKLY at year end/start
  5027.  */
  5028.   function _recur2date$result$recur$wdate$startdate$enddate=FALSE {
  5029.     foreach$wdate as $k => $v ifctype_digit$v )) $wdate[$k= (int) $v;
  5030.     $wdatets     $this->_date2timestamp$wdate );
  5031.     $startdatets $this->_date2timestamp$startdate );
  5032.     if!$enddate {
  5033.       $enddate $startdate;
  5034.       $enddate['year'+= 1;
  5035. // echo "recur __in_ ".implode('-',$startdate)." period start ".implode('-',$wdate)." period end ".implode('-',$enddate)."<br />\n";print_r($recur);echo "<br />\n";//test###
  5036.     }
  5037.     $endDatets $this->_date2timestamp$enddate )// fix break
  5038.     if!isset$recur['COUNT'&& !isset$recur['UNTIL'))
  5039.       $recur['UNTIL'$enddate// create break
  5040.     ifisset$recur['UNTIL')) {
  5041.       $tdatets $this->_date2timestamp$recur['UNTIL');
  5042.       if$endDatets $tdatets {
  5043.         $endDatets $tdatets// emergency break
  5044.         $enddate   $this->_date_time_stringdate('Y-m-d H:i:s'$endDatets ));
  5045.       }
  5046.       else
  5047.         $recur['UNTIL'$this->_date_time_stringdate('Y-m-d H:i:s'$endDatets ));
  5048.     }
  5049.     if$wdatets $endDatets {
  5050.      //echo "recur out of date ".implode('-',$this->_date_time_string(date('Y-m-d H:i:s',$wdatets),6))."<br />\n";//test
  5051.       return array()// nothing to do.. .
  5052.     }
  5053.     if!isset$recur['FREQ')) // "MUST be specified.. ."
  5054.       $recur['FREQ''DAILY'// ??
  5055.     $wkst isset$recur['WKST'&& 'SU' == $recur['WKST')) 24*60*60 0// ??
  5056.     if!isset$recur['INTERVAL'))
  5057.       $recur['INTERVAL'1;
  5058.     $countcnt !isset$recur['BYSETPOS')) 0// DTSTART counts as the first occurrence
  5059.             /* find out how to step up dates and set index for interval count */
  5060.     $step array();
  5061.     if'YEARLY' == $recur['FREQ')
  5062.       $step['year']  1;
  5063.     elseif'MONTHLY' == $recur['FREQ')
  5064.       $step['month'1;
  5065.     elseif'WEEKLY' == $recur['FREQ')
  5066.       $step['day']   7;
  5067.     else
  5068.       $step['day']   1;
  5069.     ifisset$step['year'&& isset$recur['BYMONTH'))
  5070.       $step array'month' => );
  5071.     ifempty$step && isset$recur['BYWEEKNO')) // ??
  5072.       $step array'day' => );
  5073.     ifisset$recur['BYYEARDAY'|| isset$recur['BYMONTHDAY'|| isset$recur['BYDAY'))
  5074.       $step array'day' => );
  5075.     $intervalarr array();
  5076.     if$recur['INTERVAL'{
  5077.       $intervalix $this->_recurIntervalIx$recur['FREQ']$wdate$wkst );
  5078.       $intervalarr array$intervalix => );
  5079.     }
  5080.     ifisset$recur['BYSETPOS')) // save start date + weekno
  5081.       $bysetposymd1 $bysetposymd2 $bysetposw1 $bysetposw2 array();
  5082.       $bysetposWold = (int) date'W'$wdatets $wkst ));
  5083.       $bysetposYold $wdate['year'];
  5084.       $bysetposMold $wdate['month'];
  5085.       $bysetposDold $wdate['day'];
  5086.       ifis_array$recur['BYSETPOS')) {
  5087.         foreach$recur['BYSETPOS'as $bix => $bval )
  5088.           $recur['BYSETPOS'][$bix= (int) $bval;
  5089.       }
  5090.       else
  5091.         $recur['BYSETPOS'array(int) $recur['BYSETPOS');
  5092.       $this->_stepdate$enddate$endDatets$step)// make sure to count whole last period
  5093.     }
  5094.     $this->_stepdate$wdate$wdatets$step);
  5095.     $year_old     null;
  5096.     $daynames     array'SU''MO''TU''WE''TH''FR''SA' );
  5097.              /* MAIN LOOP */
  5098.      // echo "recur start ".implode('-',$wdate)." end ".implode('-',$enddate)."<br />\n";//test
  5099.     whileTRUE {
  5100.       ifisset$endDatets && $wdatets $endDatets ))
  5101.         break;
  5102.       ifisset$recur['COUNT'&& $countcnt >= $recur['COUNT'))
  5103.         break;
  5104.       if$year_old != $wdate['year'{
  5105.         $year_old   $wdate['year'];
  5106.         $daycnts    array();
  5107.         $yeardays   $weekno 0;
  5108.         $yeardaycnt array();
  5109.         for$m 1$m <= 12$m++ // count up and update up-counters
  5110.           $daycnts[$marray();
  5111.           $weekdaycnt array();
  5112.           foreach$daynames as $dn )
  5113.             $yeardaycnt[$dn$weekdaycnt[$dn0;
  5114.           $mcnt     date't'mktime000$m1$wdate['year'));
  5115.           for$d   1$d <= $mcnt$d++ {
  5116.             $daycnts[$m][$darray();
  5117.             ifisset$recur['BYYEARDAY')) {
  5118.               $yeardays++;
  5119.               $daycnts[$m][$d]['yearcnt_up'$yeardays;
  5120.             }
  5121.             ifisset$recur['BYDAY')) {
  5122.               $day    date'w'mktime000$m$d$wdate['year'));
  5123.               $day    $daynames[$day];
  5124.               $daycnts[$m][$d]['DAY'$day;
  5125.               $weekdaycnt[$day]++;
  5126.               $daycnts[$m][$d]['monthdayno_up'$weekdaycnt[$day];
  5127.               $yeardaycnt[$day]++;
  5128.               $daycnts[$m][$d]['yeardayno_up'$yeardaycnt[$day];
  5129.             }
  5130.             if(  isset$recur['BYWEEKNO'|| $recur['FREQ'== 'WEEKLY' ))
  5131.               $daycnts[$m][$d]['weekno_up'=(int)date('W',mktime(0,0,$wkst,$m,$d,$wdate['year']));
  5132.           }
  5133.         }
  5134.         $daycnt 0;
  5135.         $yeardaycnt array();
  5136.         if(  isset$recur['BYWEEKNO'|| $recur['FREQ'== 'WEEKLY' )) {
  5137.           $weekno null;
  5138.           for$d=31$d 25$d-- // get last weekno for year
  5139.             if!$weekno )
  5140.               $weekno $daycnts[12][$d]['weekno_up'];
  5141.             elseif$weekno $daycnts[12][$d]['weekno_up'{
  5142.               $weekno $daycnts[12][$d]['weekno_up'];
  5143.               break;
  5144.             }
  5145.           }
  5146.         }
  5147.         for$m 12$m 0$m-- // count down and update down-counters
  5148.           $weekdaycnt array();
  5149.           foreach$daynames as $dn )
  5150.             $yeardaycnt[$dn$weekdaycnt[$dn0;
  5151.           $monthcnt 0;
  5152.           $mcnt     date't'mktime000$m1$wdate['year'));
  5153.           for$d   $mcnt$d 0$d-- {
  5154.             ifisset$recur['BYYEARDAY')) {
  5155.               $daycnt -= 1;
  5156.               $daycnts[$m][$d]['yearcnt_down'$daycnt;
  5157.             }
  5158.             ifisset$recur['BYMONTHDAY')) {
  5159.               $monthcnt -= 1;
  5160.               $daycnts[$m][$d]['monthcnt_down'$monthcnt;
  5161.             }
  5162.             ifisset$recur['BYDAY')) {
  5163.               $day  $daycnts[$m][$d]['DAY'];
  5164.               $weekdaycnt[$day-= 1;
  5165.               $daycnts[$m][$d]['monthdayno_down'$weekdaycnt[$day];
  5166.               $yeardaycnt[$day-= 1;
  5167.               $daycnts[$m][$d]['yeardayno_down'$yeardaycnt[$day];
  5168.             }
  5169.             if(  isset$recur['BYWEEKNO'|| $recur['FREQ'== 'WEEKLY' ))
  5170.               $daycnts[$m][$d]['weekno_down'($daycnts[$m][$d]['weekno_up'$weekno 1);
  5171.           }
  5172.         }
  5173.       }
  5174.             /* check interval */
  5175.       if$recur['INTERVAL'{
  5176.             /* create interval index */
  5177.         $intervalix $this->_recurIntervalIx$recur['FREQ']$wdate$wkst );
  5178.             /* check interval */
  5179.         $currentKey array_keys$intervalarr );
  5180.         $currentKey end$currentKey )// get last index
  5181.         if$currentKey != $intervalix )
  5182.           $intervalarr array$intervalix => $intervalarr[$currentKey));
  5183.         if(( $recur['INTERVAL'!= $intervalarr[$intervalix&&
  5184.            != $intervalarr[$intervalix)) {
  5185.             /* step up date */
  5186.     //echo "skip: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br />\n";//test
  5187.           $this->_stepdate$wdate$wdatets$step);
  5188.           continue;
  5189.         }
  5190.         else // continue within the selected interval
  5191.           $intervalarr[$intervalix0;
  5192.    //echo "cont: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br />\n";//test
  5193.       }
  5194.       $updateOK TRUE;
  5195.       if$updateOK && isset$recur['BYMONTH'))
  5196.         $updateOK $this->_recurBYcntcheck$recur['BYMONTH']
  5197.                                            $wdate['month']
  5198.                                            ,($wdate['month'13));
  5199.       if$updateOK && isset$recur['BYWEEKNO'))
  5200.         $updateOK $this->_recurBYcntcheck$recur['BYWEEKNO']
  5201.                                            $daycnts[$wdate['month']][$wdate['day']]['weekno_up']
  5202.                                            $daycnts[$wdate['month']][$wdate['day']]['weekno_down');
  5203.       if$updateOK && isset$recur['BYYEARDAY'))
  5204.         $updateOK $this->_recurBYcntcheck$recur['BYYEARDAY']
  5205.                                            $daycnts[$wdate['month']][$wdate['day']]['yearcnt_up']
  5206.                                            $daycnts[$wdate['month']][$wdate['day']]['yearcnt_down');
  5207.       if$updateOK && isset$recur['BYMONTHDAY'))
  5208.         $updateOK $this->_recurBYcntcheck$recur['BYMONTHDAY']
  5209.                                            $wdate['day']
  5210.                                            $daycnts[$wdate['month']][$wdate['day']]['monthcnt_down');
  5211.     //echo "efter BYMONTHDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br />\n";//test###
  5212.       if$updateOK && isset$recur['BYDAY')) {
  5213.         $updateOK FALSE;
  5214.         $m $wdate['month'];
  5215.         $d $wdate['day'];
  5216.         ifisset$recur['BYDAY']['DAY')) // single day, opt with year/month day order no
  5217.           $daynoexists $daynosw $daynamesw =  FALSE;
  5218.           if$recur['BYDAY']['DAY'== $daycnts[$m][$d]['DAY')
  5219.             $daynamesw TRUE;
  5220.           ifisset$recur['BYDAY'][0)) {
  5221.             $daynoexists TRUE;
  5222.             if(( isset$recur['FREQ'&& $recur['FREQ'== 'MONTHLY' )) || isset$recur['BYMONTH'))
  5223.               $daynosw $this->_recurBYcntcheck$recur['BYDAY'][0]
  5224.                                                 $daycnts[$m][$d]['monthdayno_up']
  5225.                                                 $daycnts[$m][$d]['monthdayno_down');
  5226.             elseifisset$recur['FREQ'&& $recur['FREQ'== 'YEARLY' ))
  5227.               $daynosw $this->_recurBYcntcheck$recur['BYDAY'][0]
  5228.                                                 $daycnts[$m][$d]['yeardayno_up']
  5229.                                                 $daycnts[$m][$d]['yeardayno_down');
  5230.           }
  5231.           if((  $daynoexists &&  $daynosw && $daynamesw ||
  5232.              !$daynoexists && !$daynosw && $daynamesw )) {
  5233.             $updateOK TRUE;
  5234.           }
  5235.         //echo "daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw<br />\n"; // test ###
  5236.         }
  5237.         else {
  5238.           foreach$recur['BYDAY'as $bydayvalue {
  5239.             $daynoexists $daynosw $daynamesw FALSE;
  5240.             ifisset$bydayvalue['DAY'&&
  5241.                      $bydayvalue['DAY'== $daycnts[$m][$d]['DAY'))
  5242.               $daynamesw TRUE;
  5243.             ifisset$bydayvalue[0)) {
  5244.               $daynoexists TRUE;
  5245.               if(( isset$recur['FREQ'&& $recur['FREQ'== 'MONTHLY' )) ||
  5246.                    isset$recur['BYMONTH'))
  5247.                 $daynosw $this->_recurBYcntcheck$bydayvalue['0']
  5248.                                                   $daycnts[$m][$d]['monthdayno_up']
  5249.                                                   $daycnts[$m][$d]['monthdayno_down');
  5250.               elseifisset$recur['FREQ'&& $recur['FREQ'== 'YEARLY' ))
  5251.                 $daynosw $this->_recurBYcntcheck$bydayvalue['0']
  5252.                                                   $daycnts[$m][$d]['yeardayno_up']
  5253.                                                   $daycnts[$m][$d]['yeardayno_down');
  5254.             }
  5255.         //echo "daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw<br />\n"; // test ###
  5256.             if((  $daynoexists &&  $daynosw && $daynamesw ||
  5257.                !$daynoexists && !$daynosw && $daynamesw )) {
  5258.               $updateOK TRUE;
  5259.               break;
  5260.             }
  5261.           }
  5262.         }
  5263.       }
  5264.       //echo "efter BYDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br />\n"; // test ###
  5265.             /* check BYSETPOS */
  5266.       if$updateOK {
  5267.         ifisset$recur['BYSETPOS'&&
  5268.           in_array$recur['FREQ']array'YEARLY''MONTHLY''WEEKLY''DAILY' )))) {
  5269.           ifisset$recur['WEEKLY')) {
  5270.             if$bysetposWold == $daycnts[$wdate['month']][$wdate['day']]['weekno_up')
  5271.               $bysetposw1[$wdatets;
  5272.             else
  5273.               $bysetposw2[$wdatets;
  5274.           }
  5275.           else {
  5276.             if(( isset$recur['FREQ'&& 'YEARLY'      == $recur['FREQ')  &&
  5277.                                             $bysetposYold == $wdate['year'))   ||
  5278.                isset$recur['FREQ'&& 'MONTHLY'     == $recur['FREQ')  &&
  5279.                                            (( $bysetposYold == $wdate['year')  &&
  5280.                                             $bysetposMold == $wdate['month'))) ||
  5281.                isset$recur['FREQ'&& 'MONTHLY'     == $recur['FREQ')  &&
  5282.                                            (( $bysetposYold == $wdate['year')  &&
  5283.                                             $bysetposMold == $wdate['month'])  &&
  5284.                                             $bysetposDold == $wdate['sday'))))
  5285.               $bysetposymd1[$wdatets;
  5286.             else
  5287.               $bysetposymd2[$wdatets;
  5288.           }
  5289.         }
  5290.         else {
  5291.             /* update result array if BYSETPOS is set */
  5292.           $countcnt++;
  5293.           if$startdatets <= $wdatets // only output within period
  5294.             $result[$wdatetsTRUE;
  5295.           //echo "recur ".implode('-',$this->_date_time_string(date('Y-m-d H:i:s',$wdatets),6))."<br />\n";//test
  5296.           }
  5297.          //else echo "recur undate ".implode('-',$this->_date_time_string(date('Y-m-d H:i:s',$wdatets),6))." okdatstart ".implode('-',$this->_date_time_string(date('Y-m-d H:i:s',$startdatets),6))."<br />\n";//test
  5298.           $updateOK FALSE;
  5299.         }
  5300.       }
  5301.             /* step up date */
  5302.       $this->_stepdate$wdate$wdatets$step);
  5303.             /* check if BYSETPOS is set for updating result array */
  5304.       if$updateOK && isset$recur['BYSETPOS')) {
  5305.         $bysetpos       FALSE;
  5306.         ifisset$recur['FREQ'&& 'YEARLY'  == $recur['FREQ'&&
  5307.           $bysetposYold != $wdate['year')) {
  5308.           $bysetpos     TRUE;
  5309.           $bysetposYold $wdate['year'];
  5310.         }
  5311.         elseifisset$recur['FREQ'&& 'MONTHLY' == $recur['FREQ'&&
  5312.          (( $bysetposYold != $wdate['year'|| $bysetposMold != $wdate['month')))) {
  5313.           $bysetpos     TRUE;
  5314.           $bysetposYold $wdate['year'];
  5315.           $bysetposMold $wdate['month'];
  5316.         }
  5317.         elseifisset$recur['FREQ'&& 'WEEKLY'  == $recur['FREQ')) {
  5318.           $weekno = (int) date'W'mktime00$wkst$wdate['month']$wdate['day']$wdate['year']));
  5319.           if$bysetposWold != $weekno {
  5320.             $bysetposWold $weekno;
  5321.             $bysetpos     TRUE;
  5322.           }
  5323.         }
  5324.         elseifisset$recur['FREQ'&& 'DAILY'   == $recur['FREQ'&&
  5325.          (( $bysetposYold != $wdate['year')  ||
  5326.           $bysetposMold != $wdate['month'||
  5327.           $bysetposDold != $wdate['sday'))) {
  5328.           $bysetpos     TRUE;
  5329.           $bysetposYold $wdate['year'];
  5330.           $bysetposMold $wdate['month'];
  5331.           $bysetposDold $wdate['day'];
  5332.         }
  5333.         if$bysetpos {
  5334.           ifisset$recur['BYWEEKNO')) {
  5335.             $bysetposarr1 $bysetposw1;
  5336.             $bysetposarr2 $bysetposw2;
  5337.           }
  5338.           else {
  5339.             $bysetposarr1 $bysetposymd1;
  5340.             $bysetposarr2 $bysetposymd2;
  5341.           }
  5342.           foreach$recur['BYSETPOS'as $ix {
  5343.             if$ix // both positive and negative BYSETPOS allowed
  5344.               $ix count$bysetposarr1 $ix 1);
  5345.             $ix--;
  5346.             ifisset$bysetposarr1[$ix)) {
  5347.               if$startdatets <= $bysetposarr1[$ix// only output within period
  5348.                 $result[$bysetposarr1[$ix]] TRUE;
  5349.        //echo "recur ".implode('-',$this->_date_time_string(date('Y-m-d H:i:s',$bysetposarr1[$ix]),6))."<br />\n";//test
  5350.               }
  5351.               $countcnt++;
  5352.             }
  5353.             ifisset$recur['COUNT'&& $countcnt >= $recur['COUNT'))
  5354.               break;
  5355.           }
  5356.           $bysetposarr1 $bysetposarr2;
  5357.           $bysetposarr2 array();
  5358.         }
  5359.       }
  5360.     }
  5361.   }
  5362.   function _recurBYcntcheck$BYvalue$upValue$downValue {
  5363.     ifis_array$BYvalue &&
  5364.       in_array$upValue$BYvalue || in_array$downValue$BYvalue )))
  5365.       return TRUE;
  5366.     elseif(( $BYvalue == $upValue || $BYvalue == $downValue ))
  5367.       return TRUE;
  5368.     else
  5369.       return FALSE;
  5370.   }
  5371.   function _recurIntervalIx$freq$date$wkst {
  5372.             /* create interval index */
  5373.     switch$freq {
  5374.       case 'YEARLY':
  5375.         $intervalix $date['year'];
  5376.         break;
  5377.       case 'MONTHLY':
  5378.         $intervalix $date['year'].'-'.$date['month'];
  5379.         break;
  5380.       case 'WEEKLY':
  5381.         $wdatets    $this->_date2timestamp$date );
  5382.         $intervalix = (int) date'W'$wdatets $wkst ));
  5383.        break;
  5384.       case 'DAILY':
  5385.            default:
  5386.         $intervalix $date['year'].'-'.$date['month'].'-'.$date['day'];
  5387.         break;
  5388.     }
  5389.     return $intervalix;
  5390.   }
  5391. /**
  5392.  * convert format for input date to internal date with parameters
  5393.  *
  5394.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5395.  * @since 2.2.2 - 2007-08-01
  5396.  * @param mixed $year 
  5397.  * @param mixed $month optional
  5398.  * @param int $day optional
  5399.  * @param int $hour optional
  5400.  * @param int $min optional
  5401.  * @param int $sec optional
  5402.  * @param array $params optional
  5403.  * @return array 
  5404.  */
  5405.   function _setDate$year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$tz=FALSE$params=FALSE {
  5406.     $input $parno null;
  5407.     ifis_array$year && in_arraycount$year )array346)))) {
  5408.       $input['params'$this->_setParams$montharray'VALUE' => 'DATE-TIME' ));
  5409.       ifisset$input['params']['TZID'))
  5410.         $year['tz']    $input['params']['TZID'];
  5411.       $hitval !empty$year['tz'|| !empty$year[6|| == count$year ))) 6;
  5412.       $parno           $this->_existRem$input['params']'VALUE''DATE-TIME'$hitval );
  5413.       if!isset$parno ))
  5414.         $parno         $this->_existRem$input['params']'VALUE''DATE');
  5415.       if!isset$parno ))
  5416.         $parno         count$year );
  5417.       $input['value']  $this->_date_time_array$year$parno );
  5418.     }
  5419.     elseifis_array$year && isset$year['timestamp')) {
  5420.       $input['params'$this->_setParams$montharray'VALUE' => 'DATE-TIME' ));
  5421.       ifisset$input['params']['TZID'))
  5422.         $year['tz']    $input['params']['TZID'];
  5423.       $tz              isset$year['tz')) ' '.$year['tz'null;
  5424.       $hitval          !empty$tz )) 6;
  5425.       $parno           $this->_existRem$input['params']'VALUE''DATE-TIME'$hitval );
  5426.       if!isset$parno ))
  5427.         $parno         $this->_existRem$input['params']'VALUE''DATE');
  5428.       if!isset$parno ))
  5429.         $parno         $hitval;
  5430.       $input['value']  $this->_date_time_stringdate('Y-m-d H:i:s',$year['timestamp']).$tz,$parno );
  5431.     }
  5432.     elseif<= strlentrim$year ))) // ex. 2006-08-03 10:12:18
  5433.       $input['params'$this->_setParams$montharray'VALUE' => 'DATE-TIME' ));
  5434.       $parno           $this->_existRem$input['params']'VALUE''DATE-TIME');
  5435.       if!isset$parno ))
  5436.         $parno         $this->_existRem$input['params']'VALUE''DATE');
  5437.       $input['value']  $this->_date_time_string$year$parno );
  5438.       ifisset$input['params']['TZID'))
  5439.         $input['value']['tz'$input['params']['TZID'];
  5440.     }
  5441.     else {
  5442.       $input['params'$this->_setParams$paramsarray'VALUE' => 'DATE-TIME' ));
  5443.       ifisset$input['params']['TZID'))
  5444.         $tz            $input['params']['TZID'];
  5445.       $hitval          !empty$tz )) null;
  5446.       $parno           $this->_existRem$input['params']'VALUE''DATE-TIME'$hitval );
  5447.       if!isset$parno ))
  5448.         $parno         $this->_existRem$input['params']'VALUE''DATE');
  5449.       $input['value']  array'year'  => $year'month' => $month'day'   => $day );
  5450.       if!= $parno {
  5451.         $input['value']['hour'$hour $hour '0';
  5452.         $input['value']['min']  $min )  $min  '0';
  5453.         $input['value']['sec']  $sec )  $sec  '0';
  5454.         if!empty$tz ))
  5455.           $input['value']['tz'$tz;
  5456.       }
  5457.     }
  5458.     if== $parno {
  5459.       $input['params']['VALUE''DATE';
  5460.       unset$input['value']['tz');
  5461.       unset$input['params']['TZID');
  5462.     }
  5463.     ifisset$input['value']['tz'))
  5464.       $input['value']['tz'= (string) $input['value']['tz'];
  5465.     if!empty$input['value']['tz')   &&
  5466.          $input['value']['tz'!= 'Z' &&
  5467.       !in_array($input['value']['tz']{0}array'+''-' )) &&
  5468.            ctype_digitsubstr$input['value']['tz']))) &&
  5469.         !ctype_digit$input['value']['tz') ) ) {
  5470.       $input['params']['TZID'$input['value']['tz'];
  5471.       unset$input['value']['tz');
  5472.     }
  5473.     elseifisset$input['params']['TZID'))
  5474.       unset$input['params']['TZID');
  5475.     return $input;
  5476.   }
  5477. /**
  5478.  * convert format for input date (UTC) to internal date with parameters
  5479.  *
  5480.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5481.  * @since 2.2.2 - 2007-08-02
  5482.  * @param mixed $year 
  5483.  * @param mixed $month optional
  5484.  * @param int $day optional
  5485.  * @param int $hour optional
  5486.  * @param int $min optional
  5487.  * @param int $sec optional
  5488.  * @param array $params optional
  5489.  * @return array 
  5490.  */
  5491.   function _setDate2(  $year$month=FALSE$day=FALSE$hour=FALSE$min=FALSE$sec=FALSE$params=FALSE {
  5492.     $input null;
  5493.     ifis_array$year &&
  5494.       (( == count$year )) ||
  5495.        array_key_exists'year'$year )))) {
  5496.       $input['value']  $this->_date_time_array$year);
  5497.       $input['params'$this->_setParams$month );
  5498.     }
  5499.     elseifis_array$year && isset$year['timestamp')) {
  5500.       $input['value']  $this->_date_time_stringdate'Y-m-d H:i:s'$year['timestamp'));
  5501.       $input['params'$this->_setParams$month );
  5502.     }
  5503.     elseif<= strlentrim$year ))) // ex. 2006-08-03 10:12:18
  5504.       $input['value']  $this->_date_time_string$year);
  5505.       $input['params'$this->_setParams$month );
  5506.     }
  5507.     else {
  5508.       $input['value']  array'year'  => $year
  5509.                               'month' => $month
  5510.                               'day'   => $day
  5511.                               'hour'  => $hour
  5512.                               'min'   => $min
  5513.                               'sec'   => $sec );
  5514.       $input['params'$this->_setParams$params );
  5515.     }
  5516.     if!isset$input['value']['hour'))
  5517.       $input['value']['hour'0;
  5518.     if!isset$input['value']['min'))
  5519.       $input['value']['min'0;
  5520.     if!isset$input['value']['sec'))
  5521.       $input['value']['sec'0;
  5522.     $input['value']['tz''Z';
  5523.     return $input;
  5524.   }
  5525. /**
  5526.  * set input (formatted) parameters- component property attributes
  5527.  *
  5528.  * default parameters can be set, if missing
  5529.  *
  5530.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5531.  * @since 1.x.x - 2007-05-01
  5532.  * @param array $params 
  5533.  * @param array $defaults 
  5534.  * @return array 
  5535.  */
  5536.   function _setParams$params$defaults=FALSE {
  5537.     if!is_array$params))
  5538.       $params array();
  5539.     $input array();
  5540.     foreach$params as $paramKey => $paramValue {
  5541.       ifis_array$paramValue )) {
  5542.         foreach$paramValue as $pkey => $pValue {
  5543.           if(( '"' == substr$pValue0)) && '"' == substr$pValue-)))
  5544.             $paramValue[$pkeysubstr$pValue1strlen$pValue ));
  5545.         }
  5546.       }
  5547.       elseif(( '"' == substr$paramValue0)) && '"' == substr$paramValue-)))
  5548.         $paramValue substr$paramValue1strlen$paramValue ));
  5549.       if'VALUE' == strtoupper$paramKey ))
  5550.         $input['VALUE']                 strtoupper$paramValue );
  5551.       else
  5552.         $input[strtoupper$paramKey )$paramValue;
  5553.     }
  5554.     ifis_array$defaults )) {
  5555.       foreach$defaults as $paramKey => $paramValue {
  5556.         if!isset$input[$paramKey))
  5557.           $input[$paramKey$paramValue;
  5558.       }
  5559.     }
  5560.     return (count$input )) $input null;
  5561.   }
  5562. /**
  5563.  * step date, return updated date, array and timpstamp
  5564.  *
  5565.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5566.  * @since 2.2.15 - 2007-11-12
  5567.  * @param array $date, date to step
  5568.  * @param int $timestamp 
  5569.  * @param array $step, default array( 'day' => 1 )
  5570.  * @return void 
  5571.  */
  5572.   function _stepdate&$date&$timestamp$step=array'day' => )) {
  5573.     foreach$step as $stepix => $stepvalue )
  5574.       $date[$stepix+= $stepvalue;
  5575.     $timestamp  $this->_date2timestamp$date );
  5576.     $date       $this->_date_time_stringdate('Y-m-d H:i:s'$timestamp )6);
  5577.     foreach$date as $k => $v {
  5578.       ifctype_digit$v ))
  5579.         $date[$k= (int) $v;
  5580.     }
  5581.   }
  5582. /**
  5583.  * convert (numeric) tz to offset seconds
  5584.  *
  5585.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5586.  * @since 2.2.2 - 2007-07-29
  5587.  * @param string $offset 
  5588.  * @return integer 
  5589.  */
  5590.   function _tz2offset$tz {
  5591.     $tz          trim(string) $tz );
  5592.     $offset      0;
  5593.     if((     5  == strlen$tz )) &&
  5594.        '0000' <= substr$tz-)) &&
  5595.        '9999' >= substr$tz-)) &&
  5596.          (( '+' == substr$tz0)) ||
  5597.           '-' == substr$tz0)))) {
  5598.       $hours2sec substr$tz13600;
  5599.       $min2sec   substr$tz-)   60;
  5600.       $sign      substr$tz0);
  5601.       $offset    = (int) $sign.'1' ($hours2sec $min2sec ));
  5602.     }
  5603.     elseif(( 7  == strlen$tz )) &&
  5604.      '000000' <= substr$tz-)) &&
  5605.      '999999' >= substr$tz-)) &&
  5606.          (( '+' == substr$tz0)) ||
  5607.           '-' == substr$tz0)))) {
  5608.       $hours2sec substr$tz13600;
  5609.       $min2sec   substr$tz3*   60;
  5610.       $sec       substr$tz-);
  5611.       $sign      substr$tz0);
  5612.       $offset    = (int) $sign.'1' $hours2sec $min2sec $sec ));
  5613.     }
  5614.     return $offset;
  5615.   }
  5616. /*********************************************************************************/
  5617. /*********************************************************************************/
  5618. /**
  5619.  * get general component config variables or info about subcomponents
  5620.  *
  5621.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5622.  * @since 2.2.13 - 2007-10-23
  5623.  * @param string $config 
  5624.  * @return value 
  5625.  */
  5626.   function getConfig$config {
  5627.     switchstrtoupper$config )) {
  5628.       case 'ALLOWEMPTY':
  5629.         return $this->allowEmpty;
  5630.         break;
  5631.       case 'COMPSINFO':
  5632.         unset$this->compix );
  5633.         $info array();
  5634.         foreach$this->components as $cix => $component {
  5635.           unset$component->propix );
  5636.           $info[$cix]['ordno'$cix 1;
  5637.           $info[$cix]['type']  $component->objName;
  5638.           $info[$cix]['uid']   $component->getProperty'uid' );
  5639.           $info[$cix]['props'$component->getConfig'propinfo' );
  5640.           $info[$cix]['sub']   $component->getConfig'compsinfo' );
  5641.           unset$component->propix );
  5642.         }
  5643.         return $info;
  5644.         break;
  5645.       case 'FORMAT':
  5646.         return $this->format;
  5647.         break;
  5648.       case 'LANGUAGE':
  5649.          // get language for calendar component as defined in [RFC 1766]
  5650.         return $this->language;
  5651.         break;
  5652.       case 'NL':
  5653.         return $this->nl;
  5654.         break;
  5655.       case 'PROPINFO':
  5656.         $output array();
  5657.         ifcount$this->action ))
  5658.           $output['ACTION'count$this->action 2;
  5659.         ifcount$this->attach ))
  5660.           $output['ATTACH'count$this->attach );
  5661.         ifcount$this->attendee ))
  5662.           $output['ATTENDEE'count$this->attendee );
  5663.         ifcount$this->categories ))
  5664.           $output['CATEGORIES'count$this->categories );
  5665.         ifcount$this->class ))
  5666.           $output['CLASS'count$this->class 2;
  5667.         ifcount$this->comment ))
  5668.           $output['COMMENT'count$this->comment );
  5669.         ifcount$this->completed ))
  5670.           $output['COMPLETED'count$this->completed 2;
  5671.         ifcount$this->contact ))
  5672.           $output['CONTACT'count$this->contact );
  5673.         ifcount$this->created ))
  5674.           $output['CREATED'count$this->created 2;
  5675.         ifcount$this->description ))
  5676.           $output['DESCRIPTION'count$this->description );
  5677.         ifcount$this->dtend ))
  5678.           $output['DTEND'count$this->dtend 2;
  5679.         ifcount$this->dtstart ))
  5680.           $output['DTSTART'count$this->dtstart 2;
  5681.         ifcount$this->dtstamp ))
  5682.           $output['DTSTAMP'count$this->dtstamp 2;
  5683.         ifcount$this->due ))
  5684.           $output['DUE'count$this->due 2;
  5685.         ifcount$this->duration ))
  5686.           $output['DURATION'count$this->duration 2;
  5687.         ifcount$this->exdate ))
  5688.           $output['EXDATE'count$this->exdate );
  5689.         ifcount$this->exrule ))
  5690.           $output['EXRULE'count$this->exrule );
  5691.         ifcount$this->freebusy ))
  5692.           $output['FREEBUSY'count$this->freebusy );
  5693.         ifcount$this->geo ))
  5694.           $output['GEO'count$this->geo 2;
  5695.         ifcount$this->lastmodified ))
  5696.           $output['LAST-MODIFIED'count$this->lastmodified 2;
  5697.         ifcount$this->location ))
  5698.           $output['LOCATION'count$this->location 2;
  5699.         ifcount$this->organizer ))
  5700.           $output['ORGANIZER'count$this->organizer 2;
  5701.         ifcount$this->percentcomplete ))
  5702.           $output['PERCENT-COMPLETE'count$this->percentcomplete 2;
  5703.         ifcount$this->priority ))
  5704.           $output['PRIORITY'count$this->priority 2;
  5705.         ifcount$this->rdate ))
  5706.           $output['RDATE'count$this->rdate );
  5707.         ifcount$this->recurrenceid ))
  5708.           $output['RECURRENCE-ID'count$this->recurrenceid 2;
  5709.         ifcount$this->relatedto ))
  5710.           $output['RELATED-TO'count$this->relatedto );
  5711.         ifcount$this->repeat ))
  5712.           $output['REPEAT'count$this->repeat 2;
  5713.         ifcount$this->requeststatus ))
  5714.           $output['REQUEST-STATUS'count$this->requeststatus );
  5715.         ifcount$this->resources ))
  5716.           $output['RESOURCES'count$this->resources );
  5717.         ifcount$this->sequence ))
  5718.           $output['SEQUENCE'count$this->sequence 2;
  5719.         ifcount$this->rrule ))
  5720.           $output['RRULE'count$this->rrule );
  5721.         ifcount$this->status ))
  5722.           $output['STATUS'count$this->status 2;
  5723.         ifcount$this->summary ))
  5724.           $output['SUMMARY'count$this->summary 2;
  5725.         ifcount$this->transp ))
  5726.           $output['TRANSP'count$this->transp 2;
  5727.         ifcount$this->trigger ))
  5728.           $output['TRIGGER'count$this->trigger 2;
  5729.         ifcount$this->tzid ))
  5730.           $output['TZID'count$this->tzid 2;
  5731.         ifcount$this->tzname ))
  5732.           $output['TZNAME'count$this->tzname );
  5733.         ifcount$this->tzoffsetfrom ))
  5734.           $output['TZOFFSETTFROM'count$this->tzoffsetfrom 2;
  5735.         ifcount$this->tzoffsetto ))
  5736.           $output['TZOFFSETTO'count$this->tzoffsetto 2;
  5737.         ifcount$this->tzurl ))
  5738.           $output['TZURL'count$this->tzurl 2;
  5739.         if!in_array$this->objNamearray'valarm''vtimezone' ))) {
  5740.           ifempty$this->uid['value'))
  5741.             $this->_makeuid();
  5742.           $output['UID'1;
  5743.         }
  5744.         ifcount$this->url ))
  5745.           $output['URL'count$this->url 2;
  5746.         ifcount$this->xprop ))
  5747.           $output['X-PROP'count$this->xprop );
  5748.         return $output;
  5749.         break;
  5750.       case 'UNIQUE_ID':
  5751.         ifempty$this->unique_id ))
  5752.           $this->unique_id  = gethostbyname$_SERVER['SERVER_NAME');
  5753.         return $this->unique_id;
  5754.         break;
  5755.     }
  5756.   }
  5757. /**
  5758.  * general component config setting
  5759.  *
  5760.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5761.  * @since 2.2.13 - 2007-10-25
  5762.  * @param string $config 
  5763.  * @param string $value 
  5764.  * @return void 
  5765.  */
  5766.   function setConfig$config$value {
  5767.     switchstrtoupper$config )) {
  5768.       case 'ALLOWEMPTY':
  5769.         $this->allowEmpty = $value;
  5770.         break;
  5771.       case 'FORMAT':
  5772.         $value   trim$value );
  5773.         $this->format = $value;
  5774.         break;
  5775.       case 'LANGUAGE':
  5776.          // set language for calendar component as defined in [RFC 1766]
  5777.         $value   trim$value );
  5778.         $this->language = $value;
  5779.         break;
  5780.       case 'NL':
  5781.         $this->nl = $value;
  5782.         break;
  5783.       case 'UNIQUE_ID':
  5784.         $value   trim$value );
  5785.         $this->unique_id = $value;
  5786.         break;
  5787.     }
  5788.   }
  5789. /*********************************************************************************/
  5790. /**
  5791.  * delete component property value
  5792.  *
  5793.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  5794.  * @since 2.2.15 - 2007-10-29
  5795.  * @param string $propName 
  5796.  * @param int @propix, optional, if specific property is wanted in case of multiply occurences
  5797.  * @return bool, if successfull delete TRUE
  5798.  */
  5799.   function deleteProperty$propName$propix=FALSE {
  5800.     $propName $propName strtoupper$propName 'X-PROP';
  5801.     if!$propix )
  5802.       $propix isset$this->propdelix[$propName)) $this->propdelix[$propName1;
  5803.     $this->propdelix[$propName= --$propix;
  5804.     $return FALSE;
  5805.     switch$propName {
  5806.       case 'ACTION':
  5807.         if(( $propix || !isset$this->action['value')) return FALSE;
  5808.         $this->action = array();
  5809.         return TRUE;
  5810.         break;
  5811.       case 'ATTACH':
  5812.         ifcount$this->attach <= $propix return FALSE;
  5813.         $this->attach[$propixnull;
  5814.         return TRUE;
  5815.         break;
  5816.       case 'ATTENDEE':
  5817.         ifcount$this->attendee <= $propix return FALSE;
  5818.         $this->attendee[$propixnull;
  5819.         return TRUE;
  5820.         break;
  5821.       case 'CATEGORIES':
  5822.         if!isset$this->categories[$propix])) return FALSE;
  5823.         $this->categories[$propixnull;
  5824.         return TRUE;
  5825.         break;
  5826.       case 'CLASS':
  5827.         if(( $propix || !isset$this->class['value')) return FALSE;
  5828.         $this->class = array();
  5829.         return TRUE;
  5830.         break;
  5831.       case 'COMMENT':
  5832.         if!isset$this->comment[$propix])) return FALSE;
  5833.         $this->comment[$propixnull;
  5834.         return TRUE;
  5835.         break;
  5836.       case 'COMPLETED':
  5837.         if(( $propix || !isset$this->completed['value')) return FALSE;
  5838.         $this->completed = array();
  5839.         return TRUE;
  5840.         break;
  5841.       case 'CONTACT':
  5842.         if!isset$this->contact[$propix])) return FALSE;
  5843.         $this->contact[$propixnull;
  5844.         return TRUE;
  5845.         break;
  5846.       case 'CREATED':
  5847.         if(( $propix || !isset$this->created['value')) return FALSE;
  5848.         $this->created = array();
  5849.         return TRUE;
  5850.         break;
  5851.       case 'DESCRIPTION':
  5852.         if!isset$this->description[$propix])) return FALSE;
  5853.         $this->description[$propixnull;
  5854.         return TRUE;
  5855.         break;
  5856.       case 'DTEND':
  5857.         if(( $propix || !isset$this->dtend['value')) return FALSE;
  5858.         $this->dtend = array();
  5859.         return TRUE;
  5860.         break;
  5861.       case 'DTSTAMP':
  5862.         ifin_array$this->objNamearray'valarm''vtimezone' )))
  5863.           return FALSE;
  5864.         if(( $propix || !isset$this->dtstamp['value')) return FALSE;
  5865.         $this->dtstamp = array();
  5866.         return TRUE;
  5867.         break;
  5868.       case 'DTSTART':
  5869.         if(( $propix || !isset$this->dtstart['value')) return FALSE;
  5870.         $this->dtstart = array();
  5871.         return TRUE;
  5872.         break;
  5873.       case 'DUE':
  5874.         if(( $propix || !isset$this->due['value')) return FALSE;
  5875.         $this->due = array();
  5876.         return TRUE;
  5877.         break;
  5878.       case 'DURATION':
  5879.         if(( $propix || !isset$this->duration['value')) return FALSE;
  5880.         $this->duration = array();
  5881.         return TRUE;
  5882.         break;
  5883.       case 'EXDATE':
  5884.         if!isset$this->exdate[$propix])) return FALSE;
  5885.         $this->exdate[$propixnull;
  5886.         return TRUE;
  5887.         break;
  5888.       case 'EXRULE':
  5889.         if!isset$this->exrule[$propix])) return FALSE;
  5890.         $this->exrule[$propix]['value'];
  5891.         return TRUE;
  5892.         break;
  5893.       case 'FREEBUSY':
  5894.         if!isset$this->freebusy[$propix])) return FALSE;
  5895.         $this->freebusy[$propixnull;
  5896.         return TRUE;
  5897.         break;
  5898.       case 'GEO':
  5899.         if(( $propix || !isset$this->geo['value')) return FALSE;
  5900.         $this->geo = array();
  5901.         return TRUE;
  5902.         break;
  5903.       case 'LAST-MODIFIED':
  5904.         if(( $propix || !isset$this->lastmodified['value')) return FALSE;
  5905.         $this->lastmodified = array();
  5906.         return TRUE;
  5907.         break;
  5908.       case 'LOCATION':
  5909.         if(( $propix || !isset$this->location['value')) return FALSE;
  5910.         $this->location = array();
  5911.         return TRUE;
  5912.         break;
  5913.       case 'ORGANIZER':
  5914.         if(( $propix || !isset$this->organizer['value')) return FALSE;
  5915.         $this->organizer = array();
  5916.         return TRUE;
  5917.         break;
  5918.       case 'PERCENT-COMPLETE':
  5919.         if(( $propix || !isset$this->percentcomplete['value')) return FALSE;
  5920.         $this->percentcomplete = array();
  5921.         return TRUE;
  5922.         break;
  5923.       case 'PRIORITY':
  5924.         if(( $propix || !isset$this->priority['value')) return FALSE;
  5925.         $this->priority = array();
  5926.         return TRUE;
  5927.         break;
  5928.       case 'RDATE':
  5929.         if!isset$this->rdate[$propix])) return FALSE;
  5930.         $this->rdate[$propixnull;
  5931.         return TRUE;
  5932.         break;
  5933.       case 'RECURRENCE-ID':
  5934.         if(( $propix || !isset$this->recurrenceid['value')) return FALSE;
  5935.         $this->recurrenceid = array();
  5936.         return TRUE;
  5937.         break;
  5938.       case 'RELATED-TO':
  5939.         if!isset$this->relatedto[$propix])) return FALSE;
  5940.         $this->relatedto[$propixnull;
  5941.         return TRUE;
  5942.         break;
  5943.       case 'REPEAT':
  5944.         if(( $propix || !isset$this->repeat['value')) return FALSE;
  5945.         $this->repeat = array();
  5946.         return TRUE;
  5947.         break;
  5948.       case 'REQUEST-STATUS':
  5949.         if!isset$this->requeststatus[$propix])) return FALSE;
  5950.         $this->requeststatus[$propixnull;
  5951.         return TRUE;
  5952.         break;
  5953.       case 'RESOURCES':
  5954.         if!isset$this->resources[$propix])) return FALSE;
  5955.         $this->resources[$propixnull;
  5956.         return TRUE;
  5957.         break;
  5958.       case 'RRULE':
  5959.         if!isset$this->rrule[$propix])) return FALSE;
  5960.         $this->rrule[$propixnull;
  5961.         return TRUE;
  5962.         break;
  5963.       case 'SEQUENCE':
  5964.         if(( $propix || !isset$this->sequence['value')) return FALSE;
  5965.         $this->sequence = array();
  5966.         return TRUE;
  5967.         break;
  5968.       case 'STATUS':
  5969.         if(( $propix || !isset$this->status['value')) return FALSE;
  5970.         $this->status = array();
  5971.         return TRUE;
  5972.         break;
  5973.       case 'SUMMARY':
  5974.         if(( $propix || !isset$this->summary['value')) return FALSE;
  5975.         $this->summary = array();
  5976.         return TRUE;
  5977.         break;
  5978.       case 'TRANSP':
  5979.         if(( $propix || !isset$this->transp['value')) return FALSE;
  5980.         $this->transp = array();
  5981.         return TRUE;
  5982.         break;
  5983.       case 'TRIGGER':
  5984.         if(( $propix || !isset$this->trigger['value')) return FALSE;
  5985.         $this->trigger = array();
  5986.         return TRUE;
  5987.         break;
  5988.       case 'TZID':
  5989.         if(( $propix || !isset$this->tzid['value')) return FALSE;
  5990.         $this->tzid = array();
  5991.         return TRUE;
  5992.         break;
  5993.       case 'TZNAME':
  5994.         if!isset$this->tzname[$propix])) return FALSE;
  5995.         $this->tzname[$propixnull;
  5996.         return TRUE;
  5997.         break;
  5998.       case 'TZOFFSETFROM':
  5999.         if(( $propix || !isset$this->tzoffsetfrom['value')) return FALSE;
  6000.         $this->tzoffsetfrom = array();
  6001.         return TRUE;
  6002.         break;
  6003.       case 'TZOFFSETTO':
  6004.         if(( $propix || !isset$this->tzoffsetto['value')) return FALSE;
  6005.         $this->tzoffsetto = array();
  6006.         return TRUE;
  6007.         break;
  6008.       case 'TZURL':
  6009.         if(( $propix || !isset$this->tzurl['value')) return FALSE;
  6010.         $this->tzurl = array();
  6011.         return TRUE;
  6012.         break;
  6013.       case 'UID':
  6014.         ifin_array$this->objNamearray'valarm''vtimezone' )))
  6015.           return FALSE;
  6016.         if(( $propix || !isset$this->uid['value')) return FALSE;
  6017.         $this->uid = array();
  6018.         return TRUE;
  6019.         break;
  6020.       case 'URL':
  6021.         if(( $propix || !isset$this->url['value')) return FALSE;
  6022.         $this->url = array();
  6023.         return TRUE;
  6024.         break;
  6025.       default:
  6026.         if$propName != 'X-PROP' {
  6027.           if!isset$this->xprop[$propName)) return FALSE;
  6028.           unset$this->xprop[$propName);
  6029.           return TRUE;
  6030.         }
  6031.         else {
  6032.           ifcount$this->xprop <= $propix )  return FALSE;
  6033.           $xpropno 0;
  6034.           foreach$this->xprop as $xpropkey => $xpropvalue {
  6035.             if$propix == $xpropno {
  6036.               unset$this->xprop[$xpropkey);
  6037.               $return TRUE;
  6038.               break 2;
  6039.             }
  6040.             else
  6041.               $xpropno++;
  6042.           }
  6043.         }
  6044.     }
  6045.     return $return;
  6046.   }
  6047. /**
  6048.  * get component property value/params
  6049.  *
  6050.  * if property has multiply values, consequtive function calls are needed
  6051.  *
  6052.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  6053.  * @since 2.1.1 - 2007-07-07
  6054.  * @param string $propName, optional
  6055.  * @param int @propix, optional, if specific property is wanted in case of multiply occurences
  6056.  * @param bool $inclParam=FALSE 
  6057.  * @param bool $specform=FALSE 
  6058.  * @return mixed 
  6059.  */
  6060.   function getProperty$propName=FALSE$propix=FALSE$inclParam=FALSE$specform=FALSE {
  6061.     $propName $propName strtoupper$propName 'X-PROP';
  6062.     if!$propix )
  6063.       $propix isset$this->propix[$propName)) $this->propix[$propName1;
  6064.     $this->propix[$propName= --$propix;
  6065.     switch$propName {
  6066.       case 'ACTION':
  6067.         if(( $propix || !isset$this->action['value')) return FALSE;
  6068.         return $inclParam $this->action : $this->action['value'];
  6069.         break;
  6070.       case 'ATTACH':
  6071.         ifcount$this->attach <= $propix return FALSE;
  6072.         return $inclParam $this->attach[$propix$this->attach[$propix]['value'];
  6073.         break;
  6074.       case 'ATTENDEE':
  6075.         ifcount$this->attendee <= $propix return FALSE;
  6076.         return $inclParam $this->attendee[$propix$this->attendee[$propix]['value'];
  6077.         break;
  6078.       case 'CATEGORIES':
  6079.         ifcount$this->categories <= $propix return FALSE;
  6080.         return $inclParam $this->categories[$propix$this->categories[$propix]['value'];
  6081.         break;
  6082.       case 'CLASS':
  6083.         if(( $propix || !isset$this->class['value')) return FALSE;
  6084.         return $inclParam $this->class : $this->class['value'];
  6085.         break;
  6086.       case 'COMMENT':
  6087.         ifcount$this->comment <= $propix return FALSE;
  6088.         return $inclParam $this->comment[$propix$this->comment[$propix]['value'];
  6089.         break;
  6090.       case 'COMPLETED':
  6091.         if(( $propix || !isset$this->completed['value')) return FALSE;
  6092.         return $inclParam $this->completed : $this->completed['value'];
  6093.         break;
  6094.       case 'CONTACT':
  6095.         ifcount$this->contact <= $propix return FALSE;
  6096.         return $inclParam $this->contact[$propix$this->contact[$propix]['value'];
  6097.         break;
  6098.       case 'CREATED':
  6099.         if(( $propix || !isset$this->created['value')) return FALSE;
  6100.         return $inclParam $this->created : $this->created['value'];
  6101.         break;
  6102.       case 'DESCRIPTION':
  6103.         ifcount$this->description <= $propix return FALSE;
  6104.         return $inclParam $this->description[$propix$this->description[$propix]['value'];
  6105.         break;
  6106.       case 'DTEND':
  6107.         if(( $propix || !isset$this->dtend['value')) return FALSE;
  6108.         return $inclParam $this->dtend : $this->dtend['value'];
  6109.         break;
  6110.       case 'DTSTAMP':
  6111.         ifin_array$this->objNamearray'valarm''vtimezone' )))
  6112.           return;
  6113.         if$propix )
  6114.           return null;
  6115.         if!isset$this->dtstamp['value'))
  6116.           $this->_makeDtstamp();
  6117.         return $inclParam $this->dtstamp : $this->dtstamp['value'];
  6118.         break;
  6119.       case 'DTSTART':
  6120.         if(( $propix || !isset$this->dtstart['value')) return FALSE;
  6121.         return $inclParam $this->dtstart : $this->dtstart['value'];
  6122.         break;
  6123.       case 'DUE':
  6124.         if(( $propix || !isset$this->due['value')) return FALSE;
  6125.         return $inclParam $this->due : $this->due['value'];
  6126.         break;
  6127.       case 'DURATION':
  6128.         if(( $propix || !isset$this->duration['value')) return FALSE;
  6129.         $value $specform $this->duration2date($this->duration['value'];
  6130.         return $inclParam array'value' => $value'params' =>  $this->duration['params'$value;
  6131.         break;
  6132.       case 'EXDATE':
  6133.         ifcount$this->exdate <= $propix return FALSE;
  6134.         return $inclParam $this->exdate[$propix$this->exdate[$propix]['value'];
  6135.         break;
  6136.       case 'EXRULE':
  6137.         ifcount$this->exrule <= $propix return FALSE;
  6138.         return $inclParam $this->exrule[$propix$this->exrule[$propix]['value'];
  6139.         break;
  6140.       case 'FREEBUSY':
  6141.         ifcount$this->freebusy <= $propix return FALSE;
  6142.         return $inclParam $this->freebusy[$propix$this->freebusy[$propix]['value'];
  6143.         break;
  6144.       case 'GEO':
  6145.         if(( $propix || !isset$this->geo['value')) return FALSE;
  6146.         return $inclParam $this->geo : $this->geo['value'];
  6147.         break;
  6148.       case 'LAST-MODIFIED':
  6149.         if(( $propix || !isset$this->lastmodified['value')) return FALSE;
  6150.         return $inclParam $this->lastmodified : $this->lastmodified['value'];
  6151.         break;
  6152.       case 'LOCATION':
  6153.         if(( $propix || !isset$this->location['value')) return FALSE;
  6154.         return $inclParam $this->location : $this->location['value'];
  6155.         break;
  6156.       case 'ORGANIZER':
  6157.         if(( $propix || !isset$this->organizer['value')) return FALSE;
  6158.         return $inclParam $this->organizer : $this->organizer['value'];
  6159.         break;
  6160.       case 'PERCENT-COMPLETE':
  6161.         if(( $propix || !isset$this->percentcomplete['value')) return FALSE;
  6162.         return $inclParam $this->percentcomplete : $this->percentcomplete['value'];
  6163.         break;
  6164.       case 'PRIORITY':
  6165.         if(( $propix || !isset$this->priority['value')) return FALSE;
  6166.         return $inclParam $this->priority : $this->priority['value'];
  6167.         break;
  6168.       case 'RDATE':
  6169.         ifcount$this->rdate <= $propix return FALSE;
  6170.         return $inclParam $this->rdate[$propix$this->rdate[$propix]['value'];
  6171.         break;
  6172.       case 'RECURRENCE-ID':
  6173.         if(( $propix || !isset$this->recurrenceid['value')) return FALSE;
  6174.         return $inclParam $this->recurrenceid : $this->recurrenceid['value'];
  6175.         break;
  6176.       case 'RELATED-TO':
  6177.         ifcount$this->relatedto <= $propix return FALSE;
  6178.         return $inclParam $this->relatedto[$propix$this->relatedto[$propix]['value'];
  6179.         break;
  6180.       case 'REPEAT':
  6181.         if(( $propix || !isset$this->repeat['value')) return FALSE;
  6182.         return $inclParam $this->repeat : $this->repeat['value'];
  6183.         break;
  6184.       case 'REQUEST-STATUS':
  6185.         ifcount$this->requeststatus <= $propix return FALSE;
  6186.         return $inclParam $this->requeststatus[$propix$this->requeststatus[$propix]['value'];
  6187.         break;
  6188.       case 'RESOURCES':
  6189.         ifcount$this->resources <= $propix return FALSE;
  6190.         return $inclParam $this->resources[$propix$this->resources[$propix]['value'];
  6191.         break;
  6192.       case 'RRULE':
  6193.         ifcount$this->rrule <= $propix return FALSE;
  6194.         return $inclParam $this->rrule[$propix$this->rrule[$propix]['value'];
  6195.         break;
  6196.       case 'SEQUENCE':
  6197.         if(( $propix || !isset$this->sequence['value')) return FALSE;
  6198.         return $inclParam $this->sequence : $this->sequence['value'];
  6199.         break;
  6200.       case 'STATUS':
  6201.         if(( $propix || !isset$this->status['value')) return FALSE;
  6202.         return $inclParam $this->status : $this->status['value'];
  6203.         break;
  6204.       case 'SUMMARY':
  6205.         if(( $propix || !isset$this->summary['value')) return FALSE;
  6206.         return $inclParam $this->summary : $this->summary['value'];
  6207.         break;
  6208.       case 'TRANSP':
  6209.         if(( $propix || !isset$this->transp['value')) return FALSE;
  6210.         return $inclParam $this->transp : $this->transp['value'];
  6211.         break;
  6212.       case 'TRIGGER':
  6213.         if(( $propix || !isset$this->trigger['value')) return FALSE;
  6214.         return $inclParam $this->trigger : $this->trigger['value'];
  6215.         break;
  6216.       case 'TZID':
  6217.         if(( $propix || !isset$this->tzid['value')) return FALSE;
  6218.         return $inclParam $this->tzid : $this->tzid['value'];
  6219.         break;
  6220.       case 'TZNAME':
  6221.         ifcount$this->tzname <= $propix return FALSE;
  6222.         return $inclParam $this->tzname[$propix$this->tzname[$propix]['value'];
  6223.         break;
  6224.       case 'TZOFFSETFROM':
  6225.         if(( $propix || !isset$this->tzoffsetfrom['value')) return FALSE;
  6226.         return $inclParam $this->tzoffsetfrom : $this->tzoffsetfrom['value'];
  6227.         break;
  6228.       case 'TZOFFSETTO':
  6229.         if(( $propix || !isset$this->tzoffsetto['value')) return FALSE;
  6230.         return $inclParam $this->tzoffsetto : $this->tzoffsetto['value'];
  6231.         break;
  6232.       case 'TZURL':
  6233.         if(( $propix || !isset$this->tzurl['value')) return FALSE;
  6234.         return $inclParam $this->tzurl : $this->tzurl['value'];
  6235.         break;
  6236.       case 'UID':
  6237.         ifin_array$this->objNamearray'valarm''vtimezone' )))
  6238.           return;
  6239.         if$propix )
  6240.           return null;
  6241.         ifempty$this->uid['value'))
  6242.           $this->_makeuid();
  6243.         return $inclParam $this->uid : $this->uid['value'];
  6244.         break;
  6245.       case 'URL':
  6246.         if(( $propix || !isset$this->url['value')) return FALSE;
  6247.         return $inclParam $this->url : $this->url['value'];
  6248.         break;
  6249.       default:
  6250.         if$propName != 'X-PROP' {
  6251.           if!isset$this->xprop[$propName)) return FALSE;
  6252.           return $inclParam array$propName$this->xprop[$propName)
  6253.                                 : array$propName$this->xprop[$propName]['value');
  6254.         }
  6255.         else {
  6256.           ifcount$this->xprop <= $propix )  return FALSE;
  6257.           $xpropno 0;
  6258.           foreach$this->xprop as $xpropkey => $xpropvalue {
  6259.             if$propix == $xpropno )
  6260.               return $inclParam array$xpropkey$this->xprop[$xpropkey)
  6261.                                     : array$xpropkey$this->xprop[$xpropkey]['value');
  6262.             else
  6263.               $xpropno++;
  6264.           }
  6265.           return FALSE// not found ??
  6266.         }
  6267.     }
  6268.     return FALSE;
  6269.   }
  6270. /**
  6271.  * general component property setting
  6272.  *
  6273.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  6274.  * @since 2.2.13 - 2007-10-25
  6275.  * @param mixed $args variable number of function arguments,
  6276.  *                     first argument is ALWAYS component name,
  6277.  *                     second ALWAYS component value!
  6278.  * @return void 
  6279.  */
  6280.   function setProperty({
  6281.     $numargs    func_num_args();
  6282.     if$numargs )
  6283.       return FALSE;
  6284.     $arglist    func_get_args();
  6285.     if!$this->getConfig'allowEmpty' && !isset$arglist[1|| empty$arglist[1)))
  6286.       return;
  6287.     $arglist[0strtoupper$arglist[0);
  6288.     for$argix=$numargs$argix 12$argix++ {
  6289.       if!isset$arglist[$argix))
  6290.         $arglist[$argixnull;
  6291.     }
  6292.     switch$arglist[0{
  6293.       case 'ACTION':
  6294.         $this->setAction$arglist[1]$arglist[2);
  6295.         break;
  6296.       case 'ATTACH':
  6297.         $this->setAttach$arglist[1]$arglist[2);
  6298.         break;
  6299.       case 'ATTENDEE':
  6300.         $this->setAttendee$arglist[1]$arglist[2);
  6301.         break;
  6302.       case 'CATEGORIES':
  6303.         $this->setCategories$arglist[1]$arglist[2);
  6304.         break;
  6305.       case 'CLASS':
  6306.         $this->setClass$arglist[1]$arglist[2);
  6307.         break;
  6308.       case 'COMMENT':
  6309.         $this->setComment$arglist[1]$arglist[2);
  6310.         break;
  6311.       case 'COMPLETED':
  6312.         $this->setCompleted$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7);
  6313.         break;
  6314.       case 'CONTACT':
  6315.         $this->setContact$arglist[1]$arglist[2);
  6316.         break;
  6317.       case 'CREATED':
  6318.         $this->setCreated$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7);
  6319.         break;
  6320.       case 'DESCRIPTION':
  6321.         $this->setDescription$arglist[1]$arglist[2);
  6322.         break;
  6323.       case 'DTEND':
  6324.         $this->setDtend$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7]$arglist[8);
  6325.         break;
  6326.       case 'DTSTAMP':
  6327.         $this->setDtstamp$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7);
  6328.         break;
  6329.       case 'DTSTART':
  6330.         $this->setDtstart$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7]$arglist[8);
  6331.         break;
  6332.       case 'DUE':
  6333.         $this->setDue$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7]$arglist[8);
  6334.         break;
  6335.       case 'DURATION':
  6336.         $this->setDuration$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6);
  6337.         break;
  6338.       case 'EXDATE':
  6339.         $this->setExdate$arglist[1]$arglist[2);
  6340.         break;
  6341.       case 'EXRULE':
  6342.         $this->setExrule$arglist[1]$arglist[2);
  6343.         break;
  6344.       case 'FREEBUSY':
  6345.         $this->setFreebusy$arglist[1]$arglist[2]$arglist[3);
  6346.         break;
  6347.       case 'GEO':
  6348.         $this->setGeo$arglist[1]$arglist[2]$arglist[3);
  6349.         break;
  6350.       case 'LAST-MODIFIED':
  6351.         $this->setLastModified$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7);
  6352.         break;
  6353.       case 'LOCATION':
  6354.         $this->setLocation$arglist[1]$arglist[2);
  6355.         break;
  6356.       case 'ORGANIZER':
  6357.         $this->setOrganizer$arglist[1]$arglist[2);
  6358.         break;
  6359.       case 'PERCENT-COMPLETE':
  6360.         $this->setPercentComplete$arglist[1]$arglist[2);
  6361.         break;
  6362.       case 'PRIORITY':
  6363.         $this->setPriority$arglist[1]$arglist[2);
  6364.         break;
  6365.       case 'RDATE':
  6366.         $this->setRdate$arglist[1]$arglist[2);
  6367.         break;
  6368.       case 'RECURRENCE-ID':
  6369.         $this->setRecurrenceid$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7]$arglist[8);
  6370.        break;
  6371.       case 'RELATED-TO':
  6372.         $this->setRelatedTo$arglist[1]$arglist[2);
  6373.         break;
  6374.       case 'REPEAT':
  6375.         $this->setRepeat$arglist[1]$arglist[2);
  6376.         break;
  6377.       case 'REQUEST-STATUS':
  6378.         $this->setRequestStatus$arglist[1]$arglist[2]$arglist[3]$arglist[4);
  6379.         break;
  6380.       case 'RESOURCES':
  6381.         $this->setResources$arglist[1]$arglist[2);
  6382.         break;
  6383.       case 'RRULE':
  6384.         $this->setRrule$arglist[1]$arglist[2);
  6385.         break;
  6386.       case 'SEQUENCE':
  6387.         $this->setSequence$arglist[1]$arglist[2);
  6388.         break;
  6389.       case 'STATUS':
  6390.         $this->setStatus$arglist[1]$arglist[2);
  6391.         break;
  6392.       case 'SUMMARY':
  6393.         $this->setSummary$arglist[1]$arglist[2);
  6394.         break;
  6395.       case 'TRANSP':
  6396.         $this->setTransp$arglist[1]$arglist[2);
  6397.         break;
  6398.       case 'TRIGGER':
  6399.         $this->setTrigger$arglist[1]$arglist[2]$arglist[3]$arglist[4]$arglist[5]$arglist[6]$arglist[7]$arglist[8]$arglist[9]$arglist[10]$arglist[11);
  6400.         break;
  6401.       case 'TZID':
  6402.         $this->setTzid$arglist[1]$arglist[2);
  6403.         break;
  6404.       case 'TZNAME':
  6405.         $this->setTzname$arglist[1]$arglist[2);
  6406.         break;
  6407.       case 'TZOFFSETFROM':
  6408.         $this->setTzoffsetfrom$arglist[1]$arglist[2);
  6409.         break;
  6410.       case 'TZOFFSETTO':
  6411.         $this->setTzoffsetto$arglist[1]$arglist[2);
  6412.         break;
  6413.       case 'TZURL':
  6414.         $this->setTzurl$arglist[1]$arglist[2);
  6415.         break;
  6416.       case 'UID':
  6417.         $this->setUid$arglist[1]$arglist[2);
  6418.         break;
  6419.       case 'URL':
  6420.         $this->setUrl$arglist[1]$arglist[2);
  6421.         break;
  6422.       default:
  6423.         $this->setXprop$arglist[0]$arglist[1]$arglist[2);
  6424.         break;
  6425.     }
  6426.   }
  6427. /*********************************************************************************/
  6428. /**
  6429.  * parse component unparsed data into properties
  6430.  *
  6431.  * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
  6432.  * @since 2.4.2 - 2008-02-07
  6433.  * @param mixed $unparsedtext, strict rfc2445 formatted, single property string or array of property strings
  6434.  * @return bool FALSE if error occurs during parsing
  6435.  *
  6436.  */
  6437.   function parse$unparsedtext=null {
  6438.     if$unparsedtext {
  6439.       $this->unparsed array();
  6440.       ifis_array$unparsedtext )) {
  6441.         $comp $this;
  6442.         foreach $unparsedtext as $line {
  6443.           if'END:VALARM' == strtouppersubstr$line010 ))) {
  6444.             $this->setComponent$comp );
  6445.             $comp =  $this;
  6446.             continue;
  6447.           }
  6448.           elseif'BEGIN:VALARM