mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-06-27 21:32:46 +02:00
sync-collection report for InfoLog, thought reminder app on OS X 10.8.2 does not use it, moved logic for sync-token to baseclass and determine availablity on supported-report-set
This commit is contained in:
parent
7a3d4f99ed
commit
f224fe5852
@ -430,7 +430,10 @@ class addressbook_groupdav extends groupdav_handler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'sync-level':
|
case 'sync-level':
|
||||||
// ignored for now
|
if ($option['data'] != '1')
|
||||||
|
{
|
||||||
|
$this->groupdav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->groupdav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
$this->groupdav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||||
@ -723,21 +726,6 @@ class addressbook_groupdav extends groupdav_handler
|
|||||||
return $ctags[$path] = max($ctag,$lists_ctag);
|
return $ctags[$path] = max($ctag,$lists_ctag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Query sync-token for addressbook
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param int $user
|
|
||||||
* @param int $modified=null default getctag
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function get_sync_token($path, $user, $modified=null)
|
|
||||||
{
|
|
||||||
if (!isset($modified)) $modified = $this->getctag($path, $user);
|
|
||||||
|
|
||||||
return $this->base_uri().$path.$modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add extra properties for addressbook collections
|
* Add extra properties for addressbook collections
|
||||||
*
|
*
|
||||||
@ -773,18 +761,18 @@ class addressbook_groupdav extends groupdav_handler
|
|||||||
$props['max-image-size'] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'max-image-size',4096);
|
$props['max-image-size'] = HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'max-image-size',4096);
|
||||||
|
|
||||||
// supported reports (required property for CardDAV)
|
// supported reports (required property for CardDAV)
|
||||||
$props['supported-report-set'] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
|
$props['supported-report-set'] = array(
|
||||||
HTTP_WebDAV_Server::mkprop('supported-report',array(
|
'addressbook-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||||
HTTP_WebDAV_Server::mkprop('report',array(
|
HTTP_WebDAV_Server::mkprop('report',array(
|
||||||
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-query',''))))),
|
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-query',''))))),
|
||||||
HTTP_WebDAV_Server::mkprop('supported-report',array(
|
'addressbook-multiget' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||||
HTTP_WebDAV_Server::mkprop('report',array(
|
HTTP_WebDAV_Server::mkprop('report',array(
|
||||||
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-multiget',''))))),
|
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-multiget',''))))),
|
||||||
// rfc 6578 sync-collection report
|
// rfc 6578 sync-collection report
|
||||||
HTTP_WebDAV_Server::mkprop('supported-report',array(
|
'sync-collection' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||||
HTTP_WebDAV_Server::mkprop('report',array(
|
HTTP_WebDAV_Server::mkprop('report',array(
|
||||||
HTTP_WebDAV_Server::mkprop('sync-collection',''))))),
|
HTTP_WebDAV_Server::mkprop('sync-collection',''))))),
|
||||||
));
|
);
|
||||||
return $props;
|
return $props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
$filter = $this->get_infolog_filter($path, $user);
|
$filter = $this->get_infolog_filter($path, $user);
|
||||||
|
|
||||||
// process REPORT filters or multiget href's
|
// process REPORT filters or multiget href's
|
||||||
if (($id || $options['root']['name'] != 'propfind') && !$this->_report_filters($options,$filter,$id))
|
if (($id || $options['root']['name'] != 'propfind') && !$this->_report_filters($options, $filter, $id, $nresults))
|
||||||
{
|
{
|
||||||
// return empty collection, as iCal under iOS 5 had problems with returning "404 Not found" status
|
// return empty collection, as iCal under iOS 5 had problems with returning "404 Not found" status
|
||||||
// when trying to request not supported components, eg. VTODO on a calendar collection
|
// when trying to request not supported components, eg. VTODO on a calendar collection
|
||||||
@ -179,9 +179,28 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rfc 6578 sync-collection report: filter for sync-token is already set in _report_filters
|
||||||
|
if ($options['root']['name'] == 'sync-collection')
|
||||||
|
{
|
||||||
|
// query sync-token before result, so changed happening while result get queried are not lost
|
||||||
|
$files['sync-token'] = $this->get_sync_token($path, $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($nresults))
|
||||||
|
{
|
||||||
|
$files['files'] = $this->propfind_callback($path, $filter, array(0, (int)$nresults));
|
||||||
|
|
||||||
|
if ($options['root']['name'] == 'sync-collection' && isset($files['files']['sync-token']))
|
||||||
|
{
|
||||||
|
$files['sync-token'] = $this->get_sync_token($path, $user, $files['files']['sync-token']);
|
||||||
|
unset($files['files']['sync-token']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// return iterator, calling ourself to return result in chunks
|
// return iterator, calling ourself to return result in chunks
|
||||||
$files['files'] = new groupdav_propfind_iterator($this,$path,$filter,$files['files']);
|
$files['files'] = new groupdav_propfind_iterator($this,$path,$filter,$files['files']);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,9 +224,18 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
$task_filter = $filter['filter'];
|
$task_filter = $filter['filter'];
|
||||||
unset($filter['filter']);
|
unset($filter['filter']);
|
||||||
|
|
||||||
|
$order = 'info_datemodified';
|
||||||
|
$sort = 'DESC';
|
||||||
|
if (preg_match('/^([a-z0-9_]+)( DESC| ASC)?$/i', $filter['order'], $matches))
|
||||||
|
{
|
||||||
|
$order = $matches[1];
|
||||||
|
if ($matches[2]) $sort = $matches[2];
|
||||||
|
unset($filter['order']);
|
||||||
|
}
|
||||||
|
|
||||||
$query = array(
|
$query = array(
|
||||||
'order' => 'info_datemodified',
|
'order' => $order,
|
||||||
'sort' => 'DESC',
|
'sort' => $sort,
|
||||||
'filter' => $task_filter,
|
'filter' => $task_filter,
|
||||||
'date_format' => 'server',
|
'date_format' => 'server',
|
||||||
'col_filter' => $filter,
|
'col_filter' => $filter,
|
||||||
@ -216,7 +244,7 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
|
|
||||||
if (!$calendar_data)
|
if (!$calendar_data)
|
||||||
{
|
{
|
||||||
$query['cols'] = array('info_id', 'info_datemodified', 'info_uid', 'caldav_name', 'info_subject');
|
$query['cols'] = array('info_id', 'info_datemodified', 'info_uid', 'caldav_name', 'info_subject', 'info_status');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($start))
|
if (is_array($start))
|
||||||
@ -236,6 +264,12 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
{
|
{
|
||||||
foreach($tasks as $task)
|
foreach($tasks as $task)
|
||||||
{
|
{
|
||||||
|
// sync-collection report: deleted entry need to be reported without properties
|
||||||
|
if ($task['info_status'] == 'deleted' && strpos($task_filter, '+deleted') !== false)
|
||||||
|
{
|
||||||
|
$files[] = array('path' => $path.urldecode($this->get_path($task)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$props = array(
|
$props = array(
|
||||||
'getcontenttype' => $this->agent != 'kde' ? 'text/calendar; charset=utf-8; component=VTODO' : 'text/calendar', // Konqueror (3.5) dont understand it otherwise
|
'getcontenttype' => $this->agent != 'kde' ? 'text/calendar; charset=utf-8; component=VTODO' : 'text/calendar', // Konqueror (3.5) dont understand it otherwise
|
||||||
'getlastmodified' => $task['info_datemodified'],
|
'getlastmodified' => $task['info_datemodified'],
|
||||||
@ -250,6 +284,14 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
$files[] = $this->add_resource($path, $task, $props);
|
$files[] = $this->add_resource($path, $task, $props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// hack to support limit with sync-collection report: tasks are returned in modified ASC order (oldest first)
|
||||||
|
// if limit is smaller then full result, return modified-1 as sync-token, so client requests next chunk incl. modified
|
||||||
|
// (which might contain further entries with identical modification time)
|
||||||
|
if (strpos($task_filter, '+deleted') !== false &&
|
||||||
|
$start[0] == 0 && $start[1] != groupdav_propfind_iterator::CHUNK_SIZE && $query['total'] > $start[1])
|
||||||
|
{
|
||||||
|
$files['sync-token'] = $task['info_datemodified']-1;
|
||||||
|
}
|
||||||
if ($this->debug) error_log(__METHOD__."($path) took ".(microtime(true) - $starttime).' to return '.count($files).' items');
|
if ($this->debug) error_log(__METHOD__."($path) took ".(microtime(true) - $starttime).' to return '.count($files).' items');
|
||||||
return $files;
|
return $files;
|
||||||
}
|
}
|
||||||
@ -260,9 +302,10 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @param array &$cal_filters
|
* @param array &$cal_filters
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return boolean true if filter could be processed, false for requesting not here supported VTODO items
|
* @param int &$nresult on return limit for number or results or unchanged/null
|
||||||
|
* @return boolean true if filter could be processed
|
||||||
*/
|
*/
|
||||||
function _report_filters($options,&$cal_filters,$id)
|
function _report_filters($options,&$filters,$id, &$nresults)
|
||||||
{
|
{
|
||||||
if ($options['filters'])
|
if ($options['filters'])
|
||||||
{
|
{
|
||||||
@ -311,12 +354,46 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if client set an own filter, reset the open-standard filter
|
}
|
||||||
/* not longer necessary, as we use now own and user anyway
|
// parse limit from $options['other']
|
||||||
if ($cal_filters != $cal_filters_in)
|
/* Example limit
|
||||||
|
<B:limit>
|
||||||
|
<B:nresults>10</B:nresults>
|
||||||
|
</B:limit>
|
||||||
|
*/
|
||||||
|
foreach((array)$options['other'] as $option)
|
||||||
{
|
{
|
||||||
$cal_filters['filter'] = str_replace(array('open', 'open-user'), array('own', 'user'), $cal_filters['filter']);
|
switch($option['name'])
|
||||||
}*/
|
{
|
||||||
|
case 'nresults':
|
||||||
|
$nresults = (int)$option['data'];
|
||||||
|
//error_log(__METHOD__."(...) options[other]=".array2string($options['other'])." --> nresults=$nresults");
|
||||||
|
break;
|
||||||
|
case 'limit':
|
||||||
|
break;
|
||||||
|
case 'href':
|
||||||
|
break; // from addressbook-multiget, handled below
|
||||||
|
// rfc 6578 sync-report
|
||||||
|
case 'sync-token':
|
||||||
|
if (!empty($option['data']))
|
||||||
|
{
|
||||||
|
$parts = explode('/', $option['data']);
|
||||||
|
$sync_token = array_pop($parts);
|
||||||
|
$filters[] = 'info_datemodified>'.(int)$sync_token;
|
||||||
|
$filters['filter'] .= '+deleted'; // to return deleted entries too
|
||||||
|
$filters['order'] = 'info_datemodified ASC'; // return oldest modifications first
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'sync-level':
|
||||||
|
if ($option['data'] != '1')
|
||||||
|
{
|
||||||
|
$this->groupdav->log(__METHOD__."(...) only sync-level {$option['data']} requested, but only 1 supported! options[other]=".array2string($options['other']));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->groupdav->log(__METHOD__."(...) unknown xml tag '{$option['name']}': options[other]=".array2string($options['other']));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// multiget or propfind on a given id
|
// multiget or propfind on a given id
|
||||||
//error_log(__FILE__ . __METHOD__ . "multiget of propfind:");
|
//error_log(__FILE__ . __METHOD__ . "multiget of propfind:");
|
||||||
@ -618,7 +695,7 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
/**
|
/**
|
||||||
* Get the etag for an infolog entry
|
* Get the etag for an infolog entry
|
||||||
*
|
*
|
||||||
* etag currently uses the modifcation time (info_modified), 1.9.002 adds etag column, but it's not yet used!
|
* etag currently uses the modifcation time (info_datemodified), 1.9.002 adds etag column, but it's not yet used!
|
||||||
*
|
*
|
||||||
* @param array|int $info array with infolog entry or info_id
|
* @param array|int $info array with infolog entry or info_id
|
||||||
* @return string|boolean string with etag or false
|
* @return string|boolean string with etag or false
|
||||||
@ -656,12 +733,18 @@ class infolog_groupdav extends groupdav_handler
|
|||||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VTODO')),
|
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'comp',array('name' => 'VTODO')),
|
||||||
));
|
));
|
||||||
// supported reports
|
// supported reports
|
||||||
$props['supported-report-set'] = HTTP_WebDAV_Server::mkprop('supported-report-set',array(
|
$props['supported-report-set'] = array(
|
||||||
HTTP_WebDAV_Server::mkprop('supported-report',array(
|
'calendar-query' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||||
HTTP_WebDAV_Server::mkprop('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('report',array(
|
||||||
HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-multiget','')))))));
|
HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'calendar-multiget',''))))),
|
||||||
|
// rfc 6578 sync-collection report
|
||||||
|
'sync-collection' => HTTP_WebDAV_Server::mkprop('supported-report',array(
|
||||||
|
HTTP_WebDAV_Server::mkprop('report',array(
|
||||||
|
HTTP_WebDAV_Server::mkprop('sync-collection',''))))),
|
||||||
|
);
|
||||||
|
|
||||||
// get timezone of calendar
|
// get timezone of calendar
|
||||||
if ($this->groupdav->prop_requested('calendar-timezone'))
|
if ($this->groupdav->prop_requested('calendar-timezone'))
|
||||||
|
@ -849,10 +849,10 @@ class groupdav extends HTTP_WebDAV_Server
|
|||||||
$props['getctag'] = self::mkprop(
|
$props['getctag'] = self::mkprop(
|
||||||
groupdav::CALENDARSERVER,'getctag',$handler->getctag($path,$user));
|
groupdav::CALENDARSERVER,'getctag',$handler->getctag($path,$user));
|
||||||
}
|
}
|
||||||
// add sync-token url if handler implements it
|
// add sync-token url if handler supports sync-collection report
|
||||||
if (method_exists($handler,'get_sync_token') && $this->prop_requested('sync-token') === true)
|
if (isset($props['supported-report-set']['sync-collection']) && $this->prop_requested('sync-token') === true)
|
||||||
{
|
{
|
||||||
$props['sync-token'] = self::mkprop('sync-token', $handler->get_sync_token($path,$user));
|
$props['sync-token'] = $handler->get_sync_token($path,$user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($handler && $user)
|
if ($handler && $user)
|
||||||
|
@ -579,6 +579,29 @@ abstract class groupdav_handler
|
|||||||
}
|
}
|
||||||
return $full_uri ? $uri : $path;
|
return $full_uri ? $uri : $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query sync-token
|
||||||
|
*
|
||||||
|
* We use ctag / max. modification time as sync-token. As garnularity is 1sec, we can never be sure,
|
||||||
|
* if there are more modifications to come in the current second.
|
||||||
|
*
|
||||||
|
* Therefor we are never returning current time, but 1sec less!
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param int $user
|
||||||
|
* @param int $modified=null default getctag
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_sync_token($path, $user, $modified=null)
|
||||||
|
{
|
||||||
|
if (!isset($modified)) $modified = $this->getctag($path, $user);
|
||||||
|
|
||||||
|
// never return current time, as more modifications might happen --> decrement it by 1sec
|
||||||
|
if ($modified == time()) --$modified;
|
||||||
|
|
||||||
|
return $this->base_uri().$path.$modified;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user