Blame view

sources/apps/contacts/lib/backend/abstractbackend.php 13.9 KB
d1bafeea1   Kload   [fix] Upgrade to ...
1
2
3
4
5
  <?php
  /**
   * ownCloud - Base class for Contacts backends
   *
   * @author Thomas Tanghus
6d9380f96   Cédric Dupont   Update sources OC...
6
   * @copyright 2013-2014 Thomas Tanghus (thomas@tanghus.net)
d1bafeea1   Kload   [fix] Upgrade to ...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   *
   */
  
  namespace OCA\Contacts\Backend;
  
  use OCA\Contacts\VObject\VCard;
  
  /**
6d9380f96   Cédric Dupont   Update sources OC...
28
   * Subclass this class for address book backends.
d1bafeea1   Kload   [fix] Upgrade to ...
29
   */
d1bafeea1   Kload   [fix] Upgrade to ...
30
31
32
  abstract class AbstractBackend {
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  	* The following methods MUST be implemented:
  	*
  	* @method array getAddressBooksForUser(array $options = array())
  	* @method array|null getAddressBook(string $addressbookid, array $options = array())
  	* @method array getContacts(string $addressbookid, array $options = array())
  	* @method array|null getContact(string $addressbookid, mixed $id, array $options = array())
  	* The following methods MAY be implemented:
  	* @method bool hasAddressBook(string $addressbookid)
  	* @method bool updateAddressBook(string $addressbookid, array $updates, array $options = array())
  	* @method string createAddressBook(array $properties, array $options = array())
  	* @method bool deleteAddressBook(string $addressbookid, array $options = array())
  	* @method int lastModifiedAddressBook(string $addressbookid)
  	* @method array numContacts(string $addressbookid)
  	* @method bool updateContact(string $addressbookid, string $id, VCard $contact, array $options = array())
  	* @method string createContact(string $addressbookid, VCard $contact, array $properties)
  	* @method bool deleteContact(string $addressbookid, string $id, array $options = array())
  	* @method int lastModifiedContact(string $addressbookid)
  	*/
  
  	/**
d1bafeea1   Kload   [fix] Upgrade to ...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  	 * The name of the backend.
  	 * @var string
  	 */
  	public $name;
  
  	/**
  	 * The current usert.
  	 * @var string
  	 */
  	public $userid;
  
  	protected $possibleContactPermissions = array(
  		\OCP\PERMISSION_CREATE 	=> 'createContact',
  		\OCP\PERMISSION_READ	=> 'getContact',
  		\OCP\PERMISSION_UPDATE	=> 'updateContact',
  		\OCP\PERMISSION_DELETE 	=> 'deleteContact',
  	);
  
  	protected $possibleAddressBookPermissions = array(
  		\OCP\PERMISSION_CREATE 	=> 'createAddressBook',
  		\OCP\PERMISSION_READ	=> 'getAddressBook',
  		\OCP\PERMISSION_UPDATE	=> 'updateAddressBook',
  		\OCP\PERMISSION_DELETE 	=> 'deleteAddressBook',
  	);
  
  	/**
  	* Sets up the backend
  	*
  	*/
  	public function __construct($userid = null) {
  		$this->userid = $userid ? $userid : \OCP\User::getUser();
  	}
  
  	/**
  	* @brief Get all possible permissions for contacts based on what the backend implements.
  	* @returns bitwise-or'ed actions
  	*
  	* Returns the supported actions as an int to be
  	* compared with \OCP\PERMISSION_CREATE etc.
  	*/
  	protected function getContactPermissions() {
  		$permissions = 0;
6d9380f96   Cédric Dupont   Update sources OC...
95
96
  
  		foreach ($this->possibleContactPermissions as $permission => $methodName) {
d1bafeea1   Kload   [fix] Upgrade to ...
97
98
99
  			if(method_exists($this, $methodName)) {
  				$permissions |= $permission;
  			}
6d9380f96   Cédric Dupont   Update sources OC...
100

d1bafeea1   Kload   [fix] Upgrade to ...
101
  		}
6d9380f96   Cédric Dupont   Update sources OC...
102
  		//\OCP\Util::writeLog('contacts', __METHOD__.', permissions' . $permissions, \OCP\Util::DEBUG);
d1bafeea1   Kload   [fix] Upgrade to ...
103
104
105
106
107
108
109
110
111
112
113
  		return $permissions;
  	}
  
  	/**
  	* @brief Get all permissions for address book based on what the backend implements.
  	* @returns bitwise-or'ed actions
  	*
  	* Returns the supported actions as int to be
  	* compared with \OCP\PERMISSION_CREATE etc.
  	*/
  	protected function getAddressBookPermissions() {
6d9380f96   Cédric Dupont   Update sources OC...
114

d1bafeea1   Kload   [fix] Upgrade to ...
115
  		$permissions = 0;
6d9380f96   Cédric Dupont   Update sources OC...
116
117
118
  
  		foreach ($this->possibleAddressBookPermissions as $permission => $methodName) {
  			if (method_exists($this, $methodName)) {
d1bafeea1   Kload   [fix] Upgrade to ...
119
120
  				$permissions |= $permission;
  			}
6d9380f96   Cédric Dupont   Update sources OC...
121

d1bafeea1   Kload   [fix] Upgrade to ...
122
  		}
6d9380f96   Cédric Dupont   Update sources OC...
123
  		//\OCP\Util::writeLog('contacts', __METHOD__.', permissions' . $permissions, \OCP\Util::DEBUG);
d1bafeea1   Kload   [fix] Upgrade to ...
124
125
126
127
128
129
130
131
132
133
134
135
  		return $permissions;
  	}
  
  	/**
  	* @brief Check if backend implements action for contacts
  	* @param $actions bitwise-or'ed actions
  	* @returns boolean
  	*
  	* Returns the supported actions as int to be
  	* compared with \OCP\PERMISSION_CREATE etc.
  	*/
  	public function hasContactMethodFor($permission) {
6d9380f96   Cédric Dupont   Update sources OC...
136

d1bafeea1   Kload   [fix] Upgrade to ...
137
  		return (bool)($this->getContactPermissions() & $permission);
6d9380f96   Cédric Dupont   Update sources OC...
138

d1bafeea1   Kload   [fix] Upgrade to ...
139
140
141
142
143
144
145
146
147
148
149
  	}
  
  	/**
  	* @brief Check if backend implements action for contacts
  	* @param $actions bitwise-or'ed actions
  	* @returns boolean
  	*
  	* Returns the supported actions as int to be
  	* compared with \OCP\PERMISSION_CREATE etc.
  	*/
  	public function hasAddressBookMethodFor($permission) {
6d9380f96   Cédric Dupont   Update sources OC...
150

d1bafeea1   Kload   [fix] Upgrade to ...
151
  		return (bool)($this->getAddressBookPermissions() & $permission);
6d9380f96   Cédric Dupont   Update sources OC...
152

d1bafeea1   Kload   [fix] Upgrade to ...
153
154
155
156
157
158
159
  	}
  
  	/**
  	 * Check if the backend has the address book
  	 *
  	 * This can be reimplemented in the backend to improve performance.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
160
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
161
162
  	 * @return bool
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
163
164
165
  	public function hasAddressBook($addressBookId) {
  
  		return count($this->getAddressBook($addressBookId)) > 0;
d1bafeea1   Kload   [fix] Upgrade to ...
166
167
168
169
170
171
172
173
  	}
  
  	/**
  	 * Returns the number of contacts in an address book.
  	 * Implementations can choose to override this method to either
  	 * get the result more effectively or to return null if the backend
  	 * cannot determine the number.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
174
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
175
176
  	 * @return integer|null
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
177
178
179
  	public function numContacts($addressBookId) {
  
  		return count($this->getContacts($addressBookId));
d1bafeea1   Kload   [fix] Upgrade to ...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  	}
  
  	/**
  	 * Returns the list of addressbooks for a specific user.
  	 *
  	 * The returned arrays MUST contain a unique 'id' for the
  	 * backend and a 'displayname', and it MAY contain a
  	 * 'description'.
  	 *
  	 * @param array $options - Optional (backend specific options)
  	 * @return array
  	 */
  	public abstract function getAddressBooksForUser(array $options = array());
  
  	/**
  	 * Get an addressbook's properties
  	 *
  	 * The returned array MUST contain string: 'displayname',string: 'backend'
  	 * and integer: 'permissions' value using there ownCloud CRUDS constants
  	 * (which MUST be at least \OCP\PERMISSION_READ).
  	 * Currently the only ones supported are 'displayname' and
  	 * 'description', but backends can implement additional.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
203
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
204
205
206
  	 * @param array $options - Optional (backend specific options)
  	 * @return array|null $properties
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
207
  	public abstract function getAddressBook($addressBookId, array $options = array());
d1bafeea1   Kload   [fix] Upgrade to ...
208
209
210
211
212
213
214
215
216
  
  	/**
  	 * Updates an addressbook's properties
  	 *
  	 * The $properties array contains the changes to be made.
  	 *
  	 * Currently the only ones supported are 'displayname' and
  	 * 'description', but backends can implement additional.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
217
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
218
219
220
  	 * @param array $properties
  	 * @param array $options - Optional (backend specific options)
  	 * @return bool
6d9380f96   Cédric Dupont   Update sources OC...
221
  	public function updateAddressBook($addressBookId, array $properties, array $options = array());
d1bafeea1   Kload   [fix] Upgrade to ...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  	 */
  
  	/**
  	 * Creates a new address book
  	 *
  	 * Classes that doesn't support adding address books MUST NOT implement this method.
  	 *
  	 * Currently the only ones supported are 'displayname' and
  	 * 'description', but backends can implement additional.
  	 * 'displayname' MUST be present.
  	 *
  	 * @param array $properties
  	 * @param array $options - Optional (backend specific options)
  	 * @return string|false The ID if the newly created AddressBook or false on error.
  	public function createAddressBook(array $properties, array $options = array());
  	 */
  
  	/**
  	 * Deletes an entire address book and all its contents
  	 *
  	 * Classes that doesn't support deleting address books MUST NOT implement this method.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
244
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
245
246
  	 * @param array $options - Optional (backend specific options)
  	 * @return bool
6d9380f96   Cédric Dupont   Update sources OC...
247
  	public function deleteAddressBook($addressBookId, array $options = array());
d1bafeea1   Kload   [fix] Upgrade to ...
248
249
250
251
252
253
254
255
  	 */
  
  	/**
  	 * @brief Get the last modification time for an address book.
  	 *
  	 * Must return a UNIX time stamp or null if the backend
  	 * doesn't support it.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
256
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
257
258
  	 * @returns int | null
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
259
  	public function lastModifiedAddressBook($addressBookId) {
d1bafeea1   Kload   [fix] Upgrade to ...
260
261
262
263
264
265
266
267
268
  	}
  
  	/**
  	 * @brief 'touch' an address book.
  	 *
  	 * If implemented this method must mark the address books
  	 * modification date so lastModifiedAddressBook() can be
  	 * used to invalidate the cache.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
269
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
270
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
271
  	public function setModifiedAddressBook($addressBookId) {
d1bafeea1   Kload   [fix] Upgrade to ...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  	}
  
  	/**
  	 * Returns all contacts for a specific addressbook id.
  	 *
  	 * The returned array MUST contain the unique ID a string value 'id', a string
  	 * value 'displayname', a string value 'owner' and an integer 'permissions' value using there
  	 * ownCloud CRUDS constants (which MUST be at least \OCP\PERMISSION_READ), and SHOULD
  	 * contain the properties of the contact formatted as a vCard 3.0
  	 * https://tools.ietf.org/html/rfc2426 mapped to 'carddata' or as an
  	 * \OCA\Contacts\VObject\VCard object mapped to 'vcard'.
  	 *
  	 * Example:
  	 *
  	 * array(
  	 *   0 => array('id' => '4e111fef5df', 'owner' => 'foo', 'permissions' => 1, 'displayname' => 'John Q. Public', 'vcard' => $vobject),
  	 *   1 => array('id' => 'bbcca2d1535', 'owner' => 'bar', 'permissions' => 32, 'displayname' => 'Jane Doe', 'carddata' => $data)
  	 * );
  	 *
  	 * For contacts that contain loads of data, the 'carddata' or 'vcard' MAY be omitted
  	 * as it can be fetched later.
  	 *
  	 * The following options are supported in the $options array:
  	 *
  	 * - 'limit': An integer value for the number of contacts to fetch in each call.
  	 * - 'offset': The offset to start at.
  	 * - 'omitdata': Whether to fetch the entire carddata or vcard.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
300
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
301
302
303
  	 * @param array $options - Optional options
  	 * @return array
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
304
  	public abstract function getContacts($addressBookId, array $options = array());
d1bafeea1   Kload   [fix] Upgrade to ...
305
306
307
308
309
310
  
  	/**
  	 * Returns a specfic contact.
  	 *
  	 * Same as getContacts except that either 'carddata' or 'vcard' is mandatory.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
311
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
312
313
314
315
  	 * @param mixed $id
  	 * @param array $options - Optional options
  	 * @return array|null
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
316
  	public abstract function getContact($addressBookId, $id, array $options = array());
d1bafeea1   Kload   [fix] Upgrade to ...
317
318
319
320
321
322
  
  	/**
  	 * Creates a new contact
  	 *
  	 * Classes that doesn't support adding contacts MUST NOT implement this method.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
323
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
324
325
326
327
328
329
330
331
332
333
334
  	 * @param VCard $contact
  	 * @param array $options - Optional options
  	 * @return string|bool The identifier for the new contact or false on error.
  	public function createContact($addressbookid, $contact, array $options = array());
  	 */
  
  	/**
  	 * Updates a contact
  	 *
  	 * Classes that doesn't support updating contacts MUST NOT implement this method.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
335
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
336
337
338
339
340
341
342
343
344
345
346
347
  	 * @param mixed $id
  	 * @param VCard $contact
  	 * @param array $options - Optional options
  	 * @return bool
  	public function updateContact($addressbookid, $id, $carddata, array $options = array());
  	 */
  
  	/**
  	 * Deletes a contact
  	 *
  	 * Classes that doesn't support deleting contacts MUST NOT implement this method.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
348
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
349
350
351
352
353
354
355
356
357
358
359
360
  	 * @param mixed $id
  	 * @param array $options - Optional options
  	 * @return bool
  	public function deleteContact($addressbookid, $id, array $options = array());
  	 */
  
  	/**
  	 * @brief Get the last modification time for a contact.
  	 *
  	 * Must return a UNIX time stamp or null if the backend
  	 * doesn't support it.
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
361
  	 * @param string $addressBookId
d1bafeea1   Kload   [fix] Upgrade to ...
362
363
364
  	 * @param mixed $id
  	 * @returns int | null
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
365
  	public function lastModifiedContact($addressBookId, $id) {
d1bafeea1   Kload   [fix] Upgrade to ...
366
367
368
369
370
371
372
373
374
  	}
  	
  	/**
  	 * Creates a unique key for inserting into oc_preferences.
  	 * As IDs can have any length and the key field is limited to 64 chars,
  	 * the IDs are transformed to the first 8 chars of their md5 hash.
  	 * 
  	 * @param string $addressBookId.
  	 * @param string $contactId.
6d9380f96   Cédric Dupont   Update sources OC...
375
  	 * @throws \BadMethodCallException
d1bafeea1   Kload   [fix] Upgrade to ...
376
377
378
379
  	 * @return string
  	 */
  	protected function combinedKey($addressBookId = null, $contactId = null) {
  		$key = $this->name;
6d9380f96   Cédric Dupont   Update sources OC...
380
  		if (!is_null($addressBookId)) {
d1bafeea1   Kload   [fix] Upgrade to ...
381
  			$key .= '_' . substr(md5($addressBookId), 0, 8);
6d9380f96   Cédric Dupont   Update sources OC...
382
383
  
  			if (!is_null($contactId)) {
d1bafeea1   Kload   [fix] Upgrade to ...
384
385
  				$key .= '_' . substr(md5($contactId), 0, 8);
  			}
6d9380f96   Cédric Dupont   Update sources OC...
386
387
  
  		} else if (!is_null($contactId)) {
d1bafeea1   Kload   [fix] Upgrade to ...
388
389
390
  			throw new \BadMethodCallException(
  				__METHOD__ . ' cannot be called with a contact ID but no address book ID'
  			);
6d9380f96   Cédric Dupont   Update sources OC...
391

d1bafeea1   Kload   [fix] Upgrade to ...
392
393
394
395
396
397
398
399
400
401
  		}
  		return $key;
  	}
  
  	/**
  	 * @brief Query whether a backend or an address book is active
  	 * @param string $addressbookid If null it checks whether the backend is activated.
  	 * @return boolean
  	 */
  	public function isActive($addressBookId = null) {
6d9380f96   Cédric Dupont   Update sources OC...
402

d1bafeea1   Kload   [fix] Upgrade to ...
403
404
405
406
407
408
409
410
411
412
413
414
415
  		$key = $this->combinedKey($addressBookId);
  		$key = 'active_' . $key;
  
  		return !!(\OCP\Config::getUserValue($this->userid, 'contacts', $key, 1));
  	}
  
  	/**
  	 * @brief Activate a backend or an address book
  	 * @param bool active
  	 * @param string $addressbookid If null it activates the backend.
  	 * @return boolean
  	 */
  	public function setActive($active, $addressBookId = null) {
6d9380f96   Cédric Dupont   Update sources OC...
416

d1bafeea1   Kload   [fix] Upgrade to ...
417
418
419
420
421
422
423
424
425
426
427
428
429
  		$key = $this->combinedKey($addressBookId);
  		$key = 'active_' . $key;
  
  		$this->setModifiedAddressBook($addressBookId);
  		return \OCP\Config::setUserValue($this->userid, 'contacts', $key, (int)$active);
  	}
  
  	/**
  	 * @brief get all the preferences for the addressbook
  	 * @param string $id
  	 * @return array Format array('param1' => 'value', 'param2' => 'value')
  	 */
  	public function getPreferences($addressBookId) {
6d9380f96   Cédric Dupont   Update sources OC...
430
431
  
  		$key = 'prefs_' . $this->combinedKey($addressBookId);
d1bafeea1   Kload   [fix] Upgrade to ...
432
433
  
  		$data = \OCP\Config::getUserValue($this->userid, 'contacts', $key, false);
6d9380f96   Cédric Dupont   Update sources OC...
434
  		return $data ? json_decode($data, true) : array();
d1bafeea1   Kload   [fix] Upgrade to ...
435
436
437
438
439
440
441
442
443
  	}
  	
  	/**
  	 * @brief sets the preferences for the addressbook given in parameter
  	 * @param string $id
  	 * @param array the preferences, format array('param1' => 'value', 'param2' => 'value')
  	 * @return boolean
  	 */
  	public function setPreferences($addressbookid, array $params) {
6d9380f96   Cédric Dupont   Update sources OC...
444
  		$key = 'prefs_' . $this->combinedKey($addressbookid);
d1bafeea1   Kload   [fix] Upgrade to ...
445
446
447
448
449
450
  
  		$data = json_encode($params);
  		return $data
  			? \OCP\Config::setUserValue($this->userid, 'contacts', $key, $data)
  			: false;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
451
452
453
454
455
456
457
458
  	
  	public function removePreferences($addressbookid) {
  		$key = $this->combinedKey($addressbookid);
  		$key = 'prefs_' . $key;
  		
  		\OC_Preferences::deleteKey( $this->userid, 'contacts', $key );
  		
  	}
d1bafeea1   Kload   [fix] Upgrade to ...
459
  }