manually insert or truncate the recurrences when changing enddate. recurrences rebuild (and stati reset) is now minimized to the following cases: move startdate/enddate, change recur_type, change recur_interval

This commit is contained in:
Christian Binder 2009-08-10 09:24:39 +00:00
parent ae855c4979
commit 77de24e563
3 changed files with 77 additions and 48 deletions

View File

@ -16,10 +16,6 @@ if (!defined('ACL_TYPE_IDENTIFER')) // used to mark ACL-values for the debug_mes
define('ACL_TYPE_IDENTIFER','***ACL***');
}
define('HOUR_s',60*60);
define('DAY_s',24*HOUR_s);
define('WEEK_s',7*DAY_s);
/**
* Gives read access to the calendar, but all events the user is not participating are private!
* Used by addressbook.

View File

@ -715,10 +715,13 @@ class calendar_boupdate extends calendar_bo
}
}
$set_recurrences = false;
if (($cal_id = $this->so->save($event,$set_recurrences,0,$event['etag'])) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE)
$set_recurrences_start = 0;
if (($cal_id = $this->so->save($event,$set_recurrences,$set_recurrences_start,0,$event['etag'])) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE)
{
$save_event['id'] = $cal_id;
$this->set_recurrences($save_event, 0);
// unset participants to enforce the default stati for all added recurrences
unset($save_event['participants']);
$this->set_recurrences($save_event, $set_recurrences_start);
}
$GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id,$event['id'] ? 'modify' : 'add',time());

View File

@ -44,6 +44,10 @@ define('NO_RESPONSE',1);
define('TENTATIVE',2);
define('ACCEPTED',3);
define('HOUR_s',60*60);
define('DAY_s',24*HOUR_s);
define('WEEK_s',7*DAY_s);
/**
* Class to store all calendar data (storage object)
*
@ -498,11 +502,12 @@ ORDER BY cal_user_type, cal_usre_id
*
* @param array $event
* @param boolean &$set_recurrences on return: true if the recurrences need to be written, false otherwise
* @param int &$set_recurrences_start=0 on return: time from which on the recurrences should be rebuilt, default 0=all
* @param int $change_since=0 time from which on the repetitions should be changed, default 0=all
* @param int &$etag etag=null etag to check or null, on return new etag
* @return boolean|int false on error, 0 if etag does not match, cal_id otherwise
*/
function save($event,&$set_recurrences,$change_since=0,&$etag=null)
function save($event,&$set_recurrences,&$set_recurrences_start=0,$change_since=0,&$etag=null)
{
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length']))
{
@ -577,56 +582,19 @@ ORDER BY cal_user_type, cal_usre_id
$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 (isset($event['recur_exception']) && is_array($event['recur_exception']) && count($event['recur_exception']))
{
// added and existing exceptions: delete the execeptions from the user and dates 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');
}
else
{
$event['recur_exception'] = array();
}
// deleted exceptions: re-insert recurrences into the user and dates table
if(count($deleted_exceptions = array_diff($old_exceptions,$event['recur_exception'])))
{
foreach($deleted_exceptions as $id => $deleted_exception)
{
// rebuild participants for the re-inserted recurrence
$participants = array();
$participants_only = $this->get_participants($cal_id); // participants without states
foreach($participants_only as $id => $participant_only)
{
$states = $this->get_recurrences($cal_id, $participant_only['uid']);
$participants[$participant_only['uid']] = $states[0]; // insert main status as default
}
$this->recurrence($cal_id, $deleted_exception, $deleted_exception + $old_duration, $participants);
}
}
$event['recur_exception'] = is_array($event['recur_exception']) ? $event['recur_exception'] : array();
// re-check: did so much recurrence data change that we have to rebuild it from scratch?
if (!$set_recurrences)
{
// check if the recurrence-information changed
$set_recurrences = (isset($event['cal_start']) && (int)$old_min != (int) $event['cal_start']) ||
$event['recur_type'] != $old_repeats['recur_type'] || $event['recur_data'] != $old_repeats['recur_data'] ||
(int)$event['recur_interval'] != (int)$old_repeats['recur_interval'] ||
$event['recur_enddate'] != $old_repeats['recur_enddate'];
// ToDo jaytraxx: manually handle recur_enddate change without recurrences rebuild
(int)$event['recur_interval'] != (int)$old_repeats['recur_interval'];
}
$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
if($event['recur_type'] != MCAL_RECUR_NONE)
{
$this->db->insert($this->repeats_table,$event,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
}
else
{
$this->db->delete($this->repeats_table,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
}
if ($set_recurrences)
{
// too much recurrence data has changed, we have to do a rebuild from scratch
// delete all, but the lowest dates record
$this->db->delete($this->dates_table,array(
'cal_id' => $cal_id,
@ -639,6 +607,68 @@ ORDER BY cal_user_type, cal_usre_id
'cal_recur_date != 0',
),__LINE__,__FILE__,'calendar');
}
else
{
// we adjust some possibly changed recurrences manually
// deleted exceptions: re-insert recurrences into the user and dates table
if(count($deleted_exceptions = array_diff($old_exceptions,$event['recur_exception'])))
{
foreach($deleted_exceptions as $id => $deleted_exception)
{
// rebuild participants for the re-inserted recurrence
$participants = array();
$participants_only = $this->get_participants($cal_id); // participants without states
foreach($participants_only as $id => $participant_only)
{
$states = $this->get_recurrences($cal_id, $participant_only['uid']);
$participants[$participant_only['uid']] = $states[0]; // insert main status as default
}
$this->recurrence($cal_id, $deleted_exception, $deleted_exception + $old_duration, $participants);
}
}
// check if recurrence enddate was adjusted
if(isset($event['recur_enddate']))
{
// recurrences need to be truncated
if((int)$event['recur_enddate'] > 0 &&
((int)$old_repeats['recur_enddate'] == 0 || (int)$old_repeats['recur_enddate'] > (int)$event['recur_enddate'])
)
{
$this->db->delete($this->user_table,array('cal_id' => $cal_id,'cal_recur_date > '.($event['recur_enddate'] + 1*DAY_s)),__LINE__,__FILE__,'calendar');
$this->db->delete($this->dates_table,array('cal_id' => $cal_id,'cal_start > '.($event['recur_enddate'] + 1*DAY_s)),__LINE__,__FILE__,'calendar');
}
// recurrences need to be expanded
if(((int)$event['recur_enddate'] == 0 && (int)$old_repeats['recur_enddate'] > 0)
|| ((int)$event['recur_enddate'] > 0 && (int)$old_repeats['recur_enddate'] > 0 && (int)$old_repeats['recur_enddate'] < (int)$event['recur_enddate'])
)
{
$set_recurrences = true;
$set_recurrences_start = ($old_repeats['recur_enddate'] + 1*DAY_s);
}
}
// 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
$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');
}
}
// 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
if($event['recur_type'] != MCAL_RECUR_NONE)
{
$this->db->insert($this->repeats_table,$event,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
}
else
{
$this->db->delete($this->repeats_table,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar');
}
}
// 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']))