1: <?php
2: /**
3: * This code is licensed under Afterlogic Software License.
4: * For full statements of the license see LICENSE file.
5: */
6:
7: namespace Aurora\Modules\Calendar;
8:
9: use Afterlogic\DAV\Server;
10: use Aurora\System\Api;
11: use GuzzleHttp\Client;
12: use GuzzleHttp\Exception\ConnectException;
13: use Sabre\VObject\ITip\Broker as ITipBroker;
14: use Sabre\VObject\ParseException;
15:
16: /**
17: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
18: * @copyright Copyright (c) 2023, Afterlogic Corp.
19: *
20: * @package Calendar
21: * @subpackage Managers
22: *
23: * @property Module $oModule
24: */
25: class Manager extends \Aurora\System\Managers\AbstractManagerWithStorage
26: {
27: /**
28: * @var Storages\Sabredav
29: */
30: public $oStorage;
31:
32: /**
33: * @param \Aurora\System\Module\AbstractModule $oModule
34: */
35: public function __construct(\Aurora\System\Module\AbstractModule $oModule = null)
36: {
37: parent::__construct($oModule, new Storages\Sabredav($this));
38: }
39:
40: protected function isCalendarSharingSupported($sUserUUID)
41: {
42: return true; // TODO
43: }
44:
45: /**
46: * Determines whether read/write or read-only permissions are set for accessing calendar from this account.
47: *
48: * @param string $sUserUUID Account object
49: * @param string $sCalendarId Calendar ID
50: *
51: * @return bool **ECalendarPermission::Write** or **ECalendarPermission::Read** accordingly.
52: */
53: public function getCalendarAccess($sUserUUID, $sCalendarId)
54: {
55: $oResult = null;
56: $oUser = \Aurora\System\Api::getUserById($sUserUUID);
57: if ($oUser instanceof \Aurora\Modules\Core\Models\User) {
58: $oResult = $this->oStorage->getCalendarAccess($oUser->PublicId, $sCalendarId);
59: }
60: return $oResult;
61: }
62:
63: /**
64: * @param string $sHash
65: *
66: * @return \Aurora\Modules\Calendar\Classes\Calendar|false $oCalendar
67: */
68: public function getPublicCalendarByHash($sHash)
69: {
70: return $this->getPublicCalendar($sHash);
71: }
72:
73: /**
74: * @param string $sCalendarId
75: *
76: * @return \Aurora\Modules\Calendar\Classes\Calendar|false $oCalendar
77: */
78: public function getPublicCalendar($sCalendarId)
79: {
80: $oCalendar = false;
81: try {
82: $oCalDAVCalendar = $this->oStorage->getPublicCalendar($sCalendarId);
83: if ($oCalDAVCalendar) {
84: $oCalendar = $this->oStorage->parseCalendar($oCalDAVCalendar);
85: }
86: } catch (\Exception $oException) {
87: $oCalendar = false;
88: $this->setLastException($oException);
89: }
90: return $oCalendar;
91: }
92:
93: /**
94: * Loads calendar.
95: *
96: * @param int $sUserPublicId
97: * @param string $sCalendarId Calendar ID
98: *
99: * @return \Aurora\Modules\Calendar\Classes\Calendar|false $oCalendar
100: */
101: public function getCalendar($sUserPublicId, $sCalendarId)
102: {
103: $oCalendar = false;
104: try {
105: $oCalendar = $this->oStorage->getCalendar($sUserPublicId, $sCalendarId);
106: } catch (\Exception $oException) {
107: $oCalendar = false;
108: $this->setLastException($oException);
109: }
110: return $oCalendar;
111: }
112:
113: /**
114: * @param string $sCalendarId
115: *
116: * @return string|false
117: */
118: public function getPublicCalendarHash($sCalendarId)
119: {
120: $oResult = null;
121: try {
122: $oResult = $this->oStorage->getPublicCalendarHash($sCalendarId);
123: } catch (\Exception $oException) {
124: $oResult = false;
125: $this->setLastException($oException);
126: }
127: return $oResult;
128: }
129:
130: /**
131: * (Aurora only) Returns list of user account the calendar was shared with.
132: *
133: * @param string $sUserPublicId
134: * @param \Aurora\Modules\Calendar\Classes\Calendar $oCalendar Calendar object
135: *
136: * @return array|bool
137: */
138: public function getCalendarUsers($sUserPublicId, $oCalendar)
139: {
140: $mResult = null;
141: try {
142: $mResult = $this->oStorage->getCalendarUsers($sUserPublicId, $oCalendar);
143: } catch (\Exception $oException) {
144: $mResult = false;
145: $this->setLastException($oException);
146: }
147: return $mResult;
148: }
149:
150: /**
151: *
152: * @return string|bool
153: */
154: public function getPublicUser()
155: {
156: $oResult = null;
157: try {
158: $oResult = $this->oStorage->getPublicUser();
159: } catch (\Exception $oException) {
160: $oResult = false;
161: $this->setLastException($oException);
162: }
163: return $oResult;
164: }
165:
166: /**
167: *
168: * @return string|bool
169: */
170: public function getTenantUser($oUser = null)
171: {
172: $mResult = null;
173: try {
174: $mResult = $this->oStorage->getTenantUser($oUser);
175: } catch (\Exception $oException) {
176: $mResult = false;
177: $this->setLastException($oException);
178: }
179: return $mResult;
180: }
181:
182: /**
183: *
184: * @return mixed $oAccount
185: */
186: public function getPublicAccount()
187: {
188: $oResult = null;
189: try {
190: $oResult = $this->oStorage->getPublicAccount();
191: } catch (\Exception $oException) {
192: $oResult = false;
193: $this->setLastException($oException);
194: }
195: return $oResult;
196: }
197:
198: /**
199: * Returns list of calendars for the account.
200: *
201: * @param string $sUserPublicId
202: *
203: * @return array
204: */
205: public function getUserCalendars($sUserPublicId)
206: {
207: return $this->oStorage->getCalendars($sUserPublicId);
208: }
209:
210: /**
211: * Creates new calendar.
212: *
213: * @param string $sUserPublicId
214: * @param string $sName Name of the calendar
215: * @param string $sDescription Description of the calendar
216: * @param int $iOrder Ordinal number of the calendar in calendars list
217: * @param string $sColor Color code
218: *
219: * @return \Aurora\Modules\Calendar\Classes\Calendar|false
220: */
221: public function createCalendar($sUserPublicId, $sName, $sDescription, $iOrder, $sColor, $sUUID = null)
222: {
223: $oResult = null;
224: try {
225: $oResult = $this->oStorage->createCalendar($sUserPublicId, $sName, $sDescription, $iOrder, $sColor, $sUUID);
226: } catch (\Exception $oException) {
227: $oResult = false;
228: $this->setLastException($oException);
229: }
230: return $oResult;
231: }
232:
233: public function validateSubscribedCalebdarSource($sSource)
234: {
235: $isValid = false;
236:
237: $client = new Client();
238: try {
239: $res = $client->get(
240: $sSource,
241: [
242: 'headers' => [
243: 'Accept' => '*/*',
244: ],
245: 'http_errors' => false
246: ]
247: );
248: if ($res->getStatusCode() === 200) {
249: $data = (string) $res->getBody();
250: try {
251: \Sabre\VObject\Reader::read($data);
252: $isValid = true;
253: } catch (ParseException $oEx) {
254: $isValid = false;
255: }
256: }
257: } catch (ConnectException $oEx) {
258: }
259:
260: return $isValid;
261: }
262:
263: public function createSubscribedCalendar($sUserPublicId, $sName, $sSource, $iOrder, $sColor, $sUUID = null)
264: {
265: $oResult = null;
266: try {
267: $oResult = $this->oStorage->createSubscribedCalendar($sUserPublicId, $sName, $sSource, $iOrder, $sColor, $sUUID);
268: } catch (\Exception $oException) {
269: $oResult = false;
270: $this->setLastException($oException);
271: }
272: return $oResult;
273: }
274:
275: /**
276: * Updates calendar properties.
277: *
278: * @param string $sUserPublicId
279: * @param string $sCalendarId Calendar ID
280: * @param string $sName Name of the calendar
281: * @param string $sDescription Description of the calendar
282: * @param int $iOrder Ordinal number of the calendar in calendars list
283: * @param string $sColor Color code
284: *
285: * @return \Aurora\Modules\Calendar\Classes\Calendar|false
286: */
287: public function updateCalendar($sUserPublicId, $sCalendarId, $sName, $sDescription, $iOrder, $sColor)
288: {
289: $oResult = null;
290: try {
291: $oResult = $this->oStorage->updateCalendar($sUserPublicId, $sCalendarId, $sName, $sDescription, $iOrder, $sColor);
292: } catch (\Exception $oException) {
293: $oResult = false;
294: $this->setLastException($oException);
295: }
296: return $oResult;
297: }
298:
299: /**
300: * Updates calendar properties.
301: *
302: * @param string $sUserPublicId
303: * @param string $sCalendarId Calendar ID
304: * @param string $sName Name of the calendar
305: * @param string $sSource Description of the calendar
306: * @param int $iOrder Ordinal number of the calendar in calendars list
307: * @param string $sColor Color code
308: *
309: * @return \Aurora\Modules\Calendar\Classes\Calendar|false
310: */
311: public function updateSubscribedCalendar($sUserPublicId, $sCalendarId, $sName, $sSource, $iOrder, $sColor)
312: {
313: $oResult = null;
314: try {
315: $oResult = $this->oStorage->updateSubscribedCalendar($sUserPublicId, $sCalendarId, $sName, $sSource, $iOrder, $sColor);
316: } catch (\Exception $oException) {
317: $oResult = false;
318: $this->setLastException($oException);
319: }
320: return $oResult;
321: }
322:
323: /**
324: * Change color of the calendar.
325: *
326: * @param string $sUserPublicId
327: * @param string $sCalendarId Calendar ID
328: * @param string $sColor New color code
329: *
330: * @return bool
331: */
332: public function updateCalendarColor($sUserPublicId, $sCalendarId, $sColor)
333: {
334: $oResult = null;
335: try {
336: $oResult = $this->oStorage->updateCalendarColor($sUserPublicId, $sCalendarId, $sColor);
337: } catch (\Exception $oException) {
338: $oResult = false;
339: $this->setLastException($oException);
340: }
341: return $oResult;
342: }
343:
344: public function deletePrincipalCalendars($sUserPublicId)
345: {
346: $oResult = null;
347: try {
348: $oResult = $this->oStorage->deletePrincipalCalendars($sUserPublicId);
349: } catch (\Exception $oException) {
350: $oResult = false;
351: $this->setLastException($oException);
352: }
353: return $oResult;
354: }
355:
356: /**
357: * Deletes calendar.
358: *
359: * @param string $sUserPublicId
360: * @param string $sCalendarId Calendar ID
361: *
362: * @return bool
363: */
364: public function deleteCalendar($sUserPublicId, $sCalendarId)
365: {
366: $oResult = null;
367: try {
368: $oResult = $this->oStorage->deleteCalendar($sUserPublicId, $sCalendarId);
369: } catch (\Exception $oException) {
370: $oResult = false;
371: $this->setLastException($oException);
372: }
373: return $oResult;
374: }
375:
376: /**
377: * Removes calendar from list of those shared with the specific account. [Aurora only.](http://dev.afterlogic.com/aurora)
378: *
379: * @param string $sUserPublicId Account object
380: * @param string $sCalendarId Calendar ID
381: *
382: * @return bool
383: */
384: public function unsubscribeCalendar($sUserPublicId, $sCalendarId)
385: {
386: $oResult = null;
387: if ($this->isCalendarSharingSupported($sUserPublicId)) {
388: try {
389: $oResult = $this->oStorage->unsubscribeCalendar($sUserPublicId, $sCalendarId);
390: } catch (\Exception $oException) {
391: $oResult = false;
392: $this->setLastException($oException);
393: }
394: }
395: return $oResult;
396: }
397:
398: /**
399: * (Aurora only) Share or remove sharing calendar with all users.
400: *
401: * @param string $sUserPublicId
402: * @param string $sCalendarId Calendar ID
403: * @param bool $bShareToAll If set to **true**, add sharing; if **false**, sharing is removed
404: * @param int $iPermission Permissions set for the account. Accepted values:
405: * - **ECalendarPermission::Read** (read-only access);
406: * - **ECalendarPermission::Write** (read/write access);
407: * - **ECalendarPermission::RemovePermission** (effectively removes sharing with the account).
408: *
409: * @return bool
410: */
411: public function updateCalendarShareToAll($sUserPublicId, $sCalendarId, $bShareToAll, $iPermission)
412: {
413: $sUserId = $this->getTenantUser($sUserPublicId);
414: $aShares[] = array(
415: 'name' => $sUserId,
416: 'email' => $sUserId,
417: 'access' => $bShareToAll ? $iPermission : \Aurora\Modules\Calendar\Enums\Permission::RemovePermission
418: );
419:
420: return $this->updateCalendarShares($sUserPublicId, $sCalendarId, $aShares);
421: }
422:
423: /**
424: * (Aurora only) Share or remove sharing calendar with the listed users.
425: *
426: * @param string $sUserPublicId
427: * @param string $sCalendarId Calendar ID
428: * @param array $aShares Array defining list of users and permissions. Each array item needs to have the following keys:
429: * ["email"] - email which denotes user the calendar is shared to;
430: * ["access"] - permission settings equivalent to those used in updateCalendarShare method.
431: *
432: * @return bool
433: */
434: public function updateCalendarShares($sUserPublicId, $sCalendarId, $aShares)
435: {
436: $oResult = false;
437: if ($this->isCalendarSharingSupported($sUserPublicId)) {
438: $aProcessedEmails = [];
439: $oUser = \Aurora\Modules\Core\Module::getInstance()->getUsersManager()->getUserByPublicId($sUserPublicId);
440: foreach ($aShares as $aShare) {
441: if (in_array($aShare['email'], $aProcessedEmails)) {//duplicated shares
442: return $oResult;
443: }
444: $aProcessedEmails[] = $aShare['email'];
445: if ($aShare['email'] !== $this->getTenantUser($oUser) &&
446: $aShare['email'] !== $this->getPublicUser()) {
447: $oSharedUser = \Aurora\Modules\Core\Module::getInstance()->getUsersManager()->getUserByPublicId($aShare['email']);
448: if ($oSharedUser instanceof \Aurora\Modules\Core\Models\User) {
449: //return $oResult; //TODO: Uncomment if not import
450: }
451: unset($oSharedUser);
452: }
453: }
454: $oResult = $this->oStorage->updateCalendarShares($sUserPublicId, $sCalendarId, $aShares);
455: }
456: return $oResult;
457: }
458:
459: /**
460: * Set/unset calendar as public.
461: *
462: * @param string $sCalendarId Calendar ID
463: * @param bool $bIsPublic If set to **true**, calendar is made public; if **false**, setting as public gets cancelled
464: * @param \Aurora\Modules\Core\Models\User $oUser
465: * @return bool
466: */
467: public function publicCalendar($sCalendarId, $bIsPublic = false, $oUser = null)
468: {
469: $oResult = null;
470: try {
471: $oResult = $this->oStorage->publicCalendar($sCalendarId, $bIsPublic, $oUser);
472: } catch (\Exception $oException) {
473: $oResult = false;
474: $this->setLastException($oException);
475: }
476: return $oResult;
477: }
478:
479: /**
480: * Set/unset calendar as public.
481: *
482: * @param string $sCalendarId Calendar ID
483: *
484: * @return bool
485: */
486: public function getPublishStatus($sCalendarId)
487: {
488: $oResult = null;
489: try {
490: $oResult = $this->oStorage->getPublishStatus($sCalendarId);
491: } catch (\Exception $oException) {
492: $oResult = false;
493: $this->setLastException($oException);
494: }
495: return $oResult;
496: }
497:
498: /**
499: * Share or remove sharing calendar with the specific user account. [Aurora only.](http://dev.afterlogic.com/aurora)
500: *
501: * @param string $sUserPublicId Account object
502: * @param string $sCalendarId Calendar ID
503: * @param string $sUserId User Id
504: * @param int $iPermission Permissions set for the account. Accepted values:
505: * - **ECalendarPermission::Read** (read-only access);
506: * - **ECalendarPermission::Write** (read/write access);
507: * - **ECalendarPermission::RemovePermission** (effectively removes sharing with the account).
508: *
509: * @return bool
510: */
511: public function updateCalendarShare($sUserPublicId, $sCalendarId, $sUserId, $iPermission)
512: {
513: $oResult = null;
514: if ($this->isCalendarSharingSupported($sUserPublicId)) {
515: try {
516: $oResult = $this->oStorage->updateCalendarShare($sUserPublicId, $sCalendarId, $sUserId, $iPermission);
517: } catch (\Exception $oException) {
518: $oResult = false;
519: $this->setLastException($oException);
520: }
521: }
522: return $oResult;
523: }
524:
525: /**
526: * Returns calendar data as ICS data.
527: *
528: * @param string $sUserPublicId
529: * @param string $sCalendarId Calendar ID
530: *
531: * @return string|bool
532: */
533: public function exportCalendarToIcs($sUserPublicId, $sCalendarId)
534: {
535: $mResult = null;
536: try {
537: $mResult = $this->oStorage->exportCalendarToIcs($sUserPublicId, $sCalendarId);
538: } catch (\Exception $oException) {
539: $mResult = false;
540: $this->setLastException($oException);
541: }
542: return $mResult;
543: }
544:
545: /**
546: * Populates calendar from .ICS file.
547: *
548: * @param string $sUserPublicId
549: * @param string $sCalendarId Calendar ID
550: * @param string $sTempFileName .ICS file name data are imported from
551: *
552: * @return int|bool integer (number of events added)
553: */
554: public function importToCalendarFromIcs($sUserPublicId, $sCalendarId, $sTempFileName)
555: {
556: $mResult = null;
557: try {
558: $mResult = $this->oStorage->importToCalendarFromIcs($sUserPublicId, $sCalendarId, $sTempFileName);
559: } catch (\Exception $oException) {
560: $mResult = false;
561: $this->setLastException($oException);
562: }
563: return $mResult;
564: }
565:
566: /**
567: * Account object
568: *
569: * @param string $sUserUUID
570: * @param array | string $mCalendarId Calendar ID
571: * @param string $dStart Date range start
572: * @param string $dFinish Date range end
573: *
574: * @return array|bool
575: */
576: public function getEvents($sUserUUID, $mCalendarId, $dStart = null, $dFinish = null)
577: {
578: $aResult = array();
579: try {
580: $dStart = ($dStart != null) ? date('Ymd\T000000\Z', intval($dStart) - 86400) : null;
581: $dFinish = ($dFinish != null) ? date('Ymd\T235959\Z', intval($dFinish)) : null;
582: $mCalendarId = !is_array($mCalendarId) ? array($mCalendarId) : $mCalendarId;
583:
584: foreach ($mCalendarId as $sCalendarId) {
585: $aEvents = $this->oStorage->getEvents($sUserUUID, $sCalendarId, $dStart, $dFinish);
586: if ($aEvents && is_array($aEvents)) {
587: $aResult = array_merge($aResult, $aEvents);
588: }
589: }
590: } catch (\Exception $oException) {
591: $aResult = false;
592: $this->setLastException($oException);
593: }
594: return $aResult;
595: }
596:
597: public function getEventsByUrls($sUserPublicId, $mCalendarId, $aUrls, $dStart, $dEnd, $bExpand)
598: {
599: $result = [];
600: $this->oStorage->init($sUserPublicId);
601: $oCalDAVCalendar = $this->oStorage->getCalDAVCalendar('calendar/' . $mCalendarId);
602: if ($oCalDAVCalendar) {
603: $result = $this->oStorage->getItemsByUrls($sUserPublicId, $oCalDAVCalendar, $aUrls, $dStart, $dEnd, $bExpand);
604: }
605: return $result;
606: }
607:
608: /**
609: * @param array | string $mCalendarId Calendar ID
610: * @param string $dStart Date range start
611: * @param string $dFinish Date range end
612: *
613: * @return array|bool
614: */
615: public function getPublicEvents($mCalendarId, $dStart = null, $dFinish = null, $bExpand = true, $sDefaultTimeZone = null)
616: {
617: $aResult = array();
618:
619: $dStart = ($dStart != null) ? date('Ymd\T000000\Z', intval($dStart) - 86400) : null;
620: $dFinish = ($dFinish != null) ? date('Ymd\T235959\Z', intval($dFinish)) : null;
621: $mCalendarId = !is_array($mCalendarId) ? array($mCalendarId) : $mCalendarId;
622:
623: foreach ($mCalendarId as $sCalendarId) {
624: $aEvents = $this->oStorage->getPublicEvents($sCalendarId, $dStart, $dFinish, $bExpand, $sDefaultTimeZone);
625: if ($aEvents && is_array($aEvents)) {
626: $aResult = array_merge($aResult, $aEvents);
627: }
628: }
629:
630: return $aResult;
631: }
632:
633: /**
634: * Account object
635: *
636: * @param string $sUserPublicId
637: * @param array | string $mCalendarId Calendar ID
638: * @param string $dStart Date range start
639: * @param string $dFinish Date range end
640: *
641: * @return array|bool
642: */
643: public function getTasks($sUserPublicId, $mCalendarId, $bCompeted = true, $sSearch = '', $dStart = null, $dFinish = null, $bExpand = true)
644: {
645: $aResult = array();
646: try {
647: $now = new \DateTime('now');
648: $now->setTime(0, 0);
649: if ($dStart === null) {
650: $dStart = $now->getTimestamp() - 86400 * 30;
651: }
652: if ($dFinish === null) {
653: $dFinish = $now->getTimestamp() + 86400 * 30;
654: }
655:
656: $dStart = ($dStart != null) ? date('Ymd\T000000\Z', intval($dStart) - 86400) : null;
657: $dFinish = ($dFinish != null) ? date('Ymd\T235959\Z', intval($dFinish)) : null;
658: $mCalendarId = !is_array($mCalendarId) ? array($mCalendarId) : $mCalendarId;
659:
660: foreach ($mCalendarId as $sCalendarId) {
661: $aTasks = $this->oStorage->getTasks($sUserPublicId, $sCalendarId, $bCompeted, $sSearch, $dStart, $dFinish, $bExpand);
662:
663: if ($aTasks && is_array($aTasks)) {
664: $aResult = array_merge($aResult, $aTasks);
665: }
666: }
667: } catch (\Exception $oException) {
668: $aResult = false;
669: $this->setLastException($oException);
670: }
671: return $aResult;
672: }
673:
674: /**
675: * @param string $sUserPublicId Account object
676: * @param mixed $mCalendarId
677: * @param object $dStart
678: * @param object $dEnd
679: * @param bool $bGetData
680: *
681: * @return string
682: */
683: public function getEventsInfo($sUserPublicId, $mCalendarId, $dStart = null, $dEnd = null, $bGetData = false)
684: {
685: $aResult = array();
686: try {
687: $dStart = ($dStart != null) ? date('Ymd\T000000\Z', $dStart - 86400) : null;
688: $dEnd = ($dEnd != null) ? date('Ymd\T235959\Z', $dEnd) : null;
689: $mCalendarId = !is_array($mCalendarId) ? array($mCalendarId) : $mCalendarId;
690:
691: foreach ($mCalendarId as $sCalendarId) {
692: $aEvents = $this->oStorage->getEventsInfo($sUserPublicId, $sCalendarId, $dStart, $dEnd, $bGetData);
693: if ($aEvents && is_array($aEvents)) {
694: $aResult = array_merge($aResult, $aEvents);
695: }
696: }
697: } catch (\Exception $oException) {
698: $aResult = false;
699: $this->setLastException($oException);
700: }
701: return $aResult;
702: }
703:
704: /**
705: * Return specific event.
706: *
707: * @param string $sUserPublicId
708: * @param string $sCalendarId Calendar ID
709: * @param string $sEventId Event ID
710: *
711: * @return array|bool
712: */
713: public function getEvent($sUserPublicId, $sCalendarId, $sEventId)
714: {
715: $mResult = null;
716: try {
717: $mResult = array();
718: $aData = $this->oStorage->getEvent($sUserPublicId, $sCalendarId, $sEventId);
719: if ($aData !== false) {
720: if (isset($aData['vcal'])) {
721: $oVCal = $aData['vcal'];
722: $oCalendar = $this->oStorage->getCalendar($sUserPublicId, $sCalendarId);
723: $mResult = \Aurora\Modules\Calendar\Classes\Parser::parseEvent($sUserPublicId, $oCalendar, $oVCal, $oVCal);
724: $mResult['vcal'] = $oVCal;
725: }
726: }
727: } catch (\Exception $oException) {
728: $mResult = false;
729: $this->setLastException($oException);
730: }
731: return $mResult;
732: }
733:
734:
735: // Events
736:
737: /**
738: * For recurring event, gets a base one.
739: *
740: * @param string $sUserPublicId
741: * @param string $sCalendarId Calendar ID
742: * @param string $sEventId Event ID
743: *
744: * @return array|bool
745: */
746: public function getBaseEvent($sUserPublicId, $sCalendarId, $sEventId)
747: {
748: $mResult = null;
749: try {
750: $mResult = array();
751: $aData = $this->oStorage->getEvent($sUserPublicId, $sCalendarId, $sEventId);
752: if ($aData !== false) {
753: if (isset($aData['vcal'])) {
754: $oVCal = $aData['vcal'];
755: $oVCalOriginal = clone $oVCal;
756: $oCalendar = $this->oStorage->getCalendar($sUserPublicId, $sCalendarId);
757: $oVEvent = $oVCal->getBaseComponents('VEVENT');
758: if (isset($oVEvent[0])) {
759: unset($oVCal->VEVENT);
760: $oVCal->VEVENT = $oVEvent[0];
761: }
762: $oEvent = \Aurora\Modules\Calendar\Classes\Parser::parseEvent($sUserPublicId, $oCalendar, $oVCal, $oVCalOriginal);
763: if (isset($oEvent[0])) {
764: $mResult = $oEvent[0];
765: }
766: }
767: }
768: } catch (\Exception $oException) {
769: $mResult = false;
770: $this->setLastException($oException);
771: }
772: return $mResult;
773: }
774:
775: /**
776: * For recurring event, gets all occurences within a date range.
777: *
778: * @param string $sUserPublicId
779: * @param string $sCalendarId Calendar ID
780: * @param string $sEventId Event ID
781: * @param string $dStart Date range start
782: * @param string $dEnd Date range end
783: *
784: * @return array|bool
785: */
786: public function getExpandedEvent($sUserPublicId, $sCalendarId, $sEventId, $dStart = null, $dEnd = null)
787: {
788: $mResult = null;
789:
790: try {
791: $dStart = ($dStart != null) ? date('Ymd\T000000\Z', $dStart/* + 86400*/) : null;
792: $dEnd = ($dEnd != null) ? date('Ymd\T235959\Z', $dEnd) : null;
793: $mResult = $this->oStorage->getExpandedEvent($sUserPublicId, $sCalendarId, $sEventId, $dStart, $dEnd);
794: } catch (\Exception $oException) {
795: $mResult = false;
796: $this->setLastException($oException);
797: }
798: return $mResult;
799: }
800:
801: /**
802: * @param string $sUserPublicId
803: * @param string $sCalendarId
804: * @param string $sEventId
805: * @param array $sData
806: *
807: * @return mixed
808: */
809: public function createEventFromRaw($sUserPublicId, $sCalendarId, $sEventId, $sData)
810: {
811: $mResult = false;
812: $aEvents = array();
813: try {
814: $oVCal = \Sabre\VObject\Reader::read($sData);
815: if ($oVCal && ($oVCal->VEVENT || $oVCal->VTODO)) {
816: if (!empty($sEventId)) {
817: $mResult = $this->oStorage->createEvent($sUserPublicId, $sCalendarId, $sEventId, $oVCal);
818: } else {
819: foreach ($oVCal->VEVENT as $oVEvent) {
820: $sUid = (string)$oVEvent->UID;
821: if (!isset($aEvents[$sUid])) {
822: $aEvents[$sUid] = new \Sabre\VObject\Component\VCalendar();
823: }
824: $aEvents[$sUid]->add($oVEvent);
825: }
826: $aVTodo = !empty($oVCal->VTODO) ? $oVCal->VTODO : [];
827: foreach ($aVTodo as $oVTodo) {
828: $sUid = (string)$oVTodo->UID;
829: if (!isset($aEvents[$sUid])) {
830: $aEvents[$sUid] = new \Sabre\VObject\Component\VCalendar();
831: }
832: $aEvents[$sUid]->add($oVTodo);
833: }
834:
835: $aCreatedUids = [];
836: foreach ($aEvents as $sUid => $oVCalNew) {
837: $sCreatedUid = $this->oStorage->createEvent($sUserPublicId, $sCalendarId, $sUid, $oVCalNew);
838: if ($sCreatedUid) {
839: $aCreatedUids[] = $sCreatedUid;
840: }
841: }
842: if (!empty($aCreatedUids)) {
843: $mResult = $aCreatedUids;
844: }
845: }
846: }
847: } catch (\Exception $oException) {
848: $this->setLastException($oException);
849: }
850: return $mResult;
851: }
852:
853: /**
854: * Creates event from event object.
855: *
856: * @param string $sUserPublicId
857: * @param \Aurora\Modules\Calendar\Classes\Event $oEvent Event object
858: *
859: * @return mixed
860: */
861: public function createEvent($sUserPublicId, $oEvent)
862: {
863: $oResult = null;
864: try {
865: $oEvent->Id = \Sabre\DAV\UUIDUtil::getUUID();
866:
867: $oVCal = new \Sabre\VObject\Component\VCalendar();
868: $sComponentName = !empty($oEvent->Type) ? $oEvent->Type : 'VEVENT';
869: $oComponent = new \Sabre\VObject\Component\VEvent(
870: $oVCal,
871: $sComponentName,
872: [
873: 'SEQUENCE' => 0,
874: 'TRANSP' => 'OPAQUE',
875: 'DTSTAMP' => new \DateTime('now', new \DateTimeZone('UTC')),
876: ],
877: true
878: );
879: $oVCal->add($oComponent);
880:
881: \Aurora\Modules\Calendar\Classes\Helper::populateVCalendar($sUserPublicId, $oEvent, $oVCal, $oVCal->$sComponentName);
882: $aArgs = [
883: 'sUserPublicId' => $sUserPublicId,
884: 'oEvent' => $oEvent,
885: 'oVCal' => $oVCal
886: ];
887: $this->GetModule()->broadcastEvent(
888: 'populateVCalendar',
889: $aArgs,
890: $oVCal->$sComponentName
891: );
892: $oResult = $this->oStorage->createEvent($sUserPublicId, $oEvent->IdCalendar, $oEvent->Id, $oVCal);
893: } catch (\Exception $oException) {
894: $oResult = false;
895: $this->setLastException($oException);
896: }
897: return $oResult;
898: }
899:
900: /**
901: * Update events using event object.
902: *
903: * @param string $sUserPublicId
904: * @param \Aurora\Modules\Calendar\Classes\Event $oEvent Event object
905: *
906: * @return bool
907: */
908: public function updateEvent($sUserPublicId, $oEvent)
909: {
910: $oResult = null;
911: try {
912: $aData = $this->oStorage->getEvent($sUserPublicId, $oEvent->IdCalendar, $oEvent->Id);
913: if ($aData !== false) {
914: /** @var \Sabre\VObject\Component\VCalendar */
915: $oVCal = $aData['vcal'];
916:
917: if ($oEvent->Type === 'VTODO' && isset($oVCal->VEVENT)) {
918: $sRawEventData = $oVCal->serialize();
919: $sRawEventData = str_replace('VEVENT', 'VTODO', $sRawEventData);
920: $oVCal = \Sabre\VObject\Reader::read($sRawEventData);
921: }
922:
923: if ($oEvent->Type === 'VEVENT' && isset($oVCal->VTODO)) {
924: $sRawEventData = $oVCal->serialize();
925: $sRawEventData = str_replace('VTODO', 'VEVENT', $sRawEventData);
926: $oVCal = \Sabre\VObject\Reader::read($sRawEventData);
927: }
928:
929: if ($oVCal) {
930: $sComponent = $oEvent->Type;
931:
932: $iIndex = \Aurora\Modules\Calendar\Classes\Helper::getBaseVComponentIndex($oVCal->{$sComponent});
933: if ($iIndex !== false) {
934: \Aurora\Modules\Calendar\Classes\Helper::populateVCalendar($sUserPublicId, $oEvent, $oVCal, $oVCal->{$sComponent}[$iIndex]);
935: $aArgs = [
936: 'sUserPublicId' => $sUserPublicId,
937: 'oEvent' => $oEvent,
938: 'oVCal' => $oVCal
939: ];
940: $this->GetModule()->broadcastEvent(
941: 'populateVCalendar',
942: $aArgs,
943: $oVCal->{$sComponent}[$iIndex]
944: );
945: }
946:
947: $oVCalResult = clone $oVCal;
948: if (!isset($oEvent->RRule)) {
949: unset($oVCalResult->{$sComponent});
950: if (isset($oVCal->{$sComponent})) {
951: foreach ($oVCal->{$sComponent} as $oVComponent) {
952: $oVComponent->SEQUENCE = (int) $oVComponent->SEQUENCE->getValue() + 1;
953: if (!isset($oVComponent->{'RECURRENCE-ID'})) {
954: $oVCalResult->add($oVComponent);
955: }
956: }
957: }
958: }
959:
960: $oResult = $this->oStorage->updateEvent($sUserPublicId, $oEvent->IdCalendar, $aData['url'], $oVCalResult);
961: }
962: }
963: } catch (\Exception $oException) {
964: $oResult = false;
965: $this->setLastException($oException);
966: }
967: return $oResult;
968: }
969:
970: /**
971: * @param string $sUserPublicId
972: * @param string $sCalendarId
973: * @param string $sEventUrl
974: * @param string $sData
975: *
976: * @return bool
977: */
978: public function updateEventRaw($sUserPublicId, $sCalendarId, $sEventUrl, $sData)
979: {
980: return $this->oStorage->updateEventRaw($sUserPublicId, $sCalendarId, $sEventUrl, $sData);
981: }
982:
983: /**
984: * Moves event to a different calendar.
985: *
986: * @param string $sUserPublicId
987: * @param string $sCalendarId Current calendar ID
988: * @param string $sCalendarIdNew New calendar ID
989: * @param string $sEventId Event ID
990: *
991: * @return bool
992: */
993: public function moveEvent($sUserPublicId, $sCalendarId, $sCalendarIdNew, $sEventId)
994: {
995: $oResult = null;
996: try {
997: $aData = $this->oStorage->getEvent($sUserPublicId, $sCalendarId, $sEventId);
998: if ($aData !== false && isset($aData['vcal']) && $aData['vcal'] instanceof \Sabre\VObject\Component\VCalendar) {
999: $oResult = $this->oStorage->moveEvent($sUserPublicId, $sCalendarId, $sCalendarIdNew, $sEventId, $aData['vcal']->serialize());
1000: // $this->updateEventGroupByMoving($sCalendarId, $sEventId, $sCalendarIdNew);
1001: return true;
1002: }
1003: return false;
1004: } catch (\Exception $oException) {
1005: $oResult = false;
1006: $this->setLastException($oException);
1007: }
1008: return $oResult;
1009: }
1010:
1011: /**
1012: * @param string $sCalendarId
1013: * @param string $sEventId
1014: * @param string $sNewCalendarId
1015: */
1016: public function updateEventGroupByMoving($sCalendarId, $sEventId, $sNewCalendarId)
1017: {
1018: $oContactsModule = \Aurora\System\Api::GetModule('Contacts');
1019: if ($oContactsModule) {
1020: $aEvents = $oContactsModule->CallMethod('getGroupEvent', array($sCalendarId, $sEventId));
1021: if (is_array($aEvents) && 0 < count($aEvents)) {
1022: foreach ($aEvents as $aEvent) {
1023: if (isset($aEvent['id_group'])) {
1024: $oContactsModule->CallMethod('removeEventFromGroup', array($aEvent['id_group'], $sCalendarId, $sEventId));
1025: $oContactsModule->CallMethod('addEventToGroup', array($aEvent['id_group'], $sNewCalendarId, $sEventId));
1026: }
1027: }
1028: }
1029: }
1030: }
1031:
1032: /**
1033: * Updates or deletes exclusion from recurring event.
1034: *
1035: * @param string $sUserPublicId
1036: * @param \Aurora\Modules\Calendar\Classes\Event $oEvent Event object
1037: * @param string $sRecurrenceId Recurrence ID
1038: * @param bool $bDelete If **true**, exclusion is deleted
1039: *
1040: * @return bool
1041: */
1042: public function updateExclusion($sUserPublicId, $oEvent, $sRecurrenceId, $bDelete = false)
1043: {
1044: $oResult = null;
1045: try {
1046: $oUser = \Aurora\System\Api::getAuthenticatedUser();
1047: $aData = $this->oStorage->getEvent($sUserPublicId, $oEvent->IdCalendar, $oEvent->Id);
1048: if ($aData !== false && isset($aData['vcal']) && $aData['vcal'] instanceof \Sabre\VObject\Component\VCalendar) {
1049: $oVCal = $aData['vcal'];
1050: $sComponent = isset($oVCal->VEVENT) ? 'VEVENT' : 'VTODO';
1051:
1052: $iIndex = \Aurora\Modules\Calendar\Classes\Helper::getBaseVComponentIndex($oVCal->{$sComponent});
1053: if ($iIndex !== false) {
1054: /** @var \Sabre\VObject\Component $oVComponent */
1055: $oVComponent = &$oVCal->{$sComponent}[$iIndex];
1056: $oVComponent->{'LAST-MODIFIED'} = new \DateTime('now', new \DateTimeZone('UTC'));
1057:
1058: $oDTExdate = \Aurora\Modules\Calendar\Classes\Helper::prepareDateTime($sRecurrenceId, $oUser->DefaultTimeZone);
1059: /** @var \Sabre\VObject\Property\ICalendar\DateTime */
1060: $DTSTART = $oVComponent->DTSTART;
1061: $oDTStart = $DTSTART->getDatetime();
1062:
1063: $mIndex = \Aurora\Modules\Calendar\Classes\Helper::isRecurrenceExists($oVCal->{$sComponent}, $sRecurrenceId);
1064: if ($bDelete) {
1065: // if exclude first event in occurrence
1066: if ($oDTExdate === $oDTStart) {
1067: $it = new \Sabre\VObject\Recur\EventIterator($oVCal, (string) $oVCal->{$sComponent}[$iIndex]->UID);
1068: $it->fastForward($oDTStart);
1069: $it->next();
1070:
1071: if ($it->valid()) {
1072: $oEventObj = $it->getEventObject();
1073: $oVComponent->DTSTART = $oEventObj->DTSTART;
1074: $oVComponent->DTEND = $oEventObj->DTEND;
1075: }
1076: }
1077:
1078: if (isset($oVComponent->EXDATE)) {
1079: $oEXDATE = clone $oVComponent->EXDATE;
1080: unset($oVComponent->EXDATE);
1081: foreach ($oEXDATE as $oExDate) {
1082: if ($oExDate->getDateTime() !== $oDTExdate) {
1083: $oVComponent->add('EXDATE', $oExDate->getDateTime());
1084: }
1085: }
1086: }
1087: $oVComponent->add('EXDATE', $oDTExdate);
1088:
1089: if (false !== $mIndex) {
1090: $aVEvents = $oVCal->{$sComponent};
1091: unset($oVCal->{$sComponent});
1092:
1093: foreach ($aVEvents as $oVEvent) {
1094: if ($oVEvent->{'RECURRENCE-ID'}) {
1095: $iRecurrenceId = \Aurora\Modules\Calendar\Classes\Helper::getTimestamp($oVEvent->{'RECURRENCE-ID'}, $oUser->DefaultTimeZone);
1096: if ((int)$iRecurrenceId == (int) $sRecurrenceId) {
1097: continue;
1098: }
1099: }
1100: $oVCal->add($oVEvent);
1101: }
1102: }
1103: } else {
1104: $oVEventRecur = null;
1105: if ($mIndex === false) {
1106: $oVEventRecur = $oVCal->add($sComponent, array(
1107: 'SEQUENCE' => 1,
1108: 'TRANSP' => 'OPAQUE',
1109: 'RECURRENCE-ID' => $oDTExdate
1110: ));
1111: } else {
1112: $oVEventRecur = &$oVCal->{$sComponent}[$mIndex];
1113: }
1114: if ($oVEventRecur) {
1115: $oEvent->RRule = null;
1116: \Aurora\Modules\Calendar\Classes\Helper::populateVCalendar($sUserPublicId, $oEvent, $oVCal, $oVEventRecur);
1117: $aArgs = [
1118: 'sUserPublicId' => $sUserPublicId,
1119: 'oEvent' => $oEvent,
1120: 'oVCal' => $oVCal
1121: ];
1122: $this->GetModule()->broadcastEvent(
1123: 'populateVCalendar',
1124: $aArgs,
1125: $oVEventRecur
1126: );
1127: }
1128: }
1129: $this->oStorage->updateEvent($sUserPublicId, $oEvent->IdCalendar, $oEvent->Id, $oVCal);
1130: return true;
1131: }
1132: }
1133: return false;
1134: } catch (\Exception $oException) {
1135: $oResult = false;
1136: $this->setLastException($oException);
1137: }
1138: return $oResult;
1139: }
1140:
1141: /**
1142: * deleteExclusion
1143: *
1144: * @param string $sUserPublicId Account object
1145: * @param string $sCalendarId Calendar ID
1146: * @param string $sEventId Event ID
1147: * @param string $iRecurrenceId Recurrence ID
1148: *
1149: * @return bool
1150: */
1151: public function deleteExclusion($sUserPublicId, $sCalendarId, $sEventId, $iRecurrenceId)
1152: {
1153: $oResult = null;
1154: try {
1155: $aData = $this->oStorage->getEvent($sUserPublicId, $sCalendarId, $sEventId);
1156: $oUser = \Aurora\Modules\Core\Module::Decorator()->GetUserByPublicId($sUserPublicId);
1157: if ($oUser && $aData !== false && isset($aData['vcal']) && $aData['vcal'] instanceof \Sabre\VObject\Component\VCalendar) {
1158: $oVCal = $aData['vcal'];
1159:
1160: $sComponent = 'VEVENT';
1161: if ($oVCal->VTODO) {
1162: $sComponent = 'VTODO';
1163: }
1164:
1165: $aVComponents = $oVCal->{$sComponent};
1166: unset($oVCal->{$sComponent});
1167:
1168: foreach ($aVComponents as $oVComponent) {
1169: if (isset($oVComponent->{'RECURRENCE-ID'})) {
1170: $iServerRecurrenceId = \Aurora\Modules\Calendar\Classes\Helper::getStrDate($oVComponent->{'RECURRENCE-ID'}, $oUser->DefaultTimeZone, 'Ymd');
1171: if ($iRecurrenceId == $iServerRecurrenceId) {
1172: continue;
1173: }
1174: }
1175: $oVCal->add($oVComponent);
1176: }
1177: return $this->oStorage->updateEvent($sUserPublicId, $sCalendarId, $sEventId, $oVCal);
1178: }
1179: return false;
1180: } catch (\Exception $oException) {
1181: $oResult = false;
1182: $this->setLastException($oException);
1183: }
1184: return $oResult;
1185: }
1186:
1187: /**
1188: *
1189: * @param int $start
1190: * @param int $end
1191: *
1192: * @return array|bool
1193: */
1194: public function getReminders($start = null, $end = null)
1195: {
1196: $oResult = null;
1197: try {
1198: $oResult = $this->oStorage->getReminders($start, $end);
1199: } catch (\Exception $oException) {
1200: $oResult = false;
1201: $this->setLastException($oException);
1202: }
1203: return $oResult;
1204: }
1205:
1206: /**
1207: *
1208: * @param string $sEventId
1209: * @return bool
1210: */
1211: public function deleteReminder($sEventId)
1212: {
1213: $oResult = null;
1214: try {
1215: $oResult = $this->oStorage->deleteReminder($sEventId);
1216: } catch (\Exception $oException) {
1217: $oResult = false;
1218: $this->setLastException($oException);
1219: }
1220: return $oResult;
1221: }
1222:
1223: /**
1224: *
1225: * @param string $sCalendarUri
1226: *
1227: * @return bool
1228: */
1229: public function deleteReminderByCalendar($sCalendarUri)
1230: {
1231: $oResult = null;
1232: try {
1233: $oResult = $this->oStorage->deleteReminderByCalendar($sCalendarUri);
1234: } catch (\Exception $oException) {
1235: $oResult = false;
1236: $this->setLastException($oException);
1237: }
1238: return $oResult;
1239: }
1240:
1241: /**
1242: *
1243: * @param int $time
1244: *
1245: * @return bool
1246: */
1247: public function deleteOutdatedReminders($time)
1248: {
1249: $oResult = false;
1250: try {
1251: $oResult = $this->oStorage->deleteOutdatedReminders($time);
1252: } catch (\Exception $oException) {
1253: $oResult = false;
1254: $this->setLastException($oException);
1255: }
1256: return $oResult;
1257: }
1258:
1259: /**
1260: *
1261: * @param string $sEmail
1262: * @param string $sCalendarUri
1263: * @param string $sEventId
1264: * @param string $sData
1265: *
1266: * @return bool
1267: */
1268: public function updateReminder($sEmail, $sCalendarUri, $sEventId, $sData)
1269: {
1270: $oResult = null;
1271: try {
1272: $oCalendar = $this->getCalendar($sEmail, $sCalendarUri);
1273: if ($oCalendar) {
1274: $oResult = $this->oStorage->updateReminder($oCalendar, $sEventId, $sData);
1275: }
1276: } catch (\Exception $oException) {
1277: $oResult = false;
1278: $this->setLastException($oException);
1279: }
1280: return $oResult;
1281: }
1282:
1283: /**
1284: * Returns default calendar of the account.
1285: *
1286: * @param string $sUserPublicId
1287: *
1288: * @return \Aurora\Modules\Calendar\Classes\Calendar|false $oCalendar
1289: */
1290: public function getDefaultCalendar($sUserPublicId)
1291: {
1292: $mResult = null;
1293: $aCalendars = $this->getCalendars($sUserPublicId);
1294: foreach ($aCalendars as $key => $val) {
1295: if (strpos($key, \Afterlogic\DAV\Constants::CALENDAR_DEFAULT_UUID) !== false) {
1296: $mResult = $val;
1297: break;
1298: }
1299: }
1300: return $mResult;
1301: }
1302:
1303: /**
1304: * @param string $sUserPublicId
1305: *
1306: * @return bool
1307: */
1308: public function getCalendars($sUserPublicId)
1309: {
1310: $aCalendars = [];
1311: try {
1312: $aCalendars = $this->oStorage->getCalendars($sUserPublicId);
1313: } catch (\Exception $oException) {
1314: $aCalendars = false;
1315: $this->setLastException($oException);
1316: }
1317:
1318: return $aCalendars;
1319: }
1320:
1321: public function getSharedCalendars($sUserPublicId)
1322: {
1323: $aCalendars = [];
1324: try {
1325: $aCalendars = $this->oStorage->getSharedCalendars($sUserPublicId);
1326: } catch (\Exception $oException) {
1327: $aCalendars = false;
1328: $this->setLastException($oException);
1329: }
1330:
1331: return $aCalendars;
1332: }
1333:
1334: /**
1335: * Deletes event.
1336: *
1337: * @param string $sUserPublicId
1338: * @param string $sCalendarId Calendar ID
1339: * @param string $sEventId Event ID
1340: *
1341: * @return bool
1342: */
1343: public function deleteEvent($sUserPublicId, $sCalendarId, $sEventId)
1344: {
1345: $oResult = false;
1346:
1347: $oUser = \Aurora\Modules\Core\Module::Decorator()->GetUserByPublicId($sUserPublicId);
1348: if ($oUser instanceof \Aurora\Modules\Core\Models\User) {
1349: $aData = $this->oStorage->getEvent($oUser->PublicId, $sCalendarId, $sEventId);
1350: if ($aData !== false && isset($aData['vcal']) && $aData['vcal'] instanceof \Sabre\VObject\Component\VCalendar) {
1351: $oVCal = $aData['vcal'];
1352: $aArgs = [
1353: 'sUserPublicId' => $oUser->PublicId
1354: ];
1355: $this->GetModule()->broadcastEvent(
1356: 'DeleteEvent',
1357: $aArgs,
1358: $oVCal
1359: );
1360: $oResult = $this->oStorage->deleteEvent($oUser->PublicId, $sCalendarId, $aData['url']);
1361: if ($oResult) {
1362: // TODO realise 'removeEventFromAllGroups' method in 'Contacts' module
1363: //$oContactsModule = \Aurora\System\Api::GetModule('Contacts');
1364: //$oContactsModule->CallMethod('removeEventFromAllGroups', array($sCalendarId, $sEventId));
1365: }
1366: }
1367: }
1368:
1369: return $oResult;
1370: }
1371:
1372: /**
1373: * Deletes event.
1374: *
1375: * @param string $sUserPublicId
1376: * @param string $sCalendarId Calendar ID
1377: * @param string $sEventUrl Event URL
1378: *
1379: * @return bool
1380: */
1381: public function deleteEventByUrl($sUserPublicId, $sCalendarId, $sEventUrl)
1382: {
1383: return $this->oStorage->deleteEventByUrl($sUserPublicId, $sCalendarId, $sEventUrl);
1384: }
1385:
1386:
1387: /**
1388: * @param string $sUserPublicId
1389: * @param string $sData
1390: * @param string $mFromEmail
1391: * @param bool $bUpdateAttendeeStatus
1392: *
1393: * @return array|bool
1394: */
1395: public function processICS($sUserPublicId, $sData, $mFromEmail, $bUpdateAttendeeStatus = false)
1396: {
1397: $mResult = false;
1398: $oAuthenticatedUser = Api::getAuthenticatedUser();
1399: $aAccountEmails = ['mailto:' . $oAuthenticatedUser->PublicId];
1400:
1401: $oUser = \Aurora\Modules\Core\Module::Decorator()->GetUserByPublicId($sUserPublicId);
1402: if ($oUser instanceof \Aurora\Modules\Core\Models\User) {
1403: /** @var \Aurora\Modules\Mail\Module */
1404: $oMailModuleDecorator = Api::GetModuleDecorator('Mail');
1405: if ($oMailModuleDecorator) {
1406: $aUserAccounts = $oMailModuleDecorator->GetAccounts($oUser->Id);
1407: foreach ($aUserAccounts as $oMailAccount) {
1408: if ($oMailAccount instanceof \Aurora\Modules\Mail\Models\MailAccount) {
1409: $aAccountEmails[] = 'mailto:' . $oMailAccount->Email;
1410: }
1411: }
1412: }
1413:
1414: $aAccountEmails = array_unique($aAccountEmails);
1415:
1416: /** @var \Sabre\VObject\Component\VCalendar */
1417: $newVCal = \Sabre\VObject\Reader::read($sData);
1418: if ($newVCal) {
1419: $newBaseVEvent = $newVCal->getBaseComponent('VEVENT');
1420: $sMethod = isset($newVCal->METHOD) ? $newVCal->METHOD->getValue() : 'SAVE';
1421: if (!in_array($sMethod, ['REQUEST', 'REPLY', 'CANCEL', 'PUBLISH', 'SAVE'])) {
1422: return false;
1423: }
1424:
1425: if ($sMethod === 'REPLY') {
1426: $aAccountEmails = ['mailto:' . $mFromEmail];
1427: }
1428:
1429: if ($newBaseVEvent) {
1430: $oldBaseVEvent = null;
1431: $sEventId = (string)$newBaseVEvent->UID;
1432: $oldSequence = 0;
1433: $newSequence = isset($newBaseVEvent->{'SEQUENCE'}) && $newBaseVEvent->{'SEQUENCE'}->getValue() ? $newBaseVEvent->{'SEQUENCE'}->getValue() : 0 ;
1434: $sCalendarId = $this->oStorage->findEventInCalendars($sUserPublicId, $sEventId);
1435: if ($sCalendarId) {
1436: $oldEventData = $this->oStorage->getEvent($sUserPublicId, $sCalendarId, $sEventId);
1437: if ($oldEventData !== false) {
1438: $oldVCal = $oldEventData['vcal'];
1439:
1440: if ($oldVCal) {
1441: $oldBaseVEvent = $oldVCal->getBaseComponent('VEVENT');
1442: if ($oldBaseVEvent) {
1443: $oldSequence = isset($oldBaseVEvent->{'SEQUENCE'}) && $oldBaseVEvent->{'SEQUENCE'}->getValue() ? $oldBaseVEvent->{'SEQUENCE'}->getValue() : 0 ;
1444: }
1445: }
1446:
1447: $broker = new ITipBroker();
1448: $messages = $broker->parseEvent($newVCal, $aAccountEmails, $oldVCal);
1449:
1450: $schedulePlugin = Server::getInstance()->getPlugin('caldav-schedule');
1451: if ($schedulePlugin instanceof \Afterlogic\DAV\CalDAV\Schedule\Plugin) {
1452: foreach ($messages as $message) {
1453: $schedulePlugin->scheduleLocalDeliveryParent($message);
1454: }
1455: }
1456: }
1457: }
1458:
1459: //
1460: $sWhen = '';
1461: if (isset($newBaseVEvent->DTSTART)) {
1462: /** @var \Sabre\VObject\Property\ICalendar\DateTime */
1463: $newDTStart = $newBaseVEvent->DTSTART;
1464: $sWhenDateFormat = $newDTStart->hasTime() ? 'D, M d, Y, H:i' : 'D, M d, Y';
1465:
1466: $sWhen = \Aurora\Modules\Calendar\Classes\Helper::getStrDate($newDTStart, $oUser->DefaultTimeZone, $sWhenDateFormat);
1467:
1468: if ($this->oModule->oModuleSettings->ShowWeekNumbers) {
1469: $sWeek = \Aurora\Modules\Calendar\Classes\Helper::getStrDate($newDTStart, $oUser->DefaultTimeZone, 'W');
1470: $sWhen .= ' (' . $this->oModule->i18n('LABEL_WEEK_SHORT') . $sWeek . ')';
1471: }
1472: }
1473:
1474: $organizerEmail = '';
1475: $organizer = [];
1476: if (isset($newBaseVEvent->ORGANIZER)) {
1477: $organizerEmail = str_ireplace('mailto:', '', (string) $newBaseVEvent->ORGANIZER);
1478: $displayName = '';
1479: if (isset($newBaseVEvent->ORGANIZER['CN'])) {
1480: /** @var \Sabre\VObject\Property\ICalendar\CalAddress */
1481: $cn = $newBaseVEvent->ORGANIZER['CN'];
1482: $displayName = $cn->getValue();
1483: }
1484: $organizer = [
1485: 'DisplayName' => $displayName,
1486: 'Email' => $organizerEmail
1487: ];
1488: }
1489:
1490: $ateendeeList = [];
1491: if (isset($newBaseVEvent->ATTENDEE)) {
1492: foreach ($newBaseVEvent->ATTENDEE as $oAttendee) {
1493: $ateendee = str_ireplace('mailto:', '', (string) $oAttendee);
1494: if (strtolower($ateendee) !== strtolower($organizerEmail)) {
1495: $ateendeeList[] = [
1496: 'DisplayName' => (isset($oAttendee['CN'])) ? $oAttendee['CN']->getValue() : '',
1497: 'Email' => $ateendee
1498: ];
1499: }
1500: }
1501: }
1502:
1503: if ($sMethod === 'CANCEL' && $bUpdateAttendeeStatus) {
1504: $aArgs = [
1505: 'sUserPublicId' => $oUser->PublicId,
1506: 'sCalendarId' => $sCalendarId,
1507: 'sEventId' => $sEventId
1508: ];
1509: $this->GetModule()->broadcastEvent(
1510: 'processICS::Cancel',
1511: $aArgs,
1512: $mResult
1513: );
1514: }
1515:
1516: $mResult = [
1517: 'Calendars' => $this->oStorage->GetCalendarNames($sUserPublicId),
1518: 'CalendarId' => $sCalendarId,
1519: 'UID' => $sEventId,
1520: 'Body' => $newVCal->serialize(),
1521: 'Action' => $sMethod,
1522: 'Location' => isset($newBaseVEvent->LOCATION) ? (string)$newBaseVEvent->LOCATION : '',
1523: 'Description' => isset($newBaseVEvent->DESCRIPTION) ? (string)$newBaseVEvent->DESCRIPTION : '',
1524: 'Summary' => isset($newBaseVEvent->SUMMARY) ? (string)$newBaseVEvent->SUMMARY : '',
1525: 'When' => $sWhen,
1526: 'Sequence' => $newSequence,
1527: 'Organizer' => $organizer,
1528: 'AttendeeList' => $ateendeeList,
1529: ];
1530:
1531: if ($oldSequence && $oldSequence >= $newSequence) {
1532: $aArgs = [
1533: 'oVEventResult' => $sMethod === 'REPLY' ? $newBaseVEvent : $oldBaseVEvent,
1534: 'sMethod' => $sMethod,
1535: 'aAccountEmails' => $aAccountEmails
1536: ];
1537: $this->GetModule()->broadcastEvent(
1538: 'processICS::AddAttendeesToResult',
1539: $aArgs,
1540: $mResult
1541: );
1542: }
1543: }
1544: }
1545: }
1546:
1547: return $mResult;
1548: }
1549:
1550: /**
1551: * @param string $sUserPublicId
1552: * @param string $uid
1553: *
1554: * @return string|false
1555: */
1556:
1557: public function findEventInCalendars($sUserPublicId, $uid)
1558: {
1559: return $this->oStorage->findEventInCalendars($sUserPublicId, $uid);
1560: }
1561:
1562: /**
1563: * @param string $sUserPublicId
1564: *
1565: * @return bool
1566: */
1567: public function clearAllCalendars($sUserPublicId)
1568: {
1569: $bResult = false;
1570:
1571: $oUser = Api::getUserByPublicId($sUserPublicId);
1572:
1573: if ($oUser instanceof \Aurora\Modules\Core\Models\User) {
1574: $bResult = $this->oStorage->clearAllCalendars($sUserPublicId);
1575: }
1576:
1577: return $bResult;
1578: }
1579:
1580: public function getChangesForCalendar($userPublicId, $calendarId, $syncToken, $limit = null)
1581: {
1582: return $this->oStorage->getChangesForCalendar($userPublicId, $calendarId, $syncToken, $limit);
1583: }
1584:
1585: }
1586: