* Calendar/CalDAV/eSync: tracking participant status changes now in modified date and user of calendar entry (main table), fixes sometimes not synced status changes and simplifies code a lot

This commit is contained in:
Ralf Becker 2012-09-25 14:40:17 +00:00
parent 5486b8a03f
commit 41470de3b4
6 changed files with 40 additions and 115 deletions

View File

@ -631,7 +631,6 @@ class calendar_bo
'owner' => $event['owner'],
'recur_type' => MCAL_RECUR_NONE,
'etag' => $event['etag'],
'max_user_modified' => $event['max_user_modified'],
'participants' => array_intersect_key($event['participants'],array_flip($allowed_participants)),
'public'=> 0,
'category' => $event['category'], // category is visible anyway, eg. by using planner by cat
@ -803,11 +802,11 @@ class calendar_bo
$time->setTime(23, 59, 59);
$event['recur_enddate'] = egw_time::to($time, $date_format);
}
$timestamps = array('modified','created','max_user_modified');
$timestamps = array('modified','created');
}
else
{
$timestamps = array('start','end','modified','created','recur_enddate','recurrence','max_user_modified');
$timestamps = array('start','end','modified','created','recur_enddate','recurrence');
}
// we convert here from the server-time timestamps to user-time and (optional) to a different date-format!
foreach ($timestamps as $ts)
@ -1931,18 +1930,8 @@ class calendar_bo
if (!$this->check_perms(EGW_ACL_FREEBUSY, $entry, 0, 'server')) return false;
$entry = $this->read($entry, $recur_date, true, 'server');
}
$etag = $schedule_tag = $entry['id'].':'.$entry['etag'];
$etag = $schedule_tag = $entry['id'].':'.$entry['etag'].':'.$entry['modified'];
// use new MAX(modification date) of egw_cal_user table (deals with virtual exceptions too)
if (isset($entry['max_user_modified']))
{
$modified = max($entry['max_user_modified'], $entry['modified']);
}
else
{
$modified = max($this->so->max_user_modified($entry['id'],false,$master_only), $entry['modified']);
}
$etag .= ':' . $modified;
// include exception etags into our own etag, if exceptions are included
if ($client_share_uid_excpetions && !empty($entry['uid']) &&
$entry['recur_type'] != MCAL_RECUR_NONE && $entry['recur_exception'])

View File

