]> git.mxchange.org Git - friendica-addons.git/blob - dav/common/calendar.fnk.php
Add Temporal::local() shorthand for Temporal::convert()
[friendica-addons.git] / dav / common / calendar.fnk.php
1 <?php
2
3 use Friendica\Util\Temporal;
4
5 define("DAV_ACL_READ", "{DAV:}read");
6 define("DAV_ACL_WRITE", "{DAV:}write");
7 define("DAV_DISPLAYNAME", "{DAV:}displayname");
8 define("DAV_CALENDARCOLOR", "{http://apple.com/ns/ical/}calendar-color");
9
10
11 class DAVVersionMismatchException extends Exception
12 {
13 }
14
15
16 class vcard_source_data_email
17 {
18         public $email, $type;
19
20         function __construct($type, $email)
21         {
22                 $this->email = $email;
23                 $this->type  = $type;
24         }
25 }
26
27 class vcard_source_data_homepage
28 {
29         public $homepage, $type;
30
31         function __construct($type, $homepage)
32         {
33                 $this->homepage = $homepage;
34                 $this->type     = $type;
35         }
36 }
37
38 class vcard_source_data_telephone
39 {
40         public $telephone, $type;
41
42         function __construct($type, $telephone)
43         {
44                 $this->telephone = $telephone;
45                 $this->type      = $type;
46         }
47 }
48
49 class vcard_source_data_socialnetwork
50 {
51         public $nick, $type, $url;
52
53         function __construct($type, $nick, $url)
54         {
55                 $this->nick = $nick;
56                 $this->type = $type;
57                 $this->url  = $url;
58         }
59 }
60
61 class vcard_source_data_address
62 {
63         public $street, $street2, $zip, $city, $country, $type;
64 }
65
66 class vcard_source_data_photo
67 {
68         public $binarydata;
69         public $width, $height;
70         public $type;
71 }
72
73 class vcard_source_data
74 {
75         function __construct($name_first, $name_middle, $name_last)
76         {
77                 $this->name_first  = $name_first;
78                 $this->name_middle = $name_middle;
79                 $this->name_last   = $name_last;
80         }
81
82         public $name_first, $name_middle, $name_last;
83         public $last_update;
84         public $picture_data;
85
86         /** @var array|vcard_source_data_telephone[] $telephones */
87         public $telephones;
88
89         /** @var array|vcard_source_data_homepage[] $homepages */
90         public $homepages;
91
92         /** @var array|vcard_source_data_socialnetwork[] $socialnetworks */
93         public $socialnetworks;
94
95         /** @var array|vcard_source_data_email[] $email */
96         public $emails;
97
98         /** @var array|vcard_source_data_address[] $addresses */
99         public $addresses;
100
101         /** @var vcard_source_data_photo */
102         public $photo;
103 }
104
105 /**
106  * @param vcard_source_data $vcardsource
107  * @return string
108  */
109 function vcard_source_compile($vcardsource)
110 {
111         $str = "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
112         $str .= "N:" . str_replace(";", ",", $vcardsource->name_last) . ";" . str_replace(";", ",", $vcardsource->name_first) . ";" . str_replace(";", ",", $vcardsource->name_middle) . ";;\r\n";
113         $str .= "FN:" . str_replace(";", ",", $vcardsource->name_first) . " " . str_replace(";", ",", $vcardsource->name_middle) . " " . str_replace(";", ",", $vcardsource->name_last) . "\r\n";
114         $str .= "REV:" . str_replace(" ", "T", $vcardsource->last_update) . "Z\r\n";
115
116         $item_count = 0;
117         for ($i = 0; $i < count($vcardsource->homepages); $i++) {
118                 if ($i == 0) $str .= "URL;type=" . $vcardsource->homepages[0]->type . ":" . $vcardsource->homepages[0]->homepage . "\r\n";
119                 else {
120                         $c = ++$item_count;
121                         $str .= "item$c.URL;type=" . $vcardsource->homepages[0]->type . ":" . $vcardsource->homepages[0]->homepage . "\r\n";
122                         $str .= "item$c.X-ABLabel:_\$!<HomePage>!\$_\r\n";
123                 }
124         }
125
126         if (is_object($vcardsource->photo)) {
127                 $data = base64_encode($vcardsource->photo->binarydata);
128                 $str .= "PHOTO;ENCODING=BASE64;TYPE=" . $vcardsource->photo->type . ":" . $data . "\r\n";
129         }
130
131         if (isset($vcardsource->socialnetworks) && is_array($vcardsource->socialnetworks)) foreach ($vcardsource->socialnetworks as $netw) switch ($netw->type) {
132                 case "dfrn":
133                         $str .= "X-SOCIALPROFILE;type=dfrn;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
134                         break;
135                 case "facebook":
136                         $str .= "X-SOCIALPROFILE;type=facebook;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
137                         break;
138                 case "twitter":
139                         $str .= "X-SOCIALPROFILE;type=twitter;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
140                         break;
141         }
142
143         $str .= "END:VCARD\r\n";
144         return $str;
145 }
146
147
148 /**
149  * @param int $phpDate (UTC)
150  * @return string (Lokalzeit)
151  */
152 function wdcal_php2MySqlTime($phpDate)
153 {
154         return date(Temporal::MYSQL, $phpDate);
155 }
156
157 /**
158  * @param string $sqlDate
159  * @return int
160  */
161 function wdcal_mySql2PhpTime($sqlDate)
162 {
163         $ts = DateTime::createFromFormat(Temporal::MYSQL, $sqlDate);
164         return $ts->format("U");
165 }
166
167 /**
168  * @param string $myqlDate
169  * @return array
170  */
171 function wdcal_mySql2icalTime($myqlDate)
172 {
173         $x             = explode(" ", $myqlDate);
174         $y             = explode("-", $x[0]);
175         $ret           = array("year"=> $y[0], "month"=> $y[1], "day"=> $y[2]);
176         $y             = explode(":", $x[1]);
177         $ret["hour"]   = $y[0];
178         $ret["minute"] = $y[1];
179         $ret["second"] = $y[2];
180         return $ret;
181 }
182
183
184 /**
185  * @param string $str
186  * @return string
187  */
188 function icalendar_sanitize_string($str = "")
189 {
190         return preg_replace("/[\\r\\n]+/siu", "\r\n", $str);
191 }
192
193
194 /**
195  * @return Sabre_CalDAV_AnimexxCalendarRootNode
196  */
197 function dav_createRootCalendarNode()
198 {
199         $backends = array(Sabre_CalDAV_Backend_Private::getInstance());
200         foreach ($GLOBALS["CALDAV_PRIVATE_SYSTEM_BACKENDS"] as $backendclass) $backends[] = $backendclass::getInstance();
201         return new Sabre_CalDAV_AnimexxCalendarRootNode(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), $backends);
202 }
203
204 /**
205  * @return Sabre_CardDAV_AddressBookRootFriendica
206  */
207 function dav_createRootContactsNode()
208 {
209         $backends = array(Sabre_CardDAV_Backend_Std::getInstance());
210         foreach ($GLOBALS["CARDDAV_PRIVATE_SYSTEM_BACKENDS"] as $backendclass) $backends[] = $backendclass::getInstance();
211
212         return new Sabre_CardDAV_AddressBookRootFriendica(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), $backends);
213 }
214
215
216 /**
217  * @param bool $force_authentication
218  * @param bool $needs_caldav
219  * @param bool $needs_carddav
220  * @return Sabre_DAV_Server
221  */
222 function dav_create_server($force_authentication = false, $needs_caldav = true, $needs_carddav = true)
223 {
224         $arr = array(
225                 new Sabre_DAV_SimpleCollection('principals', array(
226                         new Sabre_CalDAV_Principal_Collection(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), "principals/users"),
227                 )),
228         );
229         if ($needs_caldav) $arr[] = dav_createRootCalendarNode();
230         if ($needs_carddav) $arr[] = dav_createRootContactsNode();
231
232
233         $tree = new Sabre_DAV_SimpleCollection('root', $arr);
234
235 // The object tree needs in turn to be passed to the server class
236         $server = new Sabre_DAV_Server($tree);
237
238         if (CALDAV_URL_PREFIX != "") $server->setBaseUri(CALDAV_URL_PREFIX);
239
240         $authPlugin = new Sabre_DAV_Auth_Plugin(Sabre_DAV_Auth_Backend_Std::getInstance(), DAV_APPNAME);
241         $server->addPlugin($authPlugin);
242
243         if ($needs_caldav) {
244                 $caldavPlugin = new Sabre_CalDAV_Plugin();
245                 $server->addPlugin($caldavPlugin);
246         }
247         if ($needs_carddav) {
248                 $carddavPlugin = new Sabre_CardDAV_Plugin();
249                 $server->addPlugin($carddavPlugin);
250         }
251
252         if ($GLOBALS["CALDAV_ACL_PLUGIN_CLASS"] != "") {
253                 $aclPlugin                      = new $GLOBALS["CALDAV_ACL_PLUGIN_CLASS"]();
254                 $aclPlugin->defaultUsernamePath = "principals/users";
255                 $server->addPlugin($aclPlugin);
256         } else {
257                 $aclPlugin                      = new Sabre_DAVACL_Plugin();
258                 $aclPlugin->defaultUsernamePath = "principals/users";
259                 $server->addPlugin($aclPlugin);
260         }
261
262         if ($force_authentication) $server->broadcastEvent('beforeMethod', array("GET", "/")); // Make it authenticate
263
264         return $server;
265 }
266
267
268 /**
269  * @param Sabre_DAV_Server $server
270  * @param string $with_privilege
271  * @return array|Sabre_CalDAV_Calendar[]
272  */
273 function dav_get_current_user_calendars(&$server, $with_privilege = "")
274 {
275         if ($with_privilege == "") $with_privilege = DAV_ACL_READ;
276
277         $a             = get_app();
278         $calendar_path = "/calendars/" . strtolower($a->user["nickname"]) . "/";
279
280         /** @var Sabre_CalDAV_AnimexxUserCalendars $tree  */
281         $tree = $server->tree->getNodeForPath($calendar_path);
282         /** @var array|Sabre_CalDAV_Calendar[] $calendars  */
283         $children = $tree->getChildren();
284
285         $calendars = array();
286         /** @var Sabre_DAVACL_Plugin $aclplugin  */
287         $aclplugin = $server->getPlugin("acl");
288         foreach ($children as $child) if (is_a($child, "Sabre_CalDAV_Calendar") || is_subclass_of($child, "Sabre_CalDAV_Calendar")) {
289                 if ($with_privilege != "") {
290                         $caluri = $calendar_path . $child->getName();
291                         if ($aclplugin->checkPrivileges($caluri, $with_privilege, Sabre_DAVACL_Plugin::R_PARENT, false)) $calendars[] = $child;
292                 } else {
293                         $calendars[] = $child;
294                 }
295         }
296         return $calendars;
297 }
298
299
300 /**
301  * @param Sabre_DAV_Server $server
302  * @param Sabre_CalDAV_Calendar $calendar
303  * @param string $calendarobject_uri
304  * @param string $with_privilege
305  * @return null|Sabre\VObject\Component\VCalendar
306  */
307 function dav_get_current_user_calendarobject(&$server, &$calendar, $calendarobject_uri, $with_privilege = "")
308 {
309         $obj = $calendar->getChild($calendarobject_uri);
310
311         if ($with_privilege == "") $with_privilege = DAV_ACL_READ;
312
313         $a   = get_app();
314         $uri = "/calendars/" . strtolower($a->user["nickname"]) . "/" . $calendar->getName() . "/" . $calendarobject_uri;
315
316         /** @var Sabre_DAVACL_Plugin $aclplugin  */
317         $aclplugin = $server->getPlugin("acl");
318         if (!$aclplugin->checkPrivileges($uri, $with_privilege, Sabre_DAVACL_Plugin::R_PARENT, false)) return null;
319
320         $data    = $obj->get();
321         $vObject = Sabre\VObject\Reader::read($data);
322
323         return $vObject;
324 }
325
326
327 /**
328  * @param Sabre_DAV_Server $server
329  * @param int $id
330  * @param string $with_privilege
331  * @return null|Sabre_CalDAV_Calendar
332  */
333 function dav_get_current_user_calendar_by_id(&$server, $id, $with_privilege = "")
334 {
335         $calendars = dav_get_current_user_calendars($server, $with_privilege);
336
337         $calendar = null;
338         foreach ($calendars as $cal) {
339                 $prop = $cal->getProperties(array("id"));
340                 if (isset($prop["id"]) && $prop["id"] == $id) $calendar = $cal;
341         }
342
343         return $calendar;
344 }
345
346
347 /**
348  * @param string $uid
349  * @return Sabre\VObject\Component\VCalendar $vObject
350  */
351 function dav_create_empty_vevent($uid = "")
352 {
353         if ($uid == "") $uid = uniqid();
354         return Sabre\VObject\Reader::read("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//" . DAV_APPNAME . "//DAV-Plugin//EN\r\nBEGIN:VEVENT\r\nUID:" . $uid . "@" . dav_compat_get_hostname() .
355                 "\r\nDTSTAMP:" . date("Ymd") . "T" . date("His") . "Z\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n");
356 }
357
358
359 /**
360  * @param Sabre\VObject\Component\VCalendar $vObject
361  * @return Sabre\VObject\Component\VEvent|null
362  */
363 function dav_get_eventComponent(&$vObject)
364 {
365         $component     = null;
366         $componentType = "";
367         foreach ($vObject->getComponents() as $component) {
368                 if ($component->name !== 'VTIMEZONE') {
369                         $componentType = $component->name;
370                         break;
371                 }
372         }
373         if ($componentType != "VEVENT") return null;
374
375         return $component;
376 }