From cb1509c1c670974f54ed67d2076fef39e0d20812 Mon Sep 17 00:00:00 2001 From: Jim Hu Date: Mon, 15 Dec 2008 17:25:27 +0000 Subject: big changes to recurrence; trying to get closer to the spec --- functions/parse/end_vevent.php | 391 ++++++++++++----------------------------- 1 file changed, 112 insertions(+), 279 deletions(-) (limited to 'functions/parse/end_vevent.php') diff --git a/functions/parse/end_vevent.php b/functions/parse/end_vevent.php index 33175cf..5cf2c35 100644 --- a/functions/parse/end_vevent.php +++ b/functions/parse/end_vevent.php @@ -3,12 +3,14 @@ What happens in this file: 1. Initialization: add information not present by default -2. + a. duration + b. class + c. uid + d. adjust start_time and end_time +2. Build recur_data array +3. Add occurrences to master_array */ -if (!isset($url)) $url = ''; -if (!isset($type)) $type = ''; - // Handle DURATION if (!isset($end_unixtime)) { if(!isset($the_duration)) $the_duration = 0; @@ -36,13 +38,6 @@ if (!isset($uid)) { $uid_valid = true; } -if (!isset($summary)) $summary = ''; -if (!isset($description)) $description = ''; -if (!isset($status)) $status = ''; -if (!isset($class)) $class = ''; -if (!isset($location)) $location = ''; - - # adjust event start and end times if (isset($start_time) && isset($end_time)) { // Mozilla style all-day events or just really long events @@ -112,26 +107,8 @@ if (isset($allday_start) && $allday_start != '') { $rrule_array['END_TIME'] = $end_time; # $rrule_array['END'] = 'end'; } - -$start_date_time = strtotime($start_date); -if (!isset($fromdate)){ - #this should happen if not in one of the rss views - $this_month_start_time = strtotime($this_year.$this_month.'01'); - if ($current_view == 'year' || ($save_parsed_cals == 'yes' && !$is_webcal)|| $current_view == 'print' && $printview == 'year') { - $start_range_time = strtotime($this_year.'-01-01 -2 weeks'); - $end_range_time = strtotime($this_year.'-12-31 +2 weeks'); - } else { - $start_range_time = strtotime('-1 month -2 day', $this_month_start_time); - $end_range_time = strtotime('+2 month +2 day', $this_month_start_time); - } -}else{ - $start_range_time = strtotime($fromdate); - $end_range_time = strtotime($todate)+60*60*24; -} - -$freq_type = 'year'; -$interval = 1; +$freq_type = 'none'; # Load $rrule_array foreach ($rrule_array as $key => $val) { switch($key) { @@ -157,7 +134,7 @@ foreach ($rrule_array as $key => $val) { if (strlen($until) == 8) $until = $until.'235959'; $abs_until = $until; ereg ('([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})', $until, $regs); - $until = mktime($regs[4],$regs[5],$regs[6],$regs[2],$regs[3],$regs[1]); + $until_unixtime = mktime($regs[4],$regs[5],@$regs[6],$regs[2],$regs[3],$regs[1]); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = localizeDate($dateFormat_week,$until); break; case 'INTERVAL': @@ -167,47 +144,39 @@ foreach ($rrule_array as $key => $val) { } break; case 'BYSECOND': - $bysecond = $val; - $bysecond = split (',', $bysecond); + $bysecond = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bysecond; break; case 'BYMINUTE': - $byminute = $val; - $byminute = split (',', $byminute); + $byminute = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byminute; break; case 'BYHOUR': - $byhour = $val; - $byhour = split (',', $byhour); + $byhour = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byhour; break; case 'BYDAY': - $byday = $val; - $byday = split (',', $byday); + $byday = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byday; break; case 'BYMONTHDAY': - $bymonthday = $val; - $bymonthday = split (',', $bymonthday); + $bymonthday = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bymonthday; break; case 'BYYEARDAY': - $byyearday = $val; - $byyearday = split (',', $byyearday); + $byyearday = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byyearday; break; case 'BYWEEKNO': - $byweekno = $val; - $byweekno = split (',', $byweekno); + $byweekno = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byweekno; break; case 'BYMONTH': - $bymonth = $val; - $bymonth = split (',', $bymonth); + $bymonth = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bymonth; break; case 'BYSETPOS': - $bysetpos = $val; + $bysetpos = split (',', $val); $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bysetpos; break; case 'WKST': @@ -216,243 +185,98 @@ foreach ($rrule_array as $key => $val) { break; } } -/* -Load $recur_array -$recur_array is an array of unix times for instances of an event. This code handles repeats. -Note that dates with exceptions are counted as instances. -RDATE is currently not supported -*/ # $recur is the recurrence info that goes into the master array for this VEVENT -$recur = $recur_array[($start_date)][($hour.$minute)][$uid]['recur']; - -// if $until isn't set yet, we set it to the end of our range we're looking at -if (!isset($until)) $until = $end_range_time; -if (!isset($abs_until)) $abs_until = date('YmdHis', $end_range_time); -$end_date_time = $until; - -// If the $end_range_time is less than the $start_date_time, or $start_range_time is greater -// than $end_date_time, we may as well forget the whole thing -// It doesn't do us any good to spend time adding data we aren't even looking at -// this will prevent the year view from taking way longer than it needs to -if ($end_range_time >= $start_date_time && $start_range_time_tmp <= $end_date_time) { - - // if the beginning of our range is less than the start of the item, we may as well set it equal to it - if ($start_range_time < $start_date_time){ - $start_range_time = $start_date_time; - } - if ($end_range_time > $end_date_time) $end_range_time = $end_date_time; - - // initialize the time we will increment - $next_range_time = $start_range_time; - - // start at the $start_range and go until we hit the end of our range. - if(!isset($wkst)) $wkst='SU'; - $wkst3char = two2threeCharDays($wkst); +$recur = @$recur_array[($start_date)][($hour.$minute)][$uid]['recur']; - # set first instance if it's in range - $recur_data = array(); - if ($start_unixtime < $mArray_end && $end_unixtime > $mArray_begin){ - $recur_data[] = $start_unixtime; - } - /* - The while loop below increments $next_range_time by $freq type. For the larger freq types, there is only - one $next_range_time per repeat, but the BYXXX rules may write more than one event in that repeat cycle - $next_date_time handles those instances within a $freq_type - */ - #echo "

