mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 16:03:47 +01:00
* Calendar: fixed issue of deleted first recurrence shortens event and causes it not to be find in CalDAV or eSync ("event has exceptions before startdate"), REQUIRES SCHEMA UPDATE (visit setup)!
This commit is contained in:
parent
4c3c423b3d
commit
56a4bdfbbe
@ -1404,6 +1404,7 @@ class calendar_boupdate extends calendar_bo
|
||||
*/
|
||||
function delete($cal_id,$recur_date=0,$ignore_acl=false,$skip_notification=false)
|
||||
{
|
||||
//error_log(__METHOD__."(cal_id=$cal_id, recur_date=$recur_date, ignore_acl=$ignore_acl, skip_notifications=$skip_notification)");
|
||||
if (!($event = $this->read($cal_id,$recur_date)) ||
|
||||
!$ignore_acl && !$this->check_perms(EGW_ACL_DELETE,$event))
|
||||
{
|
||||
@ -1446,7 +1447,10 @@ class calendar_boupdate extends calendar_bo
|
||||
}
|
||||
else // delete an exception
|
||||
{
|
||||
$event['recur_exception'][] = $recur_date = $this->date2ts($event['start']);
|
||||
// need to read series master, as otherwise existing exceptions will be lost!
|
||||
$recur_date = $this->date2ts($event['start']);
|
||||
$event = $this->read($cal_id);
|
||||
$event['recur_exception'][] = $recur_date;
|
||||
unset($event['start']);
|
||||
unset($event['end']);
|
||||
$this->save($event); // updates the content-history
|
||||
|
@ -60,7 +60,7 @@ define('WEEK_s',7*DAY_s);
|
||||
* - egw_cal_repeats: recur-data: type, optional enddate, etc.
|
||||
* - egw_cal_extra: custom fields (multiple entries per cal_id possible)
|
||||
*
|
||||
* The new UI, BO and SO classes have a strikt definition, in which time-zone they operate:
|
||||
* The new UI, BO and SO classes have a strict definition, in which timezone they operate:
|
||||
* UI only operates in user-time, so there have to be no conversation at all !!!
|
||||
* BO's functions take and return user-time only (!), they convert internaly everything to servertime, because
|
||||
* SO operates only on server-time
|
||||
@ -178,9 +178,8 @@ class calendar_so
|
||||
",$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)
|
||||
{
|
||||
$row['recur_exception'] = $row['recur_exception'] ? explode(',',$row['recur_exception']) : array();
|
||||
if (!$row['recur_type']) $row['recur_type'] = MCAL_RECUR_NONE;
|
||||
$row['alarm'] = array();
|
||||
$row['recur_exception'] = $row['alarm'] = array();
|
||||
$events[$row['cal_id']] = egw_db::strip_array_keys($row,'cal_');
|
||||
|
||||
// if a uid was supplied, convert it for the further code to an id
|
||||
@ -193,28 +192,21 @@ class calendar_so
|
||||
if (!isset($event['uid']) || strlen($event['uid']) < $minimum_uid_length)
|
||||
{
|
||||
// event (without uid), not strong enough uid => create new uid
|
||||
$event['uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$event['id']);
|
||||
$event['uid'] = common::generate_uid('calendar',$event['id']);
|
||||
$this->db->update($this->cal_table, array('cal_uid' => $event['uid']),
|
||||
array('cal_id' => $event['id']),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
if ((int) $recur_date == 0 &&
|
||||
$event['recur_type'] != MCAL_RECUR_NONE &&
|
||||
!empty($event['recur_exception']))
|
||||
if (!(int)$recur_date && $event['recur_type'] != MCAL_RECUR_NONE)
|
||||
{
|
||||
sort($event['recur_exception']);
|
||||
if ($event['recur_exception'][0] < $event['start'])
|
||||
foreach($this->db->select($this->dates_table, 'cal_id,cal_start', array(
|
||||
'cal_id' => $ids,
|
||||
'recur_exception' => true,
|
||||
), __LINE__, __FILE__, false, 'ORDER BY cal_id,cal_start', 'calendar') as $row)
|
||||
{
|
||||
/* Do NOT move start- and end-date, to the earliest exception, as they will NOT be found in CalDAV or ActiveSync, because
|
||||
* we only recognice recuring events which start before or in the current timerange and end in or after it or have no end-date.
|
||||
* --> give an error message, as it is a debuging/support nightmare, if this get's silently fixed when reading events.
|
||||
* No idea how this situation (exceptions before startdate) can be created anyway.
|
||||
*
|
||||
* $event['end'] -= $event['start'] - $event['recur_exception'][0];
|
||||
* $event['start'] = $event['recur_exception'][0];
|
||||
*/
|
||||
error_log(__METHOD__."() recuring event #$event[id]: $event[title] has exceptions before it's startdate ".date('Y-m-d H:i:s',$event['start']));
|
||||
$events[$row['cal_id']]['recur_exception'][] = $row['cal_start'];
|
||||
}
|
||||
}//*/
|
||||
break; // as above select read all exceptions (and I dont think too short uid problem still exists)
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have a real recurance, if not set $recur_date=0
|
||||
@ -424,7 +416,7 @@ class calendar_so
|
||||
|
||||
$cols = self::get_columns('calendar', $this->cal_table);
|
||||
$cols[0] = $this->db->to_varchar($this->cal_table.'.cal_id');
|
||||
$cols = isset($params['cols']) ? $params['cols'] : "$this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,$this->repeats_table.recur_exception,".implode(',',$cols).",cal_start,cal_end,$this->user_table.cal_recur_date";
|
||||
$cols = isset($params['cols']) ? $params['cols'] : "$this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,".implode(',',$cols).",cal_start,cal_end,$this->user_table.cal_recur_date";
|
||||
|
||||
$where = array();
|
||||
if (is_array($params['query']))
|
||||
@ -639,7 +631,7 @@ class calendar_so
|
||||
// we only select cal_table.cal_id (and not cal_table.*) to be able to use DISTINCT (eg. MsSQL does not allow it for text-columns)
|
||||
foreach(array_keys($selects) as $key)
|
||||
{
|
||||
$selects[$key]['cols'] = "DISTINCT $this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,$this->repeats_table.recur_exception,".$this->db->to_varchar($this->cal_table.'.cal_id').",cal_start,cal_end,$this->user_table.cal_recur_date";
|
||||
$selects[$key]['cols'] = "DISTINCT $this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,".$this->db->to_varchar($this->cal_table.'.cal_id').",cal_start,cal_end,$this->user_table.cal_recur_date";
|
||||
if (!$params['enum_recuring'])
|
||||
{
|
||||
$selects[$key]['cols'] = str_replace('cal_start','MIN(cal_start) AS cal_start',$selects[$key]['cols']);
|
||||
@ -698,8 +690,7 @@ class calendar_so
|
||||
{
|
||||
$row['participants'] = array();
|
||||
}
|
||||
$row['alarm'] = array();
|
||||
$row['recur_exception'] = $row['recur_exception'] ? explode(',',$row['recur_exception']) : array();
|
||||
$row['recur_exception'] = $row['alarm'] = array();
|
||||
|
||||
// compile a list of recurrences per cal_id
|
||||
if (!in_array($id,(array)$recur_ids[$row['cal_id']])) $recur_ids[$row['cal_id']][] = $id;
|
||||
@ -755,6 +746,20 @@ class calendar_so
|
||||
$events[$id]['max_user_modified'] = $modified;
|
||||
}
|
||||
}
|
||||
// query recurrance exceptions, if needed
|
||||
if (!$params['enum_recuring'])
|
||||
{
|
||||
foreach($this->db->select($this->dates_table, 'cal_id,cal_start', array(
|
||||
'cal_id' => $ids,
|
||||
'recur_exception' => true,
|
||||
), __LINE__, __FILE__, false, 'ORDER BY cal_id,cal_start', 'calendar') as $row)
|
||||
{
|
||||
foreach((array)$recur_ids[$row['cal_id']] as $i)
|
||||
{
|
||||
$events[$i]['recurce_id'][] = $row['cal_start'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// max_user_modified for recurring events has to include all recurrences, above code only querys $recur_date!
|
||||
if (!$params['enum_recuring'] && $need_max_user_modified)
|
||||
{
|
||||
@ -1070,7 +1075,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
// event without uid or not strong enough uid
|
||||
if (!isset($event['cal_uid']) || strlen($event['cal_uid']) < $minimum_uid_length)
|
||||
{
|
||||
$update['cal_uid'] = $event['cal_uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$cal_id);
|
||||
$update['cal_uid'] = $event['cal_uid'] = common::generate_uid('calendar',$cal_id);
|
||||
}
|
||||
// set caldav_name, if not given by caller
|
||||
if (empty($event['caldav_name']) && version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.003', '>='))
|
||||
@ -1103,11 +1108,13 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
$old_min = (int) $this->db->select($this->dates_table,'MIN(cal_start)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchColumn();
|
||||
$old_duration = (int) $this->db->select($this->dates_table,'MIN(cal_end)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchColumn() - $old_min;
|
||||
$old_repeats = $this->db->select($this->repeats_table,'*',array('cal_id' => $cal_id),__LINE__,__FILE__,false,'','calendar')->fetch();
|
||||
$old_exceptions = $old_repeats['recur_exception'] ? explode(',',$old_repeats['recur_exception']) : array();
|
||||
if (!empty($old_exceptions))
|
||||
$old_exceptions = array();
|
||||
foreach($this->db->select($this->dates_table, 'cal_start', array(
|
||||
'cal_id' => $cal_id,
|
||||
'recur_exception' => true
|
||||
), __LINE__, __FILE__, false, 'ORDER BY cal_start', 'calendar') as $row)
|
||||
{
|
||||
sort($old_exceptions);
|
||||
if ($old_min > $old_exceptions[0]) $old_min = $old_exceptions[0];
|
||||
$old_exceptions[] = $row['cal_start'];
|
||||
}
|
||||
|
||||
$event['recur_exception'] = is_array($event['recur_exception']) ? $event['recur_exception'] : array();
|
||||
@ -1116,8 +1123,10 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
sort($event['recur_exception']);
|
||||
}
|
||||
|
||||
$where = array('cal_id' => $cal_id,
|
||||
'cal_recur_date' => 0);
|
||||
$where = array(
|
||||
'cal_id' => $cal_id,
|
||||
'cal_recur_date' => 0,
|
||||
);
|
||||
$old_participants = array();
|
||||
foreach ($this->db->select($this->user_table,'cal_user_type,cal_user_id,cal_status,cal_quantity,cal_role', $where,
|
||||
__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
@ -1197,14 +1206,18 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
// truncate recurrences by given exceptions
|
||||
if (count($event['recur_exception']))
|
||||
{
|
||||
// added and existing exceptions: delete the execeptions from the user and dates table, it could be the first time
|
||||
// added and existing exceptions: delete the execeptions from the user table, it could be the first time
|
||||
$this->db->delete($this->user_table,array('cal_id' => $cal_id,'cal_recur_date' => $event['recur_exception']),__LINE__,__FILE__,'calendar');
|
||||
$this->db->delete($this->dates_table,array('cal_id' => $cal_id,'cal_start' => $event['recur_exception']),__LINE__,__FILE__,'calendar');
|
||||
// update recur_exception flag based on current exceptions
|
||||
$this->db->update($this->dates_table, 'recur_exception='.$this->db->expression($this->dates_table,array(
|
||||
'cal_start' => $event['recur_exception'],
|
||||
)), array(
|
||||
'cal_id' => $cal_id,
|
||||
), __LINE__, __FILE__, 'calendar');
|
||||
}
|
||||
}
|
||||
|
||||
// write the repeats table
|
||||
$event['recur_exception'] = empty($event['recur_exception']) ? null : implode(',',$event['recur_exception']);
|
||||
unset($event[0]); // unset the 'etag=etag+1', as it's not in the repeats table
|
||||
$this->db->insert($this->repeats_table,$event,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
$setup_info['calendar']['name'] = 'calendar';
|
||||
$setup_info['calendar']['version'] = '1.9.004';
|
||||
$setup_info['calendar']['version'] = '1.9.005';
|
||||
$setup_info['calendar']['app_order'] = 3;
|
||||
$setup_info['calendar']['enable'] = 1;
|
||||
$setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index';
|
||||
@ -70,3 +70,4 @@ $setup_info['calendar']['check_install'] = array(
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
@ -62,7 +62,6 @@ $phpgw_baseline = array(
|
||||
'recur_enddate' => array('type' => 'int','precision' => '8'),
|
||||
'recur_interval' => array('type' => 'int','precision' => '2','default' => '1'),
|
||||
'recur_data' => array('type' => 'int','precision' => '2','default' => '1'),
|
||||
'recur_exception' => array('type' => 'text','comment' => 'comma-separated start timestamps of exceptions')
|
||||
),
|
||||
'pk' => array('cal_id'),
|
||||
'fk' => array(),
|
||||
@ -100,11 +99,12 @@ $phpgw_baseline = array(
|
||||
'fd' => array(
|
||||
'cal_id' => array('type' => 'int','precision' => '4','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')
|
||||
'cal_end' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'endtime in server time'),
|
||||
'recur_exception' => array('type' => 'bool','nullable' => False,'default' => '','comment' => 'date is an exception')
|
||||
),
|
||||
'pk' => array('cal_id','cal_start'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'ix' => array(array('recur_exception','cal_id')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_cal_timezones' => array(
|
||||
|
@ -2076,3 +2076,54 @@ function calendar_upgrade1_9_003()
|
||||
|
||||
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.004';
|
||||
}
|
||||
|
||||
/**
|
||||
* Store exceptions as flag in egw_cal_dates.recur_exception, instead of egw_cal_repleats.recur_exception
|
||||
*
|
||||
* Keeps information of original start in egw_cal_dates (if first recurrance got deleted) and allows for unlimited number of exceptions.
|
||||
*/
|
||||
function calendar_upgrade1_9_004()
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->AddColumn('egw_cal_dates','recur_exception',array(
|
||||
'type' => 'bool',
|
||||
'default' => '',
|
||||
'null' => false,
|
||||
'comment' => 'date is an exception'
|
||||
));
|
||||
|
||||
// migrate existing exceptions to egw_cal_dates
|
||||
foreach($GLOBALS['egw_setup']->db->select('egw_cal_repeats',
|
||||
'egw_cal_repeats.cal_id AS cal_id,egw_cal_repeats.recur_exception AS recur_exception,MIN(cal_start) AS cal_start,MIN(cal_end) AS cal_end',
|
||||
'egw_cal_repeats.recur_exception IS NOT NULL', __LINE__, __FILE__, false,
|
||||
'GROUP BY egw_cal_repeats.cal_id,egw_cal_repeats.recur_exception', 'calendar', '',
|
||||
'JOIN egw_cal_dates ON egw_cal_repeats.cal_id=egw_cal_dates.cal_id') as $row)
|
||||
{
|
||||
foreach($row['recur_exception'] ? explode(',', $row['recur_exception']) : array() as $recur_exception)
|
||||
{
|
||||
$GLOBALS['egw_setup']->db->insert('egw_cal_dates', array(
|
||||
'cal_id' => $row['cal_id'],
|
||||
'cal_start' => $recur_exception,
|
||||
'cal_end' => $recur_exception+$row['cal_end']-$row['cal_start'],
|
||||
'recur_exception' => true,
|
||||
), false, __LINE__, __FILE__, 'calendar');
|
||||
}
|
||||
}
|
||||
$GLOBALS['egw_setup']->oProc->CreateIndex('egw_cal_dates', array('recur_exception', 'cal_id'));
|
||||
|
||||
$GLOBALS['egw_setup']->oProc->DropColumn('egw_cal_repeats', array(
|
||||
'fd' => array(
|
||||
'cal_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'recur_type' => array('type' => 'int','precision' => '2','nullable' => False),
|
||||
'recur_enddate' => array('type' => 'int','precision' => '8'),
|
||||
'recur_interval' => array('type' => 'int','precision' => '2','default' => '1'),
|
||||
'recur_data' => array('type' => 'int','precision' => '2','default' => '1'),
|
||||
),
|
||||
'pk' => array('cal_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
), 'recur_exception');
|
||||
|
||||
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.005';
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user