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