ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
PDO.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Sabre\CardDAV\Backend;
4 
5 use Sabre\CardDAV;
6 use Sabre\DAV;
7 
17 class 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 }
addChange($addressBookId, $objectUri, $operation)
Adds a change record to the addressbookchanges table.
Definition: PDO.php:535
getCards($addressbookId)
Returns all cards for a specific addressbook id.
Definition: PDO.php:227
This class represents a set of properties that are going to be updated.
Definition: PropPatch.php:20
$result
$stmt
WebDAV-sync support for CardDAV backends.
Definition: SyncSupport.php:21
const NS_CARDDAV
xml namespace for CardDAV elements
Definition: Plugin.php:33
updateCard($addressBookId, $cardUri, $cardData)
Updates a card.
Definition: PDO.php:371
createCard($addressBookId, $cardUri, $cardData)
Creates a new card.
Definition: PDO.php:325
createAddressBook($principalUri, $url, array $properties)
Creates a new address book.
Definition: PDO.php:156
getAddressBooksForUser($principalUri)
Returns the list of addressbooks for a specific user.
Definition: PDO.php:60
getCard($addressBookId, $cardUri)
Returns a specific card.
Definition: PDO.php:254
$values
getMultipleCards($addressBookId, array $uris)
Returns a list of cards.
Definition: PDO.php:281
$addressBooksTableName
The PDO table name used to store addressbooks.
Definition: PDO.php:29
$query
deleteAddressBook($addressBookId)
Deletes an entire addressbook and all its contents.
Definition: PDO.php:195
$row
__construct(\PDO $pdo)
Sets up the object.
Definition: PDO.php:48
deleteCard($addressBookId, $cardUri)
Deletes a card.
Definition: PDO.php:398
$url
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
updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch)
Updates properties for an address book.
Definition: PDO.php:102
$key
Definition: croninfo.php:18
$cardsTableName
The PDO table name used to store cards.
Definition: PDO.php:34