예제 #1
0
파일: VCalendar.php 프로젝트: ephp/cal
 /**
  * select components from calendar on date or selectOption basis
  *
  * Ensure DTSTART is set for every component.
  * No date controls occurs.
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.16.4 - 2012-12-13
  * @param mixed $startY optional, start Year,  default current Year ALT. array selecOptions ( *[ <propName> => <uniqueValue> ] )
  * @param int   $startM optional, start Month, default current Month
  * @param int   $startD optional, start Day,   default current Day
  * @param int   $endY   optional, end   Year,  default $startY
  * @param int   $endY   optional, end   Month, default $startM
  * @param int   $endY   optional, end   Day,   default $startD
  * @param mixed $cType  optional, calendar component type(-s), default FALSE=all else string/array type(-s)
  * @param bool  $flat   optional, FALSE (default) => output : array[Year][Month][Day][]
  *                                TRUE            => output : array[] (ignores split)
  * @param bool  $any    optional, TRUE (default) - select component(-s) that occurs within period
  *                                FALSE          - only component(-s) that starts within period
  * @param bool  $split  optional, TRUE (default) - one component copy every DAY it occurs during the
  *                                                 period (implies flat=FALSE)
  *                                FALSE          - one occurance of component only in output array
  * @return array or FALSE
  */
 function selectComponents($startY = FALSE, $startM = FALSE, $startD = FALSE, $endY = FALSE, $endM = FALSE, $endD = FALSE, $cType = FALSE, $flat = FALSE, $any = TRUE, $split = TRUE)
 {
     /* check  if empty calendar */
     if (0 >= count($this->components)) {
         return FALSE;
     }
     if (is_array($startY)) {
         return $this->selectComponents2($startY);
     }
     /* check default dates */
     if (!$startY) {
         $startY = date('Y');
     }
     if (!$startM) {
         $startM = date('m');
     }
     if (!$startD) {
         $startD = date('d');
     }
     $startDate = mktime(0, 0, 0, $startM, $startD, $startY);
     if (!$endY) {
         $endY = $startY;
     }
     if (!$endM) {
         $endM = $startM;
     }
     if (!$endD) {
         $endD = $startD;
     }
     $endDate = mktime(23, 59, 59, $endM, $endD, $endY);
     // echo 'selectComp arg='.date( 'Y-m-d H:i:s', $startDate).' -- '.date( 'Y-m-d H:i:s', $endDate)."<br />\n"; $tcnt = 0;// test ###
     /* check component types */
     $validTypes = array('VEvent', 'VTodo', 'VJournal', 'VFreeBusy');
     if (is_array($cType)) {
         foreach ($cType as $cix => $theType) {
             $cType[$cix] = $theType = strtolower($theType);
             if (!in_array($theType, $validTypes)) {
                 $cType[$cix] = 'VEvent';
             }
         }
         $cType = array_unique($cType);
     } elseif (!empty($cType)) {
         $cType = strtolower($cType);
         if (!in_array($cType, $validTypes)) {
             $cType = array('VEvent');
         } else {
             $cType = array($cType);
         }
     } else {
         $cType = $validTypes;
     }
     if (0 >= count($cType)) {
         $cType = $validTypes;
     }
     if (FALSE === $flat && FALSE === $any) {
         // invalid combination
         $split = FALSE;
     }
     if (TRUE === $flat && TRUE === $split) {
         // invalid combination
         $split = FALSE;
     }
     /* iterate components */
     $result = array();
     $this->sort('UID');
     $compUIDcmp = null;
     $recurridList = array();
     foreach ($this->components as $cix => $component) {
         if (empty($component)) {
             continue;
         }
         unset($start);
         /* deselect unvalid type components */
         if (!in_array($component->objName, $cType)) {
             continue;
         }
         $start = $component->getProperty('dtstart');
         /* select due when dtstart is missing */
         if (empty($start) && $component->objName == 'VTodo' && FALSE === ($start = $component->getProperty('due'))) {
             continue;
         }
         if (empty($start)) {
             continue;
         }
         $compUID = $component->getProperty('UID');
         if ($compUIDcmp != $compUID) {
             $compUIDcmp = $compUID;
             unset($exdatelist, $recurridList);
         }
         $dtendExist = $dueExist = $durationExist = $endAllDayEvent = $recurrid = FALSE;
         unset($end, $startWdate, $endWdate, $rdurWsecs, $rdur, $workstart, $workend, $endDateFormat);
         // clean up
         $startWdate = ICalUtilityFunctions::_date2timestamp($start);
         $startDateFormat = isset($start['hour']) ? 'Y-m-d H:i:s' : 'Y-m-d';
         /* get end date from dtend/due/duration properties */
         $end = $component->getProperty('dtend');
         if (!empty($end)) {
             $dtendExist = TRUE;
             $endDateFormat = isset($end['hour']) ? 'Y-m-d H:i:s' : 'Y-m-d';
         }
         if (empty($end) && $component->objName == 'VTodo') {
             $end = $component->getProperty('due');
             if (!empty($end)) {
                 $dueExist = TRUE;
                 $endDateFormat = isset($end['hour']) ? 'Y-m-d H:i:s' : 'Y-m-d';
             }
         }
         if (!empty($end) && !isset($end['hour'])) {
             /* a DTEND without time part regards an event that ends the day before,
                for an all-day event DTSTART=20071201 DTEND=20071202 (taking place 20071201!!! */
             $endAllDayEvent = TRUE;
             $endWdate = mktime(23, 59, 59, $end['month'], $end['day'] - 1, $end['year']);
             $end['year'] = date('Y', $endWdate);
             $end['month'] = date('m', $endWdate);
             $end['day'] = date('d', $endWdate);
             $end['hour'] = 23;
             $end['min'] = $end['sec'] = 59;
         }
         if (empty($end)) {
             $end = $component->getProperty('duration', FALSE, FALSE, TRUE);
             // in dtend (array) format
             if (!empty($end)) {
                 $durationExist = TRUE;
             }
             $endDateFormat = isset($start['hour']) ? 'Y-m-d H:i:s' : 'Y-m-d';
             // if( !empty($end))  echo 'selectComp 4 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
         }
         if (empty($end)) {
             // assume one day duration if missing end date
             $end = array('year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59);
         }
         // if( isset($end))  echo 'selectComp 5 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
         $endWdate = ICalUtilityFunctions::_date2timestamp($end);
         if ($endWdate < $startWdate) {
             // MUST be after start date!!
             $end = array('year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59);
             $endWdate = ICalUtilityFunctions::_date2timestamp($end);
         }
         $rdurWsecs = $endWdate - $startWdate;
         // compute event (component) duration in seconds
         /* make a list of optional exclude dates for component occurence from exrule and exdate */
         $exdatelist = array();
         $workstart = ICalUtilityFunctions::_timestamp2date($startDate - $rdurWsecs, 6);
         $workend = ICalUtilityFunctions::_timestamp2date($endDate + $rdurWsecs, 6);
         while (FALSE !== ($exrule = $component->getProperty('exrule'))) {
             // check exrule
             ICalUtilityFunctions::_recur2date($exdatelist, $exrule, $start, $workstart, $workend);
         }
         while (FALSE !== ($exdate = $component->getProperty('exdate'))) {
             // check exdate
             foreach ($exdate as $theExdate) {
                 $exWdate = ICalUtilityFunctions::_date2timestamp($theExdate);
                 $exWdate = mktime(0, 0, 0, date('m', $exWdate), date('d', $exWdate), date('Y', $exWdate));
                 // on a day-basis !!!
                 if ($startDate - $rdurWsecs <= $exWdate && $endDate >= $exWdate) {
                     $exdatelist[$exWdate] = TRUE;
                 }
             }
             // end - foreach( $exdate as $theExdate )
         }
         // end - check exdate
         /* check recurrence-id (with sequence), remove hit with reccurr-id date */
         if (FALSE !== ($recurrid = $component->getProperty('recurrence-id')) && FALSE !== ($sequence = $component->getProperty('sequence'))) {
             // echo "adding ".$recurrid['year'].'-'.$recurrid['month'].'-'.$recurrid['day']." to recurridList<br>\n"; // test ###
             $recurrid = ICalUtilityFunctions::_date2timestamp($recurrid);
             $recurrid = mktime(0, 0, 0, date('m', $recurrid), date('d', $recurrid), date('Y', $recurrid));
             // on a day-basis !!!
             $recurridList[$recurrid] = TRUE;
             // no recurring to start this day
         }
         // end recurrence-id/sequence test
         /* select only components with.. . */
         if (!$any && $startWdate >= $startDate && $startWdate <= $endDate || $any && $startWdate < $endDate && $endWdate >= $startDate) {
             // occurs within the period
             /* add the selected component (WITHIN valid dates) to output array */
             if ($flat) {
                 // any=true/false, ignores split
                 if (!$recurrid) {
                     $result[$compUID] = $component->copy();
                 }
                 // copy original to output (but not anyone with recurrence-id)
             } elseif ($split) {
                 // split the original component
                 if ($endWdate > $endDate) {
                     $endWdate = $endDate;
                 }
                 // use period end date
                 $rstart = $startWdate;
                 if ($rstart < $startDate) {
                     $rstart = $startDate;
                 }
                 // use period start date
                 $startYMD = $rstartYMD = date('Ymd', $rstart);
                 $endYMD = date('Ymd', $endWdate);
                 $checkDate = mktime(0, 0, 0, date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                 // on a day-basis !!!
                 // echo "start org comp = $rstartYMD, endYMD=$endYMD<br />\n"; // test ###
                 if (!isset($exdatelist[$checkDate])) {
                     // exclude any recurrence START date, found in exdatelist
                     while ($rstartYMD <= $endYMD) {
                         // iterate
                         if (isset($exdatelist[$checkDate])) {
                             // exclude any recurrence date, found in exdatelist
                             $rstart = mktime(date('H', $rstart), date('i', $rstart), date('s', $rstart), date('m', $rstart), date('d', $rstart) + 1, date('Y', $rstart));
                             // step one day
                             $rstartYMD = date('Ymd', $rstart);
                             continue;
                         }
                         if ($rstartYMD > $startYMD) {
                             // date after dtstart
                             $datestring = date($startDateFormat, $checkDate);
                         } else {
                             $datestring = date($startDateFormat, $rstart);
                         }
                         if (isset($start['tz'])) {
                             $datestring .= ' ' . $start['tz'];
                         }
                         // echo "split org comp rstartYMD=$rstartYMD (datestring=$datestring)<br />\n"; // test ###
                         $component->setProperty('X-CURRENT-DTSTART', $datestring);
                         if ($dtendExist || $dueExist || $durationExist) {
                             if ($rstartYMD < $endYMD) {
                                 // not the last day
                                 $tend = mktime(23, 59, 59, date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                             } else {
                                 $tend = mktime(date('H', $endWdate), date('i', $endWdate), date('s', $endWdate), date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                             }
                             // on a day-basis !!!
                             if ($endAllDayEvent && $dtendExist) {
                                 $tend += 24 * 3600;
                             }
                             // alldaysevents has an end date 'day after' meaning this day
                             $datestring = date($endDateFormat, $tend);
                             if (isset($end['tz'])) {
                                 $datestring .= ' ' . $end['tz'];
                             }
                             $propName = !$dueExist ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
                             $component->setProperty($propName, $datestring);
                         }
                         // end if( $dtendExist || $dueExist || $durationExist )
                         $wd = getdate($rstart);
                         $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component->copy();
                         // copy to output
                         $rstart = mktime(date('H', $rstart), date('i', $rstart), date('s', $rstart), date('m', $rstart), date('d', $rstart) + 1, date('Y', $rstart));
                         // step one day
                         $rstartYMD = date('Ymd', $rstart);
                         $checkDate = mktime(0, 0, 0, date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                         // on a day-basis !!!
                     }
                     // end while( $rstart <= $endWdate )
                 }
             } elseif ($recurrid && !$flat && !$any && !$split) {
                 $continue = TRUE;
             } else {
                 // !$flat && !$split, i.e. no flat array and DTSTART within period
                 $checkDate = mktime(0, 0, 0, date('m', $startWdate), date('d', $startWdate), date('Y', $startWdate));
                 // on a day-basis !!!
                 if (!$any || !isset($exdatelist[$checkDate])) {
                     // exclude any recurrence date, found in exdatelist
                     $wd = getdate($startWdate);
                     $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component->copy();
                     // copy to output
                 }
             }
         }
         // end if(( $startWdate >= $startDate ) && ( $startWdate <= $endDate ))
         /* if 'any' components, check components with reccurrence rules, removing all excluding dates */
         if (TRUE === $any) {
             /* make a list of optional repeating dates for component occurence, rrule, rdate */
             $recurlist = array();
             while (FALSE !== ($rrule = $component->getProperty('rrule'))) {
                 // check rrule
                 ICalUtilityFunctions::_recur2date($recurlist, $rrule, $start, $workstart, $workend);
             }
             foreach ($recurlist as $recurkey => $recurvalue) {
                 // key=match date as timestamp
                 $recurlist[$recurkey] = $rdurWsecs;
             }
             // add duration in seconds
             while (FALSE !== ($rdate = $component->getProperty('rdate'))) {
                 // check rdate
                 foreach ($rdate as $theRdate) {
                     if (is_array($theRdate) && 2 == count($theRdate) && array_key_exists('0', $theRdate) && array_key_exists('1', $theRdate)) {
                         $rstart = ICalUtilityFunctions::_date2timestamp($theRdate[0]);
                         if ($rstart < $startDate - $rdurWsecs || $rstart > $endDate) {
                             continue;
                         }
                         if (isset($theRdate[1]['year'])) {
                             // date-date period
                             $rend = ICalUtilityFunctions::_date2timestamp($theRdate[1]);
                         } else {
                             // date-duration period
                             $rend = ICalUtilityFunctions::_duration2date($theRdate[0], $theRdate[1]);
                             $rend = ICalUtilityFunctions::_date2timestamp($rend);
                         }
                         while ($rstart < $rend) {
                             $recurlist[$rstart] = $rdurWsecs;
                             // set start date for recurrence instance + rdate duration in seconds
                             $rstart = mktime(date('H', $rstart), date('i', $rstart), date('s', $rstart), date('m', $rstart), date('d', $rstart) + 1, date('Y', $rstart));
                             // step one day
                         }
                     } else {
                         // single date
                         $theRdate = ICalUtilityFunctions::_date2timestamp($theRdate);
                         if ($startDate - $rdurWsecs <= $theRdate && $endDate >= $theRdate) {
                             $recurlist[$theRdate] = $rdurWsecs;
                         }
                         // set start date for recurrence instance + event duration in seconds
                     }
                 }
             }
             // end - check rdate
             foreach ($recurlist as $recurkey => $durvalue) {
                 // remove all recurrence START dates found in the exdatelist
                 $checkDate = mktime(0, 0, 0, date('m', $recurkey), date('d', $recurkey), date('Y', $recurkey));
                 // on a day-basis !!!
                 if (isset($exdatelist[$checkDate])) {
                     // no recurring to start this day
                     unset($recurlist[$recurkey]);
                 }
             }
             if (0 < count($recurlist)) {
                 ksort($recurlist);
                 $xRecurrence = 1;
                 $component2 = $component->copy();
                 $compUID = $component2->getProperty('UID');
                 foreach ($recurlist as $recurkey => $durvalue) {
                     // echo "recurKey=".date( 'Y-m-d H:i:s', $recurkey ).' dur='.ICalUtilityFunctions::offsetSec2His( $durvalue )."<br />\n"; // test ###;
                     if ($startDate - $rdurWsecs > $recurkey || $endDate < $recurkey) {
                         // not within period
                         continue;
                     }
                     $checkDate = mktime(0, 0, 0, date('m', $recurkey), date('d', $recurkey), date('Y', $recurkey));
                     // on a day-basis !!!
                     if (isset($recurridList[$checkDate])) {
                         // no recurring to start this day
                         continue;
                     }
                     if (isset($exdatelist[$checkDate])) {
                         // check excluded dates
                         continue;
                     }
                     if ($startWdate >= $recurkey) {
                         // exclude component start date
                         continue;
                     }
                     $rstart = $recurkey;
                     $rend = $recurkey + $durvalue;
                     /* add repeating components within valid dates to output array, only start date set */
                     if ($flat) {
                         if (!isset($result[$compUID])) {
                             // only one comp
                             $result[$compUID] = $component2->copy();
                         }
                         // copy to output
                     } elseif ($split) {
                         $xRecurrence += 1;
                         if ($rend > $endDate) {
                             $rend = $endDate;
                         }
                         $startYMD = $rstartYMD = date('Ymd', $rstart);
                         $endYMD = date('Ymd', $rend);
                         // echo "splitStart=".date( 'Y-m-d H:i:s', $rstart ).' end='.date( 'Y-m-d H:i:s', $rend )."<br />\n"; // test ###;
                         while ($rstart <= $rend) {
                             // iterate.. .
                             $checkDate = mktime(0, 0, 0, date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                             // on a day-basis !!!
                             if (isset($recurridList[$checkDate])) {
                                 // no recurring to start this day
                                 break;
                             }
                             if (isset($exdatelist[$checkDate])) {
                                 // exclude any recurrence START date, found in exdatelist
                                 break;
                             }
                             // echo "checking date after startdate=".date( 'Y-m-d H:i:s', $rstart ).' mot '.date( 'Y-m-d H:i:s', $startDate )."<br />"; // test ###;
                             if ($rstart >= $startDate) {
                                 // date after dtstart
                                 if ($rstartYMD > $startYMD) {
                                     // date after dtstart
                                     $datestring = date($startDateFormat, $checkDate);
                                 } else {
                                     $datestring = date($startDateFormat, $rstart);
                                 }
                                 if (isset($start['tz'])) {
                                     $datestring .= ' ' . $start['tz'];
                                 }
                                 // echo "spliting = $datestring<BR>\n"; // test ###
                                 $component2->setProperty('X-CURRENT-DTSTART', $datestring);
                                 if ($dtendExist || $dueExist || $durationExist) {
                                     if ($rstartYMD < $endYMD) {
                                         // not the last day
                                         $tend = mktime(23, 59, 59, date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                                     } else {
                                         $tend = mktime(date('H', $endWdate), date('i', $endWdate), date('s', $endWdate), date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                                     }
                                     // on a day-basis !!!
                                     if ($endAllDayEvent && $dtendExist) {
                                         $tend += 24 * 3600;
                                     }
                                     // alldaysevents has an end date 'day after' meaning this day
                                     $datestring = date($endDateFormat, $tend);
                                     if (isset($end['tz'])) {
                                         $datestring .= ' ' . $end['tz'];
                                     }
                                     $propName = !$dueExist ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
                                     $component2->setProperty($propName, $datestring);
                                 }
                                 // end if( $dtendExist || $dueExist || $durationExist )
                                 $component2->setProperty('X-RECURRENCE', $xRecurrence);
                                 $wd = getdate($rstart);
                                 $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component2->copy();
                                 // copy to output
                             }
                             // end if( $checkDate > $startYMD ) {    // date after dtstart
                             $rstart = mktime(date('H', $rstart), date('i', $rstart), date('s', $rstart), date('m', $rstart), date('d', $rstart) + 1, date('Y', $rstart));
                             // step one day
                             $rstartYMD = date('Ymd', $rstart);
                         }
                         // end while( $rstart <= $rend )
                     } elseif ($rstart >= $startDate) {
                         // date within period   //* flat=FALSE && split=FALSE => one comp every recur startdate *//
                         $xRecurrence += 1;
                         $checkDate = mktime(0, 0, 0, date('m', $rstart), date('d', $rstart), date('Y', $rstart));
                         // on a day-basis !!!
                         if (!isset($exdatelist[$checkDate])) {
                             // exclude any recurrence START date, found in exdatelist
                             $datestring = date($startDateFormat, $rstart);
                             if (isset($start['tz'])) {
                                 $datestring .= ' ' . $start['tz'];
                             }
                             //echo "X-CURRENT-DTSTART 2 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br />";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
                             $component2->setProperty('X-CURRENT-DTSTART', $datestring);
                             if ($dtendExist || $dueExist || $durationExist) {
                                 $tend = $rstart + $rdurWsecs;
                                 if (date('Ymd', $tend) < date('Ymd', $endWdate)) {
                                     $tend = mktime(23, 59, 59, date('m', $tend), date('d', $tend), date('Y', $tend));
                                 } else {
                                     $tend = mktime(date('H', $endWdate), date('i', $endWdate), date('s', $endWdate), date('m', $tend), date('d', $tend), date('Y', $tend));
                                 }
                                 // on a day-basis !!!
                                 if ($endAllDayEvent && $dtendExist) {
                                     $tend += 24 * 3600;
                                 }
                                 // alldaysevents has an end date 'day after' meaning this day
                                 $datestring = date($endDateFormat, $tend);
                                 if (isset($end['tz'])) {
                                     $datestring .= ' ' . $end['tz'];
                                 }
                                 $propName = !$dueExist ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
                                 $component2->setProperty($propName, $datestring);
                             }
                             // end if( $dtendExist || $dueExist || $durationExist )
                             $component2->setProperty('X-RECURRENCE', $xRecurrence);
                             $wd = getdate($rstart);
                             $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component2->copy();
                             // copy to output
                         }
                         // end if( !isset( $exdatelist[$checkDate] ))
                     }
                     // end elseif( $rstart >= $startDate )
                 }
                 // end foreach( $recurlist as $recurkey => $durvalue )
                 unset($component2);
             }
             // end if( 0 < count( $recurlist ))
             /* deselect components with startdate/enddate not within period */
             if ($endWdate < $startDate || $startWdate > $endDate) {
                 continue;
             }
         }
         // end if( TRUE === $any )
     }
     // end foreach ( $this->components as $cix => $component )
     unset($dtendExist, $dueExist, $durationExist, $endAllDayEvent, $recurrid, $recurridList, $end, $startWdate, $endWdate, $rdurWsecs, $rdur, $exdatelist, $recurlist, $workstart, $workend, $endDateFormat);
     // clean up
     if (0 >= count($result)) {
         return FALSE;
     } elseif (!$flat) {
         foreach ($result as $y => $yeararr) {
             foreach ($yeararr as $m => $montharr) {
                 foreach ($montharr as $d => $dayarr) {
                     if (empty($result[$y][$m][$d])) {
                         unset($result[$y][$m][$d]);
                     } else {
                         $result[$y][$m][$d] = array_values($dayarr);
                     }
                     // skip tricky UID-index, hoping they are in hour order.. .
                 }
                 if (empty($result[$y][$m])) {
                     unset($result[$y][$m]);
                 } else {
                     ksort($result[$y][$m]);
                 }
             }
             if (empty($result[$y])) {
                 unset($result[$y]);
             } else {
                 ksort($result[$y]);
             }
         }
         if (empty($result)) {
             unset($result);
         } else {
             ksort($result);
         }
     }
     // end elseif( !$flat )
     if (0 >= count($result)) {
         return FALSE;
     }
     return $result;
 }
예제 #2
0
 /**
  * get component property value/params
  *
  * if property has multiply values, consequtive function calls are needed
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.12.4 - 2012-04-22
  * @param string $propName, optional
  * @param int @propix, optional, if specific property is wanted in case of multiply occurences
  * @param bool $inclParam=FALSE
  * @param bool $specform=FALSE
  * @return mixed
  */
 function getProperty($propName = FALSE, $propix = FALSE, $inclParam = FALSE, $specform = FALSE)
 {
     if ('GEOLOCATION' == strtoupper($propName)) {
         $content = $this->getProperty('LOCATION');
         $content = !empty($content) ? $content . ' ' : '';
         if (FALSE === ($geo = $this->getProperty('GEO')) || empty($geo)) {
             return FALSE;
         }
         if (0.0 < $geo['latitude']) {
             $sign = '+';
         } else {
             $sign = 0.0 > $geo['latitude'] ? '-' : '';
         }
         $content .= $sign . sprintf("%09.6f", abs($geo['latitude']));
         // sprintf && lpad && float && sign !"#¤%&/(
         $content = rtrim(rtrim($content, '0'), '.');
         if (0.0 < $geo['longitude']) {
             $sign = '+';
         } else {
             $sign = 0.0 > $geo['longitude'] ? '-' : '';
         }
         return $content . $sign . sprintf('%8.6f', abs($geo['longitude'])) . '/';
         // sprintf && lpad && float && sign !"#¤%&/(
     }
     if ($this->_notExistProp($propName)) {
         return FALSE;
     }
     $propName = $propName ? strtoupper($propName) : 'X-PROP';
     if (in_array($propName, array('ATTACH', 'ATTENDEE', 'CATEGORIES', 'COMMENT', 'CONTACT', 'DESCRIPTION', 'EXDATE', 'EXRULE', 'FREEBUSY', 'RDATE', 'RELATED-TO', 'RESOURCES', 'RRULE', 'REQUEST-STATUS', 'TZNAME', 'X-PROP'))) {
         if (!$propix) {
             $propix = isset($this->propix[$propName]) ? $this->propix[$propName] + 2 : 1;
         }
         $this->propix[$propName] = --$propix;
     }
     switch ($propName) {
         case 'ACTION':
             if (!empty($this->action['value'])) {
                 return $inclParam ? $this->action : $this->action['value'];
             }
             break;
         case 'ATTACH':
             $ak = is_array($this->attach) ? array_keys($this->attach) : array();
             while (is_array($this->attach) && !isset($this->attach[$propix]) && 0 < count($this->attach) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->attach[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->attach[$propix] : $this->attach[$propix]['value'];
             break;
         case 'ATTENDEE':
             $ak = is_array($this->attendee) ? array_keys($this->attendee) : array();
             while (is_array($this->attendee) && !isset($this->attendee[$propix]) && 0 < count($this->attendee) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->attendee[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->attendee[$propix] : $this->attendee[$propix]['value'];
             break;
         case 'CATEGORIES':
             $ak = is_array($this->categories) ? array_keys($this->categories) : array();
             while (is_array($this->categories) && !isset($this->categories[$propix]) && 0 < count($this->categories) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->categories[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->categories[$propix] : $this->categories[$propix]['value'];
             break;
         case 'CLASS':
             if (!empty($this->class['value'])) {
                 return $inclParam ? $this->class : $this->class['value'];
             }
             break;
         case 'COMMENT':
             $ak = is_array($this->comment) ? array_keys($this->comment) : array();
             while (is_array($this->comment) && !isset($this->comment[$propix]) && 0 < count($this->comment) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->comment[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->comment[$propix] : $this->comment[$propix]['value'];
             break;
         case 'COMPLETED':
             if (!empty($this->completed['value'])) {
                 return $inclParam ? $this->completed : $this->completed['value'];
             }
             break;
         case 'CONTACT':
             $ak = is_array($this->contact) ? array_keys($this->contact) : array();
             while (is_array($this->contact) && !isset($this->contact[$propix]) && 0 < count($this->contact) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->contact[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->contact[$propix] : $this->contact[$propix]['value'];
             break;
         case 'CREATED':
             if (!empty($this->created['value'])) {
                 return $inclParam ? $this->created : $this->created['value'];
             }
             break;
         case 'DESCRIPTION':
             $ak = is_array($this->description) ? array_keys($this->description) : array();
             while (is_array($this->description) && !isset($this->description[$propix]) && 0 < count($this->description) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->description[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->description[$propix] : $this->description[$propix]['value'];
             break;
         case 'DTEND':
             if (!empty($this->dtend['value'])) {
                 return $inclParam ? $this->dtend : $this->dtend['value'];
             }
             break;
         case 'DTSTAMP':
             if (in_array($this->objName, array('VAlarm', 'VTimeZone', 'standard', 'daylight'))) {
                 return;
             }
             if (!isset($this->dtstamp['value'])) {
                 $this->_makeDtstamp();
             }
             return $inclParam ? $this->dtstamp : $this->dtstamp['value'];
             break;
         case 'DTSTART':
             if (!empty($this->dtstart['value'])) {
                 return $inclParam ? $this->dtstart : $this->dtstart['value'];
             }
             break;
         case 'DUE':
             if (!empty($this->due['value'])) {
                 return $inclParam ? $this->due : $this->due['value'];
             }
             break;
         case 'DURATION':
             if (!isset($this->duration['value'])) {
                 return FALSE;
             }
             $value = $specform && isset($this->dtstart['value']) && isset($this->duration['value']) ? ICalUtilityFunctions::_duration2date($this->dtstart['value'], $this->duration['value']) : $this->duration['value'];
             return $inclParam ? array('value' => $value, 'params' => $this->duration['params']) : $value;
             break;
         case 'EXDATE':
             $ak = is_array($this->exdate) ? array_keys($this->exdate) : array();
             while (is_array($this->exdate) && !isset($this->exdate[$propix]) && 0 < count($this->exdate) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->exdate[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->exdate[$propix] : $this->exdate[$propix]['value'];
             break;
         case 'EXRULE':
             $ak = is_array($this->exrule) ? array_keys($this->exrule) : array();
             while (is_array($this->exrule) && !isset($this->exrule[$propix]) && 0 < count($this->exrule) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->exrule[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->exrule[$propix] : $this->exrule[$propix]['value'];
             break;
         case 'FREEBUSY':
             $ak = is_array($this->freebusy) ? array_keys($this->freebusy) : array();
             while (is_array($this->freebusy) && !isset($this->freebusy[$propix]) && 0 < count($this->freebusy) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->freebusy[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->freebusy[$propix] : $this->freebusy[$propix]['value'];
             break;
         case 'GEO':
             if (!empty($this->geo['value'])) {
                 return $inclParam ? $this->geo : $this->geo['value'];
             }
             break;
         case 'LAST-MODIFIED':
             if (!empty($this->lastmodified['value'])) {
                 return $inclParam ? $this->lastmodified : $this->lastmodified['value'];
             }
             break;
         case 'LOCATION':
             if (!empty($this->location['value'])) {
                 return $inclParam ? $this->location : $this->location['value'];
             }
             break;
         case 'ORGANIZER':
             if (!empty($this->organizer['value'])) {
                 return $inclParam ? $this->organizer : $this->organizer['value'];
             }
             break;
         case 'PERCENT-COMPLETE':
             if (!empty($this->percentcomplete['value']) || isset($this->percentcomplete['value']) && '0' == $this->percentcomplete['value']) {
                 return $inclParam ? $this->percentcomplete : $this->percentcomplete['value'];
             }
             break;
         case 'PRIORITY':
             if (!empty($this->priority['value']) || isset($this->priority['value']) && '0' == $this->priority['value']) {
                 return $inclParam ? $this->priority : $this->priority['value'];
             }
             break;
         case 'RDATE':
             $ak = is_array($this->rdate) ? array_keys($this->rdate) : array();
             while (is_array($this->rdate) && !isset($this->rdate[$propix]) && 0 < count($this->rdate) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->rdate[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->rdate[$propix] : $this->rdate[$propix]['value'];
             break;
         case 'RECURRENCE-ID':
             if (!empty($this->recurrenceid['value'])) {
                 return $inclParam ? $this->recurrenceid : $this->recurrenceid['value'];
             }
             break;
         case 'RELATED-TO':
             $ak = is_array($this->relatedto) ? array_keys($this->relatedto) : array();
             while (is_array($this->relatedto) && !isset($this->relatedto[$propix]) && 0 < count($this->relatedto) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->relatedto[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->relatedto[$propix] : $this->relatedto[$propix]['value'];
             break;
         case 'REPEAT':
             if (!empty($this->repeat['value']) || isset($this->repeat['value']) && '0' == $this->repeat['value']) {
                 return $inclParam ? $this->repeat : $this->repeat['value'];
             }
             break;
         case 'REQUEST-STATUS':
             $ak = is_array($this->requeststatus) ? array_keys($this->requeststatus) : array();
             while (is_array($this->requeststatus) && !isset($this->requeststatus[$propix]) && 0 < count($this->requeststatus) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->requeststatus[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->requeststatus[$propix] : $this->requeststatus[$propix]['value'];
             break;
         case 'RESOURCES':
             $ak = is_array($this->resources) ? array_keys($this->resources) : array();
             while (is_array($this->resources) && !isset($this->resources[$propix]) && 0 < count($this->resources) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->resources[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->resources[$propix] : $this->resources[$propix]['value'];
             break;
         case 'RRULE':
             $ak = is_array($this->rrule) ? array_keys($this->rrule) : array();
             while (is_array($this->rrule) && !isset($this->rrule[$propix]) && 0 < count($this->rrule) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->rrule[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->rrule[$propix] : $this->rrule[$propix]['value'];
             break;
         case 'SEQUENCE':
             if (isset($this->sequence['value']) && (isset($this->sequence['value']) && '0' <= $this->sequence['value'])) {
                 return $inclParam ? $this->sequence : $this->sequence['value'];
             }
             break;
         case 'STATUS':
             if (!empty($this->status['value'])) {
                 return $inclParam ? $this->status : $this->status['value'];
             }
             break;
         case 'SUMMARY':
             if (!empty($this->summary['value'])) {
                 return $inclParam ? $this->summary : $this->summary['value'];
             }
             break;
         case 'TRANSP':
             if (!empty($this->transp['value'])) {
                 return $inclParam ? $this->transp : $this->transp['value'];
             }
             break;
         case 'TRIGGER':
             if (!empty($this->trigger['value'])) {
                 return $inclParam ? $this->trigger : $this->trigger['value'];
             }
             break;
         case 'TZID':
             if (!empty($this->tzid['value'])) {
                 return $inclParam ? $this->tzid : $this->tzid['value'];
             }
             break;
         case 'TZNAME':
             $ak = is_array($this->tzname) ? array_keys($this->tzname) : array();
             while (is_array($this->tzname) && !isset($this->tzname[$propix]) && 0 < count($this->tzname) && $propix < end($ak)) {
                 $propix++;
             }
             $this->propix[$propName] = $propix;
             if (!isset($this->tzname[$propix])) {
                 unset($this->propix[$propName]);
                 return FALSE;
             }
             return $inclParam ? $this->tzname[$propix] : $this->tzname[$propix]['value'];
             break;
         case 'TZOFFSETFROM':
             if (!empty($this->tzoffsetfrom['value'])) {
                 return $inclParam ? $this->tzoffsetfrom : $this->tzoffsetfrom['value'];
             }
             break;
         case 'TZOFFSETTO':
             if (!empty($this->tzoffsetto['value'])) {
                 return $inclParam ? $this->tzoffsetto : $this->tzoffsetto['value'];
             }
             break;
         case 'TZURL':
             if (!empty($this->tzurl['value'])) {
                 return $inclParam ? $this->tzurl : $this->tzurl['value'];
             }
             break;
         case 'UID':
             if (in_array($this->objName, array('VAlarm', 'VTimeZone', 'standard', 'daylight'))) {
                 return FALSE;
             }
             if (empty($this->uid['value'])) {
                 $this->_makeuid();
             }
             return $inclParam ? $this->uid : $this->uid['value'];
             break;
         case 'URL':
             if (!empty($this->url['value'])) {
                 return $inclParam ? $this->url : $this->url['value'];
             }
             break;
         default:
             if ($propName != 'X-PROP') {
                 if (!isset($this->xprop[$propName])) {
                     return FALSE;
                 }
                 return $inclParam ? array($propName, $this->xprop[$propName]) : array($propName, $this->xprop[$propName]['value']);
             } else {
                 if (empty($this->xprop)) {
                     return FALSE;
                 }
                 $xpropno = 0;
                 foreach ($this->xprop as $xpropkey => $xpropvalue) {
                     if ($propix == $xpropno) {
                         return $inclParam ? array($xpropkey, $this->xprop[$xpropkey]) : array($xpropkey, $this->xprop[$xpropkey]['value']);
                     } else {
                         $xpropno++;
                     }
                 }
                 return FALSE;
                 // not found ??
             }
     }
     return FALSE;
 }