mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-23 16:33:17 +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)!
r40103: * Calendar: Try alter description to varchar(16384), to not force temp. tables to disk on MySQL (because of text columns) r40112: MAX(CHAR_LENGTH(cal_description)) returns NULL, if there are no rows --> casting to int
This commit is contained in:
parent
aa253ea9d6
commit
9898162a65
@ -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,27 +192,20 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.006';
|
||||
$setup_info['calendar']['app_order'] = 3;
|
||||
$setup_info['calendar']['enable'] = 1;
|
||||
$setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index';
|
||||
@ -68,5 +68,3 @@ $setup_info['calendar']['check_install'] = array(
|
||||
'from' => 'Calendar',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
@ -15,12 +15,12 @@ $phpgw_baseline = array(
|
||||
'cal_id' => array('type' => 'auto','nullable' => False),
|
||||
'cal_uid' => array('type' => 'varchar','precision' => '255','nullable' => False,'comment' => 'unique id of event(-series)'),
|
||||
'cal_owner' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'event owner / calendar'),
|
||||
'cal_category' => array('type' => 'varchar','precision' => '30','comment' => 'category id'),
|
||||
'cal_category' => array('type' => 'varchar','precision' => '64','comment' => 'category id(s)'),
|
||||
'cal_modified' => array('type' => 'int','precision' => '8','comment' => 'ts of last modification'),
|
||||
'cal_priority' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '2'),
|
||||
'cal_public' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '1','comment' => '1=public, 0=private event'),
|
||||
'cal_title' => array('type' => 'varchar','precision' => '255','nullable' => False,'default' => '1'),
|
||||
'cal_description' => array('type' => 'text'),
|
||||
'cal_title' => array('type' => 'varchar','precision' => '255','nullable' => False),
|
||||
'cal_description' => array('type' => 'varchar','precision' => '16384'),
|
||||
'cal_location' => array('type' => 'varchar','precision' => '255'),
|
||||
'cal_reference' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'cal_id of series for exception'),
|
||||
'cal_modifier' => array('type' => 'int','precision' => '4','comment' => 'user who last modified event'),
|
||||
@ -61,8 +61,7 @@ $phpgw_baseline = array(
|
||||
'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'),
|
||||
'recur_exception' => array('type' => 'text','comment' => 'comma-separated start timestamps of exceptions')
|
||||
'recur_data' => array('type' => 'int','precision' => '2','default' => '1')
|
||||
),
|
||||
'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,84 @@ 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';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try alter description to varchar(16384), to not force temp. tables to disk on MySQL (because of text columns)
|
||||
*/
|
||||
function calendar_upgrade1_9_005()
|
||||
{
|
||||
// only alter description to varchar(16384), if it does NOT contain longer input and it can be stored as varchar
|
||||
$max_description_length = $GLOBALS['egw']->db->query('SELECT MAX(CHAR_LENGTH(cal_description)) FROM egw_cal')->fetchColumn();
|
||||
// returns NULL, if there are no rows!
|
||||
if ((int)$max_description_length <= 16384 && $GLOBALS['egw_setup']->oProc->max_varchar_length >= 16384)
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_description',array(
|
||||
'type' => 'varchar',
|
||||
'precision' => '16384'
|
||||
));
|
||||
}
|
||||
// allow more categories
|
||||
$GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_category',array(
|
||||
'type' => 'varchar',
|
||||
'precision' => '64',
|
||||
'comment' => 'category id(s)'
|
||||
));
|
||||
// remove silly default of 1
|
||||
$GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_title',array(
|
||||
'type' => 'varchar',
|
||||
'precision' => '255',
|
||||
'nullable' => False
|
||||
));
|
||||
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.006';
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user