/**
  * step date, return updated date, array and timpstamp
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.4.16 - 2008-10-18
  * @param array $date, date to step
  * @param int $timestamp
  * @param array $step, default array( 'day' => 1 )
  * @return void
  */
 public static function _stepdate(&$date, &$timestamp, $step = array('day' => 1))
 {
     foreach ($step as $stepix => $stepvalue) {
         $date[$stepix] += $stepvalue;
     }
     $timestamp = iCalUtilityFunctions::_date2timestamp($date);
     $date = iCalUtilityFunctions::_timestamp2date($timestamp, 6);
     foreach ($date as $k => $v) {
         if (ctype_digit($v)) {
             $date[$k] = (int) $v;
         }
     }
 }
Пример #2
0
 public static function _recurIntervalIx($freq, $date, $wkst)
 {
     /* create interval index */
     switch ($freq) {
         case 'YEARLY':
             $intervalix = $date['year'];
             break;
         case 'MONTHLY':
             $intervalix = $date['year'] . '-' . $date['month'];
             break;
         case 'WEEKLY':
             $wdatets = iCalUtilityFunctions::_date2timestamp($date);
             $intervalix = (int) date('W', $wdatets + $wkst);
             break;
         case 'DAILY':
         default:
             $intervalix = $date['year'] . '-' . $date['month'] . '-' . $date['day'];
             break;
     }
     return $intervalix;
 }
