PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
fluent-booking / vendor / wpfluent / caldav / src / ICal / Event.php

Event.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.5.0, at vendor/wpfluent/caldav/src/ICal/Event.php

464 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\Package\CalDav\ICal;
4
5 use Exception;
6 use DateTime;
7 use DateTimeZone;
8
9 class Event implements \JsonSerializable
10 {
11 protected $data = [];
12
13 protected $generatedEventData = '';
14
15 protected $dateTimeFormat = 'Ymd\THis\Z';
16
17 public function __construct($array = [])
18 {
19 $this->data = $array;
20
21 $this->setDefaults();
22 }
23
24 public function preCompile()
25 {
26 return $this->prepareEventData();
27 }
28
29 protected function prepareEventData()
30 {
31 $this->setDateTime();
32 $this->setCategories();
33 $this->setAttendees();
34 $this->setOrganizer();
35 $this->setAlarm();
36 $this->setRecurrence();
37 $this->setAttachments();
38 }
39
40 protected function setDefaults()
41 {
42 if (!isset($this->data['uid'])) {
43 $currentDateTime = $this->getCurrentDateTime();
44 $this->data['created'] = $currentDateTime;
45 $this->data['dtstamp'] = $currentDateTime;
46 $this->data['last-modified'] = $currentDateTime;
47 $this->data['uid'] = md5(__NAMESPACE__) . '-' . wp_generate_uuid4();
48 }
49 }
50
51 protected function getCurrentDateTime()
52 {
53 return (
54 new DateTime('now', new DateTimeZone('UTC'))
55 )->format($this->dateTimeFormat);
56 }
57
58 protected function setDateTime()
59 {
60 $dates = [
61 'dtstart' => $this->getDtStart(),
62 'dtend' => $this->getDtEnd()
63 ];
64
65 $timezone = !empty($this->data['timezone']) && $this->data['timezone'] !== 'UTC'
66 ? $this->data['timezone']
67 : null;
68
69 $prefix = $timezone ? ';TZID=' . $timezone . ':' : ':';
70 $format = $timezone ? 'Ymd\THis' : $this->dateTimeFormat;
71
72 foreach ($dates as $key => $value) {
73
74 if ($this->isPrefixedDateTime($value)) {
75 continue;
76 }
77
78 $dateTime = is_string($value)
79 ? new DateTime($value, new DateTimeZone('UTC'))
80 : $value;
81
82 if (!$dateTime instanceof DateTime) {
83 throw new Exception("Invalid value: {$value} for {$key}.");
84 }
85
86 if ($timezone) {
87 $dateTime->setTimezone(new DateTimeZone($timezone));
88 }
89
90 $this->data[$key] = $prefix . $dateTime->format($format);
91 }
92 }
93
94 private function isPrefixedDateTime($value)
95 {
96 return is_string($value) && isset($value[0]) && ($value[0] === ':' || $value[0] === ';');
97 }
98
99 protected function getDtStart()
100 {
101 if (!isset($this->data['dtstart'])) {
102 if (!isset($this->data['DTSTART'])) {
103 throw new Exception('The Event needs an dtstart/DTSTART property.');
104 } else {
105 $dtStart = $this->data['DTSTART'];
106 }
107 } else {
108 $dtStart = $this->data['dtstart'];
109 }
110
111 return $dtStart;
112 }
113
114 protected function getDtEnd()
115 {
116 if (!isset($this->data['dtend'])) {
117 if (!isset($this->data['DTEND'])) {
118 throw new Exception('The Event needs an dtend/DTEND property.');
119 } else {
120 $dtEnd = $this->data['DTEND'];
121 }
122 } else {
123 $dtEnd = $this->data['dtend'];
124 }
125
126 return $dtEnd;
127 }
128
129 protected function setCategories()
130 {
131 if (!isset($this->data['categories'])) {
132 return;
133 }
134
135 $categories = $this->data['categories'];
136
137 if (is_array($categories)) {
138 $categories = implode(',', $categories);
139 }
140
141 $categories = str_replace(', ', ',', $categories);
142
143 $this->data['categories'] = $categories;
144 }
145
146 protected function setAttendees()
147 {
148 if (!isset($this->data['attendees'])) {
149 return;
150 }
151
152 foreach ($this->data['attendees'] as &$attendee) {
153
154 if (!isset($attendee['email'])) {
155 throw new Exception('An attendee must have an email.');
156 }
157
158 if (!isset($attendee['name'])) {
159 $attendee['name'] = $attendee['email'];
160 }
161
162 $str = '';
163
164 foreach ($attendee as $key => $value) {
165 $key = strtolower($key);
166
167 if ($key == 'name') {
168 $str .= "CN={$value};";
169 } elseif ($key == 'role') {
170 $value = strtoupper($value);
171 $str .= "ROLE={$value};";
172 } elseif ($key == 'rsvp') {
173 if (is_bool($value)) {
174 $value = $value === true ? 'TRUE' : 'FALSE';
175 }
176 $value = strtoupper($value);
177 $str .= "RSVP={$value};";
178 } elseif ($key == 'partstat') {
179 $value = strtoupper($value);
180 $str .= "PARTSTAT={$value};";
181 }
182 }
183
184 $str = rtrim($str, ';');
185
186 $str .= ';SCHEDULE-AGENT=CLIENT';
187
188 $str .= ":mailto:{$attendee['email']}";
189
190 $attendee['str'] = $str;
191 }
192 }
193
194 protected function setOrganizer()
195 {
196 if (!isset($this->data['organizer'])) {
197 return;
198 }
199
200 $organizer = &$this->data['organizer'];
201
202 if (!isset($organizer['email'])) {
203 throw new \Exception('An organizer must have an email.');
204 }
205
206 if (!isset($organizer['name'])) {
207 $organizer['name'] = $organizer['email'];
208 }
209
210 $str = '';
211
212 foreach ($organizer as $key => $value) {
213
214 $key = strtolower($key);
215
216 if ($key == 'name') {
217 $str .= "CN={$value};";
218 } elseif ($key == 'language') {
219 $str .= "LANGUAGE={$value};";
220 }
221 }
222
223 if (isset($organizer['sent_by'])) {
224 $str .= "SENT-BY=mailto:{$organizer['sent_by']}";
225 }
226
227 $str = rtrim($str, ';');
228
229 $str .= ';SCHEDULE-AGENT=CLIENT';
230
231 $str .= ":mailto:{$organizer['email']}";
232
233 $organizer['str'] = $str;
234 }
235
236 protected function setAlarm()
237 {
238 if (!isset($this->data['alarm'])) {
239 return;
240 }
241
242 $alarm = &$this->data['alarm'];
243
244 $action = strtoupper($alarm['action']);
245
246 $alarm['action'] = $action;
247
248 if (isset($alarm['trigger'])) {
249
250 // For exact time of the event
251 if ($alarm['trigger'] === true) {
252 $alarm['trigger_str'] = "RELATED=START:PT0S";
253
254 return;
255 }
256
257 if (!isset($alarm['trigger']['after'])) {
258
259 if (isset($alarm['trigger']['before'])) {
260 $isBefore = $alarm['trigger']['before'] === true;
261 } else {
262 $isBefore = true;
263 }
264 } else {
265 $isBefore = $alarm['trigger']['after'] === false;
266 }
267
268 $period = $isBefore ? '-P' : 'P';
269
270 $time = '';
271
272 foreach ($alarm['trigger'] as $key => $value) {
273 if ($key == 'years' && is_numeric($value) && $value) {
274 $period = $period . $value . 'Y';
275 } elseif ($key == 'months' && is_numeric($value) && $value) {
276 $period = $period . $value . 'M';
277 } elseif ($key == 'days' && is_numeric($value) && $value) {
278 $period = $period . $value . 'D';
279 } elseif ($key == 'hours' && is_numeric($value) && $value) {
280 $time = $time . $value . 'H';
281 } elseif ($key == 'minutes' && is_numeric($value) && $value) {
282 $time = $time . $value . 'M';
283 } elseif ($key == 'seconds' && is_numeric($value) && $value) {
284 $time = $time . $value . 'S';
285 }
286 }
287 }
288
289 if ($time) {
290 $period = $period . 'T' . $time;
291 }
292
293 $alarm['trigger_str'] = "RELATED=START:{$period}";
294 }
295
296 protected function setRecurrence()
297 {
298 if (!isset($this->data['repeat'])) {
299 return;
300 }
301
302 $str = '';
303
304 $recurrence = &$this->data['repeat'];
305
306 foreach ($recurrence as $key => $value) {
307
308 $value = is_array($value) ? implode(',', $value) : $value;
309
310 $str .= strtoupper($key) . '=' . strtoupper($value) . ';';
311 }
312
313 $str = rtrim($str, ';');
314
315 $recurrence['str'] = $str;
316 }
317
318 public function setAttachments()
319 {
320 if (!isset($this->data['attachments'])) {
321 return;
322 }
323
324 $attachments = &$this->data['attachments'];
325
326 foreach ($this->data['attachments'] as $attachment) {
327
328 if (!isset($attachment['url'], $attachment['name'])) {
329 throw new Exception('An attachment requires a name and url key.');
330 }
331
332 $url = $attachment['url'];
333
334 $filename = $attachment['name'];
335
336 $attachments['list'][] = 'ATTACH;FILENAME=' . $filename . ':' . $url;
337 }
338 }
339
340 public function compile()
341 {
342 $this->preCompile();
343
344 if (!isset($this->data['sequence'])) {
345 $this->data['sequence'] = 0;
346 } else {
347 $this->data['sequence'] += 1;
348 }
349
350 $this->data['last-modified'] = $this->getCurrentDateTime();
351
352 $appNS = strtolower(explode('\\', __NAMESPACE__)[0]);
353 $calendar[] = "BEGIN:VCALENDAR";
354 $calendar[] = "VERSION:2.0";
355 $calendar[] = "CALSCALE:GREGORIAN";
356 $calendar[] = "PRODID:-//authlab.{$appNS}//CalDAV Client//EN";
357 $calendar[] = "BEGIN:VEVENT";
358 $calendar[] = "CREATED:{$this->data['created']}";
359 $calendar[] = "DTSTAMP:{$this->data['dtstamp']}";
360 $calendar[] = "LAST-MODIFIED:{$this->data['last-modified']}";
361 $calendar[] = "SEQUENCE:{$this->data['sequence']}";
362 $calendar[] = "UID:{$this->data['uid']}";
363 $calendar[] = "DTSTART{$this->data['dtstart']}";
364 $calendar[] = "DTEND{$this->data['dtend']}";
365
366 if (isset($this->data['transp'])) {
367 $calendar[] = "TRANSP:{$this->data['transp']}";
368 } else {
369 $calendar[] = "TRANSP:TRANSPARENT";
370 }
371
372 if (isset($this->data['status'])) {
373 $eventStatus = strtoupper($this->data['status']);
374 $calendar[] = "STATUS:{$eventStatus}";
375 }
376
377 if (isset($this->data['summary'])) {
378 $calendar[] = "SUMMARY:{$this->data['summary']}";
379 }
380
381 if (isset($this->data['description'])) {
382 $eventDescription = str_replace("\n", " ", $this->data['description']);
383 $calendar[] = "DESCRIPTION:{$eventDescription}";
384 }
385
386 if (isset($this->data['location'])) {
387 $calendar[] = "LOCATION:{$this->data['location']}";
388 }
389
390 if (isset($this->data['categories'])) {
391 $calendar[] = "CATEGORIES:{$this->data['categories']}";
392 }
393
394 if (isset($this->data['repeat'])) {
395 $calendar[] = "RRULE:{$this->data['repeat']['str']}";
396 }
397
398 if (isset($this->data['attendees'])) {
399 foreach ($this->data['attendees'] as $attendee) {
400 $calendar[] = "ATTENDEE;{$attendee['str']}";
401 }
402 }
403
404 if (isset($this->data['organizer'])) {
405 $calendar[] = "ORGANIZER;{$this->data['organizer']['str']}";
406 }
407
408 if (isset($this->data['attachments'])) {
409 $calendar[] = implode("\n", $this->data['attachments']['list']);
410 }
411
412 if (isset($this->data['alarm'])) {
413 $calendar[] = "BEGIN:VALARM";
414
415 if (isset($this->data['alarm']['action'])) {
416 $calendar[] = "ACTION:{$this->data['alarm']['action']}";
417 }
418
419 if (isset($this->data['alarm']['description'])) {
420
421 $alarmDescription = str_replace(
422 "\n", " ", $this->data['alarm']['description']
423 );
424
425 $calendar[] = "DESCRIPTION:{$alarmDescription}";
426 }
427
428 if (isset($this->data['alarm']['trigger'])) {
429 $calendar[] = "TRIGGER;{$this->data['alarm']['trigger_str']}";
430 }
431
432 $calendar[] = "END:VALARM";
433 }
434
435 $calendar[] = "END:VEVENT";
436 $calendar[] = "END:VCALENDAR";
437
438 $this->generatedEventData = implode("\n", $calendar);
439
440 return $this->generatedEventData;
441 }
442
443 public function getUid()
444 {
445 return $this->data['uid'];
446 }
447
448 public function __get($key)
449 {
450 return $this->data[$key];
451 }
452
453 public function __set($key, $value)
454 {
455 $this->data[$key] = $value;
456 }
457
458 #[\ReturnTypeWillChange]
459 public function jsonSerialize()
460 {
461 return $this->data;
462 }
463 }
464