/home/ivoiecob/email.hirewise-va.com/modules/Calendar/Classes/Parser.php
<?php
/**
* This code is licensed under Afterlogic Software License.
* For full statements of the license see LICENSE file.
*/
namespace Aurora\Modules\Calendar\Classes;
/**
* @license https://afterlogic.com/products/common-licensing Afterlogic Software License
* @copyright Copyright (c) 2023, Afterlogic Corp.
*
* @internal
*
* @package Calendar
* @subpackage Classes
*/
class Parser
{
/**
* @param \Aurora\Modules\Calendar\Classes\Calendar $oCalendar
* @param \Sabre\VObject\Component\VCalendar $oExpandedVCal
* @param \Sabre\VObject\Component\VCalendar $oVCal Default value is **null**.
* @param string $sDefaultTimeZone
*
* @return array
*/
public static function parseEvent($sUserPublicId, $oCalendar, $oExpandedVCal, $oVCal = null, $sDefaultTimeZone = null)
{
$aResult = array();
$aRules = array();
$aExcludedRecurrences = array();
$oUser = \Aurora\Modules\Core\Module::Decorator()->GetUserByPublicId($sUserPublicId);
if ($oUser instanceof \Aurora\Modules\Core\Models\User) {
$sTimeZone = $oUser->DefaultTimeZone;
} elseif ($sDefaultTimeZone) {
$sTimeZone = $sDefaultTimeZone;
} else {
$sTimeZone = 'UTC';
}
$sComponent = $sType = 'VEVENT';
if (isset($oExpandedVCal->{$sComponent})) {
$sType = $sComponent;
} else {
$sComponent = 'VTODO';
if (isset($oExpandedVCal->{$sComponent})) {
$sType = $sComponent;
}
}
if (isset($oVCal)) {
$aRules = self::getRRules($sTimeZone, $oVCal, $sComponent);
$aExcludedRecurrences = self::getExcludedRecurrences($oVCal);
}
if (isset($oExpandedVCal->{$sComponent}) && ($oUser instanceof \Aurora\Modules\Core\Models\User || $oCalendar->IsPublic)) {
/** @var \Sabre\VObject\Component $oVComponent */
foreach ($oExpandedVCal->{$sComponent} as $oVComponent) {
$sOwnerEmail = $oCalendar->Owner;
$aEvent = array();
if (isset($oVComponent->UID)) {
$sUid = (string)$oVComponent->UID;
$sRecurrenceId = \Aurora\Modules\Calendar\Classes\Helper::getRecurrenceId($oVComponent);
$sId = $sUid . '-' . $sRecurrenceId;
$aEvent['type'] = $sType;
if (array_key_exists($sId, $aExcludedRecurrences) && isset($oVComponent->{'RECURRENCE-ID'})) {
/** @var \Sabre\VObject\Component $oVComponent */
$oVComponent = $aExcludedRecurrences[$sId];
$aEvent['excluded'] = true;
}
$aArgs = [
'oVComponent' => $oVComponent,
'sOwnerEmail' => $sOwnerEmail,
'oUser' => $oUser
];
\Aurora\System\Api::GetModule('Calendar')->broadcastEvent(
'parseEvent',
$aArgs,
$aEvent
);
$sOwnerEmail = $aArgs['sOwnerEmail'];
$oOwner = \Aurora\Modules\Core\Module::Decorator()->GetUserByPublicId($sOwnerEmail);
$sOwnerName = ($oOwner instanceof \Aurora\Modules\Core\Models\User) ? $oOwner->Name : '';
/** @var \Sabre\VObject\Property\ICalendar\DateTime $oDTSTART */
$oDTSTART = $oVComponent->DTSTART;
$bAllDay = $oDTSTART && !$oDTSTART->hasTime();
$sCurrentTimeZone = ($bAllDay) ? 'UTC' : $sTimeZone;
$aEvent['alarms'] = self::parseAlarms($oVComponent);
/** @var \Sabre\VObject\Property\ICalendar\DateTime $oDTEND */
$oDTEND = null;
if ($sComponent === 'VTODO') {
if (isset($oVComponent->DTEND)) {
/** @var \Sabre\VObject\Property\ICalendar\DateTime $oDTEND */
$oDTEND = $oVComponent->DTEND;
} elseif (isset($oVComponent->DUE)) {
/** @var \Sabre\VObject\Property\ICalendar\DateTime $oDTEND */
$oDTEND = $oVComponent->DUE;
}
} elseif (isset($oVComponent->DTEND)) {
/** @var \Sabre\VObject\Property\ICalendar\DateTime $oDTEND */
$oDTEND = $oVComponent->DTEND;
}
if ($oDTEND) {
if (!$oDTSTART) {
$oDTSTART = $oDTEND->getDateTime();
}
} else {
if ($oDTSTART) {
/** @var \DateTimeImmutable $dtStart */
$dtStart = $oDTSTART->getDateTime();
if ($dtStart) {
$oVComponent->DTEND = $dtStart->add(new \DateInterval('PT1H'));
$oDTEND = $oVComponent->DTEND;
}
}
}
$aEvent['calendarId'] = $oCalendar->Id;
$aEvent['id'] = $sId;
$aEvent['uid'] = $sUid;
$aEvent['subject'] = $oVComponent->SUMMARY ? (string)$oVComponent->SUMMARY : '';
$aEvent['description'] = $oVComponent->DESCRIPTION ? (string)$oVComponent->DESCRIPTION : '';
$aEvent['location'] = $oVComponent->LOCATION ? (string)$oVComponent->LOCATION : '';
$aEvent['start'] = \Aurora\Modules\Calendar\Classes\Helper::getStrDate($oVComponent->DTSTART, $sCurrentTimeZone);
$aEvent['startTS'] = \Aurora\Modules\Calendar\Classes\Helper::getTimestamp($oVComponent->DTSTART, $sCurrentTimeZone);
$aEvent['end'] = \Aurora\Modules\Calendar\Classes\Helper::getStrDate($oDTEND, $sCurrentTimeZone);
$aEvent['endTS'] = \Aurora\Modules\Calendar\Classes\Helper::getTimestamp($oDTEND, $sCurrentTimeZone);
$aEvent['allDay'] = $bAllDay;
$aEvent['owner'] = $sOwnerEmail;
$aEvent['ownerName'] = $sOwnerName;
$aEvent['modified'] = false;
$aEvent['recurrenceId'] = $sRecurrenceId;
$aEvent['lastModified'] = \Aurora\Modules\Calendar\Classes\Helper::getTimestamp($oVComponent->{'LAST-MODIFIED'}, $sCurrentTimeZone);
if (isset($aRules[$sUid]) && $aRules[$sUid] instanceof RRule) {
$aEvent['rrule'] = $aRules[$sUid]->toArray();
}
$bStatus = false;
if ($oVComponent->STATUS) {
$sStatus = (string)$oVComponent->STATUS;
$bStatus = strtolower($sStatus) === 'completed' ? true : false;
}
$aEvent['status'] = $bStatus;
$aEvent['withDate'] = isset($oVComponent->DTSTART) && $oDTEND;
$aEvent['isPrivate'] = isset($oVComponent->CLASS) && (string) $oVComponent->CLASS === 'PRIVATE';
$oAuthenticatedUser = \Aurora\Api::getAuthenticatedUser();
if ($aEvent['isPrivate'] && $sOwnerEmail !== $oAuthenticatedUser->PublicId) {
// $aEvent['subject'] = '';
$aEvent['description'] = '';
$aEvent['location'] = '';
}
}
$aResult[] = $aEvent;
}
}
return $aResult;
}
/**
* @param \Sabre\VObject\Component $oVComponent
*
* @return array
*/
public static function parseAlarms($oVComponent)
{
$aResult = array();
if ($oVComponent->VALARM) {
foreach ($oVComponent->VALARM as $oVAlarm) {
if (isset($oVAlarm->TRIGGER) && $oVAlarm->TRIGGER instanceof \Sabre\VObject\Property\ICalendar\Duration) {
$aResult[] = \Aurora\Modules\Calendar\Classes\Helper::getOffsetInMinutes($oVAlarm->TRIGGER->getDateInterval());
}
}
rsort($aResult);
}
return $aResult;
}
/**
* @param \Sabre\VObject\Component $oVComponent
*
* @return array
*/
public static function parseAttendees($oVComponent)
{
$aResult = array();
if (isset($oVComponent->ATTENDEE)) {
foreach ($oVComponent->ATTENDEE as $oAttendee) {
$iStatus = \Aurora\Modules\Calendar\Enums\AttendeeStatus::Unknown;
if (isset($oAttendee['PARTSTAT'])) {
switch (strtoupper((string)$oAttendee['PARTSTAT'])) {
case 'ACCEPTED':
$iStatus = \Aurora\Modules\Calendar\Enums\AttendeeStatus::Accepted;
break;
case 'DECLINED':
$iStatus = \Aurora\Modules\Calendar\Enums\AttendeeStatus::Declined;
break;
case 'TENTATIVE':
$iStatus = \Aurora\Modules\Calendar\Enums\AttendeeStatus::Tentative;
;
break;
}
}
if (isset($oAttendee['EMAIL'])) {
$sEmail = (string)$oAttendee['EMAIL'];
} else {
$sEmail = str_replace('mailto:', '', strtolower($oAttendee->getValue()));
$iPos = strpos($sEmail, 'principals/');
if ($iPos !== false) {
$sEmail = \trim(substr($sEmail, $iPos + 11), '/');
}
}
$aResult[] = array(
'access' => 0,
'email' => $sEmail,
'name' => isset($oAttendee['CN']) ? (string)$oAttendee['CN'] : '',
'status' => $iStatus
);
}
}
return $aResult;
}
/**
* @param string $DefaultTimeZone
* @param \Sabre\VObject\Component $oVComponentBase
*
* @return RRule|null
*/
public static function parseRRule($DefaultTimeZone, $oVComponentBase)
{
$oResult = null;
$aWeekDays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
$aPeriods = array(
\Aurora\Modules\Calendar\Enums\PeriodStr::Secondly,
\Aurora\Modules\Calendar\Enums\PeriodStr::Minutely,
\Aurora\Modules\Calendar\Enums\PeriodStr::Hourly,
\Aurora\Modules\Calendar\Enums\PeriodStr::Daily,
\Aurora\Modules\Calendar\Enums\PeriodStr::Weekly,
\Aurora\Modules\Calendar\Enums\PeriodStr::Monthly,
\Aurora\Modules\Calendar\Enums\PeriodStr::Yearly
);
if (isset($oVComponentBase->RRULE)) {
$oResult = new RRule($DefaultTimeZone);
$aRules = $oVComponentBase->RRULE->getParts();
if (isset($aRules['FREQ'])) {
$bIsPosiblePeriod = array_search(strtolower($aRules['FREQ']), array_map('strtolower', $aPeriods));
if ($bIsPosiblePeriod !== false) {
$oResult->Period = $bIsPosiblePeriod - 2;
}
}
if (isset($aRules['INTERVAL'])) {
$oResult->Interval = $aRules['INTERVAL'];
}
if (isset($aRules['COUNT'])) {
$oResult->Count = $aRules['COUNT'];
}
if (isset($aRules['UNTIL'])) {
$oResult->Until = date_format(date_create($aRules['UNTIL']), 'U');
}
if (isset($oResult->Count)) {
$oResult->End = \Aurora\Modules\Calendar\Enums\RepeatEnd::Count;
} elseif (isset($oResult->Until)) {
$oResult->End = \Aurora\Modules\Calendar\Enums\RepeatEnd::Date;
} else {
$oResult->End = \Aurora\Modules\Calendar\Enums\RepeatEnd::Infinity;
}
if (isset($aRules['BYDAY'])) {
if (!is_array($aRules['BYDAY'])) {
$aByDay[] = $aRules['BYDAY'];
} else {
$aByDay = $aRules['BYDAY'];
}
foreach ($aByDay as $sDay) {
if (strlen($sDay) > 2) {
$iNum = (int)substr($sDay, 0, -2);
if ($iNum === 1) {
$oResult->WeekNum = 0;
}
if ($iNum === 2) {
$oResult->WeekNum = 1;
}
if ($iNum === 3) {
$oResult->WeekNum = 2;
}
if ($iNum === 4) {
$oResult->WeekNum = 3;
}
if ($iNum === -1) {
$oResult->WeekNum = 4;
}
}
foreach ($aWeekDays as $sWeekDay) {
if (strpos($sDay, $sWeekDay) !== false) {
$oResult->ByDays[] = $sWeekDay;
}
}
}
}
$oResult->StartBase = \Aurora\Modules\Calendar\Classes\Helper::getTimestamp($oVComponentBase->DTSTART, $DefaultTimeZone);
$oResult->EndBase = \Aurora\Modules\Calendar\Classes\Helper::getTimestamp($oVComponentBase->DTEND, $DefaultTimeZone);
}
return $oResult;
}
/**
* @param string $DefaultTimeZone
* @param \Sabre\VObject\Component\VCalendar $oVCal
* @param string $sComponent
*
* @return array
*/
public static function getRRules($DefaultTimeZone, $oVCal, $sComponent = 'VEVENT')
{
$aResult = array();
foreach ($oVCal->getBaseComponents($sComponent) as $oVComponentBase) {
if (isset($oVComponentBase->RRULE)) {
$oRRule = self::parseRRule($DefaultTimeZone, $oVComponentBase);
if ($oRRule) {
$aResult[(string)$oVComponentBase->UID] = $oRRule;
}
}
}
return $aResult;
}
/**
* @param \Sabre\VObject\Component\VCalendar $oVCal
*
* @return array
*/
public static function getExcludedRecurrences($oVCal)
{
$aRecurrences = array();
foreach ($oVCal->children() as $oComponent) {
if (!$oComponent instanceof \Sabre\VObject\Component) {
continue;
}
if (isset($oComponent->{'RECURRENCE-ID'})) {
$iRecurrenceId = \Aurora\Modules\Calendar\Classes\Helper::getRecurrenceId($oComponent);
$aRecurrences[(string)$oComponent->UID . '-' . $iRecurrenceId] = $oComponent;
}
}
return $aRecurrences;
}
}