From b9f502c10cd6b5dacacc6c79a5cca6fa67ff9ea7 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 9 Mar 2015 18:56:42 +0000 Subject: [PATCH] * Calendar: fix not shown last recurrence of limited recurring event in day-view (requires database update for existing events) --- calendar/inc/class.calendar_ical.inc.php | 13 ------- calendar/inc/class.calendar_rrule.inc.php | 30 ++++++---------- calendar/inc/class.calendar_so.inc.php | 17 +++++++++ calendar/setup/setup.inc.php | 2 +- calendar/setup/tables_update.inc.php | 43 +++++++++++++++++++++++ 5 files changed, 72 insertions(+), 33 deletions(-) diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php index a5352f75c6..e625b5e3a7 100644 --- a/calendar/inc/class.calendar_ical.inc.php +++ b/calendar/inc/class.calendar_ical.inc.php @@ -609,19 +609,6 @@ class calendar_ical extends calendar_boupdate $rrule = $rriter->generate_rrule($version); if ($event['recur_enddate']) { - if ($this->productManufacturer == 'groupdav' && $this->productName == 'iphone') - { - // Fix iPhone issue - $length = ($event['end'] - $event['start']); - $rrule['UNTIL']->modify($length . ' second'); - $rrule['UNTIL']->setTime(23, 59, 59); - } - else - { - $length = ($event['end'] - $event['start']) / 2; - $rrule['UNTIL']->modify((int)$length . ' second'); - } - if (!$tzid || $version != '1.0') { if (!isset(self::$tz_cache['UTC'])) diff --git a/calendar/inc/class.calendar_rrule.inc.php b/calendar/inc/class.calendar_rrule.inc.php index 937192ad58..f6449d5c9e 100644 --- a/calendar/inc/class.calendar_rrule.inc.php +++ b/calendar/inc/class.calendar_rrule.inc.php @@ -215,10 +215,10 @@ class calendar_rrule implements Iterator * * @param DateTime $time start of event in it's own timezone * @param int $type self::NONE, self::DAILY, ..., self::YEARLY - * @param int $interval=1 1, 2, ... - * @param DateTime $enddate=null enddate or null for no enddate (in which case we user '+5 year' on $time) - * @param int $weekdays=0 self::SUNDAY=1|self::MONDAY=2|...|self::SATURDAY=64 - * @param array $exceptions=null DateTime objects with exceptions + * @param int $interval =1 1, 2, ... + * @param DateTime $enddate =null enddate or null for no enddate (in which case we user '+5 year' on $time) + * @param int $weekdays =0 self::SUNDAY=1|self::MONDAY=2|...|self::SATURDAY=64 + * @param array $exceptions =null DateTime objects with exceptions */ public function __construct(DateTime $time,$type,$interval=1,DateTime $enddate=null,$weekdays=0,array $exceptions=null) { @@ -238,7 +238,7 @@ class calendar_rrule implements Iterator if (!in_array($type,array(self::NONE, self::DAILY, self::WEEKLY, self::MONTHLY_MDAY, self::MONTHLY_WDAY, self::YEARLY))) { - throw new egw_exception_wrong_parameter(__METHOD__."($time,$type,$interval,$enddate,$data,...) type $type is NOT valid!"); + throw new egw_exception_wrong_parameter(__METHOD__."($time,$type,$interval,$enddate,$weekdays,...) type $type is NOT valid!"); } $this->type = $type; @@ -315,7 +315,7 @@ class calendar_rrule implements Iterator * Get recurrence interval duration in seconds * * @param int $type self::(DAILY|WEEKLY|MONTHLY_(M|W)DAY|YEARLY) - * @param int $interval=1 + * @param int $interval =1 * @return int */ public static function recurrence_interval($type, $interval=1) @@ -620,7 +620,7 @@ class calendar_rrule implements Iterator /** * Generate a VEVENT RRULE - * @param string $version='1.0' could be '2.0', too + * @param string $version ='2.0' could be '1.0' too * * $return array vCalendar RRULE */ @@ -697,15 +697,7 @@ class calendar_rrule implements Iterator if ($this->enddate) { - $this->rewind(); - $enddate = $this->current(); - do - { - $this->next_no_exception(); - $occurrence = $this->current(); - } - while ($this->valid() && ($enddate = $occurrence)); - $rrule['UNTIL'] = $enddate; + $rrule['UNTIL'] = $this->enddate; } return $rrule; @@ -715,7 +707,7 @@ class calendar_rrule implements Iterator * Get instance for a given event array * * @param array $event - * @param boolean $usertime=true true: event timestamps are usertime (default for calendar_bo::(read|search), false: servertime + * @param boolean $usertime =true true: event timestamps are usertime (default for calendar_bo::(read|search), false: servertime * @param string $to_tz timezone for exports (null for event's timezone) * * @return calendar_rrule false on error @@ -863,8 +855,8 @@ if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE_ $tz = new DateTimeZone($_REQUEST['tz']); $time = new egw_time($_REQUEST['time'],$tz); if ($_REQUEST['enddate']) $enddate = new egw_time($_REQUEST['enddate'],$tz); - $weekdays = 0; foreach((array)$_REQUEST['weekdays'] as $mask) $weekdays |= $mask; - if ($_REQUEST['exceptions']) foreach(preg_split("/[,\r\n]+ ?/",$_REQUEST['exceptions']) as $exception) $exceptions[] = new egw_time($exception); + $weekdays = 0; foreach((array)$_REQUEST['weekdays'] as $mask) { $weekdays |= $mask; } + if ($_REQUEST['exceptions']) foreach(preg_split("/[,\r\n]+ ?/",$_REQUEST['exceptions']) as $exception) { $exceptions[] = new egw_time($exception); } $rrule = new calendar_rrule($time,$_REQUEST['type'],$_REQUEST['interval'],$enddate,$weekdays,$exceptions); echo "

".$time->format('l').', '.$time.' ('.$tz->getName().') '.$rrule."

\n"; diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php index 98645395a6..db3374dfcd 100644 --- a/calendar/inc/class.calendar_so.inc.php +++ b/calendar/inc/class.calendar_so.inc.php @@ -1315,6 +1315,23 @@ ORDER BY cal_user_type, cal_usre_id $event['recur_interval'] = 1; } + // set recur-enddate/range-end to real end-date of last recurrence + if ($event['recur_type'] != MCAL_RECUR_NONE && $event['recur_enddate']) + { + $rrule = calendar_rrule::event2rrule($event, false); + $rrule->rewind(); + $enddate = $rrule->current(); + do + { + $rrule->next_no_exception(); + $occurrence = $rrule->current(); + } + while ($rrule->valid() && ($enddate = $occurrence)); + $enddate->modify(($event['end'] - $event['start']).' second'); + $event['recur_enddate'] = $enddate->format('server'); + //error_log(__METHOD__."($event[title]) start=".egw_time::to($event['start'],'string').', end='.egw_time::to($event['end'],'string').', range_end='.egw_time::to($event['recur_enddate'],'string')); + } + // add colum prefix 'cal_' if there's not already a 'recur_' prefix foreach($event as $col => $val) { diff --git a/calendar/setup/setup.inc.php b/calendar/setup/setup.inc.php index 8d929bc80c..dbe074e244 100755 --- a/calendar/setup/setup.inc.php +++ b/calendar/setup/setup.inc.php @@ -10,7 +10,7 @@ */ $setup_info['calendar']['name'] = 'calendar'; -$setup_info['calendar']['version'] = '14.1.001'; +$setup_info['calendar']['version'] = '14.2.001'; $setup_info['calendar']['app_order'] = 3; $setup_info['calendar']['enable'] = 1; $setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index'; diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index 5054c1f4db..5ebabde439 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -2330,3 +2330,46 @@ ORDER BY master.cal_id DESC", __LINE__, __FILE__, 0, -1, false, egw_db::FETCH_AS } return $GLOBALS['setup_info']['calendar']['currentver'] = '14.1.001'; } + +/** + * Modify range_end of recurring events to be end-time of last recurrence (and not just a date) + * + * This fixes not fund last recurrence in day-view. + * + * @return string + */ +function calendar_upgrade14_1_001() +{ + foreach($GLOBALS['egw_setup']->db->query( +"SELECT egw_cal.cal_id AS cal_id,cal_start,cal_end,range_start,range_end,egw_cal_repeats.*,tz_tzid AS tzid +FROM egw_cal +JOIN egw_cal_repeats ON egw_cal_repeats.cal_id=egw_cal.cal_id +JOIN egw_cal_dates ON egw_cal_dates.cal_id=egw_cal.cal_id AND cal_start=range_start +JOIN egw_cal_timezones ON egw_cal.tz_id=egw_cal_timezones.tz_id", __LINE__, __FILE__, 0, -1, false, egw_db::FETCH_ASSOC) as $event) + { + $event = egw_db::strip_array_keys($event, 'cal_'); + $event['recur_enddate'] = $event['range_end']; + $rrule = calendar_rrule::event2rrule($event, false); + $rrule->rewind(); + $enddate = $rrule->current(); + do + { + $rrule->next_no_exception(); + $occurrence = $rrule->current(); + } + while ($rrule->valid() && ($enddate = $occurrence)); + $enddate->modify(($event['end'] - $event['start']).' second'); + if (($range_end = $enddate->format('server')) != $event['range_end']) + { + $GLOBALS['egw_setup']->db->update('egw_cal',array( + 'range_end' => $range_end, + 'cal_etag=cal_etag+1', + 'cal_modified' => time(), + ), array( + 'cal_id' => $event['id'], + ), __LINE__, __FILE__, 'calendar'); + //error_log(__FUNCTION__."() #$event[id], start=".date('Y-m-d H:i:s', $event['start']).', end='.date('Y-m-d H:i:s', $event['end']).', range_end='.date('Y-m-d H:i:s', $event['recur_enddate']).' --> '.date('Y-m-d H:i:s', $range_end)); + } + } + return $GLOBALS['setup_info']['calendar']['currentver'] = '14.2.001'; +} \ No newline at end of file