예제 #1
0
 /**
  * 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 = iCal_UtilityFunctions::_date2timestamp($date);
     $date = iCal_UtilityFunctions::_timestamp2date($timestamp, 6);
     foreach ($date as $k => $v) {
         if (ctype_digit($v)) {
             $date[$k] = (int) $v;
         }
     }
 }
예제 #2
0
파일: Vcalendar.php 프로젝트: roojs/pear
 /**
  * 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.10.13 - 2011-09-23
  * @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);
     } else {
         if (!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;
     }
     // end validate and reset arguments..
     /* iterate components */
     $result = array();
     foreach ($this->components as $cix => $component) {
         //print_r($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 = iCal_UtilityFunctions::_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 = iCal_UtilityFunctions::_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 = iCal_UtilityFunctions::_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 = iCal_UtilityFunctions::_timestamp2date($startDate - $rdurWsecs, 6);
         $workend = iCal_UtilityFunctions::_timestamp2date($endDate + $rdurWsecs, 6);
         while (FALSE !== ($exrule = $component->getProperty('exrule'))) {
             // check exrule
             iCal_UtilityFunctions::_recur2date($exdatelist, $exrule, $start, $workstart, $workend);
         }
         while (FALSE !== ($exdate = $component->getProperty('exdate'))) {
             // check exdate
             foreach ($exdate as $theExdate) {
                 $exWdate = iCal_UtilityFunctions::_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
         //var_dump(array($startWdate ,$startDate , $startWdate , $endDate ));exit;
         /* select only components with startdate within period */
         if ($startWdate >= $startDate && $startWdate <= $endDate) {
             /* add the selected component (WITHIN valid dates) to output array */
             if ($flat) {
                 $result[$component->getProperty('UID')] = $component->copy();
                 // copy original to output;
             } 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 = 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 !!!
                 while (date('Ymd', $rstart) <= $endYMD) {
                     // 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 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
                         continue;
                     }
                     if (date('Ymd', $rstart) > $startYMD) {
                         // date after dtstart
                         $datestring = date($startDateFormat, mktime(0, 0, 0, date('m', $rstart), date('d', $rstart), date('Y', $rstart)));
                     } else {
                         $datestring = date($startDateFormat, $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) < $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';
                         $component->setProperty($propName, $datestring);
                     }
                     // end if( $dtendExist || $dueExist || $durationExist )
                     $wd = getdate($rstart);
                     if (!isset($result[$wd['year']][$wd['mon']][$wd['mday']][$component->getProperty('UID')])) {
                         $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 )
                 //print_R($result);exit;
             }
             // end if( $split )   -  else use component date
         }
         // 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
                 iCal_UtilityFunctions::_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 = iCal_UtilityFunctions::_date2timestamp($theRdate[0]);
                         if ($rstart < $startDate - $rdurWsecs || $rstart > $endDate) {
                             continue;
                         }
                         if (isset($theRdate[1]['year'])) {
                             // date-date period
                             $rend = iCal_UtilityFunctions::_date2timestamp($theRdate[1]);
                         } else {
                             // date-duration period
                             $rend = iCal_UtilityFunctions::_duration2date($theRdate[0], $theRdate[1]);
                             $rend = iCal_UtilityFunctions::_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 = iCal_UtilityFunctions::_date2timestamp($theRdate);
                         if ($startDate - $rdurWsecs <= $theRdate && $endDate >= $theRdate) {
                             $recurlist[$theRdate] = $rdurWsecs;
                         }
                         // set start date for recurrence instance + event duration in seconds
                     }
                 }
             }
             // end - check rdate
             if (0 < count($recurlist)) {
                 ksort($recurlist);
                 $xRecurrence = 1;
                 foreach ($recurlist as $recurkey => $durvalue) {
                     // echo "recurKey=".date( 'Y-m-d H:i:s', $recurkey ).' dur='.iCal_UtilityFunctions::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);
                                 if (!isset($result[$wd['year']][$wd['mon']][$wd['mday']][$component2->getProperty('UID')])) {
                                     $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);
                             if (!isset($result[$wd['year']][$wd['mon']][$wd['mday']][$component2->getProperty('UID')])) {
                                 $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;
             }
         }
         // end if( TRUE === $any )
     }
     // end foreach ( $this->components as $cix => $component )
     if (0 >= count($result)) {
         return FALSE;
     }
     if (!$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, hoping they are in hour order.. .
                 ksort($result[$y][$m]);
             }
             ksort($result[$y]);
         }
         ksort($result);
     }
     // end elseif( !$flat )
     //print_R($result);
     return $result;
 }