New tz_id column in egw_cal storing id into egw_cal_timezones

Please note: timestamps in egw_cal* tables are in server-time,
tz_id / timezone is only used to (re-)calculate recurrences and to
export in iCals (NOT yet implemented)
This commit is contained in:
Ralf Becker 2009-11-04 15:00:08 +00:00
parent b70d208d3f
commit 4e9120ecf0
10 changed files with 145 additions and 204 deletions

View File

@ -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 "<p>bocal::db2data(\$events,$date_format) \$events is no array<br />\n".function_backtrace()."</p>\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));
*/
}
/**

View File

@ -639,7 +639,7 @@ class calendar_boupdate extends calendar_bo
//echo "<p>bocalendar::send_alarm("; print_r($alarm); echo ")</p>\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']))
{

View File

@ -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 "<p>socal::move($cal_id,$start,$end,$change_since,$old_start,$old_end)</p>\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();

View File

@ -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

View File

@ -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

View File

@ -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',);

View File

@ -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(

View File

@ -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(),

View File

@ -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';
}

View File

@ -119,7 +119,7 @@
.selectRole select { width: 100%; }
</styles>
</template>
<template id="calendar.edit.recurrence" template="" lang="" group="0" version="1.7.001">
<template id="calendar.edit.recurrence" template="" lang="" group="0" version="1.7.002">
<grid>
<columns>
<column width="95"/>
@ -152,7 +152,11 @@
</row>
<row class="row" height="12">
<description options=",,,recur_enddate" value="End date"/>
<date id="recur_enddate" statustext="repeat the event until which date (empty means unlimited)" span="all"/>
<date id="recur_enddate" statustext="repeat the event until which date (empty means unlimited)"/>
<description options=",,,tzid" value="Timezone"/>
<menulist>
<menupopup type="select-timezone" id="tzid" statustext="Timezone in which recurrences have identical time"/>
</menulist>
</row>
<row class="row" valign="top">
<description options=",,,recur_data" value="Repeat days"/>