Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/calendar/classes/general/ |
Upload File : |
<?php use Bitrix\Main\Localization\Loc; use Bitrix\Calendar\Internals; class CCalendarReminder { public const TYPE_DAY_BEFORE = 'daybefore'; public const TYPE_SPECIFIC_DATETIME = 'date'; public const SIMPLE_TYPE_LIST = ['min', 'hour', 'day']; public const REMINDER_INACCURACY = 30; public const REMINDER_NEXT_DELAY = 120; public static function ReminderAgent($eventId = 0, $userId = 0, $viewPath = '', $calendarType = '', $ownerId = 0, $index = 0) { if (empty($userId)) { $userId = $ownerId; } if ($eventId > 0 && $userId > 0 && \Bitrix\Main\Loader::includeModule("im")) { $event = false; $nowTime = time(); $events = CCalendarEvent::GetList([ 'arFilter' => [ "ID" => $eventId, "DELETED" => "N", "FROM_LIMIT" => CCalendar::Date($nowTime - 3600, false), "TO_LIMIT" => CCalendar::GetMaxDate(), "ACTIVE_SECTION" => "Y" ], 'userId' => $userId, 'parseRecursion' => true, 'maxInstanceCount' => 3, 'preciseLimits' => true, 'fetchAttendees' => false, 'checkPermissions' => false, 'setDefaultLimit' => false ]); if ($events && is_array($events[0])) { $event = $events[0]; } if ($event && $event['MEETING_STATUS'] !== 'N') { $fromTs = CCalendar::Timestamp($event['DATE_FROM'], false, $event['DT_SKIP_TIME'] !== 'Y'); if ($event['DT_SKIP_TIME'] !== 'Y') { $fromTs -= $event['~USER_OFFSET_FROM']; } if (empty($calendarType)) { $calendarType = $event['CAL_TYPE']; } $viewPathUri = (new \Bitrix\Main\Web\Uri($viewPath)) ->deleteParams(['EVENT_DATE']) ->addParams(['EVENT_DATE' => CCalendar::Date($fromTs, false)]) ; $notificationFields = self::getNotifyFields([ 'userId' => $userId, 'entryId' => $eventId, 'entryName' => $event['NAME'], 'location' => Bitrix\Calendar\Rooms\Util::getTextLocation($event['LOCATION']), 'calendarType' => $calendarType, 'event' => $event, 'fromTs' => $fromTs, 'dateFrom' => CCalendar::Date($fromTs, $event['DT_SKIP_TIME'] !== 'Y', true, true), 'viewPath' => $viewPathUri->getUri(), 'index' => $index ]); CIMNotify::Add($notificationFields); foreach(\Bitrix\Main\EventManager::getInstance()->findEventHandlers("calendar", "OnRemindEvent") as $event) { ExecuteModuleEventEx($event, [[ 'eventId' => $eventId, 'userId' => $userId, 'viewPath' => $viewPathUri->getUri(), 'calType' => $calendarType, 'ownerId' => $ownerId ]]); } if (CCalendarEvent::CheckRecurcion($event)) { self::updateReminders([ 'id' => $eventId, 'arFields' => $event, 'userId' => $userId, 'path' => $viewPathUri->getUri(), 'updateRecursive' => true ]); } } CCalendar::SetOffset(false, null); } } public static function RemoveAgent($params) { // remove obsolete agents $res = CAgent::getList([], [ 'NAME' => "CCalendar::ReminderAgent(".$params['eventId'].", ".$params['userId']."%", 'MODULE_ID' => 'calendar' ]); while($item = $res->fetch()) { CAgent::Delete($item['ID']); } } public static function getNotifyFields($params = []): array { $userId = $params['userId']; $entryId = $params['entryId']; $notifyFields = [ 'FROM_USER_ID' => $userId, 'TO_USER_ID' => $userId, 'NOTIFY_TYPE' => IM_NOTIFY_SYSTEM, 'NOTIFY_MODULE' => "calendar", 'NOTIFY_EVENT' => "reminder", 'NOTIFY_TAG' => "CALENDAR|INVITE|".$entryId."|".$userId."|REMINDER|".$params['fromTs']."|".$params['index'], 'NOTIFY_SUB_TAG' => "CALENDAR|INVITE|".$entryId ]; if ($params['location']) { $notifyFields['MESSAGE'] = fn (?string $languageId = null) => Loc::getMessage( 'EC_EVENT_REMINDER_1', [ '#EVENT_NAME#' => $params['entryName'], '#DATE_FROM#' => $params['dateFrom'], '#URL_VIEW#' => $params['viewPath'] ], $languageId ) . "\n\n" . Loc::getMessage( 'EC_EVENT_REMINDER_LOCATION', ['#LOCATION#' => $params['location']], $languageId ); } else { $notifyFields['MESSAGE'] = fn (?string $languageId = null) => Loc::getMessage( 'EC_EVENT_REMINDER_1', [ '#EVENT_NAME#' => $params['entryName'], '#DATE_FROM#' => $params['dateFrom'], '#URL_VIEW#' => $params['viewPath'] ], $languageId ); } $dateFromFormatted = fn (?string $languageId = null) => CCalendar::GetFromToHtml( $params['fromTs'], $params['fromTs'] + $params['event']['DT_LENGTH'], $params['event']['DT_SKIP_TIME'] === 'Y', $params['event']['DT_LENGTH'], $languageId ); $notifyFields["PUSH_MESSAGE"] = fn (?string $languageId = null) => self::getPushMessage( $params['entryName'], $dateFromFormatted($languageId), $languageId ); return $notifyFields; } private static function getPushMessage($entryName, $dateFromFormatted, $languageId = null): string { $result = Loc::getMessage( 'EC_EVENT_REMINDER_PUSH', [ '#EVENT_NAME#' => $entryName, '#DATE_FROM#' => $dateFromFormatted ], $languageId ); $result = str_replace('–', '-', $result); return mb_substr($result, 0, \CCalendarNotify::PUSH_MESSAGE_MAX_LENGTH); } public static function AddAgent($remindTime, $params): void { global $DB; if (!empty($remindTime) && $DB->IsDate($remindTime, false, LANG, "FULL")) { $tzEnabled = CTimeZone::Enabled(); if ($tzEnabled) { CTimeZone::Disable(); } $indexParam = isset($params['index']) ? ', '.$params['index'] : ''; CAgent::AddAgent( "CCalendar::ReminderAgent(".(int)$params['eventId'].", " .(int)$params['userId'].", '" .addslashes($params['viewPath'])."', '" .addslashes($params['calendarType'])."', " .(int)$params['ownerId'].$indexParam.");", "calendar", "Y", 0, "", "Y", $remindTime, 100, false, false ); if ($tzEnabled) { CTimeZone::Enable(); } } } public static function updateReminders($params = []): void { $eventId = (int)$params['id']; $entryFields = $params['arFields']; $reminders = $params['reminders'] ?? null; $userId = (int)$params['userId']; $ownerId = $entryFields['OWNER_ID'] ?? $entryFields['CREATED_BY'] ?? null; if (!$reminders) { $reminders = self::prepareReminder($entryFields['REMIND']); } $path = CCalendar::GetPathForCalendarEx($ownerId); $viewPath = (new \Bitrix\Main\Web\Uri($path)) ->deleteParams(["action", "sessid", "bx_event_calendar_request", "EVENT_ID", "EVENT_DATE"]) ->addParams(['EVENT_ID' => $eventId]) ; $agentParams = [ 'eventId' => $eventId, 'userId' => $ownerId, 'viewPath' => $viewPath->getUri(), 'calendarType' => $entryFields["CAL_TYPE"] ?? null, 'ownerId' => $entryFields["OWNER_ID"] ?? null ]; // 1. clean reminders self::RemoveAgent($agentParams); // Prevent duplication of reminders for non-user's calendar context (mantis:0128287) if ($entryFields['CAL_TYPE'] === 'user') { // 2. Set new reminders if (CCalendarEvent::CheckRecurcion($entryFields)) { $entryList = CCalendarEvent::GetList( [ 'arFilter' => [ "ID" => $eventId, "DELETED" => "N", "FROM_LIMIT" => CCalendar::Date(time() - 3600, false), "TO_LIMIT" => CCalendar::GetMaxDate() ], 'arSelect' => CCalendarEvent::$defaultSelectEvent, 'userId' => $userId, 'parseRecursion' => true, 'maxInstanceCount' => 4, 'preciseLimits' => true, 'fetchAttendees' => false, 'checkPermissions' => false, 'setDefaultLimit' => false ] ); if (is_array($entryList)) { $index = 0; foreach ($entryList as $entry) { $eventTimestamp = CCalendar::Timestamp($entry['DATE_FROM'], false, true); $eventTimestamp = $eventTimestamp - CCalendar::GetTimezoneOffset($entry["TZ_FROM"], $eventTimestamp) + (int)date("Z", $eventTimestamp); // List of added timestamps of reminders to avoid duplication $addedIndex = []; foreach ($reminders as $reminder) { $reminderTimestamp = self::getReminderTimestamp( $eventTimestamp, $reminder, $entryFields['TZ_FROM'] ?? null ); $limitTime = !empty($params['updateRecursive']) ? time() + self::REMINDER_NEXT_DELAY : time() - self::REMINDER_INACCURACY; if ( !is_null($reminderTimestamp) && !in_array($reminderTimestamp, $addedIndex) && $reminderTimestamp >= $limitTime ) { $agentParams['index'] = $index++; if ($reminder['type'] === self::TYPE_SPECIFIC_DATETIME) { unset($agentParams['index']); } self::AddAgent(\CCalendar::Date($reminderTimestamp), $agentParams); $addedIndex[] = $reminderTimestamp; } } } } } else { // Start of the event in server timezone $eventTimestamp = $entryFields['DATE_FROM_TS_UTC'] + (int)date("Z", $entryFields['DATE_FROM_TS_UTC']); $index = 0; // List of added timestamps of reminders to avoid duplication $addedIndex = []; foreach ($reminders as $reminder) { $reminderTimestamp = self::getReminderTimestamp( $eventTimestamp, $reminder, $entryFields['TZ_FROM'] ?? null ); if ( !is_null($reminderTimestamp) && !in_array($reminderTimestamp, $addedIndex) && $reminderTimestamp >= time() + self::REMINDER_INACCURACY ) { $agentParams['index'] = $index++; self::AddAgent(\CCalendar::Date($reminderTimestamp), $agentParams); $addedIndex[] = $reminderTimestamp; } } } } } public static function sortReminder($a, $b): int { return self::getReminderDelta($a) - self::getReminderDelta($b); } public static function getReminderDelta($reminder): int { $delta = 0; if (is_array($reminder) && in_array($reminder['type'], self::SIMPLE_TYPE_LIST, true)) { $delta = (int)$reminder['count'] * 60; if ($reminder['type'] === 'hour') { $delta *= 60; //Hour } elseif ($reminder['type'] === 'day') { $delta *= 60 * 24; //Day } } return $delta; } public static function getReminderTimestamp($eventTimestamp, $reminder, $timezoneName = null) { $reminderTimestamp = null; if (is_array($reminder) && isset($reminder['type'])) { $type = $reminder['type']; if (in_array($type, self::SIMPLE_TYPE_LIST, true)) { $delta = (int)$reminder['count'] * 60; if ($reminder['type'] === 'hour') { $delta *= 60; //Hour } elseif ($reminder['type'] === 'day') { $delta *= 60 * 24; //Day } $reminderTimestamp = $eventTimestamp - $delta; } elseif($type === self::TYPE_DAY_BEFORE) { $daysBefore = (int)$reminder['before']; $hour = floor((int)$reminder['time'] / 60); $min = (int)($reminder['time'] - $hour * 60); $reminderTimestamp = mktime($hour, $min, 0, date("m", $eventTimestamp), date("d", $eventTimestamp) - $daysBefore, date("Y", $eventTimestamp)); if ($timezoneName) { $timezoneServerOffset = \CCalendar::GetTimezoneOffset($timezoneName, $eventTimestamp) - date("Z", $eventTimestamp); $reminderTimestamp -= $timezoneServerOffset; } } elseif($type === self::TYPE_SPECIFIC_DATETIME) { $reminderTimestamp = \CCalendar::Timestamp($reminder['value'], false, true); $reminderTimestamp = $reminderTimestamp - \CCalendar::GetTimezoneOffset($timezoneName, $reminderTimestamp) + (int)date("Z", $reminderTimestamp); } } return $reminderTimestamp; } public static function prepareReminder($reminder = []): array { $reminderList = []; if (is_array($reminder)) { foreach ($reminder as $remindValue) { if (is_array($remindValue)) { if (isset($remindValue['type']) && in_array($remindValue['type'], self::SIMPLE_TYPE_LIST, true)) { $reminderList[] = [ 'type' => $remindValue['type'], 'count' => (int)$remindValue['count'] ]; } elseif ($remindValue['type'] === self::TYPE_DAY_BEFORE) { $reminderList[] = [ 'type' => $remindValue['type'], 'before' => (int)$remindValue['before'], 'time' => (int)$remindValue['time'] ]; } elseif ($remindValue['type'] === self::TYPE_SPECIFIC_DATETIME) { $reminderList[] = [ 'type' => $remindValue['type'], 'value' => \CCalendar::Date(\CCalendar::Timestamp($remindValue['value'])) ]; } } else { $explodedValue = explode('|', $remindValue); if (count($explodedValue) > 1) { if ($explodedValue[0] === self::TYPE_DAY_BEFORE) { $reminderList[] = [ 'type' => self::TYPE_DAY_BEFORE, 'before' => (int)$explodedValue[1], 'time' => (int)$explodedValue[2] ]; } elseif($explodedValue[0] === self::TYPE_SPECIFIC_DATETIME) { $reminderList[] = [ 'type' => self::TYPE_SPECIFIC_DATETIME, 'value' => \CCalendar::Date(\CCalendar::Timestamp($explodedValue[1])) ]; } } else { $reminderList[] = [ 'type' => 'min', 'count' => (int)$remindValue ]; } } } } usort($reminderList, ['CCalendarReminder', 'sortReminder']); return $reminderList; } public static function GetTextReminders($valueList = array()) { if (is_array($valueList)) { foreach($valueList as $i => $value) { if($value['type'] === 'min') { $value['text'] = Loc::getMessage('EC_REMIND1_VIEW_'.$value['count']); if(!$value['text']) { $value['text'] = Loc::getMessage( 'EC_REMIND1_VIEW_MIN_COUNT', ['#COUNT#' => (int)$value['count']] ); } } elseif($value['type'] === 'hour') { $value['text'] = Loc::getMessage( 'EC_REMIND1_VIEW_HOUR_COUNT', ['#COUNT#' => (int)$value['count']] ); } elseif($value['type'] === 'day') { $value['text'] = Loc::getMessage( 'EC_REMIND1_VIEW_DAY_COUNT', ['#COUNT#' => (int)$value['count']] ); } $valueList[$i] = $value; } } return $valueList; } }