diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php index a6ae031abc..e2c5bc1ca0 100644 --- a/calendar/inc/class.calendar_bo.inc.php +++ b/calendar/inc/class.calendar_bo.inc.php @@ -58,12 +58,6 @@ class calendar_bo */ var $debug=false; - /** - * @var int $tz_offset_s offset in secconds between user and server-time, - * it need to be add to a server-time to get the user-time or substracted from a user-time to get the server-time - */ - var $tz_offset_s; - /** * @var int $now_su timestamp of actual user-time */ @@ -173,9 +167,7 @@ class calendar_bo $this->common_prefs =& $GLOBALS['egw_info']['user']['preferences']['common']; $this->cal_prefs =& $GLOBALS['egw_info']['user']['preferences']['calendar']; - $this->tz_offset_s = $this->datetime->tz_offset; - - $this->now_su = time() + $this->tz_offset_s; + $this->now_su = egw_time::to('now','ts'); $this->user = $GLOBALS['egw_info']['user']['account_id']; @@ -557,7 +549,7 @@ class calendar_bo $this->debug_message('bocal::check_move_horizont(%1): calling set_recurrences(%2,%3)',true,$new_horizont,$event,$old_horizont); } // insert everything behind max(cal_start), which can be less then $old_horizont because of bugs in the past - $this->set_recurrences($event,$recuring[$cal_id]+1+$this->tz_offset_s); // set_recurences operates in user-time! + $this->set_recurrences($event,egw_time::server2user($recuring[$cal_id]+1)); // set_recurences operates in user-time! } } // update the horizont @@ -613,29 +605,35 @@ class calendar_bo function db2data(&$events,$date_format='ts') { if (!is_array($events)) echo "

bocal::db2data(\$events,$date_format) \$events is no array
\n".function_backtrace()."

