PageRenderTime 38ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/core/Tiki/SabreDav/CardDAVBackend.php

https://gitlab.com/ElvisAns/tiki
PHP | 309 lines | 157 code | 22 blank | 130 comment | 7 complexity | 3eedc4b0b01a4896e3601fdb50590903 MD5 | raw file
  1. <?php
  2. // (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
  3. //
  4. // All Rights Reserved. See copyright.txt for details and a complete list of authors.
  5. // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
  6. // $Id$
  7. namespace Tiki\SabreDav;
  8. use Sabre\CardDAV;
  9. use Sabre\DAV;
  10. use TikiLib;
  11. use Perms;
  12. /**
  13. * Tiki database CardDAV backend.
  14. *
  15. * This backend is used to store address book data in Tiki MySQL database.
  16. * It allows provides support for 2 system-level address books:
  17. * 1. webmail contacts
  18. * 2. user system data
  19. */
  20. class CardDAVBackend extends CardDAV\Backend\AbstractBackend
  21. {
  22. /**
  23. * Returns the list of addressbooks for a specific user.
  24. *
  25. * @param string $principalUri
  26. *
  27. * @return array
  28. */
  29. public function getAddressBooksForUser($principalUri)
  30. {
  31. global $user;
  32. $principal = PrincipalBackend::mapUriToUser($principalUri);
  33. if ($principal != $user) {
  34. throw new DAV\Exception\Forbidden("You don't have permission to view this user's address books.");
  35. }
  36. $result = [];
  37. $addressBookTypes = AddressBookType\Factory::all($user);
  38. foreach ($addressBookTypes as $abt) {
  39. if (! $abt->isEnabled()) {
  40. continue;
  41. }
  42. foreach ($abt->getAddressBooks() as $ab) {
  43. $result[] = $ab;
  44. }
  45. }
  46. return $result;
  47. }
  48. /**
  49. * Updates properties for an address book.
  50. *
  51. * The list of mutations is stored in a Sabre\DAV\PropPatch object.
  52. * To do the actual updates, you must tell this object which properties
  53. * you're going to process with the handle() method.
  54. *
  55. * Calling the handle method is like telling the PropPatch object "I
  56. * promise I can handle updating this property".
  57. *
  58. * Read the PropPatch documentation for more info and examples.
  59. *
  60. * @param string $addressBookId
  61. * @param \Sabre\DAV\PropPatch $propPatch
  62. */
  63. public function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch)
  64. {
  65. global $user;
  66. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  67. if (! $addressBook instanceof AddressBookType\Custom) {
  68. throw new DAV\Exception\Forbidden("Address book properties are read-only.");
  69. }
  70. $supportedProperties = [
  71. '{DAV:}displayname',
  72. '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description',
  73. ];
  74. $propPatch->handle($supportedProperties, function ($mutations) use ($addressBookId) {
  75. $updates = [];
  76. foreach ($mutations as $property => $newValue) {
  77. switch ($property) {
  78. case '{DAV:}displayname':
  79. $updates['name'] = $newValue;
  80. break;
  81. case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description':
  82. $updates['description'] = $newValue;
  83. break;
  84. }
  85. }
  86. TikiLib::lib('addressbook')->update_address_book($addressBookId, $updates);
  87. return true;
  88. });
  89. }
  90. /**
  91. * Creates a new address book.
  92. *
  93. * @param string $principalUri
  94. * @param string $url just the 'basename' of the url
  95. * @param array $properties
  96. *
  97. * @return int Last insert id
  98. */
  99. public function createAddressBook($principalUri, $url, array $properties)
  100. {
  101. global $user;
  102. $principal = PrincipalBackend::mapUriToUser($principalUri);
  103. if ($principal != $user) {
  104. throw new DAV\Exception\Forbidden("You don't have permission to create address books for this user.");
  105. }
  106. $values = [
  107. 'name' => null,
  108. 'description' => null,
  109. 'user' => $user,
  110. 'uri' => $url,
  111. ];
  112. foreach ($properties as $property => $newValue) {
  113. switch ($property) {
  114. case '{DAV:}displayname':
  115. $values['name'] = $newValue;
  116. break;
  117. case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description':
  118. $values['description'] = $newValue;
  119. break;
  120. default:
  121. throw new DAV\Exception\BadRequest('Unknown property: ' . $property);
  122. }
  123. }
  124. return TikiLib::lib('addressbook')->update_address_book(0, $values);
  125. }
  126. /**
  127. * Deletes an entire addressbook and all its contents.
  128. *
  129. * @param int $addressBookId
  130. */
  131. public function deleteAddressBook($addressBookId)
  132. {
  133. global $user;
  134. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  135. if (! $addressBook instanceof AddressBookType\Custom) {
  136. throw new DAV\Exception\Forbidden("Address book cannot be deleted.");
  137. }
  138. TikiLib::lib('addressbook')->delete_address_book($addressBookId);
  139. }
  140. /**
  141. * Returns all cards for a specific addressbook id.
  142. *
  143. * This method should return the following properties for each card:
  144. * * carddata - raw vcard data
  145. * * uri - Some unique url
  146. * * lastmodified - A unix timestamp
  147. *
  148. * It's recommended to also return the following properties:
  149. * * etag - A unique etag. This must change every time the card changes.
  150. * * size - The size of the card in bytes.
  151. *
  152. * If these last two properties are provided, less time will be spent
  153. * calculating them. If they are specified, you can also ommit carddata.
  154. * This may speed up certain requests, especially with large cards.
  155. *
  156. * @param mixed $addressBookId
  157. *
  158. * @return array
  159. */
  160. public function getCards($addressBookId)
  161. {
  162. global $user;
  163. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  164. return $addressBook->getCards();
  165. }
  166. /**
  167. * Returns a specific card.
  168. *
  169. * The same set of properties must be returned as with getCards. The only
  170. * exception is that 'carddata' is absolutely required.
  171. *
  172. * If the card does not exist, you must return false.
  173. *
  174. * @param mixed $addressBookId
  175. * @param string $cardUri
  176. *
  177. * @return array
  178. */
  179. public function getCard($addressBookId, $cardUri)
  180. {
  181. return array_shift($this->getMultipleCards($addressBookId, [$cardUri]));
  182. }
  183. /**
  184. * Returns a list of cards.
  185. *
  186. * This method should work identical to getCard, but instead return all the
  187. * cards in the list as an array.
  188. *
  189. * If the backend supports this, it may allow for some speed-ups.
  190. *
  191. * @param mixed $addressBookId
  192. * @param array $uris
  193. *
  194. * @return array
  195. */
  196. public function getMultipleCards($addressBookId, array $uris)
  197. {
  198. global $user;
  199. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  200. return $addressBook->getCards($uris);
  201. }
  202. /**
  203. * Creates a new card.
  204. *
  205. * The addressbook id will be passed as the first argument. This is the
  206. * same id as it is returned from the getAddressBooksForUser method.
  207. *
  208. * The cardUri is a base uri, and doesn't include the full path. The
  209. * cardData argument is the vcard body, and is passed as a string.
  210. *
  211. * It is possible to return an ETag from this method. This ETag is for the
  212. * newly created resource, and must be enclosed with double quotes (that
  213. * is, the string itself must contain the double quotes).
  214. *
  215. * You should only return the ETag if you store the carddata as-is. If a
  216. * subsequent GET request on the same card does not have the same body,
  217. * byte-by-byte and you did return an ETag here, clients tend to get
  218. * confused.
  219. *
  220. * If you don't return an ETag, you can just return null.
  221. *
  222. * @param mixed $addressBookId
  223. * @param string $cardUri
  224. * @param string $cardData
  225. *
  226. * @return string|null
  227. */
  228. public function createCard($addressBookId, $cardUri, $cardData)
  229. {
  230. global $user;
  231. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  232. return $addressBook->createCard($cardUri, $cardData);
  233. }
  234. /**
  235. * Updates a card.
  236. *
  237. * The addressbook id will be passed as the first argument. This is the
  238. * same id as it is returned from the getAddressBooksForUser method.
  239. *
  240. * The cardUri is a base uri, and doesn't include the full path. The
  241. * cardData argument is the vcard body, and is passed as a string.
  242. *
  243. * It is possible to return an ETag from this method. This ETag should
  244. * match that of the updated resource, and must be enclosed with double
  245. * quotes (that is: the string itself must contain the actual quotes).
  246. *
  247. * You should only return the ETag if you store the carddata as-is. If a
  248. * subsequent GET request on the same card does not have the same body,
  249. * byte-by-byte and you did return an ETag here, clients tend to get
  250. * confused.
  251. *
  252. * If you don't return an ETag, you can just return null.
  253. *
  254. * @param mixed $addressBookId
  255. * @param string $cardUri
  256. * @param string $cardData
  257. *
  258. * @return string|null
  259. */
  260. public function updateCard($addressBookId, $cardUri, $cardData)
  261. {
  262. global $user;
  263. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  264. return $addressBook->updateCard($cardUri, $cardData);
  265. }
  266. /**
  267. * Deletes a card.
  268. *
  269. * @param mixed $addressBookId
  270. * @param string $cardUri
  271. *
  272. * @return bool
  273. */
  274. public function deleteCard($addressBookId, $cardUri)
  275. {
  276. global $user;
  277. $addressBook = AddressBookType\Factory::fromId($addressBookId, $user);
  278. return $addressBook->updateCard($cardUri, $cardData);
  279. }
  280. }