mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-20 21:08:54 +01:00
Fix GroupDAV issues
This commit is contained in:
parent
3935667813
commit
ee00114a2e
@ -1,24 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare: GroupDAV access
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
* EGroupware: CalDAV/CardDAV/GroupDAV access
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007/8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-9 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once('HTTP/WebDAV/Server.php');
|
||||
|
||||
/**
|
||||
* eGroupWare: GroupDAV access
|
||||
* EGroupware: GroupDAV access
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
* Using a modified PEAR HTTP/WebDAV/Server class from egw-pear!
|
||||
*
|
||||
* One can use the following url's releative (!) to http://domain.com/egroupware/groupdav.php
|
||||
*
|
||||
* - /addressbook/ all addressbooks current user has rights to
|
||||
* - /calendar/ calendar of current user
|
||||
* - /infolog/ infologs of current user
|
||||
* - / base of the above, only certain clients (KDE, Apple) can autodetect folders from there
|
||||
* - /<username>/addressbook/ addressbook of user or group <username> given the user has rights to view it
|
||||
* - /<username>/calendar/ calendar of user <username> given the user has rights to view it
|
||||
* - /<username>/infolog/ InfoLog's of user <username> given the user has rights to view it
|
||||
* - /<username>/ base of the above, only certain clients (KDE, Apple) can autodetect folders from there
|
||||
*
|
||||
* Calling one of the above collections with a GET request / regular browser generates an automatic index
|
||||
* from the data of a allprop PROPFIND, allow to browse CalDAV/CardDAV/GroupDAV tree with a regular browser.
|
||||
*
|
||||
* @link http://www.groupdav.org GroupDAV spec
|
||||
*/
|
||||
@ -36,6 +48,10 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
* CardDAV namespace
|
||||
*/
|
||||
const CARDDAV = 'urn:ietf:params:xml:ns:carddav';
|
||||
/**
|
||||
* Calendarserver namespace (eg. for ctag)
|
||||
*/
|
||||
const CALENDARSERVER = 'http://calendarserver.org/ns/';
|
||||
/**
|
||||
* Realm and powered by string
|
||||
*/
|
||||
@ -151,7 +167,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
if ($this->debug) error_log(__CLASS__."::$method(".array2string($options,true).')');
|
||||
|
||||
// parse path in form [/account_lid]/app[/more]
|
||||
if (!self::_parse_path($options['path'],$id,$app,$user) && $app && !$user)
|
||||
if (!self::_parse_path($options['path'],$id,$app,$user,$user_prefix) && $app && !$user)
|
||||
{
|
||||
if ($this->debug > 1) error_log(__CLASS__."::$method: user=$user, app=$app, id=$id: 404 not found!");
|
||||
return '404 Not Found';
|
||||
@ -164,40 +180,45 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
// self url
|
||||
$files['files'][] = array(
|
||||
'path' => '/',
|
||||
'path' => $user_prefix.'/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname','eGroupWare'),
|
||||
self::mkprop('displayname','EGroupware (Cal|Card|Group)DAV server'),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
// adding the calendar extra property (calendar-home-set, etc.) here, allows apple iCal to "autodetect" the URL
|
||||
self::mkprop(groupdav::CALDAV,'calendar-home-set',$this->base_uri.'/calendar/'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
),
|
||||
);
|
||||
if ($options['depth'])
|
||||
{
|
||||
// principals collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/principals/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Accounts')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
),
|
||||
);
|
||||
// groups collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/groups/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Groups')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
),
|
||||
);
|
||||
|
||||
if (empty($user_prefix))
|
||||
{
|
||||
// principals collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/principals/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Accounts')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
),
|
||||
);
|
||||
// groups collection
|
||||
$files['files'][] = array(
|
||||
'path' => '/groups/',
|
||||
'props' => array(
|
||||
self::mkprop('displayname',lang('Groups')),
|
||||
self::mkprop('resourcetype','collection'),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
),
|
||||
);
|
||||
}
|
||||
foreach($this->root as $app => $data)
|
||||
{
|
||||
if (!$GLOBALS['egw_info']['user']['apps'][$app]) continue; // no rights for the given app
|
||||
|
||||
$files['files'][] = array(
|
||||
'path' => '/'.$app.'/',
|
||||
'props' => $this->_properties($app),
|
||||
'path' => $user_prefix.'/'.$app.'/',
|
||||
'props' => $this->_properties($app,false,$user),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -212,7 +233,7 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
{
|
||||
if ($method != 'REPORT' && !$id) // no self URL for REPORT requests (only PROPFIND) or propfinds on an id
|
||||
{
|
||||
$files['files'][] = array(
|
||||
$files['files'][0] = array(
|
||||
'path' => '/'.$app.'/',
|
||||
// KAddressbook doubles the folder, if the self URL contains the GroupDAV/CalDAV resourcetypes
|
||||
'props' => $this->_properties($app,$app=='addressbook'&&strpos($_SERVER['HTTP_USER_AGENT'],'KHTML') !== false),
|
||||
@ -220,6 +241,12 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
}
|
||||
if (!$options['depth'] && !$id)
|
||||
{
|
||||
// add ctag if handler implements it (only for depth 0)
|
||||
if (method_exists($handler,'getctag'))
|
||||
{
|
||||
$files['files'][0]['props'][] = HTTP_WebDAV_Server::mkprop(
|
||||
groupdav::CALENDARSERVER,'getctag',$handler->getctag($options['path'],$user));
|
||||
}
|
||||
return true; // depth 0 --> show only the self url
|
||||
}
|
||||
return $handler->propfind($options['path'],$options,$files,$user,$id);
|
||||
@ -232,25 +259,29 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
*
|
||||
* @param string $app
|
||||
* @param boolean $no_extra_types=false should the GroupDAV and CalDAV types be added (KAddressbook has problems with it in self URL)
|
||||
* @param int $user=null owner of the collection, default current user
|
||||
* @return array of DAV properties
|
||||
*/
|
||||
function _properties($app,$no_extra_types=false)
|
||||
function _properties($app,$no_extra_types=false,$user=null)
|
||||
{
|
||||
if (!$user) $user = $GLOBALS['egw_info']['user']['account_fullname'];
|
||||
|
||||
$props = array(
|
||||
self::mkprop('displayname',$this->translation->convert(lang($app),$this->egw_charset,'utf-8')),
|
||||
self::mkprop('displayname',$this->translation->convert(lang($app).' '.common::grab_owner_name($user),$this->egw_charset,'utf-8')),
|
||||
self::mkprop('current-user-principal',array(self::mkprop('href',$this->base_uri.'/principals/'.$GLOBALS['egw_info']['user']['account_lid'].'/'))),
|
||||
);
|
||||
foreach($this->root[$app] as $prop => $values)
|
||||
foreach((array)$this->root[$app] as $prop => $values)
|
||||
{
|
||||
if ($prop == 'resourcetype')
|
||||
{
|
||||
$resourcetype = array(
|
||||
self::mkprop('collection','collection'),
|
||||
self::mkprop('collection',''),
|
||||
);
|
||||
if (!$no_extra_types)
|
||||
{
|
||||
foreach($this->root[$app]['resourcetype'] as $ns => $type)
|
||||
{
|
||||
$resourcetype[] = self::mkprop($ns,'resourcetype', $type);
|
||||
$resourcetype[] = self::mkprop($ns,$type,'');
|
||||
}
|
||||
}
|
||||
$props[] = self::mkprop('resourcetype',$resourcetype);
|
||||
@ -299,24 +330,182 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
/**
|
||||
* GET method handler
|
||||
*
|
||||
* @param array parameter passing array
|
||||
* @param array $options parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function GET(&$options)
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__.'('.array2string($options).')');
|
||||
|
||||
if (!$this->_parse_path($options['path'],$id,$app,$user))
|
||||
if (!$this->_parse_path($options['path'],$id,$app,$user) || $app == 'principals')
|
||||
{
|
||||
return $this->autoindex($options);
|
||||
|
||||
error_log(__METHOD__."(".array2string($options).") 404 Not Found");
|
||||
return '404 Not Found';
|
||||
}
|
||||
if (($handler = self::app_handler($app)))
|
||||
{
|
||||
return $handler->get($options,$id);
|
||||
}
|
||||
error_log(__METHOD__."(".array2string($options).") 501 Not Implemented");
|
||||
return '501 Not Implemented';
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an automatic index (listing and properties) for a collection
|
||||
*
|
||||
* @param array $options parameter passing array, index "path" contains requested path
|
||||
*/
|
||||
protected function autoindex($options)
|
||||
{
|
||||
$propfind_options = array(
|
||||
'path' => $options['path'],
|
||||
'depth' => 1,
|
||||
);
|
||||
$files = array();
|
||||
if (($ret = $this->PROPFIND($propfind_options,$files)) !== true)
|
||||
{
|
||||
return $ret; // no collection
|
||||
}
|
||||
header('Content-type: text/html; charset='.$GLOBALS['egw']->translation->charset());
|
||||
echo "<html>\n<head>\n\t<title>".'EGroupware (Cal|Card|Group)DAV server '.htmlspecialchars($options['path'])."</title>\n";
|
||||
echo "\t<meta http-equiv='content-type' content='text/html; charset=utf-8' />\n";
|
||||
echo "\t<style type='text/css'>\n.th { background-color: #e0e0e0; }\n.row_on { background-color: #F1F1F1; }\n".
|
||||
".row_off { background-color: #ffffff; }\ntd { padding-left: 5px; }\nth { padding-left: 5px; text-align: left; }\n\t</style>\n";
|
||||
echo "</head>\n<body>\n";
|
||||
|
||||
echo '<h1>(Cal|Card|Group)DAV ';
|
||||
$path = '/groupdav.php';
|
||||
foreach(explode('/',$this->_unslashify($options['path'])) as $n => $name)
|
||||
{
|
||||
$path .= ($n != 1 ? '/' : '').$name;
|
||||
echo html::a_href(htmlspecialchars($name.'/'),$path);
|
||||
}
|
||||
echo "</h1>\n";
|
||||
|
||||
$n = 0;
|
||||
foreach($files['files'] as $file)
|
||||
{
|
||||
if (!isset($collection_props))
|
||||
{
|
||||
$collection_props = $this->props2array($file['props']);
|
||||
echo '<h3>'.lang('Collection listing').': '.htmlspecialchars($collection_props['DAV:displayname'])."</h3>\n";
|
||||
continue; // own entry --> displaying properies later
|
||||
}
|
||||
if(!$n++)
|
||||
{
|
||||
echo "<table>\n\t<tr class='th'><th>#</th><th>".lang('Name')."</th><th>".lang('Size')."</th><th>".lang('Last modified')."</th><th>".
|
||||
lang('ETag')."</th><th>".lang('Content type')."</th><th>".lang('Resource type')."</th></tr>\n";
|
||||
}
|
||||
$props = $this->props2array($file['props']);
|
||||
//echo $file['path']; _debug_array($props);
|
||||
$class = $class == 'row_on' ? 'row_off' : 'row_on';
|
||||
$name = $this->_slashify(basename($this->_unslashify($file['path'])));
|
||||
/*
|
||||
if (substr($file['path'],-1) == '/')
|
||||
{
|
||||
$name = basename(substr($file['path'],0,-1)).'/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$name = basename($file['path']);
|
||||
}
|
||||
*/
|
||||
echo "\t<tr class='$class'>\n\t\t<td>$n</td>\n\t\t<td>".html::a_href(htmlspecialchars($name),'/groupdav.php'.$file['path'])."</td>\n";
|
||||
echo "\t\t<td>".$props['DAV:getcontentlength']."</td>\n";
|
||||
echo "\t\t<td>".(!empty($props['DAV:getlastmodified']) ? date('Y-m-d H:i:s',$props['DAV:getlastmodified']) : '')."</td>\n";
|
||||
echo "\t\t<td>".$props['DAV:getetag']."</td>\n";
|
||||
echo "\t\t<td>".htmlspecialchars($props['DAV:getcontenttype'])."</td>\n";
|
||||
echo "\t\t<td>".self::prop_value($props['DAV:resourcetype'])."</td>\n\t</tr>\n";
|
||||
}
|
||||
if (!$n)
|
||||
{
|
||||
echo '<p>'.lang('Collection empty.')."</p>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "</table>\n";
|
||||
}
|
||||
echo '<h3>'.lang('Properties')."</h3>\n";
|
||||
echo "<table>\n\t<tr class='th'><th>".lang('Namespace')."</th><th>".lang('Name')."</th><th>".lang('Value')."</th></tr>\n";
|
||||
foreach($collection_props as $name => $value)
|
||||
{
|
||||
$class = $class == 'row_on' ? 'row_off' : 'row_on';
|
||||
$ns = explode(':',$name);
|
||||
$name = array_pop($ns);
|
||||
$ns = implode(':',$ns);
|
||||
echo "\t<tr class='$class'>\n\t\t<td>".htmlspecialchars($ns)."</td><td>".htmlspecialchars($name)."</td>\n";
|
||||
echo "\t\t<td>".self::prop_value($value)."</td>\n\t</tr>\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
|
||||
echo "</body>\n</html>\n";
|
||||
|
||||
common::egw_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a property value for output
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function prop_value($value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
if (isset($value[0]['ns']))
|
||||
{
|
||||
$value = $this->_hierarchical_prop_encode($value);
|
||||
}
|
||||
$value = htmlspecialchars(array2string($value));
|
||||
}
|
||||
elseif (preg_match('/^https?:\/\//',$value))
|
||||
{
|
||||
$value = html::a_href($value,$value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = htmlspecialchars($value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return numeric indexed array with values for keys 'ns', 'name' and 'val' as array 'ns:name' => 'val'
|
||||
*
|
||||
* @param array $props
|
||||
* @return array
|
||||
*/
|
||||
protected function props2array(array $props)
|
||||
{
|
||||
$arr = array();
|
||||
foreach($props as $prop)
|
||||
{
|
||||
switch($prop['ns'])
|
||||
{
|
||||
case 'DAV:';
|
||||
$ns = 'DAV';
|
||||
break;
|
||||
case self::CALDAV:
|
||||
$ns = 'CalDAV';
|
||||
break;
|
||||
case self::CARDDAV:
|
||||
$ns = 'CardDAV';
|
||||
break;
|
||||
case self::GROUPDAV:
|
||||
$ns = 'GroupDAV';
|
||||
break;
|
||||
default:
|
||||
$ns = $prop['ns'];
|
||||
}
|
||||
$arr[$ns.':'.$prop['name']] = is_array($prop['val']) ?
|
||||
$this->_hierarchical_prop_encode($prop['val']) : $prop['val'];
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method handler
|
||||
*
|
||||
@ -482,34 +671,51 @@ class groupdav extends HTTP_WebDAV_Server
|
||||
* @param int &$id
|
||||
* @param string &$app addressbook, calendar, infolog (=infolog)
|
||||
* @param int &$user
|
||||
* @param string &$user_prefix=null
|
||||
* @return boolean true on success, false on error
|
||||
*/
|
||||
function _parse_path($path,&$id,&$app,&$user)
|
||||
function _parse_path($path,&$id,&$app,&$user,&$user_prefix=null)
|
||||
{
|
||||
$parts = explode('/',$path);
|
||||
|
||||
if (in_array($parts[1],array('principals','groups')))
|
||||
if ($this->debug)
|
||||
{
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
list(,$app,$id) = $parts;
|
||||
return true;
|
||||
error_log(__METHOD__." called with ('$path') id=$id, app='$app', user=$user");
|
||||
}
|
||||
if ($path[0] == '/')
|
||||
{
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
$parts = explode('/', $this->_unslashify($path));
|
||||
|
||||
if ($GLOBALS['egw']->accounts->name2id($parts[0]))
|
||||
{
|
||||
// /$user/$app/...
|
||||
$user = array_shift($parts);
|
||||
}
|
||||
|
||||
list($id) = explode('.',array_pop($parts)); // remove evtl. .ics extension
|
||||
$app = array_shift($parts);
|
||||
|
||||
$app = array_pop($parts);
|
||||
|
||||
if (($user = array_pop($parts)))
|
||||
if ($user)
|
||||
{
|
||||
$user_prefix = '/'.$user;
|
||||
$user = $GLOBALS['egw']->accounts->name2id($user,'account_lid',$app != 'addressbook' ? 'u' : null);
|
||||
}
|
||||
else
|
||||
{
|
||||
$user_prefix = '';
|
||||
$user = $GLOBALS['egw_info']['user']['account_id'];
|
||||
}
|
||||
|
||||
if (($id = array_pop($parts)))
|
||||
{
|
||||
list($id) = explode('.',$id); // remove evtl. .ics extension
|
||||
}
|
||||
|
||||
if (!($ok = $id && in_array($app,array('addressbook','calendar','infolog','principals','groups')) && $user))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."('$path') returning false: id=$id, app='$app', user=$user");
|
||||
if ($this->debug)
|
||||
{
|
||||
error_log(__METHOD__."('$path') returning false: id=$id, app='$app', user=$user");
|
||||
}
|
||||
}
|
||||
return $ok;
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: abstract baseclass for groupdav/caldav/carddav handlers
|
||||
* EGroupware: GroupDAV access: abstract baseclass for groupdav/caldav/carddav handlers
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007/8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2007-9 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* eGroupWare: GroupDAV access: abstract baseclass for groupdav/caldav/carddav handlers
|
||||
* EGroupware: GroupDAV access: abstract baseclass for groupdav/caldav/carddav handlers
|
||||
*/
|
||||
abstract class groupdav_handler
|
||||
{
|
||||
@ -81,8 +81,9 @@ abstract class groupdav_handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
{
|
||||
//error_log(__METHOD__." called");
|
||||
$this->app = $app;
|
||||
if (!is_null($debug)) $this->debug = $debug;
|
||||
#if (!is_null($debug)) $this->debug = $debug = 3;
|
||||
$this->base_uri = is_null($base_uri) ? $base_uri : $_SERVER['SCRIPT_NAME'];
|
||||
$this->agent = self::get_agent();
|
||||
|
||||
@ -101,6 +102,16 @@ abstract class groupdav_handler
|
||||
*/
|
||||
abstract function propfind($path,$options,&$files,$user);
|
||||
|
||||
/**
|
||||
* Propfind callback, if interator is used
|
||||
*
|
||||
* @param array $filter
|
||||
* @param array|boolean $start false=return all or array(start,num)
|
||||
* @param int &$total
|
||||
* @return array with "files" array with values for keys path and props
|
||||
*/
|
||||
function &propfind_callback(array $filter,$start,&$total) { }
|
||||
|
||||
/**
|
||||
* Handle get request for an applications entry
|
||||
*
|
||||
@ -171,7 +182,7 @@ abstract class groupdav_handler
|
||||
}
|
||||
if (!is_array($entry) || !isset($entry['id']) || !(isset($entry['modified']) || isset($entry['etag'])))
|
||||
{
|
||||
error_log(__METHOD__."(".array2string($entry).") Cant create etag!");
|
||||
// error_log(__METHOD__."(".array2string($entry).") Cant create etag!");
|
||||
return false;
|
||||
}
|
||||
return '"'.$entry['id'].':'.(isset($entry['etag']) ? $entry['etag'] : $entry['modified']).'"';
|
||||
@ -303,4 +314,136 @@ abstract class groupdav_handler
|
||||
}
|
||||
return $agent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator for propfinds using propfind callback of a groupdav_handler to query results in chunks
|
||||
*
|
||||
* The propfind method just computes a filter and then returns an instance of this iterator instead of the files:
|
||||
*
|
||||
* function propfind($path,$options,&$files,$user,$id='')
|
||||
* {
|
||||
* $filter = array();
|
||||
* // compute filter from path, options, ...
|
||||
*
|
||||
* $files['files'] = new groupdav_propfind_iterator($this,$filter,$files['files']);
|
||||
*
|
||||
* return true;
|
||||
* }
|
||||
*/
|
||||
class groupdav_propfind_iterator implements Iterator
|
||||
{
|
||||
/**
|
||||
* Handler to call for entries
|
||||
*
|
||||
* @var groupdav_handler
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* Filter of propfind call
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filter;
|
||||
|
||||
/**
|
||||
* Extra responses to return too
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* Start value for callback
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $start=0;
|
||||
|
||||
/**
|
||||
* Number of entries queried from callback in one call
|
||||
*
|
||||
*/
|
||||
const CHUNK_SIZE = 500;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param groupdav_handler $handler
|
||||
* @param array $filter filter for propfind call
|
||||
* @param array $files=null extra files/responses to return too
|
||||
*/
|
||||
public function __construct(groupdav_handler $handler,array $filter,array &$files=null)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
$this->filter = $filter;
|
||||
$this->files = $files;
|
||||
reset($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current element
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return current($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
$current = $this->current();
|
||||
|
||||
return $current['path']; // we return path as key
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element (called after each foreach loop)
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if (next($this->files) !== false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!$this->handler)
|
||||
{
|
||||
return false; // no further entries
|
||||
}
|
||||
// try query further files via propfind callback of handler and store result in $this->files
|
||||
$this->files = $this->handler->propfind_callback($this->filter,array($this->start,self::CHUNK_SIZE));
|
||||
$this->start += self::CHUNK_SIZE;
|
||||
reset($this->files);
|
||||
|
||||
if (count($this->files) < self::CHUNK_SIZE) // less entries then asked --> no further available
|
||||
{
|
||||
unset($this->handler);
|
||||
}
|
||||
return current($this->files) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element (called at beginning of foreach loop)
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid ()
|
||||
{
|
||||
return current($this->files) !== false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user