3 use Friendica\Core\L10n;
5 class Sabre_CardDAV_Backend_Friendica extends Sabre_CardDAV_Backend_Virtual
9 * @var null|Sabre_CardDAV_Backend_Friendica
11 private static $instance = null;
15 * @return Sabre_CardDAV_Backend_Friendica
17 public static function getInstance() {
18 if (self::$instance == null) {
19 self::$instance = new Sabre_CardDAV_Backend_Friendica();
21 return self::$instance;
28 public function getNamespace()
30 return CARDDAV_NAMESPACE_PRIVATE;
37 public static function getBackendTypeName() {
38 return L10n::t("Friendica-Contacts");
42 * Returns the list of addressbooks for a specific user.
44 * @param string $principalUri
47 public function getAddressBooksForUser($principalUri)
49 $uid = dav_compat_principal2uid($principalUri);
53 $books = q("SELECT id, ctag FROM %s%saddressbooks WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'",
54 CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($uid), dbesc(CARDDAV_FRIENDICA_CONTACT));
55 $ctag = $books[0]["ctag"];
58 'id' => $books[0]["id"],
60 'principaluri' => $principalUri,
61 '{DAV:}displayname' => L10n::t("Friendica-Contacts"),
62 '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => L10n::t("Your Friendica-Contacts"),
63 '{http://calendarserver.org/ns/}getctag' => $ctag,
64 '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data' =>
65 new Sabre_CardDAV_Property_SupportedAddressData(),
74 * @param array $contact
77 private static function dav_contactarr2vcardsource($contact)
79 $name = explode(" ", $contact["name"]);
80 $first_name = $last_name = "";
83 for ($i = 0; $i < $num && $first_name == ""; $i++) if ($name[$i] != "") {
84 $first_name = $name[$i];
87 for ($i = $num - 1; $i >= 0 && $last_name == ""; $i--) if (isset($name[$i]) && $name[$i] != "") {
88 $last_name = $name[$i];
91 foreach ($name as $n) if ($n != "") $middle_name[] = $n;
92 $vcarddata = new vcard_source_data($first_name, implode(" ", $middle_name), $last_name);
93 $vcarddata->homepages[] = new vcard_source_data_homepage("pref", $contact["url"]);
94 $vcarddata->last_update = ($contact["last-update"] > 0 ? $contact["last-update"] : $contact["created"]);
96 $photo = q("SELECT * FROM photo WHERE `contact-id` = %d ORDER BY scale DESC", $contact["id"]); //prefer size 80x80
97 if ($photo && count($photo) > 0) {
98 $photodata = new vcard_source_data_photo();
99 $photodata->width = $photo[0]["width"];
100 $photodata->height = $photo[0]["height"];
101 $photodata->type = "JPEG";
102 $photodata->binarydata = $photo[0]["data"];
103 $vcarddata->photo = $photodata;
106 switch ($contact["network"]) {
108 $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("facebook", $contact["notify"], "http://www.facebook.com/" . $contact["notify"]);
111 $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("dfrn", $contact["nick"], $contact["url"]);
114 $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("twitter", $contact["nick"], "http://twitter.com/" . $contact["nick"]); // @TODO Stimmt das?
118 $vcard = vcard_source_compile($vcarddata);
120 "id" => $contact["id"],
121 "carddata" => $vcard,
122 "uri" => $contact["id"] . ".vcf",
123 "lastmodified" => wdcal_mySql2PhpTime($vcarddata->last_update),
124 "etag" => md5($vcard),
125 "size" => strlen($vcard),
132 * @param int $addressbookId
134 * @throws Sabre_DAV_Exception_NotFound
136 static protected function createCache_internal($addressbookId, $force = false) {
137 //$notin = (count($exclude_ids) > 0 ? " AND id NOT IN (" . implode(", ", $exclude_ids) . ") " : "");
138 $addressbook = q("SELECT * FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
139 if (count($addressbook) != 1 || $addressbook[0]["namespace"] != CARDDAV_NAMESPACE_PRIVATE) throw new Sabre_DAV_Exception_NotFound();
140 $contacts = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0 ORDER BY `name` ASC", $addressbook[0]["namespace_id"]);
142 foreach ($contacts as $contact) {
143 $x = static::dav_contactarr2vcardsource($contact);
144 q("INSERT INTO %s%saddressbookobjects (`addressbook_id`, `contact`, `carddata`, `uri`, `lastmodified`, `etag`, `size`) VALUES (%d, %d, '%s', '%s', NOW(), '%s', %d)",
145 CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId, $contact["id"], dbesc($x["carddata"]), dbesc($x["uri"]), dbesc($x["etag"]), $x["size"]
153 * @param int $addressbookId
154 * @param int $contactId
156 * @throws Sabre_DAV_Exception_NotFound
158 static protected function createCardCache($addressbookId, $contactId, $force = false)
160 $addressbook = q("SELECT * FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
161 if (count($addressbook) != 1 || $addressbook[0]["namespace"] != CARDDAV_NAMESPACE_PRIVATE) throw new Sabre_DAV_Exception_NotFound();
163 $contacts = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0 AND `id` = %d ORDER BY `name` ASC",
164 $addressbook[0]["namespace_id"], IntVal($contactId));
165 $contact = $contacts[0];
167 $x = static::dav_contactarr2vcardsource($contact);
168 q("INSERT INTO %s%saddressbookobjects (`addressbook_id`, `contact`, `carddata`, `uri`, `lastmodified`, `etag`, `size`) VALUES (%d, %d, '%s', '%s', NOW(), '%s', %d)",
169 CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId, $contact["id"], dbesc($x["carddata"]), dbesc($x["uri"]), dbesc($x["etag"]), $x["size"]
175 * The addressbook id will be passed as the first argument. This is the
176 * same id as it is returned from the getAddressbooksForUser method.
178 * The cardUri is a base uri, and doesn't include the full path. The
179 * cardData argument is the vcard body, and is passed as a string.
181 * It is possible to return an ETag from this method. This ETag should
182 * match that of the updated resource, and must be enclosed with double
183 * quotes (that is: the string itself must contain the actual quotes).
185 * You should only return the ETag if you store the carddata as-is. If a
186 * subsequent GET request on the same card does not have the same body,
187 * byte-by-byte and you did return an ETag here, clients tend to get
190 * If you don't return an ETag, you can just return null.
192 * @param string $addressBookId
193 * @param string $cardUri
194 * @param string $cardData
195 * @throws Sabre_DAV_Exception_Forbidden
196 * @return string|null
198 public function updateCard($addressBookId, $cardUri, $cardData)
200 $x = explode("-", $addressBookId);
202 $etag = md5($cardData);
203 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",
204 CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), time(), $etag, strlen($cardData), dbesc($cardUri), IntVal($x[10]), IntVal($x[1])
206 q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
208 return '"' . $etag . '"';
214 * @param string $addressBookId
215 * @param string $cardUri
216 * @throws Sabre_DAV_Exception_Forbidden
219 public function deleteCard($addressBookId, $cardUri)
221 $x = explode("-", $addressBookId);
223 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));
224 q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));