\n"; - foreach($events as $id => $event) + foreach($events as $id => &$event) { + // convert timezone id of event to tzid (iCal id like 'Europe/Berlin') + unset($event_timezone); + if (!$event['tz_id'] || !($event['tzid'] = calendar_timezones::id2tz($event['tz_id']))) + { + $event['tzid'] = egw_time::$server_timezone->getName(); + } // we convert here from the server-time timestamps to user-time and (optional) to a different date-format! foreach(array('start','end','modified','created','recur_enddate','recurrence') as $ts) { if (empty($event[$ts])) continue; - $events[$id][$ts] = $this->date2usertime($event[$ts],$date_format); + $event[$ts] = $this->date2usertime($event[$ts],$date_format); } // same with the recur exceptions if (isset($event['recur_exception']) && is_array($event['recur_exception'])) { - foreach($event['recur_exception'] as $n => $date) + foreach($event['recur_exception'] as $n => &$date) { - $events[$id]['recur_exception'][$n] = $this->date2usertime($date,$date_format); + $date = $this->date2usertime($date,$date_format); } } // same with the alarms if (isset($event['alarm']) && is_array($event['alarm'])) { - foreach($event['alarm'] as $n => $alarm) + foreach($event['alarm'] as $n => &$alarm) { - $events[$id]['alarm'][$n]['time'] = $this->date2usertime($alarm['time'],$date_format); + $alarm['time'] = $this->date2usertime($alarm['time'],$date_format); } } } @@ -646,30 +644,13 @@ class calendar_bo * * @param int $date timestamp in server-time * @param string $date_format='ts' date-formats: 'ts'=timestamp, 'server'=timestamp in server-time, 'array'=array or string with date-format + * @return mixed depending of $date_format */ function date2usertime($ts,$date_format='ts') { if (empty($ts) || $date_format == 'server') return $ts; return egw_time::server2user($ts,$date_format); -/* - switch ($date_format) - { - case 'ts': - return egw_time::server2user($ts,'int'); - return $ts + $this->tz_offset_s; - - case 'server': - return $ts; - - case 'array': - return $this->date2array((int) $ts,true); - - case 'string': - return $this->date2string($ts,true); - } - return $this->date2string($ts,true,$date_format); -*/ } /** @@ -1094,76 +1075,6 @@ class calendar_bo static function date2ts($date,$user2server=False) { return $user2server ? egw_time::user2server($date,'ts') : egw_time::to($date,'ts'); -/* - $date_in = $date; - - switch(gettype($date)) - { - case 'string': // YYYYMMDD or iso8601 YYYY-MM-DDThh:mm:ss[Z|[+-]hh:mm] string - if (is_numeric($date) && $date > 21000000) - { - $date = (int) $date; // this is already as timestamp - break; - } - // evaluate evtl. added timezone - if (strlen($date) > 12) - { - if (substr($date,-1) == 'Z') - { - $time_offset = date('Z'); - } - elseif(preg_match('/([+-]{1})([0-9]{2}):?([0-9]{2})$/',$date,$matches)) - { - $time_offset = date('Z')-($matches[1] == '+' ? 1 : -1)*(3600*$matches[2]+60*$matches[3]); - } - } - // removing all non-nummerical chars, gives YYYYMMDDhhmmss, independent of the iso8601 format - $date = str_replace(array('-',':','T','Z',' ','+'),'',$date); - $date = array( - 'year' => (int) substr($date,0,4), - 'month' => (int) substr($date,4,2), - 'day' => (int) substr($date,6,2), - 'hour' => (int) substr($date,8,2), - 'minute' => (int) substr($date,10,2), - 'second' => (int) substr($date,12,2), - ); - // fall-through - case 'array': // day, month and year keys - if (isset($date['raw']) && $date['raw']) // we already have a timestamp - { - $date = $date['raw']; - break; - } - if (!isset($date['year']) && isset($date['full'])) - { - $date['year'] = (int) substr($date['full'],0,4); - $date['month'] = (int) substr($date['full'],4,2); - $date['day'] = (int) substr($date['full'],6,2); - } - $date = adodb_mktime((int)$date['hour'],(int)$date['minute'],(int)$date['second'],(int)$date['month'], - (int) (isset($date['day']) ? $date['day'] : $date['mday']),(int)$date['year']); - break; - case 'integer': // already a timestamp - break; - default: // eg. boolean, means now in user-time (!) - $date = $this->now_su; - break; - } - if ($time_offset) - { - $date += $time_offset; - if (!$user2server) $date += $this->tz_offset_s; // we have to return user time! - } - if ($user2server) - { - $date -= $this->tz_offset_s; - } - if ($this->debug && ($this->debug > 3 || $this->debug == 'date2ts')) - { - $this->debug_message('bocal::date2ts(%1,user2server=%2)=%3)',False,$date_in,$user2server,$date); - } - return $date; -*/ } /** @@ -1176,32 +1087,6 @@ class calendar_bo static function date2array($date,$server2user=False) { return $server2user ? egw_time::server2user($date,'array') : egw_time::to($date,'array'); -/* - $date_called = $date; - - if (!is_array($date) || count($date) < 8 || $server2user) // do we need a conversation - { - if (!is_int($date)) - { - $date = $this->date2ts($date); - } - if ($server2user) - { - $date += $this->tz_offset_s; - } - $arr = array(); - foreach(array('second'=>'s','minute'=>'i','hour'=>'H','day'=>'d','month'=>'m','year'=>'Y','full'=>'Ymd') as $key => $frmt) - { - $arr[$key] = (int) adodb_date($frmt,$date); - } - $arr['raw'] = $date; - } - if ($this->debug && ($this->debug > 3 || $this->debug == 'date2array')) - { - $this->debug_message('bocal::date2array(%1,server2user=%2)=%3)',False,$date_called,$server2user,$arr); - } - return $arr; -*/ } /** @@ -1215,41 +1100,6 @@ class calendar_bo static function date2string($date,$server2user=False,$format='Ymd') { return $server2user ? egw_time::server2user($date,$format) : egw_time::to($date,$format); -/* - $date_in = $date; - - if (!$format) $format = 'Ymd'; - - if (is_array($date) && isset($date['full']) && !$server2user && $format == 'Ymd') - { - $date = $date['full']; - } - else - { - $date = $this->date2ts($date,False); - - // if timezone is requested, we dont need to convert to user-time - if (($tz_used = substr($format,-1)) == 'O' || $tz_used == 'Z') $server2user = false; - - if ($server2user && substr($format,-1) ) - { - $date += $this->tz_offset_s; - } - if (substr($format,-2) == '\\Z') // GMT aka. Zulu time - { - $date = adodb_gmdate($format,$date); - } - else - { - $date = adodb_date($format,$date); - } - } - if ($this->debug && ($this->debug > 3 || $this->debug == 'date2string')) - { - $this->debug_message('bocal::date2string(%1,server2user=%2,format=%3)=%4)',False,$date_in,$server2user,$format,$date); - } - return $date; -*/ } /** @@ -1262,22 +1112,6 @@ class calendar_bo static function format_date($date,$format='') { return egw_time::to($date,$format); -/* - $timeformat = $this->common_prefs['timeformat'] != '12' ? 'H:i' : 'h:i a'; - if ($format === '') // date+time wanted - { - $format = $this->common_prefs['dateformat'].', '.$timeformat; - } - elseif ($format === false) // time wanted - { - $format = $timeformat; - } - elseif ($format === true) - { - $format = $this->common_prefs['dateformat']; - } - return adodb_date($format,$this->date2ts($date,False)); -*/ } /** diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index 81ecdbeb3f..949d02d43e 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -639,7 +639,7 @@ class calendar_boupdate extends calendar_bo //echo "