$summary
next range time:".date("Ymd his",$next_range_time)."
start range time ".date("Ymd his",$start_range_time)."
end range time ".date("Ymd his",$end_range_time); - while (($next_range_time >= $start_range_time) && ($next_range_time <= $end_range_time)) { - # pick the right compare function from date_functions.php - # $diff is the number of occurrences between start_date and next_range_time - $func = $freq_type.'Compare'; - $diff = $func(date('Ymd',$next_range_time), $start_date); - $rcount = $diff; - if(count($byday) > 1) $rcount = $diff * count($byday); - if ($rcount < $count && $diff % $interval == 0) { - $year = date('Y', $next_range_time); - $month = date('m', $next_range_time); - switch ($rrule_array['FREQ']) { - case 'DAILY': - $recur_data[] = $next_range_time; - break; - case 'WEEKLY': - // Populate $byday with the default day if it's not set. - if (!isset($byday)) $byday[] = strtoupper(substr(date('D', $start_date_time), 0, 2)); - $the_sunday = dateOfWeek(date("Ymd",$next_range_time), $wkst3char); - foreach($byday as $key=>$day) { - $day = two2threeCharDays($day); - #need to find the first day of the appropriate week. - if ($key == 0){ - $next_date_time = strtotime("next $day",strtotime($the_sunday)) + (12 * 60 * 60); - }else{ - $next_date_time = strtotime("next $day",$next_date_time) + (12 * 60 * 60); - } - $recur_data[] = $next_date_time; #echo "
$key $day ".strtotime("Ymd his", $next_date_time); - } - break; - case 'MONTHLY': - if (empty($bymonth)) $bymonth = array(1,2,3,4,5,6,7,8,9,10,11,12); - if (!empty($bysetpos)){ - /* bysetpos code from dustinbutler - start on day 1 or last day. - if day matches any BYDAY the count is incremented. - SETPOS = 4, need 4th match - SETPOS = -1, need 1st match - */ - if ($bysetpos > 0) { - $next_day = '+1 day'; - $day = 1; - } else { - $next_day = '-1 day'; - $day = $totalDays[$month]; - } - $day = mktime(0, 0, 0, $month, $day, $year); - $countMatch = 0; - while ($countMatch != abs($bysetpos)) { - /* Does this day match a BYDAY value? */ - $thisDay = $day; - $textDay = strtoupper(substr(date('D', $thisDay), 0, 2)); - if (in_array($textDay, $byday)) { - $countMatch++; - } - $day = strtotime($next_day, $thisDay); - } - if(in_array(date("m", $next_date_time), $bymonth)) $recur_data[] = $next_date_time; - }elseif (count($bymonthday) > 0 && empty($byday)) { - foreach($bymonthday as $day) { - if ($day < 0) $day = ((date('t', $next_range_time)) + ($day)) + 1; - if (checkdate($month,$day,$year)) { - $next_date_time = mktime(0,0,0,$month,$day,$year); - if(in_array(date("m", $next_date_time), $bymonth)) $recur_data[] = $next_date_time; - } - } - } else { - foreach($byday as $day) { - /* set $byday_arr - [0] => byday string, e.g. 4TH - [1] => sign/modifier - [2] => 4 number - [3] => TH day abbr - */ - ereg ('([-\+]{0,1})?([0-9]{1})?([A-Z]{2})', $day, $byday_arr); - $on_day = two2threeCharDays($byday_arr[3]); - $next_date_time = strtotime($byday_arr[1].$byday_arr[2].$on_day, $next_range_time); - if(empty($bymonthday) && in_array(date("m", $next_date_time), $bymonth)) $recur_data[] = $next_date_time; - - if (isset($bymonthday) && (!empty($bymonthday))) { - // This supports MONTHLY where BYDAY and BYMONTH are both set - foreach($bymonthday as $day) { - if (checkdate($month,$day,$year)) { - $next_date_time = mktime(0,0,0,$month,$day,$year); - $daday = strtolower(strftime("%a", $next_date_time)); - if ($daday == $on_day && in_array($month, $bymonth)) { - if(in_array(date("m", $next_date_time), $bymonth)) $recur_data[] = $next_date_time; - } - } - } - } - } # end foreach $byday - } - break; - case 'YEARLY': - if ((!isset($bymonth)) || (sizeof($bymonth) == 0)) $bymonth = array(date('m', $start_date_time)); - foreach($bymonth as $month) { - if (isset($bysetpos)){ - /* bysetpos code from dustinbutler - start on day 1 or last day. - if day matches any BYDAY the count is incremented. - SETPOS = 4, need 4th match - SETPOS = -1, need 1st match - */ - if ($bysetpos > 0) { - $next_day = '+1 day'; - $day = 1; - } else { - $next_day = '-1 day'; - $day = date("t",$month); - } - $day = mktime(12, 0, 0, $month, $day, $year); - $countMatch = 0; - while ($countMatch != abs($bysetpos)) { - /* Does this day match a BYDAY value? */ - $thisDay = $day; - $textDay = strtoupper(substr(date('D', $thisDay), 0, 2)); - if (in_array($textDay, $byday)) { - $countMatch++; - } - $day = strtotime($next_day, $thisDay); - } - $recur_data[] = $thisDay; - } - if ((isset($byday)) && (is_array($byday))) { - $checkdate_time = mktime(0,0,0,$month,1,$year); - foreach($byday as $day) { - ereg ('([-\+]{0,1})?([0-9]{1})?([A-Z]{2})', $day, $byday_arr); - if ($byday_arr[2] != '') { - $nth = $byday_arr[2]-1; - } else { - $nth = 0; - } - $on_day = two2threeCharDays($byday_arr[3]); - $on_day_num = two2threeCharDays($byday_arr[3],false); - if ($byday_arr[1] == '-') { - $last_day_tmp = date('t',$checkdate_time); - $checkdate_time = strtotime(date('Y-m-'.$last_day_tmp, $checkdate_time)); - $last_tmp = (date('w',$checkdate_time) == $on_day_num) ? '' : 'last '; - $next_date_time = strtotime($last_tmp.$on_day.' -'.$nth.' week', $checkdate_time); - } else { - $next_date_time = strtotime($on_day.' +'.$nth.' week', $checkdate_time); - } - } - } else { - $day = date('d', $start_date_time); - $next_date_time = mktime(0,0,0,$month,$day,$year+1); - //echo date('Ymd',$next_date_time).$summary.'
'; - } - if (isset($next_date_time) && $next_date_time != '') $recur_data[] = $next_date_time; - } - if (isset($byyearday)) { - foreach ($byyearday as $yearday) { - ereg ('([-\+]{0,1})?([0-9]{1,3})', $yearday, $byyearday_arr); - if ($byyearday_arr[1] == '-') { - $ydtime = mktime(0,0,0,12,31,$this_year); - $yearnum = $byyearday_arr[2] - 1; - $next_date_time = strtotime('-'.$yearnum.' days', $ydtime); - } else { - $ydtime = mktime(0,0,0,1,1,$this_year); - $yearnum = $byyearday_arr[2] - 1; - $next_date_time = strtotime('+'.$yearnum.' days', $ydtime); - } - if (isset($next_date_time) && $next_date_time != '') $recur_data[] = $next_date_time; - } - } - break; - default: - // anything else we need to end the loop - $next_range_time = $end_range_time + 100; - } # end switch - } - $next_range_time = strtotime('+'.$interval.' '.$freq_type, $next_range_time); - } #end while loop -} # end if time compare +/* ============================ Load $recur_data ============================ +$recur_data is an array of unix times for instances of an event. This code handles repeats. +Note that dates with exceptions are counted as instances. +RDATE is currently not supported +A. Set up the time range to scan for events. +If COUNT is not set (default is 1,000,000) then we don't have to start at start_date; we can start at the minimum interval for the view. +variables ending in date are in phpical date format: YYYYMMDD +variables ending with time are in phpical time format: HHMM +variables ending in unixtime are in unixtime -#foreach($recur_data as $time) echo "
".date("Ymd his",$time); +mArray_begin and mArray_end are set in initialization by date_range.php and may be overwritten by rss_common.php. These should be the default for start_range and end_range unixtimes. Conditions where overwrite these: + COUNT < 1,000,000 - we have to count occurrences; reset next_range_unixtime starting value + $until_unixtime < $mArray_end - stop iterating early + !isset($rrule_array['FREQ']) - only iterate once, set the end_range_unixtime to the end_date_unixtime +Note that start_range_unixtime and end_range_unixtime are not the same as start_date_unixtime and end_date_unixtime */ +$next_range_unixtime = $mArray_begin; +$end_range_unixtime = $mArray_end+60*60*24; +$start_date_unixtime = strtotime($start_date); +if($count < 1000000) $next_range_unixtime = $start_date_unixtime; +if(isset($until) && $end_range_unixtime > $until_unixtime) $end_range_unixtime = $until_unixtime; +if(!isset($rrule_array['FREQ'])){ + $end_range_unixtime = strtotime($end_date); + $count = 1; +} +// if the beginning of our range is less than the start of the item, we may as well set it equal to it +if ($next_range_unixtime < $start_date_unixtime) $next_range_unixtime = $start_date_unixtime; + +// convert wkst to a 3 char day for strtotime to work +$wkst3char = two2threeCharDays($wkst); +/* The while loop below increments $next_range_time by $freq type. For the larger freq types, there is only +one $next_range_time per repeat, but the BYXXX rules may write more than one event in that repeat cycle +$next_date_time handles those instances within a $freq_type */ +#echo "
$summary\n\tstart mArray time:".date("Ymd his",$mArray_begin)."\n\tstart range time:".date("Ymd his",$next_range_unixtime)."\n\tend range time ".date("Ymd his",$end_range_unixtime)."
"; +$recur_data = array(); +while ($next_range_unixtime <= $end_range_unixtime) { + $year = date('Y', $next_range_unixtime); + $month = date('m', $next_range_unixtime); + # pick the right compare function from date_functions.php + # $diff is the number of occurrences between start_date and next_range_time + $func = $freq_type.'Compare'; + $diff = $func(date('Ymd',$next_range_time), $start_date); + switch ($freq_type){ + case 'day': + add_recur($next_range_unixtime); + break; + case 'week': + add_recur(expand_byday($next_range_unixtime)); + break; + case 'month': + $next_date_unixtime = mktime(12,0,0,$month,date('d',$start_unixtime),$year); echo "month".date("Ymd his",$next_date_unixtime); + add_recur(($next_date_unixtime)); + break; + case 'year': + $next_date_unixtime = mktime(12,0,0,date('m',$start_unixtime),date('d',$start_unixtime),$year); echo "year:$hour,$min,0,".date('m',$start_unixtime).",".date('d',$start_unixtime).",$year".date("Ymd his",$next_date_unixtime);print_r($datetime); + add_recur(($next_date_unixtime)); + break; + default: + add_recur($start_unixtime); + break 2; + } + $next_range_unixtime = strtotime('+'.$interval.' '.$freq_type, $next_range_unixtime); +} #end while loop +$recur_data = array_unique($recur_data); +sort($recur_data); +echo "
$summary recur_data:";
+#var_dump($recur_data);
+foreach($recur_data as $time) echo "\n".date("Ymd his",$time);
+echo "
"; +if ($count < count($recur_data)){ + $arr = array_slice($recur_data,0,$count); + $recur_data =$arr; +} # use recur_data array to write the master array // use the same code to write the data instead of always changing it 5 times -$recur_data_hour = @substr($start_time,0,2); -$recur_data_minute = @substr($start_time,2,2); -foreach($recur_data as $recur_data_time) { - $recur_data_year = date('Y', $recur_data_time); - $recur_data_month = date('m', $recur_data_time); - $recur_data_day = date('d', $recur_data_time); +$recur_data_hour = @substr($start_unixtime,0,2); +$recur_data_minute = @substr($start_unixtime,2,2); +foreach($recur_data as $recur_data_unixtime) { + $recur_data_year = date('Y', $recur_data_unixtime); + $recur_data_month = date('m', $recur_data_unixtime); + $recur_data_day = date('d', $recur_data_unixtime); $recur_data_date = $recur_data_year.$recur_data_month.$recur_data_day; - if (($recur_data_time >= $start_date_time) && ($recur_data_time <= $end_date_time) && ($count_to != $count) && !in_array($recur_data_date, $except_dates)) { + if ( !in_array($recur_data_date, $except_dates) ) { if (isset($allday_start) && $allday_start != '') { - $start_time2 = $recur_data_time; - $end_time2 = strtotime('+'.$diff_allday_days.' days', $recur_data_time); + $start_time2 = $recur_data_unixtime; + $end_time2 = strtotime('+'.$diff_allday_days.' days', $recur_data_unixtime); while ($start_time2 < $end_time2) { $start_date2 = date('Ymd', $start_time2); $master_array[($start_date2)][('-1')][$uid] = array ( @@ -473,7 +297,7 @@ foreach($recur_data as $recur_data_time) { $start_unixtime_tmp = mktime($recur_data_hour,$recur_data_minute,0,$recur_data_month,$recur_data_day,$recur_data_year); $end_unixtime_tmp = $start_unixtime_tmp + $length; - if (($end_time >= $bleed_time) && ($bleed_check == '-1')) { + if (($end_time >= $phpiCal_config->bleed_time) && ($bleed_check == '-1')) { $start_tmp = strtotime(date('Ymd',$start_unixtime_tmp)); $end_date_tmp = date('Ymd',$end_unixtime_tmp); while ($start_tmp < $end_unixtime_tmp) { @@ -530,8 +354,6 @@ foreach($recur_data as $recur_data_time) { if (!isset($end_time_tmp1)) $end_time_tmp1 = $end_time; // Let's double check the until to not write past it - $until_check = $recur_data_date.$hour.$minute.'00'; - if ($abs_until > $until_check) { $master_array[($recur_data_date)][($hour.$minute)][$uid] = array ( 'event_start' => $start_time, 'event_end' => $end_time_tmp1, @@ -555,7 +377,7 @@ foreach($recur_data as $recur_data_time) { $master_array[($recur_data_date)][($hour.$minute)][$uid]['display_end'] = $display_end_tmp; } checkOverlap($recur_data_date, ($hour.$minute), $uid); - } + } } } @@ -580,5 +402,16 @@ if (is_array($except_dates)) { // Clear event data now that it's been saved. unset($start_time, $start_time_tmp, $end_time, $end_time_tmp, $start_unixtime, $start_unixtime_tmp, $end_unixtime, $end_unixtime_tmp, $summary, $length, $description, $status, $class, $location, $organizer, $attendee); - +//If you want to see the values in the arrays, uncomment below. +//print '
';
+//print_r($master_array);
+//print_r($overlap_array);
+//print_r($day_array);
+//print_r($rrule_array);
+//print_r($byday_arr);
+//print_r($recurrence_delete);
+//print_r($cal_displaynames);
+//print_r($cal_filelist);
+//print_r($tz_array);
+//print '
'; ?> \ No newline at end of file -- cgit v1.2.3