1<?php 2/* end_vevent.php 3 4What happens in this file: 51. Initialization: add information not present by default 6 a. duration 7 b. class 8 c. uid 9 d. adjust start_time and end_time 102. Build recur_data array 113. Add occurrences to master_array 12*/ 13if (!isset($start_date)) $start_date = "19700101"; 14 15// CLASS support 16if (isset($class)) { 17 if ($class == 'PRIVATE') { 18 $summary ='**PRIVATE**'; 19 $description ='**PRIVATE**'; 20 } elseif ($class == 'CONFIDENTIAL') { 21 $summary ='**CONFIDENTIAL**'; 22 $description ='**CONFIDENTIAL**'; 23 } 24} 25 26// make sure we have some value for $uid 27if (!isset($uid)) { 28 $uid = $uid_counter; 29 $uid_counter++; 30 $uid_valid = false; 31}elseif(in_array($uid, $uid_list)) { 32 # UID seen before. If sequence is the default, bump it. 33 if ($sequence == 0) $sequence++; 34}else{ 35 $uid_valid = true; 36} 37$uid_list[] = $uid; 38 39# Handle DURATION 40if (!isset($end_unixtime)) { 41 if(!isset($the_duration)) $the_duration = 0; 42 $end_unixtime = $start_unixtime + $the_duration; 43 $end_time = date ('Hi', $end_unixtime); 44} 45# at this point $end_unixtime should be set 46# adjust event start and end times 47if (isset($start_time) && isset($end_time)) { 48 // Mozilla style all-day events or just really long events 49 if (($end_unixtime - $start_unixtime) > 24*60*60) { 50 $allday_start = $start_date; 51 $allday_end = ($start_date + 1); 52 } 53} 54# look for events that span more than one day 55if (isset($start_unixtime,$end_unixtime) && date('Ymd',$start_unixtime) < date('Ymd',$end_unixtime)) { 56 $spans_day = true; 57 $bleed_check = (($start_unixtime - $end_unixtime) <= (60*60*24)) ? '-1' : '0'; 58} else { 59 $spans_day = false; 60 $bleed_check = 0; 61} 62 63$length = $end_unixtime - $start_unixtime; 64if ($length < 0){ 65 $length = 0; 66 $end_time = $start_time; 67} 68# get hour and minute adjusted to allowed grid times 69$drawKey = drawEventTimes($start_time, $end_time, ($length >= (60*60*24))); 70preg_match ('/([0-9]{2})([0-9]{2})/', $drawKey['draw_start'], $time3); 71preg_match ('/([0-9]{2})([0-9]{2})/', $drawKey['draw_end'], $time4); 72$hour = $time3[1]; 73$minute = $time3[2]; 74$end_hour = $time4[1]; 75$end_minute = $time4[2]; 76 77 78// RECURRENCE-ID Support 79if (isset($recurrence_d)) { 80 81 $recurrence_delete["$recurrence_d"]["$recurrence_t"] = $uid; 82} 83 84if (isset($allday_start) && $allday_start != '') { 85 $hour = '-'; 86 $minute = '1'; 87 $rrule_array['START_DAY'] = $allday_start; 88 # $rrule_array['END_DAY'] = $allday_end; # this doesn't seem to be used anywhere. 89# $rrule_array['END'] = 'end'; 90 $recur_start = $allday_start; 91 $start_date = $allday_start; 92 if (isset($allday_end)) { 93 $diff_allday_days = dayCompare($allday_end, $allday_start); 94 } else { 95 $diff_allday_days = 1; 96 } 97} else { 98 $rrule_array['START_DATE'] = $start_date; 99 $rrule_array['START_TIME'] = $start_time; 100 $rrule_array['END_TIME'] = $end_time; 101# $rrule_array['END'] = 'end'; 102} 103 104$freq_type = 'none'; 105# Load $rrule_array 106foreach ($rrule_array as $key => $val) { 107 switch($key) { 108 case 'FREQ': 109 switch ($val) { 110 case 'YEARLY': $freq_type = 'year'; break; 111 case 'MONTHLY': $freq_type = 'month'; break; 112 case 'WEEKLY': $freq_type = 'week'; break; 113 case 'DAILY': $freq_type = 'day'; break; 114 case 'HOURLY': $freq_type = 'hour'; break; 115 case 'MINUTELY': $freq_type = 'minute'; break; 116 case 'SECONDLY': $freq_type = 'second'; break; 117 } 118 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = strtolower($val); 119 break; 120 case 'COUNT': 121 $count = $val; 122 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $count; 123 break; 124 case 'UNTIL': 125 # UNTIL must be in UTC 126 $until = date("YmdHis",strtotime($val)); 127 ereg ('([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})', $until, $regs); 128 $until_unixtime = mktime($regs[4],@$regs[5],@$regs[6],$regs[2],$regs[3],$regs[1]); 129 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = localizeDate($dateFormat_week,$until); 130 break; 131 case 'INTERVAL': 132 if ($val > 0){ 133 $interval = $val; 134 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $interval; 135 } 136 break; 137 case 'BYSECOND': 138 $bysecond = split (',', $val); 139 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bysecond; 140 break; 141 case 'BYMINUTE': 142 $byminute = split (',', $val); 143 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byminute; 144 break; 145 case 'BYHOUR': 146 $byhour = split (',', $val); 147 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byhour; 148 break; 149 case 'BYDAY': 150 $byday = split (',', $val); 151 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byday; 152 break; 153 case 'BYMONTHDAY': 154 $bymonthday = split (',', $val); 155 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bymonthday; 156 break; 157 case 'BYYEARDAY': 158 $byyearday = split (',', $val); 159 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byyearday; 160 break; 161 case 'BYWEEKNO': 162 $byweekno = split (',', $val); 163 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $byweekno; 164 break; 165 case 'BYMONTH': 166 $bymonth = split (',', $val); 167 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bymonth; 168 break; 169 case 'BYSETPOS': 170 $bysetpos = split (',', $val); 171 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $bysetpos; 172 break; 173 case 'WKST': 174 $wkst = $val; 175 $recur_array[($start_date)][($hour.$minute)][$uid]['recur'][$key] = $wkst; 176 break; 177 } 178} 179# convert wkst to a 3 char day for strtotime to work 180$wkst3char = two2threeCharDays($wkst); 181if($current_view == 'search') $freq_type = 'none'; 182# $recur is the recurrence info that goes into the master array for this VEVENT 183$recur =''; 184if (isset($recur_array[($start_date)][($hour.$minute)][$uid]['recur'])) $recur = $recur_array[($start_date)][($hour.$minute)][$uid]['recur']; 185 186/* ============================ Load $recur_data ============================ 187$recur_data is an array of unix times for days of recurrences of an event. This code handles repeats at the day level or above. The next loop handles the times. 188RDATE is currently not supported 189 190A. Set up the time range to scan for events. 191If 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. 192variables ending in date are in phpical date format: YYYYMMDD 193variables ending with time are in phpical time format: HHMM 194variables ending in unixtime are in unixtime 195 196mArray_begin and mArray_end are set in initialization by date_range.php and may be overwritten by rss_common.php. 197 198$start_date_unixtime should be the default for starting the range. Need this for the intervals to work out (e.g. every other day, week, month etc) 199mArray_end should be the default for end_range unixtimes. 200Conditions where overwrite these: 201 $until_unixtime < $mArray_end - stop iterating early 202 !isset($rrule_array['FREQ']) - only iterate once, set the end_range_unixtime to the end_date_unixtime 203Note that start_range_unixtime and end_range_unixtime are not the same as start_date_unixtime and end_date_unixtime */ 204 205$end_range_unixtime = $mArray_end+60*60*24; 206$start_date_unixtime = strtotime($start_date); 207$next_range_unixtime = $start_date_unixtime; 208 209# conditions where we don't need to iterate over the whole range 210# if repeating without limit, and steps are by 1, don't go back before the mArray beginning. 211if($count == 1000000 && $interval == 1 && $mArray_begin > $next_range_unixtime) $next_range_unixtime = $mArray_begin; 212 213# if the beginning of our range is less than the start of the item, we may as well set the range to start at start_time 214if ($next_range_unixtime < $start_date_unixtime) $next_range_unixtime = $start_date_unixtime; 215 216# stop at the until limit if set 217if(isset($until) && $end_range_unixtime > $until_unixtime) $end_range_unixtime = $until_unixtime;else $until_unixtime = $mArray_end; 218 219# more adjustments 220switch ($freq_type){ 221 case 'week': 222 # need to get the first value of $next_range_unixtime onto the right day of the week 223 $next_range_unixtime = strtotime("this ".date("D", $start_date_unixtime), $next_range_unixtime); 224 break; 225 case 'year': 226 $end_range_unixtime += 366*24*60*60; 227 break; 228} 229 230#nonrepeating events can stop at the first instance 231if(!isset($rrule_array['FREQ']) && isset($end_date)){ 232 $end_range_unixtime = strtotime($end_date); 233 $count = 1; 234} 235 236/* The while loop below increments $next_range_time by $freq type. For the larger freq types, there is only 237one $next_range_time per repeat, but the BYXXX rules may write more than one event in that repeat cycle 238$next_date_time handles those instances within a $freq_type */ 239#echo "<pre>$summary\n\tstart mArray time:".date("Ymd his",$mArray_begin)."\n\tnext_range_unixtime:".date("Ymd his",$next_range_unixtime)."\n\tend range time ".date("Ymd his",$end_range_unixtime)."\n"; 240$recur_data = array(); 241while ($next_range_unixtime <= $end_range_unixtime && $count > 0) { 242 $year = date("Y", $next_range_unixtime); 243 $month = date('m', $next_range_unixtime); 244 $time = mktime(12,0,0,$month,date("d",$start_unixtime),$year); 245 switch ($freq_type){ 246 case 'day': 247 add_recur($next_range_unixtime); 248 break; 249 case 'week': 250 add_recur(expand_byday($next_range_unixtime)); 251 break; 252 case 'month': 253 if(!empty($bymonthday)) $time = mktime(12,0,0,$month,1,$year); 254 $times = expand_bymonthday(array($time));#echo "\n $month exp bymonthday";dump_times($times); 255 foreach($times as $time){ 256 add_recur(expand_byday($time)); 257 } 258 break; 259 case 'year': 260 $times = expand_bymonth($time); #echo "exp bymonth";dump_times($times); 261 $times = expand_byweekno($times); #echo "exp byweekno";dump_times($times); 262 $times = expand_byyearday($times); #echo "exp byyearday";dump_times($times); 263 $times = expand_bymonthday($times); #echo "\nexp bymonthday";dump_times($times); 264 foreach($times as $time){ 265 add_recur(expand_byday($time)); 266 } 267 break; 268 default: 269 add_recur($start_unixtime); 270 break 2; 271 } 272 $next_range_unixtime = strtotime('+'.$interval.' '.$freq_type, $next_range_unixtime); #echo "\nnext $interval $freq_type".date("Ymd",$next_range_unixtime)."\n"; 273} #end while loop 274sort($recur_data); 275 276/* ============================ Use $recur_data array to write the master array ============================ 277// This used to use 5 different blocks to write the array... can it be reduced further? 278 279For each recurrence date, an event may still cross day boundaries. So we need to loop from the start_date for that recurrence to the end of that recurrence. 280To generate $recur_data we mostly only paid attention to start times. 281 282Now, a single event must be split into multiple master array values for each day on which it occurs 283 284$hour and $minute are the values from the start_time, rounded to the nearest grid time. 285 286*/ 287$recur_data_hour = @substr($start_time,0,2); 288$recur_data_minute = @substr($start_time,2,2); 289if (isset($allday_start) && $allday_start != ''){ 290 $recur_data_hour = '00'; 291 $recur_data_minute = '00'; 292} 293foreach($recur_data as $recur_data_unixtime) { 294 $recur_data_year = date('Y', $recur_data_unixtime); 295 $recur_data_month = date('m', $recur_data_unixtime); 296 $recur_data_day = date('d', $recur_data_unixtime); 297 $recur_data_date = $recur_data_year.$recur_data_month.$recur_data_day; 298 299 # initialize the loop range to the recur date + grid time 300 $next_range_unixtime = mktime($recur_data_hour,$recur_data_minute,0,$recur_data_month,$recur_data_day,$recur_data_year); 301 $end_range_unixtime = $next_range_unixtime + $length; 302 $end_date_tmp = date("Ymd",$end_range_unixtime); 303 #echo "<pre>$summary ".date("Ymd H:i:s",$next_range_unixtime)." ".date("Ymd H:i:s",$end_range_unixtime)."\n"; 304 305 # default the time_key to -1 for allday events, overwrite as needed 306 $time_key = -1; 307 308 $start_unixtime_tmp = strtotime($recur_data_date.$start_time); 309 $end_unixtime_tmp = strtotime($end_date_tmp.$end_time); 310 while (date("Ymd", $next_range_unixtime) <= $end_date_tmp) { 311 $this_date_tmp = date('Ymd',$next_range_unixtime); 312 $next_range_unixtime = strtotime('+1 day',$next_range_unixtime); 313 314 if (!isset($allday_start) || $allday_start == '') $time_key = $hour.$minute; 315 $display_end_tmp = $end_hour.$end_minute; 316 if($time_key > -1){ 317 # the day is not the first day of the recurrence 318 if ($this_date_tmp > $recur_data_date) $time_key = '0000'; 319 # the day is not the last day of the recurrence 320 if ($this_date_tmp < $end_date_tmp) $display_end_tmp = '2400'; 321 } 322 if($this_date_tmp == $end_date_tmp && ($end_time == '0000')) continue; 323 if(!isset($master_array[$this_date_tmp][$time_key][$uid]['sequence']) || 324 $sequence > $master_array[$this_date_tmp][$time_key][$uid]['sequence'] 325 ){ 326 $master_array[$this_date_tmp][$time_key][$uid] = array ( 327 'event_start' => $start_time, # hhmm 328 'event_end' => $end_time, # hhmm 329 'display_start' => $time_key, # hhmm 330 'display_end' => $display_end_tmp, # hhmm 331 'start_unixtime' => $start_unixtime_tmp, # start unixtime for this recurrence 332 'end_unixtime' => $end_unixtime_tmp, # end unixtime for this recurrence 333 'event_text' => $summary, # 334 'event_length' => $length, # length in seconds 335 'event_overlap' => 0, # checkOverlap modifies this 336 'description' => $description, 337 'status' => $status, 338 'class' => $class, 339 'spans_day' => $spans_day, 340 'location' => $location, 341 'categories' => $vtodo_categories, 342 'organizer' => serialize($organizer), 343 'attendee' => serialize($attendee), 344 'calnumber' => $calnumber, 345 'calname' => $actual_calname, 346 'timezone' => $start_tz, 347 'other' => trim($other), 348 'geo' => $geo, 349 'url' => $url, 350 'sequence' => $sequence, 351 'recur' => $recur 352 ); 353 } 354 if($time_key > -1) checkOverlap($this_date_tmp, $time_key, $uid); 355 } 356} # end foreach recur_data 357unset($recur_data); 358 359 360// This should remove any exdates that were missed. 361// Added for version 0.9.5 modified in 2.22 remove anything that doesn't have an event_start 362if (is_array($except_dates)) { 363 foreach ($except_dates as $key => $value) { 364 if (isset ($master_array[$value])){ 365 foreach ($master_array[$value] as $time => $value2){ 366 if (!isset($value2[$uid]['event_start'])){ 367 unset($master_array[$value][$time][$uid]); 368 } 369 } 370 } 371 } 372} 373 374// Clear event data now that it's been saved. 375unset($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); 376//If you want to see the values in the arrays, uncomment below. 377//print '<pre>'; 378//print_r($master_array); 379//print_r($overlap_array); 380//print_r($day_array); 381//print_r($rrule_array); 382//print_r($byday_arr); 383//print_r($recurrence_delete); 384//print_r($cal_displaynames); 385//print_r($cal_filelist); 386//print_r($tz_array); 387//print '</pre>'; 388?>