bocalendar::send_alarm("; print_r($alarm); echo ")

\n"; $GLOBALS['egw_info']['user']['account_id'] = $this->owner = $alarm['owner']; - $event_time_user = $alarm['time'] + $alarm['offset'] + $this->tz_offset_s; // alarm[time] is in server-time, read requires user-time + $event_time_user = egw_time::server2user($alarm['time'] + $alarm['offset']); // alarm[time] is in server-time, read requires user-time if (!$alarm['owner'] || !$alarm['cal_id'] || !($event = $this->read($alarm['cal_id'],$event_time_user))) { return False; // event not found @@ -700,6 +700,11 @@ class calendar_boupdate extends calendar_bo // we convert here from user-time to timestamps in server-time! if (isset($event[$ts])) $event[$ts] = $event[$ts] ? $this->date2ts($event[$ts],true) : 0; } + // convert tzid name to integer tz_id, of set user default + if (empty($event['tzid']) || !($event['tz_id'] = calendar_timezones::tz2id($event['tzid']))) + { + $event['tz_id'] = calendar_timezones::tz2id($event['tzid'] = egw_time::$user_timezone->getName()); + } // same with the recur exceptions if (isset($event['recur_exception']) && is_array($event['recur_exception'])) { diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php index c01e55258a..cab9309fbb 100644 --- a/calendar/inc/class.calendar_so.inc.php +++ b/calendar/inc/class.calendar_so.inc.php @@ -155,7 +155,7 @@ class calendar_so $where[] = 'cal_start >= '.(int)$recur_date; } $events = array(); - foreach($this->db->select($this->cal_table,"$this->repeats_table.*,$this->cal_table.*,MIN(cal_start) AS cal_start,MIN(cal_end) AS cal_end,tz_id", + foreach($this->db->select($this->cal_table,"$this->repeats_table.*,$this->cal_table.*,MIN(cal_start) AS cal_start,MIN(cal_end) AS cal_end", $where,__LINE__,__FILE__,false,'GROUP BY '.$group_by_cols,'calendar',0, ",$this->dates_table LEFT JOIN $this->repeats_table ON $this->dates_table.cal_id=$this->repeats_table.cal_id". " WHERE $this->cal_table.cal_id=$this->dates_table.cal_id") as $row) @@ -703,7 +703,7 @@ ORDER BY cal_user_type, cal_usre_id // update start- and endtime if present in the event-array, evtl. we need to move all recurrences if (isset($event['cal_start']) && isset($event['cal_end'])) { - $this->move($cal_id,$event['cal_start'],$event['cal_end'],$event['tz_id'],!$cal_id ? false : $change_since); + $this->move($cal_id,$event['cal_start'],$event['cal_end'],!$cal_id ? false : $change_since); } // update participants if present in the event-array if (isset($event['cal_participants'])) @@ -772,14 +772,13 @@ ORDER BY cal_user_type, cal_usre_id * @param int $cal_id * @param int $start new starttime * @param int $end new endtime - * @param int $tz_id timezone id to set * @param int|boolean $change_since=0 false=new entry, > 0 time from which on the repetitions should be changed, default 0=all * @param int $old_start=0 old starttime or (default) 0, to query it from the db * @param int $old_end=0 old starttime or (default) 0 * @todo Recalculate recurrences, if timezone changes * @return int|boolean number of moved recurrences or false on error */ - function move($cal_id,$start,$end,$tz_id,$change_since=0,$old_start=0,$old_end=0) + function move($cal_id,$start,$end,$change_since=0,$old_start=0,$old_end=0) { //echo "

socal::move($cal_id,$start,$end,$change_since,$old_start,$old_end)