Пример #3
0
 /**
  * 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.9.7 - 2011-06-04
  * @param mixed $startY optional, start Year, default current Year ALT. array selecOptions
  * @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 that take place within period
  *                               FALSE - only components that starts within period
  * @param bool $split optional,  TRUE (default) - one component copy every day it take place 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 (TRUE === $flat && TRUE === $split) {
         // invalid combination
         $split = FALSE;
     }
     /* iterate components */
     $result = 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;
         }
         $dtendExist = $dueExist = $durationExist = $endAllDayEvent = FALSE;
         unset($end, $startWdate, $endWdate, $rdurWsecs, $rdur, $exdatelist, $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 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;
                 }
             }
         }
         /* if 'any' components, check repeating components, 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
                     }
                 }
             }
             if (0 < count($recurlist)) {
                 ksort($recurlist);
                 $xRecurrence = 1;
                 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($exdatelist[$checkDate])) {
                         // check excluded dates
                         continue;
                     }
                     if ($startWdate >= $recurkey) {
                         // exclude component start date
                         continue;
                     }
                     $component2 = $component->copy();
                     $rstart = $recurkey;
                     $rend = $recurkey + $durvalue;
                     /* add repeating components within valid dates to output array, only start date set */
                     if ($flat) {
                         $datestring = date($startDateFormat, $recurkey);
                         if (isset($start['tz'])) {
                             $datestring .= ' ' . $start['tz'];
                         }
                         // echo "X-CURRENT-DTSTART 0 =$datestring tcnt =".++$tcnt."<br />";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
                         $component2->setProperty('X-CURRENT-DTSTART', $datestring);
                         if ($dtendExist || $dueExist || $durationExist) {
                             $datestring = date($endDateFormat, $recurkey + $durvalue);
                             // fixa korrekt sluttid
                             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);
                         $result[$component2->getProperty('UID')] = $component2->copy();
                         // copy to output
                     } elseif ($split) {
                         if ($rend > $endDate) {
                             $rend = $endDate;
                         }
                         $startYMD = 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($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 (date('Ymd', $rstart) > $startYMD) {
                                     // date after dtstart
                                     $datestring = date($startDateFormat, $checkDate);
                                 } else {
                                     $datestring = date($startDateFormat, $rstart);
                                 }
                                 if (isset($start['tz'])) {
                                     $datestring .= ' ' . $start['tz'];
                                 }
                                 //echo "X-CURRENT-DTSTART 1 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br />";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
                                 $component2->setProperty('X-CURRENT-DTSTART', $datestring);
                                 if ($dtendExist || $dueExist || $durationExist) {
                                     if (date('Ymd', $rstart) < $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 !!!
                                     $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']][$component2->getProperty('UID')] = $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
                         }
                         // end while( $rstart <= $rend )
                         $xRecurrence += 1;
                     } elseif ($rstart >= $startDate) {
                         // date within period   //* flat=FALSE && split=FALSE *//
                         $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
                             $xRecurrence += 1;
                             $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) {
                                 $rstart += $rdurWsecs;
                                 if (date('Ymd', $rstart) < date('Ymd', $endWdate)) {
                                     $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 !!!
                                 $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']][$component2->getProperty('UID')] = $component2->copy();
                             // copy to output
                         }
                         // end if( !isset( $exdatelist[$checkDate] ))
                     }
                     // end elseif( $rstart >= $startDate )
                 }
                 // end foreach( $recurlist as $recurkey => $durvalue )
             }
             // end if( 0 < count( $recurlist ))
             /* deselect components with startdate/enddate not within period */
             if ($endWdate < $startDate || $startWdate > $endDate) {
                 continue;
             }
         } elseif ($startWdate < $startDate || $startWdate > $endDate) {
             continue;
         }
         /* add the selected component (WITHIN valid dates) to output array */
         if ($flat) {
             $result[$component->getProperty('UID')] = $component->copy();
         } 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
             $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
                 foreach (array('X-CURRENT-DTSTART', 'X-CURRENT-DTEND', 'X-CURRENT-DUE', 'X-RECURRENCE') as $propName) {
                     $component->deleteProperty($propName);
                 }
                 // remove any x-props, if set
                 while ($rstart <= $endWdate) {
                     // iterate
                     if ($rstart > $startWdate) {
                         // if NOT startdate, set X-properties
                         $datestring = date($startDateFormat, mktime(0, 0, 0, date('m', $rstart), date('d', $rstart), date('Y', $rstart)));
                         if (isset($start['tz'])) {
                             $datestring .= ' ' . $start['tz'];
                         }
                         // echo "X-CURRENT-DTSTART 3 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br />";$component->setProperty( 'X-CNT', $tcnt ); // test ###
                         $component->setProperty('X-CURRENT-DTSTART', $datestring);
                         if ($dtendExist || $dueExist || $durationExist) {
                             if (date('Ymd', $rstart) < date('Ymd', $endWdate)) {
                                 $tend = mktime(0, 0, 0, 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 !!!
                             $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 )
                     }
                     // end if( $rstart > $startWdate )
                     $wd = getdate($rstart);
                     $result[$wd['year']][$wd['mon']][$wd['mday']][$component->getProperty('UID')] = $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
                 }
                 // end while( $rstart <= $endWdate )
             }
             // end if( !isset( $exdatelist[$checkDate] ))
         } elseif ($startWdate >= $startDate) {
             // within period
             $checkDate = mktime(0, 0, 0, date('m', $startWdate), date('d', $startWdate), date('Y', $startWdate));
             // on a day-basis !!!
             if (!isset($exdatelist[$checkDate])) {
                 // exclude any recurrence START date, found in exdatelist
                 foreach (array('X-CURRENT-DTSTART', 'X-CURRENT-DTEND', 'X-CURRENT-DUE', 'X-RECURRENCE') as $propName) {
                     $component->deleteProperty($propName);
                 }
                 // remove any x-props, if set
                 $wd = getdate($startWdate);
                 $result[$wd['year']][$wd['mon']][$wd['mday']][$component->getProperty('UID')] = $component->copy();
                 // copy to output
             }
         }
     }
     // end foreach ( $this->components as $cix => $component )
     if (0 >= count($result)) {
         return FALSE;
     } elseif (!$flat) {
         foreach ($result as $y => $yeararr) {
             foreach ($yeararr as $m => $montharr) {
                 foreach ($montharr as $d => $dayarr) {
                     $result[$y][$m][$d] = array_values($dayarr);
                 }
                 // skip tricky UID-index
                 ksort($result[$y][$m]);
             }
             ksort($result[$y]);
         }
         ksort($result);
     }
     // end elseif( !$flat )
     return $result;
 }