ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Sabre\CardDAV\Backend\PDO Class Reference

PDO CardDAV backend. More...

+ Inheritance diagram for Sabre\CardDAV\Backend\PDO:
+ Collaboration diagram for Sabre\CardDAV\Backend\PDO:

Public Member Functions

 __construct (\PDO $pdo)
 Sets up the object. More...
 
 getAddressBooksForUser ($principalUri)
 Returns the list of addressbooks for a specific user. More...
 
 updateAddressBook ($addressBookId, \Sabre\DAV\PropPatch $propPatch)
 Updates properties for an address book. More...
 
 createAddressBook ($principalUri, $url, array $properties)
 Creates a new address book. More...
 
 deleteAddressBook ($addressBookId)
 Deletes an entire addressbook and all its contents. More...
 
 getCards ($addressbookId)
 Returns all cards for a specific addressbook id. More...
 
 getCard ($addressBookId, $cardUri)
 Returns a specific card. More...
 
 getMultipleCards ($addressBookId, array $uris)
 Returns a list of cards. More...
 
 createCard ($addressBookId, $cardUri, $cardData)
 Creates a new card. More...
 
 updateCard ($addressBookId, $cardUri, $cardData)
 Updates a card. More...
 
 deleteCard ($addressBookId, $cardUri)
 Deletes a card. More...
 
 getChangesForAddressBook ($addressBookId, $syncToken, $syncLevel, $limit=null)
 The getChanges method returns all the changes that have happened, since the specified syncToken in the specified address book. More...
 
- Public Member Functions inherited from Sabre\CardDAV\Backend\AbstractBackend
 getMultipleCards ($addressBookId, array $uris)
 Returns a list of cards. More...
 

Data Fields

 $addressBooksTableName = 'addressbooks'
 The PDO table name used to store addressbooks. More...
 
 $cardsTableName = 'cards'
 The PDO table name used to store cards. More...
 
 $addressBookChangesTableName = 'addressbookchanges'
 

Protected Member Functions

 addChange ($addressBookId, $objectUri, $operation)
 Adds a change record to the addressbookchanges table. More...
 

Protected Attributes

 $pdo
 

Detailed Description

PDO CardDAV backend.

This CardDAV backend uses PDO to store addressbooks