@ -232,7 +232,7 @@ class calendar_groupdav extends groupdav_handler
$props = array(
'getcontenttype' => $this->agent != 'kde' ? 'text/calendar; charset=utf-8; component=VEVENT' : 'text/calendar',
'getetag' => '"'.$etag.'"',
'getlastmodified' => max($event['modified'], $event['max_user_modified']),
'getlastmodified' => $event['modified'],
);
if ($this->use_schedule_tag)
{
@ -1215,15 +1215,17 @@ class calendar_groupdav extends groupdav_handler
}
$props['supported-calendar-component-set'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,
'supported-calendar-component-set',$supported_components);
$props['supported-report-set'] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
HTTP_WebDAV_Server::mkprop('supported-report',array(
$props['supported-report-set'] = array(
'calendar-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
HTTP_WebDAV_Server::mkprop('report',array(
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-query',''))),
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-query',''))))),
'calendar-multiget' => HTTP_WebDAV_Server::mkprop('supported-report',array(
HTTP_WebDAV_Server::mkprop('report',array(
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget',''))),
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget',''))))),
'free-busy-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
HTTP_WebDAV_Server::mkprop('report',array(
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'free-busy-query',''))),
))));
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'free-busy-query',''))))),
);
$props['supported-calendar-data'] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'supported-calendar-data',array(
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data', array('content-type' => 'text/calendar', 'version'=> '2.0')),
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data', array('content-type' => 'text/x-calendar', 'version'=> '1.0'))));

View File

@ -856,11 +856,7 @@ class calendar_ical extends calendar_boupdate
{
$attributes['CREATED'] = $event['created'] ? $event['created'] : $event['modified'];
}
if ($event['max_user_modified'])
{
$attributes['LAST-MODIFIED'] = max($event['modified'], $event['max_user_modified']);
}
elseif ($event['modified'])
if ($event['modified'])
{
$attributes['LAST-MODIFIED'] = $event['modified'];
}

View File

@ -241,7 +241,6 @@ class calendar_so
}
}
$need_max_user_modified = array();
// participants, if a recur_date give, we read that recurance, plus the one users from the default entry with recur_date=0
// sorting by cal_recur_date ASC makes sure recurence status always overwrites series status
foreach($this->db->select($this->user_table,'*',array(
@ -256,23 +255,6 @@ class calendar_so
$events[$row['cal_id']]['participants'][$uid] = $status;
$events[$row['cal_id']]['participant_types'][$row['cal_user_type']][$row['cal_user_id']] = $status;
if ($events[$row['cal_id']]['recur_type'])
{
$need_max_user_modified[$row['cal_id']] = $row['cal_id'];
}
elseif (($modified = $this->db->from_timestamp($row['cal_user_modified'])) > $events[$row['cal_id']]['max_user_modified'])
{
$events[$row['cal_id']]['max_user_modified'] = $modified;
}
}
// max_user_modified for recurring events has to include all recurrences, above code only querys $recur_date!
if ($need_max_user_modified)
{
foreach($this->max_user_modified($need_max_user_modified) as $id => $modified)
{
$events[$id]['max_user_modified'] = $modified;
}
}
// custom fields
@ -297,44 +279,6 @@ class calendar_so
return $events;
}
/**
* Get maximum modification time of participant data of given event(s)
*
* This includes ALL recurences of an event series
*
* @param int|array $ids one or multiple cal_id's
* @param boolean $return_maximum=false if true return only the maximum, even for multiple ids
* @param boolean $master_only=false only check recurance master (egw_cal_user.recur_date=0)
* @return int|array (array of) modification timestamp(s)
*/
function max_user_modified($ids, $return_maximum=false, $master_only=false)
{
if (!is_array($ids)) $return_maximum = true;
$where = array('cal_id' => $ids);
if ($master_only) $where['cal_recur_date'] = 0;
if ($return_maximum)
{
if (($etags = $this->db->select($this->user_table,'MAX(cal_user_modified)',$where,
__LINE__,__FILE__,false,'','calendar')->fetchColumn()))
{
$etags = $this->db->from_timestamp($etags);
}
}
else
{
$etags = array();
foreach($this->db->select($this->user_table,'cal_id,MAX(cal_user_modified) AS user_etag',$where,
__LINE__,__FILE__,false,'GROUP BY cal_id','calendar') as $row)
{
$etags[$row['cal_id']] = $this->db->from_timestamp($row['user_etag']);
}
}
//error_log(__METHOD__.'('.array2string($ids).', '.array2string($return_maximum).', '.array2string($master_only).') = '.array2string($etags).' '.function_backtrace());
return $etags;
}
/**
* Get maximum modification time of events for given participants and optional owned by them
*
@ -347,6 +291,10 @@ class calendar_so
*/
function get_ctag($users, $owner_too=false,$master_only=false)
{
static $ctags = array(); // some per-request caching
$signature = serialize(func_get_args());
if (isset($ctags[$signature])) return $ctags[$signature];
$where = array(
'cal_user_type' => 'u',
'cal_user_id' => $users,
@ -367,14 +315,8 @@ class calendar_so
'cal_owner' => $users,
),')');
}
if (($data = $this->db->select($this->user_table,array(
'MAX(cal_user_modified) AS max_user_modified',
'MAX(cal_modified) AS max_modified',
),$where,__LINE__,__FILE__,false,'','calendar',0,'JOIN egw_cal ON egw_cal.cal_id=egw_cal_user.cal_id')->fetch()))
{
$data = max($this->db->from_timestamp($data['max_user_modified']),$data['max_modified']);
}
return $data;
return $ctags[$signature] = $this->db->select($this->user_table,'MAX(cal_modified) AS max_modified',
$where,__LINE__,__FILE__,false,'','calendar',0,'JOIN egw_cal ON egw_cal.cal_id=egw_cal_user.cal_id')->fetchColumn();
}
/**
@ -729,7 +671,6 @@ class calendar_so
{
$ids = array_unique($ids);
$need_max_user_modified = array();
// now ready all users with the given cal_id AND (cal_recur_date=0 or the fitting recur-date)
// This will always read the first entry of each recuring event too, we eliminate it later
$recur_dates[] = 0;
@ -762,16 +703,6 @@ class calendar_so
// set data, if recurrence is requested
if (isset($events[$id])) $events[$id]['participants'][$uid] = $status;
// fill max_user_modified:
if (!$params['master_only'] && $events[$id]['recur_type'])
{
$need_max_user_modified[$id] = $id;
}
elseif (isset($events[$id]) && ($modified = $this->db->from_timestamp($row['cal_user_modified'])) > $events[$id]['max_user_modified'])
{
$events[$id]['max_user_modified'] = $modified;
}
}
// query recurrance exceptions, if needed
if (!$params['enum_recuring'])
@ -787,14 +718,6 @@ class calendar_so
}
}
}
// 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)
{
foreach($this->max_user_modified($need_max_user_modified) as $id => $modified)
{
$events[$id]['max_user_modified'] = $modified;
}
}
//custom fields are not shown in the regular views, so we only query them, if explicitly required
if (!is_null($params['cfs']))
{
@ -1651,7 +1574,11 @@ ORDER BY cal_user_type, cal_usre_id
if (!is_null($role) && $role != 'REQ-PARTICIPANT') $set['cal_role'] = $role;
$this->db->insert($this->user_table,$set,$where,__LINE__,__FILE__,'calendar');
}
$ret = $this->db->affected_rows();
// update modified and modifier in main table
if (($ret = $this->db->affected_rows()))
{
$this->updateModified($cal_id, time(), $GLOBALS['egw_info']['user']['account_id']);
}
//error_log(__METHOD__."($cal_id,$user_type,$user_id,$status,$recur_date) = $ret");
return $ret;
}

View File

@ -10,7 +10,7 @@
*/
$setup_info['calendar']['name'] = 'calendar';
$setup_info['calendar']['version'] = '1.9.008';
$setup_info['calendar']['version'] = '1.9.009';
$setup_info['calendar']['app_order'] = 3;
$setup_info['calendar']['enable'] = 1;
$setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index';

View File

@ -2212,9 +2212,9 @@ function calendar_upgrade1_9_007()
{
foreach(array('egw_cal_repeats','egw_cal_dates','egw_cal_user','egw_cal_extra') as $table)
{
$GLOBALS['egw_setup']->db->query("DELETE FROM $table WHERE cal_id IN (SELECT cal_id FROM egw_cal WHERE range_start=0 OR range_start IS NULL)");
$GLOBALS['egw_setup']->db->query("DELETE FROM $table WHERE cal_id IN (SELECT cal_id FROM egw_cal WHERE range_start=0 OR range_start IS NULL)", __LINE__, __FILE__);
}
$GLOBALS['egw_setup']->db->query("DELETE FROM egw_cal WHERE range_start=0 OR range_start IS NULL");
$GLOBALS['egw_setup']->db->query("DELETE FROM egw_cal WHERE range_start=0 OR range_start IS NULL", __LINE__, __FILE__);
// now we can remove temporary default of 0 from range_start and set it NOT NULL
$GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','range_start',array(
@ -2227,10 +2227,21 @@ function calendar_upgrade1_9_007()
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.008';
}
/**
* UPDATE cal_modified to contain maximum of cal_user_modified and current cal_modified, to get a single modification date per calendar-entry
*/
function calendar_upgrade1_9_008()
{
$max_user_modified = 'SELECT '.$GLOBALS['egw_setup']->db->unix_timestamp('MAX(cal_user_modified)').' FROM egw_cal_user WHERE egw_cal.cal_id=egw_cal_user.cal_id';
$GLOBALS['egw_setup']->db->query("UPDATE egw_cal SET cal_modified=($max_user_modified) WHERE cal_modified < ($max_user_modified)", __LINE__, __FILE__);
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.009';
}
/**
* Add cal_rrule columns, drop egw_cal_repeats table
*/
/*function calendar_upgrade1_9_008()
/*function calendar_upgrade1_9_009()
{
$GLOBALS['egw_setup']->oProc->AddColumn('egw_cal','cal_rrule',array(
'type' => 'varchar',
@ -2255,6 +2266,6 @@ function calendar_upgrade1_9_007()
}
$GLOBALS['egw_setup']->oProc->DropTable('egw_cal_repeats');
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.009';
return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.010';
}
*/