ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
PDO.php
Go to the documentation of this file.
1<?php
2
4
6use Sabre\DAV;
7
17class PDO extends AbstractBackend implements SyncSupport {
18
24 protected $pdo;
25
29 public $addressBooksTableName = 'addressbooks';
30
34 public $cardsTableName = 'cards';
35
41 public $addressBookChangesTableName = 'addressbookchanges';
42
48 function __construct(\PDO $pdo) {
49
50 $this->pdo = $pdo;
51
52 }
53
60 function getAddressBooksForUser($principalUri) {
61
62 $stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, synctoken FROM ' . $this->addressBooksTableName . ' WHERE principaluri = ?');
63 $stmt->execute([$principalUri]);
64
65 $addressBooks = [];
66
67 foreach ($stmt->fetchAll() as $row) {
68
69 $addressBooks[] = [
70 'id' => $row['id'],
71 'uri' => $row['uri'],
72 'principaluri' => $row['principaluri'],
73 '{DAV:}displayname' => $row['displayname'],
74 '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
75 '{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
76 '{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0',
77 ];
78
79 }
80
81 return $addressBooks;
82
83 }
84
85
102 function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) {
103
104 $supportedProperties = [
105 '{DAV:}displayname',
106 '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description',
107 ];
108
109 $propPatch->handle($supportedProperties, function($mutations) use ($addressBookId) {
110
111 $updates = [];
112 foreach ($mutations as $property => $newValue) {
113
114 switch ($property) {
115 case '{DAV:}displayname' :
116 $updates['displayname'] = $newValue;
117 break;
118 case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' :
119 $updates['description'] = $newValue;
120 break;
121 }
122 }
123 $query = 'UPDATE ' . $this->addressBooksTableName . ' SET ';
124 $first = true;
125 foreach ($updates as $key => $value) {
126 if ($first) {
127 $first = false;
128 } else {
129 $query .= ', ';
130 }
131 $query .= ' ' . $key . ' = :' . $key . ' ';
132 }
133 $query .= ' WHERE id = :addressbookid';
134
135 $stmt = $this->pdo->prepare($query);
136 $updates['addressbookid'] = $addressBookId;
137
138 $stmt->execute($updates);
139
140 $this->addChange($addressBookId, "", 2);
141
142 return true;
143
144 });
145
146 }
147
156 function createAddressBook($principalUri, $url, array $properties) {
157
158 $values = [
159 'displayname' => null,
160 'description' => null,
161 'principaluri' => $principalUri,
162 'uri' => $url,
163 ];
164
165 foreach ($properties as $property => $newValue) {
166
167 switch ($property) {
168 case '{DAV:}displayname' :
169 $values['displayname'] = $newValue;
170 break;
171 case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' :
172 $values['description'] = $newValue;
173 break;
174 default :
175 throw new DAV\Exception\BadRequest('Unknown property: ' . $property);
176 }
177
178 }
179
180 $query = 'INSERT INTO ' . $this->addressBooksTableName . ' (uri, displayname, description, principaluri, synctoken) VALUES (:uri, :displayname, :description, :principaluri, 1)';
181 $stmt = $this->pdo->prepare($query);
182 $stmt->execute($values);
183 return $this->pdo->lastInsertId(
184 $this->addressBooksTableName . '_id_seq'
185 );
186
187 }
188
195 function deleteAddressBook($addressBookId) {
196
197 $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?');
198 $stmt->execute([$addressBookId]);
199
200 $stmt = $this->pdo->prepare('DELETE FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
201 $stmt->execute([$addressBookId]);
202
203 $stmt = $this->pdo->prepare('DELETE FROM ' . $this->addressBookChangesTableName . ' WHERE addressbookid = ?');
204 $stmt->execute([$addressBookId]);
205
206 }
207
227 function getCards($addressbookId) {
228
229 $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, size FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?');
230 $stmt->execute([$addressbookId]);
231
232 $result = [];
233 while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
234 $row['etag'] = '"' . $row['etag'] . '"';
235 $row['lastmodified'] = (int)$row['lastmodified'];
236 $result[] = $row;
237 }
238 return $result;
239
240 }
241
254 function getCard($addressBookId, $cardUri) {
255
256 $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified, etag, size FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ? LIMIT 1');
257 $stmt->execute([$addressBookId, $cardUri]);
258
259 $result = $stmt->fetch(\PDO::FETCH_ASSOC);
260
261 if (!$result) return false;
262
263 $result['etag'] = '"' . $result['etag'] . '"';
264 $result['lastmodified'] = (int)$result['lastmodified'];
265 return $result;
266
267 }
268
281 function getMultipleCards($addressBookId, array $uris) {
282
283 $query = 'SELECT id, uri, lastmodified, etag, size, carddata FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri IN (';
284 // Inserting a whole bunch of question marks
285 $query .= implode(',', array_fill(0, count($uris), '?'));
286 $query .= ')';
287
288 $stmt = $this->pdo->prepare($query);
289 $stmt->execute(array_merge([$addressBookId], $uris));
290 $result = [];
291 while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
292 $row['etag'] = '"' . $row['etag'] . '"';
293 $row['lastmodified'] = (int)$row['lastmodified'];
294 $result[] = $row;
295 }
296 return $result;
297
298 }
299
325 function createCard($addressBookId, $cardUri, $cardData) {
326
327 $stmt = $this->pdo->prepare('INSERT INTO ' . $this->cardsTableName . ' (carddata, uri, lastmodified, addressbookid, size, etag) VALUES (?, ?, ?, ?, ?, ?)');
328
329 $etag = md5($cardData);
330
331 $stmt->execute([
332 $cardData,
333 $cardUri,
334 time(),
335 $addressBookId,
336 strlen($cardData),
337 $etag,
338 ]);
339
340 $this->addChange($addressBookId, $cardUri, 1);
341
342 return '"' . $etag . '"';
343
344 }
345
371 function updateCard($addressBookId, $cardUri, $cardData) {
372
373 $stmt = $this->pdo->prepare('UPDATE ' . $this->cardsTableName . ' SET carddata = ?, lastmodified = ?, size = ?, etag = ? WHERE uri = ? AND addressbookid =?');
374
375 $etag = md5($cardData);
376 $stmt->execute([
377 $cardData,
378 time(),
379 strlen($cardData),
380 $etag,
381 $cardUri,
382 $addressBookId
383 ]);
384
385 $this->addChange($addressBookId, $cardUri, 2);
386
387 return '"' . $etag . '"';
388
389 }
390
398 function deleteCard($addressBookId, $cardUri) {
399
400 $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ?');
401 $stmt->execute([$addressBookId, $cardUri]);
402
403 $this->addChange($addressBookId, $cardUri, 3);
404
405 return $stmt->rowCount() === 1;
406
407 }
408
465 function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null) {
466
467 // Current synctoken
468 $stmt = $this->pdo->prepare('SELECT synctoken FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
469 $stmt->execute([$addressBookId]);
470 $currentToken = $stmt->fetchColumn(0);
471
472 if (is_null($currentToken)) return null;
473
474 $result = [
475 'syncToken' => $currentToken,
476 'added' => [],
477 'modified' => [],
478 'deleted' => [],
479 ];
480
481 if ($syncToken) {
482
483 $query = "SELECT uri, operation FROM " . $this->addressBookChangesTableName . " WHERE synctoken >= ? AND synctoken < ? AND addressbookid = ? ORDER BY synctoken";
484 if ($limit > 0) $query .= " LIMIT " . (int)$limit;
485
486 // Fetching all changes
487 $stmt = $this->pdo->prepare($query);
488 $stmt->execute([$syncToken, $currentToken, $addressBookId]);
489
490 $changes = [];
491
492 // This loop ensures that any duplicates are overwritten, only the
493 // last change on a node is relevant.
494 while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
495
496 $changes[$row['uri']] = $row['operation'];
497
498 }
499
500 foreach ($changes as $uri => $operation) {
501
502 switch ($operation) {
503 case 1:
504 $result['added'][] = $uri;
505 break;
506 case 2:
507 $result['modified'][] = $uri;
508 break;
509 case 3:
510 $result['deleted'][] = $uri;
511 break;
512 }
513
514 }
515 } else {
516 // No synctoken supplied, this is the initial sync.
517 $query = "SELECT uri FROM " . $this->cardsTableName . " WHERE addressbookid = ?";
518 $stmt = $this->pdo->prepare($query);
519 $stmt->execute([$addressBookId]);
520
521 $result['added'] = $stmt->fetchAll(\PDO::FETCH_COLUMN);
522 }
523 return $result;
524
525 }
526
535 protected function addChange($addressBookId, $objectUri, $operation) {
536
537 $stmt = $this->pdo->prepare('INSERT INTO ' . $this->addressBookChangesTableName . ' (uri, synctoken, addressbookid, operation) SELECT ?, synctoken, ?, ? FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
538 $stmt->execute([
539 $objectUri,
540 $addressBookId,
541 $operation,
542 $addressBookId
543 ]);
544 $stmt = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET synctoken = synctoken + 1 WHERE id = ?');
545 $stmt->execute([
546 $addressBookId
547 ]);
548
549 }
550}
$result
An exception for terminatinating execution or to throw for unit testing.
PDO CardDAV backend.
Definition: PDO.php:17
getMultipleCards($addressBookId, array $uris)
Returns a list of cards.
Definition: PDO.php:281
getCards($addressbookId)
Returns all cards for a specific addressbook id.
Definition: PDO.php:227
updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch)
Updates properties for an address book.
Definition: PDO.php:102
getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit=null)
The getChanges method returns all the changes that have happened, since the specified syncToken in th...
Definition: PDO.php:465
$cardsTableName
The PDO table name used to store cards.
Definition: PDO.php:34
createAddressBook($principalUri, $url, array $properties)
Creates a new address book.
Definition: PDO.php:156
getCard($addressBookId, $cardUri)
Returns a specific card.
Definition: PDO.php:254
$addressBooksTableName
The PDO table name used to store addressbooks.
Definition: PDO.php:29
addChange($addressBookId, $objectUri, $operation)
Adds a change record to the addressbookchanges table.
Definition: PDO.php:535
deleteAddressBook($addressBookId)
Deletes an entire addressbook and all its contents.
Definition: PDO.php:195
getAddressBooksForUser($principalUri)
Returns the list of addressbooks for a specific user.
Definition: PDO.php:60
deleteCard($addressBookId, $cardUri)
Deletes a card.
Definition: PDO.php:398
__construct(\PDO $pdo)
Sets up the object.
Definition: PDO.php:48
createCard($addressBookId, $cardUri, $cardData)
Creates a new card.
Definition: PDO.php:325
updateCard($addressBookId, $cardUri, $cardData)
Updates a card.
Definition: PDO.php:371
const NS_CARDDAV
xml namespace for CardDAV elements
Definition: Plugin.php:33
This class represents a set of properties that are going to be updated.
Definition: PropPatch.php:20
$key
Definition: croninfo.php:18
WebDAV-sync support for CardDAV backends.
Definition: SyncSupport.php:21
$row
$stmt
$query
$url
$values