Author
Evert Pot (http://evertpot.com/) http://sabre.io/license/ Modified BSD License

Definition at line 17 of file PDO.php.

Constructor & Destructor Documentation

◆ __construct()

Sabre\CardDAV\Backend\PDO::__construct ( \PDO  $pdo)

Sets up the object.

Parameters
\PDO$pdo

Definition at line 48 of file PDO.php.

References Sabre\CardDAV\Backend\PDO\$pdo.

48  {
49 
50  $this->pdo = $pdo;
51 
52  }

Member Function Documentation

◆ addChange()

Sabre\CardDAV\Backend\PDO::addChange (   $addressBookId,
  $objectUri,
  $operation 
)
protected

Adds a change record to the addressbookchanges table.

Parameters
mixed$addressBookId
string$objectUri
int$operation1 = add, 2 = modify, 3 = delete
Returns
void

Definition at line 535 of file PDO.php.

References $stmt.

Referenced by Sabre\CardDAV\Backend\PDO\createCard(), Sabre\CardDAV\Backend\PDO\deleteCard(), Sabre\CardDAV\Backend\PDO\updateAddressBook(), and Sabre\CardDAV\Backend\PDO\updateCard().

535  {
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  }
$stmt
+ Here is the caller graph for this function:

◆ createAddressBook()

Sabre\CardDAV\Backend\PDO::createAddressBook (   $principalUri,
  $url,
array  $properties 
)

Creates a new address book.

Parameters
string$principalUri
string$urlJust the 'basename' of the url.
array$properties
Returns
int Last insert id

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 156 of file PDO.php.

References $query, $stmt, $url, $values, and Sabre\CardDAV\Plugin\NS_CARDDAV.

156  {
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  }
$stmt
const NS_CARDDAV
xml namespace for CardDAV elements
Definition: Plugin.php:33
$values
$query
$url

◆ createCard()

Sabre\CardDAV\Backend\PDO::createCard (   $addressBookId,
  $cardUri,
  $cardData 
)

Creates a new card.

The addressbook id will be passed as the first argument. This is the same id as it is returned from the getAddressBooksForUser method.

The cardUri is a base uri, and doesn't include the full path. The cardData argument is the vcard body, and is passed as a string.

It is possible to return an ETag from this method. This ETag is for the newly created resource, and must be enclosed with double quotes (that is, the string itself must contain the double quotes).

You should only return the ETag if you store the carddata as-is. If a subsequent GET request on the same card does not have the same body, byte-by-byte and you did return an ETag here, clients tend to get confused.

If you don't return an ETag, you can just return null.

Parameters
mixed$addressBookId
string$cardUri
string$cardData
Returns
string|null

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 325 of file PDO.php.

References $stmt, and Sabre\CardDAV\Backend\PDO\addChange().

325  {
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  }
addChange($addressBookId, $objectUri, $operation)
Adds a change record to the addressbookchanges table.
Definition: PDO.php:535
$stmt
+ Here is the call graph for this function:

◆ deleteAddressBook()

Sabre\CardDAV\Backend\PDO::deleteAddressBook (   $addressBookId)

Deletes an entire addressbook and all its contents.

Parameters
int$addressBookId
Returns
void

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 195 of file PDO.php.

References $stmt.

195  {
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  }
$stmt

◆ deleteCard()

Sabre\CardDAV\Backend\PDO::deleteCard (   $addressBookId,
  $cardUri 
)

Deletes a card.

Parameters
mixed$addressBookId
string$cardUri
Returns
bool

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 398 of file PDO.php.

References $stmt, and Sabre\CardDAV\Backend\PDO\addChange().

398  {
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  }
addChange($addressBookId, $objectUri, $operation)
Adds a change record to the addressbookchanges table.
Definition: PDO.php:535
$stmt
+ Here is the call graph for this function:

◆ getAddressBooksForUser()

Sabre\CardDAV\Backend\PDO::getAddressBooksForUser (   $principalUri)

Returns the list of addressbooks for a specific user.

Parameters
string$principalUri
Returns
array

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 60 of file PDO.php.

References $row, $stmt, and Sabre\CardDAV\Plugin\NS_CARDDAV.

60  {
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  }
$stmt
const NS_CARDDAV
xml namespace for CardDAV elements
Definition: Plugin.php:33
$row

◆ getCard()

Sabre\CardDAV\Backend\PDO::getCard (   $addressBookId,
  $cardUri 
)

Returns a specific card.

The same set of properties must be returned as with getCards. The only exception is that 'carddata' is absolutely required.

If the card does not exist, you must return false.

Parameters
mixed$addressBookId
string$cardUri
Returns
array

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 254 of file PDO.php.

References $result, and $stmt.

254  {
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  }
$result
$stmt

◆ getCards()

Sabre\CardDAV\Backend\PDO::getCards (   $addressbookId)

Returns all cards for a specific addressbook id.

This method should return the following properties for each card:

  • carddata - raw vcard data
  • uri - Some unique url
  • lastmodified - A unix timestamp

It's recommended to also return the following properties:

  • etag - A unique etag. This must change every time the card changes.
  • size - The size of the card in bytes.

If these last two properties are provided, less time will be spent calculating them. If they are specified, you can also ommit carddata. This may speed up certain requests, especially with large cards.

Parameters
mixed$addressbookId
Returns
array

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 227 of file PDO.php.

References $result, $row, and $stmt.

227  {
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  }
$result
$stmt
$row

◆ getChangesForAddressBook()

Sabre\CardDAV\Backend\PDO::getChangesForAddressBook (   $addressBookId,
  $syncToken,
  $syncLevel,
  $limit = null 
)

The getChanges method returns all the changes that have happened, since the specified syncToken in the specified address book.

This function should return an array, such as the following:

[ 'syncToken' => 'The current synctoken', 'added' => [ 'new.txt', ], 'modified' => [ 'updated.txt', ], 'deleted' => [ 'foo.php.bak', 'old.txt' ] ];

The returned syncToken property should reflect the current syncToken of the addressbook, as reported in the {http://sabredav.org/ns}sync-token property. This is needed here too, to ensure the operation is atomic.

If the $syncToken argument is specified as null, this is an initial sync, and all members should be reported.

The modified property is an array of nodenames that have changed since the last token.

The deleted property is an array with nodenames, that have been deleted from collection.

The $syncLevel argument is basically the 'depth' of the report. If it's 1, you only have to report changes that happened only directly in immediate descendants. If it's 2, it should also include changes from the nodes below the child collections. (grandchildren)

The $limit argument allows a client to specify how many results should be returned at most. If the limit is not specified, it should be treated as infinite.

If the limit (infinite or not) is higher than you're willing to return, you should throw a Sabre() exception.

If the syncToken is expired (due to data cleanup) or unknown, you must return null.

The limit is 'suggestive'. You are free to ignore it.

Parameters
string$addressBookId
string$syncToken
int$syncLevel
int$limit
Returns
array

Implements Sabre\CardDAV\Backend\SyncSupport.

Definition at line 465 of file PDO.php.

References $query, $result, $row, and $stmt.

465  {
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  }
$result
$stmt
$query
$row

◆ getMultipleCards()

Sabre\CardDAV\Backend\PDO::getMultipleCards (   $addressBookId,
array  $uris 
)

Returns a list of cards.

This method should work identical to getCard, but instead return all the cards in the list as an array.

If the backend supports this, it may allow for some speed-ups.

Parameters
mixed$addressBookId
array$uris
Returns
array

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 281 of file PDO.php.

References $query, $result, $row, and $stmt.

281  {
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  }
$result
$stmt
$query
$row

◆ updateAddressBook()

Sabre\CardDAV\Backend\PDO::updateAddressBook (   $addressBookId,
\Sabre\DAV\PropPatch  $propPatch 
)

Updates properties for an address book.

The list of mutations is stored in a Sabre object. To do the actual updates, you must tell this object which properties you're going to process with the handle() method.

Calling the handle method is like telling the PropPatch object "I promise I can handle updating this property".

Read the PropPatch documentation for more info and examples.

Parameters
string$addressBookId
\Sabre\DAV\PropPatch$propPatch
Returns
void

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 102 of file PDO.php.

References $key, $query, $stmt, Sabre\CardDAV\Backend\PDO\addChange(), and Sabre\CardDAV\Plugin\NS_CARDDAV.

102  {
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  }
addChange($addressBookId, $objectUri, $operation)
Adds a change record to the addressbookchanges table.
Definition: PDO.php:535
$stmt
const NS_CARDDAV
xml namespace for CardDAV elements
Definition: Plugin.php:33
$query
$key
Definition: croninfo.php:18
+ Here is the call graph for this function:

◆ updateCard()

Sabre\CardDAV\Backend\PDO::updateCard (   $addressBookId,
  $cardUri,
  $cardData 
)

Updates a card.

The addressbook id will be passed as the first argument. This is the same id as it is returned from the getAddressBooksForUser method.

The cardUri is a base uri, and doesn't include the full path. The cardData argument is the vcard body, and is passed as a string.

It is possible to return an ETag from this method. This ETag should match that of the updated resource, and must be enclosed with double quotes (that is: the string itself must contain the actual quotes).

You should only return the ETag if you store the carddata as-is. If a subsequent GET request on the same card does not have the same body, byte-by-byte and you did return an ETag here, clients tend to get confused.

If you don't return an ETag, you can just return null.

Parameters
mixed$addressBookId
string$cardUri
string$cardData
Returns
string|null

Implements Sabre\CardDAV\Backend\BackendInterface.

Definition at line 371 of file PDO.php.

References $stmt, and Sabre\CardDAV\Backend\PDO\addChange().

371  {
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  }
addChange($addressBookId, $objectUri, $operation)
Adds a change record to the addressbookchanges table.
Definition: PDO.php:535
$stmt
+ Here is the call graph for this function:

Field Documentation

◆ $addressBookChangesTableName

Sabre\CardDAV\Backend\PDO::$addressBookChangesTableName = 'addressbookchanges'

Definition at line 41 of file PDO.php.

◆ $addressBooksTableName

Sabre\CardDAV\Backend\PDO::$addressBooksTableName = 'addressbooks'

The PDO table name used to store addressbooks.

Definition at line 29 of file PDO.php.

◆ $cardsTableName

Sabre\CardDAV\Backend\PDO::$cardsTableName = 'cards'

The PDO table name used to store cards.

Definition at line 34 of file PDO.php.

◆ $pdo

Sabre\CardDAV\Backend\PDO::$pdo
protected

Definition at line 24 of file PDO.php.

Referenced by Sabre\CardDAV\Backend\PDO\__construct().


The documentation for this class was generated from the following file: