ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Plugin.php
Go to the documentation of this file.
1<?php
2
3namespace Sabre\DAV\Sync;
4
5use Sabre\DAV;
8
21class Plugin extends DAV\ServerPlugin {
22
28 protected $server;
29
30 const SYNCTOKEN_PREFIX = 'http://sabre.io/ns/sync/';
31
40 function getPluginName() {
41
42 return 'sync';
43
44 }
45
54 function initialize(DAV\Server $server) {
55
56 $this->server = $server;
57 $server->xml->elementMap['{DAV:}sync-collection'] = 'Sabre\\DAV\\Xml\\Request\\SyncCollectionReport';
58
59 $self = $this;
60
61 $server->on('report', function($reportName, $dom, $uri) use ($self) {
62
63 if ($reportName === '{DAV:}sync-collection') {
64 $this->server->transactionType = 'report-sync-collection';
65 $self->syncCollection($uri, $dom);
66 return false;
67 }
68
69 });
70
71 $server->on('propFind', [$this, 'propFind']);
72 $server->on('validateTokens', [$this, 'validateTokens']);
73
74 }
75
86 function getSupportedReportSet($uri) {
87
88 $node = $this->server->tree->getNodeForPath($uri);
89 if ($node instanceof ISyncCollection && $node->getSyncToken()) {
90 return [
91 '{DAV:}sync-collection',
92 ];
93 }
94
95 return [];
96
97 }
98
99
107 function syncCollection($uri, SyncCollectionReport $report) {
108
109 // Getting the data
110 $node = $this->server->tree->getNodeForPath($uri);
111 if (!$node instanceof ISyncCollection) {
112 throw new DAV\Exception\ReportNotSupported('The {DAV:}sync-collection REPORT is not supported on this url.');
113 }
114 $token = $node->getSyncToken();
115 if (!$token) {
116 throw new DAV\Exception\ReportNotSupported('No sync information is available at this node');
117 }
118
119 $syncToken = $report->syncToken;
120 if (!is_null($syncToken)) {
121 // Sync-token must start with our prefix
122 if (substr($syncToken, 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
123 throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
124 }
125
126 $syncToken = substr($syncToken, strlen(self::SYNCTOKEN_PREFIX));
127
128 }
129 $changeInfo = $node->getChanges($syncToken, $report->syncLevel, $report->limit);
130
131 if (is_null($changeInfo)) {
132
133 throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
134
135 }
136
137 // Encoding the response
139 $changeInfo['syncToken'],
140 $uri,
141 $changeInfo['added'],
142 $changeInfo['modified'],
143 $changeInfo['deleted'],
144 $report->properties
145 );
146
147 }
148
160 protected function sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties) {
161
162
163 $fullPaths = [];
164
165 // Pre-fetching children, if this is possible.
166 foreach (array_merge($added, $modified) as $item) {
167 $fullPath = $collectionUrl . '/' . $item;
168 $fullPaths[] = $fullPath;
169 }
170
171 $responses = [];
172 foreach ($this->server->getPropertiesForMultiplePaths($fullPaths, $properties) as $fullPath => $props) {
173
174 // The 'Property_Response' class is responsible for generating a
175 // single {DAV:}response xml element.
176 $responses[] = new DAV\Xml\Element\Response($fullPath, $props);
177
178 }
179
180
181
182 // Deleted items also show up as 'responses'. They have no properties,
183 // and a single {DAV:}status element set as 'HTTP/1.1 404 Not Found'.
184 foreach ($deleted as $item) {
185
186 $fullPath = $collectionUrl . '/' . $item;
187 $responses[] = new DAV\Xml\Element\Response($fullPath, [], 404);
188
189 }
190 $multiStatus = new DAV\Xml\Response\MultiStatus($responses, self::SYNCTOKEN_PREFIX . $syncToken);
191
192 $this->server->httpResponse->setStatus(207);
193 $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
194 $this->server->httpResponse->setBody(
195 $this->server->xml->write('{DAV:}multistatus', $multiStatus, $this->server->getBaseUri())
196 );
197
198 }
199
208 function propFind(DAV\PropFind $propFind, DAV\INode $node) {
209
210 $propFind->handle('{DAV:}sync-token', function() use ($node) {
211 if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) {
212 return;
213 }
214 return self::SYNCTOKEN_PREFIX . $token;
215 });
216
217 }
218
229 function validateTokens(RequestInterface $request, &$conditions) {
230
231 foreach ($conditions as $kk => $condition) {
232
233 foreach ($condition['tokens'] as $ii => $token) {
234
235 // Sync-tokens must always start with our designated prefix.
236 if (substr($token['token'], 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
237 continue;
238 }
239
240 // Checking if the token is a match.
241 $node = $this->server->tree->getNodeForPath($condition['uri']);
242
243 if (
244 $node instanceof ISyncCollection &&
245 $node->getSyncToken() == substr($token['token'], strlen(self::SYNCTOKEN_PREFIX))
246 ) {
247 $conditions[$kk]['tokens'][$ii]['validToken'] = true;
248 }
249
250 }
251
252 }
253
254 }
255
267 function getPluginInfo() {
268
269 return [
270 'name' => $this->getPluginName(),
271 'description' => 'Adds support for WebDAV Collection Sync (rfc6578)',
272 'link' => 'http://sabre.io/dav/sync/',
273 ];
274
275 }
276
277}
foreach($paths as $path) $request
Definition: asyncclient.php:32
An exception for terminatinating execution or to throw for unit testing.
This class holds all the information about a PROPFIND request.
Definition: PropFind.php:11
The baseclass for all server plugins.
Main DAV server class.
Definition: Server.php:23
This plugin all WebDAV-sync capabilities to the Server.
Definition: Plugin.php:21
getSupportedReportSet($uri)
Returns a list of reports this plugin supports.
Definition: Plugin.php:86
const SYNCTOKEN_PREFIX
Definition: Plugin.php:30
initialize(DAV\Server $server)
Initializes the plugin.
Definition: Plugin.php:54
sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties)
Sends the response to a sync-collection request.
Definition: Plugin.php:160
syncCollection($uri, SyncCollectionReport $report)
This method handles the {DAV:}sync-collection HTTP REPORT.
Definition: Plugin.php:107
validateTokens(RequestInterface $request, &$conditions)
The validateTokens event is triggered before every request.
Definition: Plugin.php:229
getPluginInfo()
Returns a bunch of meta-data about the plugin.
Definition: Plugin.php:267
getPluginName()
Returns a plugin name.
Definition: Plugin.php:40
propFind(DAV\PropFind $propFind, DAV\INode $node)
This method is triggered whenever properties are requested for a node.
Definition: Plugin.php:208
WebDAV {DAV:}response parser.
Definition: Response.php:20
WebDAV MultiStatus parser.
Definition: MultiStatus.php:22
The INode interface is the base interface, and the parent class of both ICollection and IFile.
Definition: INode.php:12
If a class extends ISyncCollection, it supports WebDAV-sync.
getSyncToken()
This method returns the current sync-token for this collection.
The RequestInterface represents a HTTP request.