\n"; @@ -796,7 +795,6 @@ ORDER BY cal_user_type, cal_usre_id 'cal_id' => $cal_id, 'cal_start' => $start, 'cal_end' => $end, - 'tz_id' => $tz_id, ),false,__LINE__,__FILE__,'calendar'); return 1; @@ -820,7 +818,7 @@ ORDER BY cal_user_type, cal_usre_id if ($move_start || $move_end) { // move the event and it's recurrences - $this->db->query("UPDATE $this->dates_table SET cal_start=cal_start+$move_start,cal_end=cal_end+$move_end,tz_id=".(int)$tz_id." WHERE $where". + $this->db->query("UPDATE $this->dates_table SET cal_start=cal_start+$move_start,cal_end=cal_end+$move_end WHERE $where". ((int) $change_since ? ' AND cal_start >= '.(int) $change_since : ''),__LINE__,__FILE__); } return $this->db->affected_rows(); diff --git a/calendar/setup/egw_de.lang b/calendar/setup/egw_de.lang index 35785ebba4..53fce37e41 100644 --- a/calendar/setup/egw_de.lang +++ b/calendar/setup/egw_de.lang @@ -325,6 +325,8 @@ thu calendar de Do til calendar de bis timeframe calendar de Zeitrahmen timeframe to search calendar de Zeitrahmen für die Suche +timezone calendar de Zeitzone +timezone in which recurrences have identical time calendar de Zeitzone in der Wiederholungen zu identischer Uhrzeit stattfinden title of the event calendar de Titel des Termin to many might exceed your execution-time-limit calendar de zu viele können ihre Laufzeitbeschränkung überschreiten translation calendar de Übersetzung diff --git a/calendar/setup/egw_en.lang b/calendar/setup/egw_en.lang index 8348710619..8eb0b87051 100644 --- a/calendar/setup/egw_en.lang +++ b/calendar/setup/egw_en.lang @@ -325,6 +325,8 @@ thu calendar en Thu til calendar en til timeframe calendar en Timeframe timeframe to search calendar en Timeframe to search +timezone calendar en Timezone +timezone in which recurrences have identical time calendar en Timezone in which recurrences have identical time title of the event calendar en Title of the event to many might exceed your execution-time-limit calendar en to many might exceed your execution-time-limit translation calendar en Translation diff --git a/calendar/setup/etemplates.inc.php b/calendar/setup/etemplates.inc.php index 2c0fbaf964..9fe111ed8a 100644 --- a/calendar/setup/etemplates.inc.php +++ b/calendar/setup/etemplates.inc.php @@ -2,7 +2,7 @@ /** * eGroupWare - eTemplates for Application calendar * http://www.egroupware.org - * generated by soetemplate::dump4setup() 2009-10-12 22:52 + * generated by soetemplate::dump4setup() 2009-11-01 13:40 * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package calendar @@ -31,7 +31,7 @@ $templ_data[] = array('name' => 'calendar.edit.participants','template' => '','l $templ_data[] = array('name' => 'calendar.edit.print','template' => '','lang' => '','group' => '0','version' => '1.6.001','data' => 'a:1:{i:0;a:7:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:6:{s:1:"A";s:2:"95";s:2:"c3";s:4:",top";s:2:"c1";s:3:"row";s:2:"c2";s:2:"th";s:2:"h1";s:8:",@no_add";s:1:"D";s:24:",@hide_status_recurrence";}i:1;a:6:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:3:"New";}s:1:"B";a:4:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:14:"select-account";s:4:"size";s:27:"User or group,calendar+,,10";s:4:"name";s:7:"account";s:4:"help";s:13:"User or group";}i:2;a:3:{s:4:"type";s:10:"link-entry";s:4:"name";s:8:"resource";s:4:"size";s:14:"@cal_resources";}}s:1:"C";a:3:{s:4:"type";s:3:"int";s:4:"size";s:4:"1,,3";s:4:"name";s:8:"quantity";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:3:{s:4:"type";s:6:"button";s:5:"label";s:3:"Add";s:4:"name";s:3:"add";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:2;a:6:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Type";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:12:"Participants";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:8:"Quantity";}s:1:"D";a:2:{s:4:"type";s:5:"label";s:5:"label";s:10:"All future";}s:1:"E";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Status";}s:1:"F";a:2:{s:4:"type";s:5:"label";s:5:"label";s:7:"Actions";}}i:3;a:6:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:4:"name";s:11:"${row}[app]";}s:1:"B";a:6:{s:4:"type";s:5:"label";s:4:"data";a:2:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:6:"${row}";s:8:"readonly";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:26:"accounts_status[$row_cont]";s:8:"onchange";s:1:"1";s:4:"help";s:30:"Accept or reject an invitation";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:13:"${row}[title]";s:7:"no_lang";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:3:"int";s:4:"name";s:16:"${row}[quantity]";s:4:"size";s:4:"1,,3";}s:1:"D";a:3:{s:4:"type";s:8:"checkbox";s:4:"name";s:25:"${row}[status_recurrence]";s:5:"align";s:6:"center";}s:1:"E";a:4:{s:4:"type";s:6:"select";s:4:"name";s:14:"${row}[status]";s:7:"no_lang";s:1:"1";s:8:"onchange";i:1;}s:1:"F";a:9:{s:4:"type";s:6:"button";s:4:"data";a:2:{i:0;a:1:{s:2:"h1";s:19:",!@resources_status";}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:16:"resources_select";s:4:"name";s:6:"${row}";s:8:"readonly";s:1:"1";s:7:"no_lang";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:27:"resources_status[$row_cont]";s:8:"onchange";s:1:"1";s:4:"help";s:30:"Accept or reject an invitation";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:22:"delete[$row_cont[uid]]";s:5:"align";s:6:"center";s:5:"label";s:6:"Delete";s:8:"onchange";i:1;s:4:"size";s:6:"delete";}}}s:4:"rows";i:3;s:4:"cols";i:6;s:4:"size";s:17:"100%,200,,,,,auto";s:4:"name";s:12:"participants";s:7:"options";a:3:{i:0;s:4:"100%";i:1;s:3:"200";i:6;s:4:"auto";}}}','size' => '100%,200,,,,,auto','style' => '','modified' => '1229280346',); -$templ_data[] = array('name' => 'calendar.edit.recurrence','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:11:{s:2:"c1";s:3:"row";s:1:"A";s:2:"95";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:1:"D";s:3:"50%";s:2:"h1";s:12:",!@reference";s:2:"h3";s:2:"12";s:2:"c5";s:7:"row,top";s:2:"h4";s:2:"12";s:2:"h2";s:2:"12";s:2:"c2";s:2:"th";}i:1;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"Exception";}s:1:"B";a:4:{s:4:"type";s:9:"date-time";s:4:"span";s:5:",gray";s:8:"readonly";s:1:"1";s:4:"name";s:10:"recurrence";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"span";s:5:",gray";s:4:"name";s:9:"reference";}s:1:"D";a:3:{s:4:"type";s:5:"label";s:4:"span";s:5:",gray";s:4:"name";s:3:"uid";}}i:2;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:8:"all,gray";s:5:"label";s:27:"Repeating Event Information";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:16:"be back soon ;-)";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:3;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:13:",,,recur_type";s:5:"label";s:11:"Repeat type";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:10:"recur_type";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"size";s:17:",,,recur_interval";s:5:"label";s:8:"Interval";}s:1:"D";a:4:{s:4:"type";s:13:"select-number";s:4:"name";s:14:"recur_interval";s:4:"help";s:53:"repeating interval, eg. 2 to repeat every second week";s:4:"size";s:9:"None,2,31";}}i:4;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:16:",,,recur_enddate";s:5:"label";s:8:"End date";}s:1:"B";a:4:{s:4:"type";s:4:"date";s:4:"name";s:13:"recur_enddate";s:4:"help";s:57:"repeat the event until which date (empty means unlimited)";s:4:"span";s:3:"all";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:5;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:13:",,,recur_data";s:5:"label";s:11:"Repeat days";}s:1:"B";a:4:{s:4:"type";s:10:"select-dow";s:4:"size";s:3:"6,1";s:4:"name";s:10:"recur_data";s:4:"help";s:44:"Days of the week for a weekly repeated event";}s:1:"C";a:4:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:10:"Exceptions";}i:2;a:5:{s:4:"type";s:6:"button";s:4:"name";s:17:"button[exception]";s:5:"label";s:16:"@exception_label";s:4:"help";s:38:"Create an exception for the given date";s:7:"no_lang";s:1:"1";}}s:1:"D";a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:4:"$row";s:8:"readonly";s:1:"1";}s:1:"B";a:6:{s:4:"type";s:6:"button";s:5:"label";s:6:"Delete";s:4:"size";s:6:"delete";s:4:"name";s:27:"delete_exception[$row_cont]";s:4:"help";s:21:"Delete this exception";s:7:"onclick";s:40:"return confirm(\'Delete this exception\');";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:15:"recur_exception";s:7:"options";a:0:{}}}}s:4:"rows";i:5;s:4:"cols";i:4;s:4:"size";s:8:"100%,210";s:7:"options";a:2:{i:0;s:4:"100%";i:1;s:3:"210";}}}','size' => '100%,210','style' => '','modified' => '1210321464',); +$templ_data[] = array('name' => 'calendar.edit.recurrence','template' => '','lang' => '','group' => '0','version' => '1.7.002','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:11:{s:2:"c1";s:3:"row";s:1:"A";s:2:"95";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:1:"D";s:3:"50%";s:2:"h1";s:12:",!@reference";s:2:"h3";s:2:"12";s:2:"c5";s:7:"row,top";s:2:"h4";s:2:"12";s:2:"h2";s:2:"12";s:2:"c2";s:2:"th";}i:1;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"Exception";}s:1:"B";a:4:{s:4:"type";s:9:"date-time";s:4:"span";s:5:",gray";s:8:"readonly";s:1:"1";s:4:"name";s:10:"recurrence";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"span";s:5:",gray";s:4:"name";s:9:"reference";}s:1:"D";a:3:{s:4:"type";s:5:"label";s:4:"span";s:5:",gray";s:4:"name";s:3:"uid";}}i:2;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:8:"all,gray";s:5:"label";s:27:"Repeating Event Information";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:16:"be back soon ;-)";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:3;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:13:",,,recur_type";s:5:"label";s:11:"Repeat type";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:10:"recur_type";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"size";s:17:",,,recur_interval";s:5:"label";s:8:"Interval";}s:1:"D";a:4:{s:4:"type";s:13:"select-number";s:4:"name";s:14:"recur_interval";s:4:"help";s:53:"repeating interval, eg. 2 to repeat every second week";s:4:"size";s:9:"None,2,31";}}i:4;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:16:",,,recur_enddate";s:5:"label";s:8:"End date";}s:1:"B";a:3:{s:4:"type";s:4:"date";s:4:"name";s:13:"recur_enddate";s:4:"help";s:57:"repeat the event until which date (empty means unlimited)";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"size";s:7:",,,tzid";s:5:"label";s:8:"Timezone";}s:1:"D";a:3:{s:4:"type";s:15:"select-timezone";s:4:"name";s:4:"tzid";s:4:"help";s:49:"Timezone in which recurrences have identical time";}}i:5;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:13:",,,recur_data";s:5:"label";s:11:"Repeat days";}s:1:"B";a:4:{s:4:"type";s:10:"select-dow";s:4:"size";s:3:"6,1";s:4:"name";s:10:"recur_data";s:4:"help";s:44:"Days of the week for a weekly repeated event";}s:1:"C";a:4:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:10:"Exceptions";}i:2;a:5:{s:4:"type";s:6:"button";s:4:"name";s:17:"button[exception]";s:5:"label";s:16:"@exception_label";s:4:"help";s:38:"Create an exception for the given date";s:7:"no_lang";s:1:"1";}}s:1:"D";a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:4:"$row";s:8:"readonly";s:1:"1";}s:1:"B";a:6:{s:4:"type";s:6:"button";s:5:"label";s:6:"Delete";s:4:"size";s:6:"delete";s:4:"name";s:27:"delete_exception[$row_cont]";s:4:"help";s:21:"Delete this exception";s:7:"onclick";s:40:"return confirm(\'Delete this exception\');";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"name";s:15:"recur_exception";s:7:"options";a:0:{}}}}s:4:"rows";i:5;s:4:"cols";i:4;s:4:"size";s:8:"100%,210";s:7:"options";a:2:{i:0;s:4:"100%";i:1;s:3:"210";}}}','size' => '100%,210','style' => '','modified' => '1210321464',); $templ_data[] = array('name' => 'calendar.export','template' => '','lang' => '','group' => '0','version' => '1.0.1.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:8:{i:0;a:1:{s:2:"h5";s:2:",1";}i:1;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:8:",,,start";s:5:"label";s:5:"Start";}s:1:"B";a:3:{s:4:"type";s:4:"date";s:4:"name";s:5:"start";s:4:"help";s:23:"Startdate of the export";}}i:3;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:6:",,,end";s:5:"label";s:3:"End";}s:1:"B";a:3:{s:4:"type";s:4:"date";s:4:"name";s:3:"end";s:4:"help";s:21:"Enddate of the export";}}i:4;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:7:",,,file";s:5:"label";s:8:"Filename";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"name";s:4:"file";s:4:"help";s:24:"Filename of the download";}}i:5;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:10:",,,version";s:5:"label";s:7:"Version";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:7:"version";}}i:6;a:2:{s:1:"A";a:1:{s:4:"type";s:5:"label";}s:1:"B";a:3:{s:4:"type";s:6:"button";s:5:"label";s:8:"Download";s:4:"name";s:8:"download";}}i:7;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:7;s:4:"cols";i:2;s:5:"align";s:6:"center";s:7:"options";a:0:{}}}','size' => '','style' => '','modified' => '1130738737',); diff --git a/calendar/setup/setup.inc.php b/calendar/setup/setup.inc.php index 0cde18a9e2..bca3601702 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'] = '1.7.003'; +$setup_info['calendar']['version'] = '1.7.005'; $setup_info['calendar']['app_order'] = 3; $setup_info['calendar']['enable'] = 1; $setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index'; @@ -68,3 +68,5 @@ $setup_info['calendar']['check_install'] = array( + + diff --git a/calendar/setup/tables_current.inc.php b/calendar/setup/tables_current.inc.php index 2876f69712..a0930be355 100644 --- a/calendar/setup/tables_current.inc.php +++ b/calendar/setup/tables_current.inc.php @@ -29,7 +29,8 @@ $phpgw_baseline = array( 'cal_etag' => array('type' => 'int','precision' => '4','default' => '0','comment' => 'etag for optimistic locking'), 'cal_creator' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'creating user'), 'cal_created' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'creation time of event'), - 'cal_recurrence' => array('type' => 'int','precision' => '8','nullable' => False,'default' => '0','comment' => 'cal_start of original recurrence for exception') + 'cal_recurrence' => array('type' => 'int','precision' => '8','nullable' => False,'default' => '0','comment' => 'cal_start of original recurrence for exception'), + 'tz_id' => array('type' => 'int','precision' => '4','comment' => 'key into egw_cal_timezones') ), 'pk' => array('cal_id'), 'fk' => array(), @@ -70,11 +71,12 @@ $phpgw_baseline = array( 'fd' => array( 'cal_id' => array('type' => 'int','precision' => '4','nullable' => False), 'cal_recur_date' => array('type' => 'int','precision' => '8','default' => '0'), - 'cal_user_type' => array('type' => 'varchar','precision' => '1','nullable' => False,'default' => 'u'), - 'cal_user_id' => array('type' => 'varchar','precision' => '128','nullable' => False), - 'cal_status' => array('type' => 'char','precision' => '1','default' => 'A'), - 'cal_quantity' => array('type' => 'int','precision' => '4','default' => '1'), - 'cal_role' => array('type' => 'varchar','precision' => '64','default' => 'REQ-PARTICIPANT') + 'cal_user_type' => array('type' => 'varchar','precision' => '1','nullable' => False,'default' => 'u','comment' => 'u=user, g=group, c=contact, r=resource, e=email'), + 'cal_user_id' => array('type' => 'varchar','precision' => '128','nullable' => False,'comment' => 'id or email-address for type=e'), + 'cal_status' => array('type' => 'char','precision' => '1','default' => 'A','comment' => 'U=unknown, A=accepted, R=rejected, T=tentative'), + 'cal_quantity' => array('type' => 'int','precision' => '4','default' => '1','comment' => 'only for certain types (eg. resources)'), + 'cal_role' => array('type' => 'varchar','precision' => '64','default' => 'REQ-PARTICIPANT','comment' => 'CHAIR, REQ-PARTICIPANT, OPT-PARTICIPANT, NON-PARTICIPANT, X-CAT-$cat_id'), + 'cal_user_modified' => array('type' => 'timestamp','default' => 'current_timestamp','comment' => 'automatic timestamp of last update') ), 'pk' => array('cal_id','cal_recur_date','cal_user_type','cal_user_id'), 'fk' => array(), @@ -95,8 +97,8 @@ $phpgw_baseline = array( 'egw_cal_dates' => array( 'fd' => array( 'cal_id' => array('type' => 'int','precision' => '4','nullable' => False), - 'cal_start' => array('type' => 'int','precision' => '8','nullable' => False), - 'cal_end' => array('type' => 'int','precision' => '8','nullable' => False) + 'cal_start' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'starttime in server time'), + 'cal_end' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'endtime in server time') ), 'pk' => array('cal_id','cal_start'), 'fk' => array(), diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index ad5d1b2775..c1f618aa78 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -1630,7 +1630,11 @@ function calendar_upgrade1_5_002() return $GLOBALS['setup_info']['calendar']['currentver'] = '1.6'; } - +/** + * Adding column for recurrence time of master event to improve iCal handling of exceptions + * + * @return string + */ function calendar_upgrade1_6() { $GLOBALS['egw_setup']->oProc->AddColumn('egw_cal','cal_creator',array( @@ -1691,7 +1695,11 @@ function calendar_upgrade1_6() return $GLOBALS['setup_info']['calendar']['currentver'] = '1.7.001'; } - +/** + * Adding participant roles table to improve iCal support + * + * @return string + */ function calendar_upgrade1_7_001() { $GLOBALS['egw_setup']->oProc->AddColumn('egw_cal_user','cal_role',array( @@ -1703,7 +1711,11 @@ function calendar_upgrade1_7_001() return $GLOBALS['setup_info']['calendar']['currentver'] = '1.7.002'; } - +/** + * Adding timezones table egw_cal_timezones + * + * @return string + */ function calendar_upgrade1_7_002() { $GLOBALS['egw_setup']->oProc->CreateTable('egw_cal_timezones',array( @@ -1726,3 +1738,83 @@ function calendar_upgrade1_7_002() return $GLOBALS['setup_info']['calendar']['currentver'] = '1.7.003'; } +/** + * Adding automatic timestamp for participant table, maximum can be used as part of a ctag for CalDAV + * + * @return string + */ +function calendar_upgrade1_7_003() +{ + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_user','cal_user_type',array( + 'type' => 'varchar', + 'precision' => '1', + 'nullable' => False, + 'default' => 'u', + 'comment' => 'u=user, g=group, c=contact, r=resource, e=email' + )); + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_user','cal_user_id',array( + 'type' => 'varchar', + 'precision' => '128', + 'nullable' => False, + 'comment' => 'id or email-address for type=e' + )); + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_user','cal_status',array( + 'type' => 'char', + 'precision' => '1', + 'default' => 'A', + 'comment' => 'U=unknown, A=accepted, R=rejected, T=tentative' + )); + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_user','cal_quantity',array( + 'type' => 'int', + 'precision' => '4', + 'default' => '1', + 'comment' => 'only for certain types (eg. resources)' + )); + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_user','cal_role',array( + 'type' => 'varchar', + 'precision' => '64', + 'default' => 'REQ-PARTICIPANT', + 'comment' => 'CHAIR, REQ-PARTICIPANT, OPT-PARTICIPANT, NON-PARTICIPANT, X-CAT-$cat_id' + )); + $GLOBALS['egw_setup']->oProc->AddColumn('egw_cal_user','cal_user_modified',array( + 'type' => 'timestamp', + 'default' => 'current_timestamp', + 'comment' => 'automatic timestamp of last update' + )); + + return $GLOBALS['setup_info']['calendar']['currentver'] = '1.7.004'; +} + +/** + * Adding timezone id column, to fully support timezones in calendar + * + * @return string + */ +function calendar_upgrade1_7_004() +{ + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_dates','cal_start',array( + 'type' => 'int', + 'precision' => '8', + 'nullable' => False, + 'comment' => 'starttime in server time' + )); + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal_dates','cal_end',array( + 'type' => 'int', + 'precision' => '8', + 'nullable' => False, + 'comment' => 'endtime in server time' + )); + $GLOBALS['egw_setup']->oProc->AddColumn('egw_cal','tz_id',array( + 'type' => 'int', + 'precision' => '4', + 'comment' => 'key into egw_cal_timezones' + )); + + // set id of server timezone for existing events, as that's the timezone their recurrences are using + if (($tzid = date_default_timezone_get()) && ($tz_id = calendar_timezones::tz2id($tzid))) + { + $GLOBALS['egw_setup']->db->query('UPDATE egw_cal SET tz_id='.(int)$tz_id,__LINE__,__FILE__); + } + return $GLOBALS['setup_info']['calendar']['currentver'] = '1.7.005'; +} + diff --git a/calendar/templates/default/edit.xet b/calendar/templates/default/edit.xet index a5291eb1e1..33f77d93bc 100644 --- a/calendar/templates/default/edit.xet +++ b/calendar/templates/default/edit.xet @@ -119,7 +119,7 @@ .selectRole select { width: 100%; } -