1: | <?php |
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | namespace Aurora\Modules\CalendarMeetingsPlugin; |
9: | |
10: | use Aurora\Modules\Core\Module as CoreModule; |
11: | use Aurora\Modules\Calendar\Module as CalendarModule; |
12: | use Aurora\Modules\Calendar\Classes\Helper as CalendarHelper; |
13: | use Aurora\System\Api; |
14: | use MailSo\Mime\Email; |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | |
21: | |
22: | |
23: | |
24: | |
25: | class Module extends \Aurora\System\Module\AbstractModule |
26: | { |
27: | |
28: | protected $oManager = null; |
29: | |
30: | public $oApiFileCache = null; |
31: | |
32: | |
33: | |
34: | |
35: | |
36: | |
37: | public static function getInstance() |
38: | { |
39: | return parent::getInstance(); |
40: | } |
41: | |
42: | |
43: | |
44: | |
45: | public static function Decorator() |
46: | { |
47: | return parent::Decorator(); |
48: | } |
49: | |
50: | |
51: | |
52: | |
53: | public function getModuleSettings() |
54: | { |
55: | return $this->oModuleSettings; |
56: | } |
57: | |
58: | public function getManager() |
59: | { |
60: | if ($this->oManager === null) { |
61: | $this->oManager = new Manager($this); |
62: | } |
63: | |
64: | return $this->oManager; |
65: | } |
66: | |
67: | public function getCacheManager() |
68: | { |
69: | if ($this->oApiFileCache === null) { |
70: | $this->oApiFileCache = new \Aurora\System\Managers\Filecache(); |
71: | } |
72: | |
73: | return $this->oApiFileCache; |
74: | } |
75: | |
76: | public function init() |
77: | { |
78: | $this->AddEntries([ |
79: | 'invite' => 'EntryInvite' |
80: | ]); |
81: | |
82: | $this->subscribeEvent('Calendar::CreateIcs', array($this, 'onCreateIcs')); |
83: | $this->subscribeEvent('Calendar::populateVCalendar', array($this, 'onPopulateVCalendar')); |
84: | $this->subscribeEvent('Calendar::DeleteEvent', array($this, 'onDeleteEvent')); |
85: | $this->subscribeEvent('Calendar::UpdateEventAttendees', array($this, 'onUpdateEventAttendees')); |
86: | $this->subscribeEvent('CalendarMeetingsPlugin::processICS::UpdateEvent', array($this, 'onProcessICSUpdateEvent')); |
87: | $this->subscribeEvent('CalendarMeetingsPlugin::processICS::Cancel', array($this, 'onProcessICSCancel')); |
88: | $this->subscribeEvent('Calendar::processICS::UpdateEvent', array($this, 'onProcessICSUpdateEvent')); |
89: | $this->subscribeEvent('Calendar::processICS::Cancel', array($this, 'onProcessICSCancel')); |
90: | $this->subscribeEvent('Calendar::processICS::AddAttendeesToResult', array($this, 'onAddAttendeesToResult')); |
91: | $this->subscribeEvent('Calendar::parseEvent', array($this, 'onParseEvent')); |
92: | |
93: | $this->aErrors = [ |
94: | Enums\ErrorCodes::CannotSendAppointmentMessage => $this->i18N('ERROR_CANNOT_SEND_APPOINTMENT_MESSAGE'), |
95: | Enums\ErrorCodes::CannotSendAppointmentMessageNoOrganizer => $this->i18N('ERROR_CANNOT_SEND_APPOINTMENT_MESSAGE_NO_ORGANIZER') |
96: | ]; |
97: | } |
98: | |
99: | |
100: | |
101: | |
102: | |
103: | |
104: | |
105: | |
106: | public function UpdateAttendeeStatus($UserId, $File, $FromEmail) |
107: | { |
108: | \Aurora\System\Api::CheckAccess($UserId); |
109: | $sUserPublicId = \Aurora\System\Api::getUserPublicIdById($UserId); |
110: | $mResult = false; |
111: | |
112: | if (empty($File) || empty($FromEmail)) { |
113: | throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::InvalidInputParameter); |
114: | } |
115: | $sData = $this->getCacheManager()->get($sUserPublicId, $File, '', CalendarModule::GetName()); |
116: | if (!empty($sData)) { |
117: | $mResult = $this->getManager()->processICS($sUserPublicId, $sData, $FromEmail, true); |
118: | } |
119: | |
120: | return $mResult; |
121: | } |
122: | |
123: | |
124: | |
125: | |
126: | |
127: | |
128: | |
129: | |
130: | |
131: | |
132: | |
133: | |
134: | public function SetAppointmentAction($UserId, $CalendarId, $EventId, $File, $AppointmentAction, $Attendee, $AllEvents = 2, $RecurrenceId = null) |
135: | { |
136: | \Aurora\System\Api::CheckAccess($UserId); |
137: | $sUserPublicId = \Aurora\System\Api::getUserPublicIdById($UserId); |
138: | $mResult = false; |
139: | |
140: | if (empty($AppointmentAction) || empty($CalendarId)) { |
141: | throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::InvalidInputParameter); |
142: | } |
143: | $sData = ''; |
144: | if (!empty($EventId)) { |
145: | $aEventData = $this->getManager()->getEvent($sUserPublicId, $CalendarId, $EventId); |
146: | if (isset($aEventData) && isset($aEventData['vcal']) && $aEventData['vcal'] instanceof \Sabre\VObject\Component\VCalendar) { |
147: | $oVCal = $aEventData['vcal']; |
148: | $oVCal->METHOD = 'REQUEST'; |
149: | $sData = $oVCal->serialize(); |
150: | } |
151: | } elseif (!empty($File)) { |
152: | $sData = $this->getCacheManager()->get($sUserPublicId, $File, '', CalendarModule::GetName()); |
153: | } |
154: | if (!empty($sData)) { |
155: | $mProcessResult = $this->getManager()->appointmentAction($sUserPublicId, $Attendee, $AppointmentAction, $CalendarId, $sData, $AllEvents, $RecurrenceId); |
156: | if ($mProcessResult) { |
157: | $mResult = array( |
158: | 'Uid' => $mProcessResult |
159: | ); |
160: | } |
161: | } |
162: | |
163: | return $mResult; |
164: | } |
165: | |
166: | public function EntryInvite() |
167: | { |
168: | $sResult = ''; |
169: | $aInviteValues = \Aurora\System\Api::DecodeKeyValues($this->oHttp->GetQuery('invite')); |
170: | |
171: | if (isset($aInviteValues['organizer'])) { |
172: | $sOrganizerPublicId = $aInviteValues['organizer']; |
173: | $oOrganizerUser = CoreModule::Decorator()->GetUserByPublicId($sOrganizerPublicId); |
174: | if ($sOrganizerPublicId && isset($aInviteValues['attendee'], $aInviteValues['eventId'], $aInviteValues['action'])) { |
175: | $calendarId = $aInviteValues['calendarId']; |
176: | if (empty($calendarId)) { |
177: | $calendarId = $this->getManager()->findEventInCalendars($sOrganizerPublicId, $aInviteValues['eventId']); |
178: | } |
179: | $sAction = ''; |
180: | $oEvent = $this->getManager()->getEvent($sOrganizerPublicId, $calendarId, $aInviteValues['eventId']); |
181: | $oModuleManager = \Aurora\System\Api::GetModuleManager(); |
182: | $sTheme = $oModuleManager->getModuleConfigValue('CoreWebclient', 'Theme'); |
183: | if ($oEvent && is_array($oEvent) && 0 < count($oEvent) && isset($oEvent[0])) { |
184: | $sResult = \file_get_contents($this->GetPath() . '/templates/CalendarEventInviteExternal.html'); |
185: | if (is_string($sResult)) { |
186: | $dt = new \DateTime(); |
187: | $dt->setTimestamp($oEvent[0]['startTS']); |
188: | if (!$oEvent[0]['allDay']) { |
189: | $sDefaultTimeZone = new \DateTimeZone($oOrganizerUser->DefaultTimeZone); |
190: | $dt->setTimezone($sDefaultTimeZone); |
191: | } |
192: | |
193: | $sAction = $aInviteValues['action']; |
194: | $sActionColor = 'green'; |
195: | $sActionText = ''; |
196: | switch (strtoupper($sAction)) { |
197: | case 'ACCEPTED': |
198: | $sActionColor = 'green'; |
199: | $sActionText = 'Accepted'; |
200: | break; |
201: | case 'DECLINED': |
202: | $sActionColor = 'red'; |
203: | $sActionText = 'Declined'; |
204: | break; |
205: | case 'TENTATIVE': |
206: | $sActionColor = '#A0A0A0'; |
207: | $sActionText = 'Tentative'; |
208: | break; |
209: | } |
210: | |
211: | $sDateFormat = 'm/d/Y'; |
212: | $sTimeFormat = 'h:i A'; |
213: | switch ($oOrganizerUser->DateFormat) { |
214: | case \Aurora\System\Enums\DateFormat::DDMMYYYY: |
215: | $sDateFormat = 'd/m/Y'; |
216: | break; |
217: | case \Aurora\System\Enums\DateFormat::DD_MONTH_YYYY: |
218: | $sDateFormat = 'd/m/Y'; |
219: | break; |
220: | default: |
221: | $sDateFormat = 'm/d/Y'; |
222: | break; |
223: | } |
224: | switch ($oOrganizerUser->TimeFormat) { |
225: | case \Aurora\System\Enums\TimeFormat::F24: |
226: | $sTimeFormat = 'H:i'; |
227: | break; |
228: | case \Aurora\System\Enums\DateFormat::DD_MONTH_YYYY: |
229: | \Aurora\System\Enums\TimeFormat::F12; |
230: | $sTimeFormat = 'h:i A'; |
231: | break; |
232: | default: |
233: | $sTimeFormat = 'h:i A'; |
234: | break; |
235: | } |
236: | $sDateTime = $dt->format($sDateFormat . ' ' . $sTimeFormat); |
237: | |
238: | $mResult = array( |
239: | '{{EVENT_NAME}}' => $oEvent[0]['subject'], |
240: | '{{EVENT_BEGIN}}' => ucfirst($this->i18N('EVENT_BEGIN')), |
241: | '{{EVENT_DATE}}' => $sDateTime, |
242: | '{{CALENDAR}}' => ucfirst($this->i18N('CALENDAR')), |
243: | '{{EVENT_DESCRIPTION}}' => $oEvent[0]['description'], |
244: | '{{EVENT_ACTION}}' => $sActionText, |
245: | '{{ACTION_COLOR}}' => $sActionColor, |
246: | '{{THEME_NAME}}' => $sTheme, |
247: | ); |
248: | |
249: | $sResult = strtr($sResult, $mResult); |
250: | } else { |
251: | $sResult = "Error occured"; |
252: | \Aurora\System\Api::Log('Empty page template.', \Aurora\System\Enums\LogLevel::Error); |
253: | } |
254: | } else { |
255: | \Aurora\System\Api::Log('Event not found.', \Aurora\System\Enums\LogLevel::Error); |
256: | |
257: | $sResult = file_get_contents($this->GetPath() . '/templates/EventNotFound.html'); |
258: | |
259: | if (is_string($sResult)) { |
260: | $mResult = array( |
261: | '{{INFO}}' => ucfirst($this->i18N('ERROR_APPOINTMENT_NOT_FOUND')), |
262: | '{{THEME_NAME}}' => $sTheme, |
263: | ); |
264: | |
265: | $sResult = strtr($sResult, $mResult); |
266: | } else { |
267: | $sResult = "Error occured"; |
268: | \Aurora\System\Api::Log('Empty page template.', \Aurora\System\Enums\LogLevel::Error); |
269: | } |
270: | } |
271: | $sAttendee = $aInviteValues['attendee']; |
272: | if (!empty($sAttendee)) { |
273: | $oAttendee = Email::Parse($sAttendee); |
274: | $sAttendee = $oAttendee->GetEmail(); |
275: | |
276: | if (isset($oEvent) && isset($oEvent['vcal']) && $oEvent['vcal'] instanceof \Sabre\VObject\Component\VCalendar) { |
277: | $oVCal = $oEvent['vcal']; |
278: | $oVCal->METHOD = 'REQUEST'; |
279: | $sData = $oVCal->serialize(); |
280: | $oAttendeeUser = CoreModule::Decorator()->GetUserByPublicId($sAttendee); |
281: | $bIsExternalAttendee = false; |
282: | if ($oAttendeeUser) { |
283: | $sOrganizerPublicId = $oAttendeeUser->PublicId; |
284: | } else { |
285: | $bIsExternalAttendee = true; |
286: | } |
287: | $actionResult = false; |
288: | try { |
289: | $actionResult = $this->getManager()->appointmentAction($sOrganizerPublicId, $sAttendee, $sAction, $calendarId, $sData, 2, null, true, $bIsExternalAttendee); |
290: | } catch (\Aurora\System\Exceptions\Exception $e) { |
291: | Api::LogException($e); |
292: | $actionResult = false; |
293: | } |
294: | if (!$actionResult) { |
295: | $sResult = file_get_contents($this->GetPath() . '/templates/EventNotFound.html'); |
296: | |
297: | if (is_string($sResult)) { |
298: | $mResult = array( |
299: | '{{INFO}}' => ucfirst($this->i18N('ERROR_APPOINTMENT_UPDATE_STATUS')), |
300: | '{{THEME_NAME}}' => $sTheme, |
301: | ); |
302: | |
303: | $sResult = strtr($sResult, $mResult); |
304: | } |
305: | } |
306: | } |
307: | } |
308: | } |
309: | } |
310: | |
311: | return $sResult; |
312: | } |
313: | |
314: | |
315: | |
316: | |
317: | |
318: | public function GetSettings() |
319: | { |
320: | \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous); |
321: | |
322: | $aSettings = array( |
323: | 'AllowAppointments' => $this->oModuleSettings->AllowAppointments |
324: | ); |
325: | |
326: | return $aSettings; |
327: | } |
328: | |
329: | public function onCreateIcs($aData, &$oIcs) |
330: | { |
331: | $oIcs->Attendee = isset($aData['Attendee']) ? $aData['Attendee'] : null; |
332: | $oIcs->Type = $aData['Action']; |
333: | } |
334: | |
335: | public function onPopulateVCalendar(&$aData, &$oVEvent) |
336: | { |
337: | |
338: | $oEvent = & $aData['oEvent']; |
339: | |
340: | $oUser = \Aurora\System\Api::getAuthenticatedUser(); |
341: | |
342: | $aAttendees = []; |
343: | $aAttendeeEmails = []; |
344: | $aObjAttendees = []; |
345: | if (isset($oVEvent->ORGANIZER)) { |
346: | $sOwnerEmail = str_replace('mailto:', '', strtolower((string) $oVEvent->ORGANIZER)); |
347: | $iPos = strpos($sOwnerEmail, 'principals/'); |
348: | if ($iPos !== false) { |
349: | $sOwnerEmail = \trim(substr($sOwnerEmail, $iPos + 11), '/'); |
350: | } |
351: | } |
352: | |
353: | if (isset($oVEvent->ATTENDEE)) { |
354: | $aAttendeeEmails = []; |
355: | foreach ($oEvent->Attendees as $aItem) { |
356: | $sStatus = ''; |
357: | switch ($aItem['status']) { |
358: | case \Aurora\Modules\Calendar\Enums\AttendeeStatus::Accepted: |
359: | $sStatus = 'ACCEPTED'; |
360: | break; |
361: | case \Aurora\Modules\Calendar\Enums\AttendeeStatus::Declined: |
362: | $sStatus = 'DECLINED'; |
363: | break; |
364: | case \Aurora\Modules\Calendar\Enums\AttendeeStatus::Tentative: |
365: | $sStatus = 'TENTATIVE'; |
366: | break; |
367: | case \Aurora\Modules\Calendar\Enums\AttendeeStatus::Unknown: |
368: | $sStatus = 'NEEDS-ACTION'; |
369: | break; |
370: | } |
371: | |
372: | $aAttendeeEmails[strtolower($aItem['email'])] = $sStatus; |
373: | } |
374: | |
375: | $aObjAttendees = $oVEvent->ATTENDEE; |
376: | unset($oVEvent->ATTENDEE); |
377: | foreach ($aObjAttendees as $oAttendee) { |
378: | $sAttendee = str_replace('mailto:', '', strtolower((string)$oAttendee)); |
379: | $oPartstat = $oAttendee->offsetGet('PARTSTAT'); |
380: | if (in_array($sAttendee, array_keys($aAttendeeEmails))) { |
381: | if (isset($oPartstat) && (string)$oPartstat === $aAttendeeEmails[$sAttendee]) { |
382: | $oVEvent->add($oAttendee); |
383: | $aAttendees[] = $sAttendee; |
384: | } |
385: | } |
386: | } |
387: | } |
388: | |
389: | if (isset($oEvent->Attendees) && count($oEvent->Attendees) > 0) { |
390: | if (!isset($oVEvent->ORGANIZER)) { |
391: | $oVEvent->ORGANIZER = 'mailto:' . $oUser->PublicId; |
392: | } |
393: | foreach ($oEvent->Attendees as $oAttendee) { |
394: | if (!in_array($oAttendee['email'], $aAttendees)) { |
395: | $oVEvent->add( |
396: | 'ATTENDEE', |
397: | 'mailto:' . $oAttendee['email'], |
398: | array( |
399: | 'CN' => !empty($oAttendee['name']) ? $oAttendee['name'] : $oAttendee['email'], |
400: | 'RSVP' => 'TRUE' |
401: | ) |
402: | ); |
403: | } |
404: | } |
405: | } else { |
406: | unset($oVEvent->ORGANIZER); |
407: | } |
408: | } |
409: | |
410: | public function onDeleteEvent($aData, &$oVCal) |
411: | { |
412: | $sUserPublicId = $aData['sUserPublicId']; |
413: | |
414: | $iIndex = CalendarHelper::getBaseVComponentIndex($oVCal->VEVENT); |
415: | if ($iIndex !== false) { |
416: | |
417: | $oVEvent = $oVCal->VEVENT[$iIndex]; |
418: | |
419: | $sOrganizer = (isset($oVEvent->ORGANIZER)) ? |
420: | str_replace('mailto:', '', strtolower((string)$oVEvent->ORGANIZER)) : null; |
421: | $iPos = false; |
422: | if (!empty($sOrganizer)) { |
423: | $iPos = strpos($sOrganizer, 'principals/'); |
424: | } |
425: | |
426: | if ($iPos !== false) { |
427: | $sOrganizer = \trim(substr($sOrganizer, $iPos + 11), '/'); |
428: | } |
429: | |
430: | if (isset($sOrganizer)) { |
431: | if ($sOrganizer === $sUserPublicId) { |
432: | $oDateTimeNow = new \DateTimeImmutable("now"); |
433: | |
434: | $oDTSTART = $oVEvent->DTSTART; |
435: | $oDateTimeEvent = $oDTSTART->getDateTime(); |
436: | $oDateTimeRepeat = CalendarHelper::getNextRepeat($oDateTimeNow, $oVEvent); |
437: | $bRrule = isset($oVEvent->RRULE); |
438: | $bEventFore = $oDateTimeEvent ? $oDateTimeEvent > $oDateTimeNow : false; |
439: | $bNextRepeatFore = $oDateTimeRepeat ? $oDateTimeRepeat > $oDateTimeNow : false; |
440: | |
441: | if (isset($oVEvent->ATTENDEE) && ($bRrule ? $bNextRepeatFore : $bEventFore)) { |
442: | foreach ($oVEvent->ATTENDEE as $oAttendee) { |
443: | $sEmail = str_replace('mailto:', '', strtolower((string)$oAttendee)); |
444: | |
445: | $oVCalResult = clone $oVCal; |
446: | $oVCalResult->METHOD = 'CANCEL'; |
447: | $sSubject = (string)$oVEvent->SUMMARY . ': Canceled'; |
448: | |
449: | Classes\Helper::sendAppointmentMessage($sUserPublicId, $sEmail, $sSubject, $oVCalResult, 'REQUEST'); |
450: | unset($oVCal->METHOD); |
451: | } |
452: | } |
453: | } |
454: | } |
455: | } |
456: | } |
457: | |
458: | public function onUpdateEventAttendees($aData, &$oEvent) |
459: | { |
460: | $aEventData = $this->getManager()->getEvent($aData['UserPublicId'], $oEvent->IdCalendar, $oEvent->Id); |
461: | if (isset($aEventData[0]) && isset($aEventData[0]['attendees'])) { |
462: | $oldAttendees = $aEventData[0]['attendees']; |
463: | $newAttendees = @json_decode($aData['attendees'], true); |
464: | |
465: | $deleteAttendees = []; |
466: | foreach ($oldAttendees as $old) { |
467: | $found = false; |
468: | foreach ($newAttendees as $new) { |
469: | if (strtolower($new['email']) === strtolower($old['email'])) { |
470: | $found = true; |
471: | break; |
472: | } |
473: | } |
474: | if (!$found) { |
475: | $deleteAttendees[] = $old; |
476: | } |
477: | } |
478: | |
479: | $oVCalResult = clone $aEventData['vcal']; |
480: | $oVCalResult->METHOD = 'CANCEL'; |
481: | if (isset($oVCalResult->VEVENT)) { |
482: | $sSubject = (string) $oVCalResult->VEVENT->SUMMARY . ': Canceled'; |
483: | $oVCalResult->VEVENT->SEQUENCE = (int) $oVCalResult->VEVENT->SEQUENCE->getValue() + 1; |
484: | |
485: | foreach ($deleteAttendees as $deleteAttendee) { |
486: | $sEmail = $deleteAttendee['email']; |
487: | |
488: | unset($oVCalResult->VEVENT->ATTENDEE); |
489: | |
490: | $oVCalResult->VEVENT->add( |
491: | 'ATTENDEE', |
492: | 'mailto:' . $deleteAttendee['email'], |
493: | array( |
494: | 'CN' => !empty($deleteAttendee['name']) ? $deleteAttendee['name'] : $deleteAttendee['email'], |
495: | 'PARTSTAT' => 'DECLINED' |
496: | ) |
497: | ); |
498: | |
499: | Classes\Helper::sendAppointmentMessage($aData['UserPublicId'], $sEmail, $sSubject, $oVCalResult, 'REQUEST'); |
500: | } |
501: | } |
502: | } |
503: | $oEvent->Attendees = @json_decode($aData['attendees'], true); |
504: | } |
505: | |
506: | public function onProcessICSUpdateEvent(&$aData, &$mResult) |
507: | { |
508: | $oVCalResult = $aData['oVCalResult']; |
509: | $oVEventResult = $aData['oVEventResult']; |
510: | $sUserPublicId = $aData['sUserPublicId']; |
511: | $sCalendarId = $aData['sCalendarId']; |
512: | $sEventId = $aData['sEventId']; |
513: | $sMethod = $aData['sMethod']; |
514: | $sequence = $aData['sequence']; |
515: | $sequenceServer = $aData['sequenceServer']; |
516: | |
517: | $oVEvent = $aData['oVEvent']; |
518: | $mFromEmail = $aData['mFromEmail']; |
519: | |
520: | $sType = $sMethod; |
521: | $oCurrentAttendee = null; |
522: | if (isset($oVEvent->ATTENDEE) && $sequenceServer >= $sequence) { |
523: | foreach ($oVEvent->ATTENDEE as $oAttendee) { |
524: | if ($mFromEmail && $mFromEmail === str_replace('mailto:', '', strtolower((string) $oAttendee->getValue()))) { |
525: | $oCurrentAttendee = $oAttendee; |
526: | break; |
527: | } |
528: | } |
529: | if (isset($oVEventResult->ATTENDEE, $oCurrentAttendee)) { |
530: | foreach ($oVEventResult->ATTENDEE as &$oAttendeeResult) { |
531: | if ($oAttendeeResult->getValue() === $oCurrentAttendee->getValue()) { |
532: | if (isset($oCurrentAttendee['PARTSTAT'])) { |
533: | $oAttendeeResult['PARTSTAT'] = $oCurrentAttendee['PARTSTAT']->getValue(); |
534: | $sType = $sType . '-' . (string) $oAttendeeResult['PARTSTAT']; |
535: | |
536: | $oLAST_MODIFIED = $oVEvent->{'LAST-MODIFIED'}; |
537: | |
538: | $oRespondedAt = $oLAST_MODIFIED->getDateTime(); |
539: | $oRespondedAt->setTimezone(new \DateTimeZone('UTC')); |
540: | $oAttendeeResult['RESPONDED-AT'] = gmdate("Ymd\THis\Z", $oRespondedAt->getTimestamp()); |
541: | } |
542: | break; |
543: | } |
544: | } |
545: | } |
546: | } |
547: | unset($oVCalResult->METHOD); |
548: | $oVEventResult->{'LAST-MODIFIED'} = new \DateTime('now', new \DateTimeZone('UTC')); |
549: | $mResult = $this->getManager()->updateEventRaw($sUserPublicId, $sCalendarId, $sEventId, $oVCalResult->serialize()); |
550: | if ($mResult) { |
551: | $mResult = $sType; |
552: | } |
553: | |
554: | } |
555: | |
556: | public function onProcessICSCancel(&$aData, &$mResult) |
557: | { |
558: | $sCalendarId = $aData['sCalendarId']; |
559: | $sUserPublicId = $aData['sUserPublicId']; |
560: | $sEventId = $aData['sEventId']; |
561: | |
562: | if ($this->getManager()->deleteEvent($sUserPublicId, $sCalendarId, $sEventId)) { |
563: | $mResult = true; |
564: | } |
565: | } |
566: | |
567: | public function onAddAttendeesToResult(&$aData, &$mResult) |
568: | { |
569: | $oVEventResult = $aData['oVEventResult']; |
570: | $aAccountEmails = $aData['aAccountEmails']; |
571: | $sMethod = $aData['sMethod']; |
572: | |
573: | if (isset($oVEventResult->ATTENDEE)) { |
574: | foreach ($oVEventResult->ATTENDEE as $oAttendee) { |
575: | $sAttendee = strtolower((string)$oAttendee); |
576: | if (in_array($sAttendee, $aAccountEmails) && isset($oAttendee['PARTSTAT']) && $sMethod !== 'SAVE') { |
577: | $mResult['Attendee'] = str_replace('mailto:', '', $sAttendee); |
578: | $mResult['Action'] = $sMethod . '-' . $oAttendee['PARTSTAT']->getValue(); |
579: | } |
580: | } |
581: | } |
582: | } |
583: | |
584: | public function onParseEvent(&$aData, &$aEvent) |
585: | { |
586: | $oVComponent = $aData['oVComponent']; |
587: | $sOwnerEmail = $aData['sOwnerEmail']; |
588: | $oUser = $aData['oUser']; |
589: | |
590: | $bIsAppointment = false; |
591: | $aEvent['attendees'] = array(); |
592: | if (isset($oVComponent->ATTENDEE)) { |
593: | $aEvent['attendees'] = \Aurora\Modules\Calendar\Classes\Parser::parseAttendees($oVComponent); |
594: | |
595: | if (isset($oVComponent->ORGANIZER)) { |
596: | $sOwnerEmail = str_replace('mailto:', '', strtolower((string)$oVComponent->ORGANIZER)); |
597: | $iPos = strpos($sOwnerEmail, 'principals/'); |
598: | if ($iPos !== false) { |
599: | $sOwnerEmail = \trim(substr($sOwnerEmail, $iPos + 11), '/'); |
600: | } |
601: | $aData['sOwnerEmail'] = $sOwnerEmail; |
602: | $aEvent['organizer'] = $sOwnerEmail; |
603: | $aEvent['organizerName'] = isset($oVComponent->ORGANIZER['CN']) ? (string)$oVComponent->ORGANIZER['CN'] : ''; |
604: | } |
605: | $bIsAppointment = ($oUser instanceof \Aurora\Modules\Core\Models\User && $sOwnerEmail !== $oUser->PublicId); |
606: | } |
607: | |
608: | $aEvent['appointment'] = $bIsAppointment; |
609: | $aEvent['appointmentAccess'] = 0; |
610: | } |
611: | } |
612: | |