]> git.mxchange.org Git - friendica-addons.git/blob - dav/dav_carddav_backend_friendica_community.inc.php
Libertree: Posting works again (new "source" field)
[friendica-addons.git] / dav / dav_carddav_backend_friendica_community.inc.php
1 <?php
2
3 class Sabre_CardDAV_Backend_FriendicaCommunity extends Sabre_CardDAV_Backend_Abstract
4 {
5
6         /**
7          * Sets up the object
8          */
9         public function __construct()
10         {
11
12         }
13
14         /**
15          * Returns the list of addressbooks for a specific user.
16          *
17          * @param string $principalUri
18          * @return array
19          */
20         public function getAddressBooksForUser($principalUri)
21         {
22                 $uid = dav_compat_principal2uid($principalUri);
23
24                 $addressBooks = array();
25
26                 $books = q("SELECT ctag FROM %s%saddressbooks_community WHERE uid = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($uid));
27                 if (count($books) == 0) {
28                         q("INSERT INTO %s%saddressbooks_community (uid, ctag) VALUES (%d, 1)", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($uid));
29                         $ctag = 1;
30                 } else {
31                         $ctag = $books[0]["ctag"];
32                 }
33                 $addressBooks[] = array(
34                         'id'                                                                => CARDDAV_NAMESPACE_COMMUNITYCONTACTS . "-" . $uid,
35                         'uri'                                                               => "friendica",
36                         'principaluri'                                                      => $principalUri,
37                         '{DAV:}displayname'                                                 => t("Friendica-Contacts"),
38                         '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => t("Your Friendica-Contacts"),
39                         '{http://calendarserver.org/ns/}getctag'                            => $ctag,
40                         '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data'  =>
41                         new Sabre_CardDAV_Property_SupportedAddressData(),
42                 );
43
44                 return $addressBooks;
45
46         }
47
48
49         /**
50          * Updates an addressbook's properties
51          *
52          * See Sabre_DAV_IProperties for a description of the mutations array, as
53          * well as the return value.
54          *
55          * @param string $addressBookId
56          * @param array $mutations
57          * @throws Sabre_DAV_Exception_Forbidden
58          * @see Sabre_DAV_IProperties::updateProperties
59          * @return bool|array
60          */
61         public function updateAddressBook($addressBookId, array $mutations)
62         {
63                 throw new Sabre_DAV_Exception_Forbidden();
64         }
65
66         /**
67          * Creates a new address book
68          *
69          * @param string $principalUri
70          * @param string $url Just the 'basename' of the url.
71          * @param array $properties
72          * @throws Sabre_DAV_Exception_Forbidden
73          * @return void
74          */
75         public function createAddressBook($principalUri, $url, array $properties)
76         {
77                 throw new Sabre_DAV_Exception_Forbidden();
78         }
79
80         /**
81          * Deletes an entire addressbook and all its contents
82          *
83          * @param int $addressBookId
84          * @throws Sabre_DAV_Exception_Forbidden
85          * @return void
86          */
87         public function deleteAddressBook($addressBookId)
88         {
89                 throw new Sabre_DAV_Exception_Forbidden();
90         }
91
92
93         /**
94          * @param array $contact
95          * @return array
96          */
97         private function dav_contactarr2vcardsource($contact)
98         {
99                 $name        = explode(" ", $contact["name"]);
100                 $first_name  = $last_name = "";
101                 $middle_name = array();
102                 $num         = count($name);
103                 for ($i = 0; $i < $num && $first_name == ""; $i++) if ($name[$i] != "") {
104                         $first_name = $name[$i];
105                         unset($name[$i]);
106                 }
107                 for ($i = $num - 1; $i >= 0 && $last_name == ""; $i--) if (isset($name[$i]) && $name[$i] != "") {
108                         $last_name = $name[$i];
109                         unset($name[$i]);
110                 }
111                 foreach ($name as $n) if ($n != "") $middle_name[] = $n;
112                 $vcarddata              = new vcard_source_data($first_name, implode(" ", $middle_name), $last_name);
113                 $vcarddata->homepages[] = new vcard_source_data_homepage("pref", $contact["url"]);
114                 $vcarddata->last_update = ($contact["last-update"] > 0 ? $contact["last-update"] : $contact["created"]);
115
116                 $photo = q("SELECT * FROM photo WHERE `contact-id` = %d ORDER BY scale DESC", $contact["id"]); //prefer size 80x80
117                 if ($photo && count($photo) > 0) {
118                         $photodata             = new vcard_source_data_photo();
119                         $photodata->width      = $photo[0]["width"];
120                         $photodata->height     = $photo[0]["height"];
121                         $photodata->type       = "JPEG";
122                         $photodata->binarydata = $photo[0]["data"];
123                         $vcarddata->photo      = $photodata;
124                 }
125
126                 switch ($contact["network"]) {
127                         case "face":
128                                 $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("facebook", $contact["notify"], "http://www.facebook.com/" . $contact["notify"]);
129                                 break;
130                         case "dfrn":
131                                 $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("dfrn", $contact["nick"], $contact["url"]);
132                                 break;
133                         case "twitter":
134                                 $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("twitter", $contact["nick"], "http://twitter.com/" . $contact["nick"]); // @TODO Stimmt das?
135                                 break;
136                 }
137
138                 $vcard = vcard_source_compile($vcarddata);
139                 return array(
140                         "id"           => $contact["id"],
141                         "carddata"     => $vcard,
142                         "uri"          => $contact["id"] . ".vcf",
143                         "lastmodified" => wdcal_mySql2PhpTime($vcarddata->last_update),
144                         "etag"         => md5($vcard),
145                         "size"         => strlen($vcard),
146                 );
147
148         }
149
150         /**
151          * @param int $uid
152          * @param array|int[] $exclude_ids
153          * @return array
154          */
155         private function dav_getCommunityContactsVCards($uid = 0, $exclude_ids = array())
156         {
157                 $notin    = (count($exclude_ids) > 0 ? " AND id NOT IN (" . implode(", ", $exclude_ids) . ") " : "");
158                 $uid      = IntVal($uid);
159                 $contacts = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0 $notin ORDER BY `name` ASC", $uid);
160
161                 $retdata = array();
162                 foreach ($contacts as $contact) {
163                         $x            = $this->dav_contactarr2vcardsource($contact);
164                         $x["contact"] = $contact["id"];
165                         $retdata[]    = $x;
166                 }
167                 return $retdata;
168         }
169
170
171         /**
172          * Returns all cards for a specific addressbook id.
173          *
174          * This method should return the following properties for each card:
175          *   * carddata - raw vcard data
176          *   * uri - Some unique url
177          *   * lastmodified - A unix timestamp
178          *
179          * It's recommended to also return the following properties:
180          *   * etag - A unique etag. This must change every time the card changes.
181          *   * size - The size of the card in bytes.
182          *
183          * If these last two properties are provided, less time will be spent
184          * calculating them. If they are specified, you can also ommit carddata.
185          * This may speed up certain requests, especially with large cards.
186          *
187          * @param string $addressbookId
188          * @return array
189          */
190         public function getCards($addressbookId)
191         {
192                 $add = explode("-", $addressbookId);
193
194                 $indb           = q('SELECT id, carddata, uri, lastmodified, etag, size, contact, manually_deleted FROM %s%scards WHERE namespace = %d AND namespace_id = %d',
195                         CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($add[0]), IntVal($add[1])
196                 );
197                 $found_contacts = array();
198                 $contacts       = array();
199                 foreach ($indb as $x) {
200                         if ($x["manually_deleted"] == 0) $contacts[] = $x;
201                         $found_contacts[] = IntVal($x["contact"]);
202                 }
203                 $new_found = $this->dav_getCommunityContactsVCards($add[1], $found_contacts);
204                 foreach ($new_found as $new) {
205                         q("INSERT INTO %s%scards (namespace, namespace_id, contact, carddata, uri, lastmodified, manually_edited, manually_deleted, etag, size)
206                                         VALUES (%d, %d, %d, '%s', '%s', %d, 0, 0, '%s', %d)", CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
207                                 IntVal($add[0]), IntVal($add[1]), IntVal($new["contact"]), dbesc($new["carddata"]), dbesc($new["uri"]), time(), md5($new["carddata"]), strlen($new["carddata"])
208                         );
209                 }
210                 return array_merge($contacts, $new_found);
211         }
212
213         /**
214          * Returns a specfic card.
215          *
216          * The same set of properties must be returned as with getCards. The only
217          * exception is that 'carddata' is absolutely required.
218          *
219          * @param mixed $addressBookId
220          * @param string $cardUri
221          * @throws Sabre_DAV_Exception_NotFound
222          * @return array
223          */
224         public function getCard($addressBookId, $cardUri)
225         {
226                 $x = explode("-", $addressBookId);
227                 $x = q("SELECT id, carddata, uri, lastmodified, etag, size FROM %s%scards WHERE namespace = %d AND namespace_id = %d AND uri = '%s'",
228                         CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[0]), IntVal($x[1]), dbesc($cardUri));
229                 if (count($x) == 0) throw new Sabre_DAV_Exception_NotFound();
230                 return $x[0];
231         }
232
233         /**
234          * Creates a new card.
235          *
236          * The addressbook id will be passed as the first argument. This is the
237          * same id as it is returned from the getAddressbooksForUser method.
238          *
239          * The cardUri is a base uri, and doesn't include the full path. The
240          * cardData argument is the vcard body, and is passed as a string.
241          *
242          * It is possible to return an ETag from this method. This ETag is for the
243          * newly created resource, and must be enclosed with double quotes (that
244          * is, the string itself must contain the double quotes).
245          *
246          * You should only return the ETag if you store the carddata as-is. If a
247          * subsequent GET request on the same card does not have the same body,
248          * byte-by-byte and you did return an ETag here, clients tend to get
249          * confused.
250          *
251          * If you don't return an ETag, you can just return null.
252          *
253          * @param string $addressBookId
254          * @param string $cardUri
255          * @param string $cardData
256          * @throws Sabre_DAV_Exception_Forbidden
257          * @return string
258          */
259         public function createCard($addressBookId, $cardUri, $cardData)
260         {
261                 throw new Sabre_DAV_Exception_Forbidden();
262         }
263
264         /**
265          * Updates a card.
266          *
267          * The addressbook id will be passed as the first argument. This is the
268          * same id as it is returned from the getAddressbooksForUser method.
269          *
270          * The cardUri is a base uri, and doesn't include the full path. The
271          * cardData argument is the vcard body, and is passed as a string.
272          *
273          * It is possible to return an ETag from this method. This ETag should
274          * match that of the updated resource, and must be enclosed with double
275          * quotes (that is: the string itself must contain the actual quotes).
276          *
277          * You should only return the ETag if you store the carddata as-is. If a
278          * subsequent GET request on the same card does not have the same body,
279          * byte-by-byte and you did return an ETag here, clients tend to get
280          * confused.
281          *
282          * If you don't return an ETag, you can just return null.
283          *
284          * @param string $addressBookId
285          * @param string $cardUri
286          * @param string $cardData
287          * @throws Sabre_DAV_Exception_Forbidden
288          * @return string|null
289          */
290         public function updateCard($addressBookId, $cardUri, $cardData)
291         {
292                 $x = explode("-", $addressBookId);
293
294                 $etag = md5($cardData);
295                 q("UPDATE %s%scards SET carddata = '%s', lastmodified = %d, etag = '%s', size = %d, manually_edited = 1 WHERE uri = '%s' AND namespace = %d AND namespace_id =%d",
296                         CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), time(), $etag, strlen($cardData), dbesc($cardUri), IntVal($x[10]), IntVal($x[1])
297                 );
298                 q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
299
300                 return '"' . $etag . '"';
301         }
302
303         /**
304          * Deletes a card
305          *
306          * @param string $addressBookId
307          * @param string $cardUri
308          * @throws Sabre_DAV_Exception_Forbidden
309          * @return bool
310          */
311         public function deleteCard($addressBookId, $cardUri)
312         {
313                 $x = explode("-", $addressBookId);
314
315                 q("UPDATE %s%scards SET manually_deleted = 1 WHERE namespace = %d AND namespace_id = %d AND uri = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[0]), IntVal($x[1]), dbesc($cardUri));
316                 q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
317
318                 return true;
319         }
320 }