%PDF- %PDF-
| Direktori : /proc/self/root/home/bitrix/www/bitrix/modules/calendar/classes/general/ |
| Current File : //proc/self/root/home/bitrix/www/bitrix/modules/calendar/classes/general/calendar.php |
<?
/** var CMain $APPLICATION */
use Bitrix\Main;
use Bitrix\Main\Localization\Loc;
use Bitrix\Calendar\PushTable;
use Bitrix\Calendar\Sync\GoogleApiSync;
IncludeModuleLangFile(__FILE__);
class CCalendar
{
const
INTEGRATION_GOOGLE_API = "googleapi",
CALENDAR_MAX_TIMESTAMP = 2145938400,
DAY_LENGTH = 86400; // 60 * 60 * 24
private static
$id = false,
$instance,
$CALENDAR_MAX_DATE,
$CALENDAR_MIN_DATE,
$type,
$arTypes,
$ownerId = 0,
$settings,
$siteId,
$userSettings = array(),
$pathToUser,
$bOwner,
$userId,
$curUserId,
$userMeetingSection,
$meetingSections = array(),
$crmSections = array(),
$offset,
$arTimezoneOffsets = array(),
$perm = array(),
$isArchivedGroup = false,
$userNameTemplate = "#NAME# #LAST_NAME#",
$bSuperpose,
$bCanAddToSuperpose,
$bExtranet,
$bIntranet,
$bWebservice,
$arSPTypes = array(),
$showTasks,
$viewTaskPath = '',
$editTaskPath = '',
$actionUrl,
$path = '',
$outerUrl,
$accessNames = array(),
$bSocNet,
$bAnonym,
$allowReserveMeeting = true,
$SectionsControlsDOMId = 'sidebar',
$arAccessTask = array(),
$ownerNames = array(),
$meetingRoomList,
$cachePath = "calendar/",
$cacheTime = 2592000, // 30 days by default
$bCache = true,
$readOnly,
$showLogin = true,
$pathesForSite = false,
$pathes = array(), // links for several sites
$userManagers = array(),
$arUserDepartment = array(),
$bAMPM = false,
$bWideDate = false,
$arExchEnabledCache = array(),
$silentErrorMode = false,
$weekStart,
$bCurUserSocNetAdmin,
$serverPath,
$pathesList = array('path_to_user','path_to_user_calendar','path_to_group','path_to_group_calendar','path_to_vr','path_to_rm'),
$pathesListEx = null,
$isGoogleApiEnabled = null,
$timezones = array();
function Init($params)
{
global $USER, $APPLICATION;
$access = new CAccess();
$access->UpdateCodes();
if (!$USER || !is_object($USER))
$USER = new CUser;
// Owner params
self::$siteId = isset($params['siteId']) ? $params['siteId'] : SITE_ID;
self::$type = $params['type'];
self::$arTypes = CCalendarType::GetList();
self::$bIntranet = CCalendar::IsIntranetEnabled();
self::$bSocNet = self::IsSocNet();
self::$userId = (isset($params['userId']) && $params['userId'] > 0) ? intVal($params['userId']) : CCalendar::GetCurUserId(true);
self::$bOwner = self::$type == 'user' || self::$type == 'group';
self::$settings = self::GetSettings();
self::$userSettings = CCalendarUserSettings::Get();
self::$pathesForSite = self::GetPathes(self::$siteId);
self::$pathToUser = self::$pathesForSite['path_to_user'];
self::$bSuperpose = $params['allowSuperpose'] != false && self::$bSocNet;
self::$bAnonym = !$USER || !$USER->IsAuthorized();
self::$userNameTemplate = self::$settings['user_name_template'];
self::$bAMPM = IsAmPmMode();
self::$bWideDate = strpos(FORMAT_DATETIME, 'MMMM') !== false;
self::$id = $this->GetId();
if (isset($params['SectionControlsDOMId']))
self::$SectionsControlsDOMId = $params['SectionControlsDOMId'];
if (self::$bOwner && isset($params['ownerId']) && $params['ownerId'] > 0)
self::$ownerId = intVal($params['ownerId']);
self::$showTasks = (self::$type == 'user' || self::$type == 'group')
&& $params['showTasks'] !== false
&& \Bitrix\Main\Loader::includeModule('tasks')
&& self::$userSettings['showTasks'] != 'N';
if (self::$showTasks)
{
self::$viewTaskPath = $params['viewTaskPath'];
self::$editTaskPath = $params['editTaskPath'];
if (!self::$viewTaskPath)
{
self::$showTasks = false;
}
}
self::GetPermissions(array(
'type' => self::$type,
'bOwner' => self::$bOwner,
'userId' => self::$userId,
'ownerId' => self::$ownerId
));
// Cache params
if (isset($params['cachePath']))
self::$cachePath = $params['cachePath'];
if (isset($params['cacheTime']))
self::$cacheTime = $params['cacheTime'];
self::$bCache = self::$cacheTime > 0;
// Urls
$page = preg_replace(
array(
"/EVENT_ID=.*?\&/i",
"/EVENT_DATE=.*?\&/i",
"/CHOOSE_MR=.*?\&/i",
"/action=.*?\&/i",
"/bx_event_calendar_request=.*?\&/i",
"/clear_cache=.*?\&/i",
"/bitrix_include_areas=.*?\&/i",
"/bitrix_show_mode=.*?\&/i",
"/back_url_admin=.*?\&/i"
),
"", $params['pageUrl'].'&'
);
$page = preg_replace(array("/^(.*?)\&$/i","/^(.*?)\?$/i"), "\$1", $page);
self::$actionUrl = $page;
if (self::$bOwner && !empty(self::$ownerId))
self::$path = self::GetPath(self::$type, self::$ownerId, true);
else
self::$path = CCalendar::GetServerPath().$page;
self::$outerUrl = $APPLICATION->GetCurPageParam('', array("action", "bx_event_calendar_request", "clear_cache", "bitrix_include_areas", "bitrix_show_mode", "back_url_admin", "SEF_APPLICATION_CUR_PAGE_URL", "EVENT_ID", "EVENT_DATE", "CHOOSE_MR"), false);
// *** Meeting room params ***
$RMiblockId = self::$settings['rm_iblock_id'];
self::$allowReserveMeeting = $params["allowResMeeting"] && $RMiblockId > 0;
if(self::$allowReserveMeeting && !$USER->IsAdmin() && (CIBlock::GetPermission($RMiblockId) < "R"))
self::$allowReserveMeeting = false;
}
public function Show($params = array())
{
global $APPLICATION;
$arType = false;
foreach(self::$arTypes as $type)
{
if(self::$type == $type['XML_ID'])
$arType = $type;
}
if (!$arType)
{
$APPLICATION->ThrowException('[EC_WRONG_TYPE] '.Loc::getMessage('EC_WRONG_TYPE'));
return false;
}
if (!CCalendarType::CanDo('calendar_type_view', self::$type))
{
$APPLICATION->ThrowException(Loc::getMessage("EC_ACCESS_DENIED"));
return false;
}
$startupEvent = false;
$showNewEventDialog = false;
//Show new event dialog
if (isset($_GET['EVENT_ID']))
{
if ($_GET['EVENT_ID'] == 'NEW')
{
$showNewEventDialog = true;
}
elseif(substr($_GET['EVENT_ID'], 0, 4) == 'EDIT')
{
$startupEvent = self::GetStartUpEvent(intval(substr($_GET['EVENT_ID'], 4)));
if ($startupEvent)
$startupEvent['EDIT'] = true;
if ($startupEvent['DT_FROM'])
{
$ts = self::Timestamp($startupEvent['DT_FROM']);
$init_month = date('m', $ts);
$init_year = date('Y', $ts);
}
}
// Show popup event at start
elseif ($startupEvent = self::GetStartUpEvent($_GET['EVENT_ID']))
{
$eventFromTs = self::Timestamp($startupEvent['DATE_FROM']);
$currentDateTs = self::Timestamp($_GET['EVENT_DATE']);
if ($currentDateTs > $eventFromTs)
{
$startupEvent['~CURRENT_DATE'] = self::Date($currentDateTs, false);
$init_month = date('m', $currentDateTs);
$init_year = date('Y', $currentDateTs);
}
else
{
$init_month = date('m', $eventFromTs);
$init_year = date('Y', $eventFromTs);
}
}
}
if (!$init_month && !$init_year && strlen($params["initDate"]) > 0 && strpos($params["initDate"], '.') !== false)
{
$ts = self::Timestamp($params["initDate"]);
$init_month = date('m', $ts);
$init_year = date('Y', $ts);
}
if (!isset($init_month))
$init_month = date("m");
if (!isset($init_year))
$init_year = date("Y");
$id = $this->GetId();
$weekHolidays = array();
if (isset(self::$settings['week_holidays']))
{
$days = array('MO' => 0, 'TU' => 1, 'WE' => 2,'TH' => 3,'FR' => 4,'SA' => 5,'SU' => 6);
foreach(self::$settings['week_holidays'] as $day)
$weekHolidays[] = $days[$day];
}
else
$weekHolidays = array(5, 6);
$yearHolidays = array();
if (isset(self::$settings['year_holidays']))
{
foreach(explode(',', self::$settings['year_holidays']) as $date)
{
$date = trim($date);
$ardate = explode('.', $date);
if (count($ardate) == 2 && $ardate[0] && $ardate[1])
$yearHolidays[] = intVal($ardate[0]).'.'.(intVal($ardate[1]) - 1);
}
}
$yearWorkdays = array();
if (isset(self::$settings['year_workdays']))
{
foreach(explode(',', self::$settings['year_workdays']) as $date)
{
$date = trim($date);
$ardate = explode('.', $date);
if (count($ardate) == 2 && $ardate[0] && $ardate[1])
$yearWorkdays[] = intVal($ardate[0]).'.'.(intVal($ardate[1]) - 1);
}
}
$bSyncPannel = self::IsPersonal();
$bExchange = CCalendar::IsExchangeEnabled() && self::$type == 'user';
$bExchangeConnected = $bExchange && CDavExchangeCalendar::IsExchangeEnabledForUser(self::$ownerId);
$bCalDAV = CCalendar::IsCalDAVEnabled() && self::$type == "user";
$bGoogleApi = CCalendar::isGoogleApiEnabled() && self::$type == "user";
$bWebservice = CCalendar::IsWebserviceEnabled();
$bExtranet = CCalendar::IsExtranetEnabled();
$userTimezoneOffsetUTC = self::GetCurrentOffsetUTC(self::$userId);
$userTimezoneName = self::GetUserTimezoneName(self::$userId, false);
$userTimezoneDefault = '';
// We don't have default timezone for this offset for this user
// We will ask him but we should suggest some suitable for his offset
if (!$userTimezoneName)
{
$userTimezoneDefault = self::GetGoodTimezoneForOffset($userTimezoneOffsetUTC);
}
$JSConfig = Array(
'id' => $id,
'type' => self::$type,
'userId' => self::$userId,
'userName' => self::GetUserName(self::$userId), // deprecated
'ownerId' => self::$ownerId,
'user' => array(
'id' => self::$userId,
'name' => self::GetUserName(self::$userId),
'url' => self::GetUserUrl(self::$userId),
'avatar' => self::GetUserAvatarSrc(self::$userId),
'smallAvatar' => self::GetUserAvatarSrc(self::$userId, array('AVATAR_SIZE' => 18))
),
'perm' => $arType['PERM'], // Permissions from type
'permEx' => self::$perm,
'showTasks' => self::$showTasks,
'sectionControlsDOMId' => self::$SectionsControlsDOMId,
'week_holidays' => $weekHolidays,
'year_holidays' => $yearHolidays,
'year_workdays' => $yearWorkdays,
'init_month' => $init_month,
'init_year' => $init_year,
'pathToUser' => self::$pathToUser,
'path' => self::$path,
'actionUrl' => self::$actionUrl,
'settings' => self::$settings,
'userSettings' => self::$userSettings,
'bAnonym' => self::$bAnonym,
'bIntranet' => self::$bIntranet,
'bWebservice' => $bWebservice,
'bExtranet' => $bExtranet,
'bSocNet' => self::$bSocNet,
'bExchange' => $bExchangeConnected,
'startupEvent' => $startupEvent,
'workTime' => array(self::$settings['work_time_start'], self::$settings['work_time_end']), // Decrecated !!
'userWorkTime' => array(self::$settings['work_time_start'], self::$settings['work_time_end']),
'meetingRooms' => self::GetMeetingRoomList(array(
'RMiblockId' => self::$settings['rm_iblock_id'],
'pathToMR' => self::$pathesForSite['path_to_rm']
)),
'allowResMeeting' => self::$allowReserveMeeting,
'bAMPM' => self::$bAMPM,
'WDControllerCID' => 'UFWD'.$id,
'userTimezoneOffsetUTC' => $userTimezoneOffsetUTC,
'userTimezoneName' => $userTimezoneName,
'userTimezoneDefault' => $userTimezoneDefault,
'sectionCustomization' => CCalendarUserSettings::getSectionCustomization(self::$userId),
'locationFeatureEnabled' => !self::IsBitrix24() || \Bitrix\Bitrix24\Feature::isFeatureEnabled("calendar_location")
);
$JSConfig['lastSection'] = CCalendarSect::GetLastUsedSection(self::$type, self::$ownerId, self::$userId);
if(self::$type == 'user' && self::$userId != self::$ownerId)
{
$JSConfig['ownerUser'] = array(
'id' => self::$ownerId,
'name' => self::GetUserName(self::$ownerId),
'url' => self::GetUserUrl(self::$ownerId),
'avatar' => self::GetUserAvatarSrc(self::$ownerId),
'smallAvatar' => self::GetUserAvatarSrc(self::$ownerId, array('AVATAR_SIZE' => 18))
);
}
$placementParams = false;
if (\Bitrix\Main\Loader::includeModule('rest'))
{
$placementParams = [
'gridPlacementCode' => \CCalendarRestService::PLACEMENT_GRID_VIEW,
'gridPlacementList' => \Bitrix\Rest\PlacementTable::getHandlersList(\CCalendarRestService::PLACEMENT_GRID_VIEW),
'serviceUrl' => '/bitrix/components/bitrix/app.layout/lazyload.ajax.php?&site='.SITE_ID.'&'.bitrix_sessid_get()
];
// if(is_array($gridPlacementHandlerList))
// {
// foreach($gridPlacementHandlerList as $placementHandler)
// {
//$tabId = 'placement_'.$placementHandler['ID'];
// $arResult["Title"][$tabId] = (
// !empty($placementHandler['TITLE']) > 0
// ? $placementHandler['TITLE']
// : $placementHandler['APP_NAME']
// );
// $arResult["Urls"][$tabId] = $arResult["Urls"]["view"]."app/".$placementHandler['ID']."/";
// }
// }
}
$JSConfig['placementParams'] = $placementParams;
if(self::$type == 'user' && self::$userId == self::$ownerId)
{
$JSConfig['counters'] = array(
'invitation' => CUserCounter::GetValue(self::$userId, 'calendar')
);
$JSConfig['filterId'] = \Bitrix\Calendar\Ui\CalendarFilter::getFilterId(self::$type, self::$ownerId, self::$userId);
}
// Access permissons for type
if (CCalendarType::CanDo('calendar_type_edit_access', self::$type))
$JSConfig['TYPE_ACCESS'] = $arType['ACCESS'];
if ($bCalDAV || $bGoogleApi)
{
self::InitExternalCalendarsSyncParams($JSConfig);
}
if ($bSyncPannel)
{
$macSyncInfo = self::GetSyncInfo(self::$userId, 'mac');
$iphoneSyncInfo = self::GetSyncInfo(self::$userId, 'iphone');
$androidSyncInfo = self::GetSyncInfo(self::$userId, 'android');
$outlookSyncInfo = self::GetSyncInfo(self::$userId, 'outlook');
$exchangeSyncInfo = self::GetSyncInfo(self::$userId, 'exchange');
$JSConfig['syncInfo'] = array(
'google' => array(
'active' => ($bCalDAV || $bGoogleApi) && ($JSConfig['googleCalDavStatus']['connection_id'] > 0 || $JSConfig['googleCalDavStatus']['authLink']),
'connected' => $JSConfig['googleCalDavStatus']['connection_id'] > 0,
'syncDate' => $JSConfig['googleCalDavStatus']['sync_date']
),
'macosx' => array(
'active' => true,
'connected' => $macSyncInfo['connected'],
'syncDate' => $macSyncInfo['date'],
),
'iphone' => array(
'active' => true,
'connected' => $iphoneSyncInfo['connected'],
'syncDate' => $iphoneSyncInfo['date'],
),
'android' => array(
'active' => true,
'connected' => $androidSyncInfo['connected'],
'syncDate' => $androidSyncInfo['date'],
),
'outlook' => array(
'active' => true,
'connected' => $outlookSyncInfo['connected'],
'syncDate' => $outlookSyncInfo['date'],
),
'office365' => array(
'active' => false,
'connected' => false,
'syncDate' => false
),
'exchange' => array(
'active' => $bExchange,
'connected' => $bExchangeConnected,
'syncDate' => $exchangeSyncInfo['date']
)
);
}
else
{
$JSConfig['syncInfo'] = false;
}
// If enabled superposed sections - fetch it
$arAddSections = self::GetDisplayedSuperposed(self::$userId);
if (!is_array($arAddSections))
$arAddSections = array();
$arSectionIds = array();
$hiddenSections = CCalendarUserSettings::getHiddenSections(self::$userId);
$arDisplayedSPSections = array();
$arDisplayedNowSPSections = array();
foreach($arAddSections as $sect)
{
$arDisplayedSPSections[] = $sect;
if (!in_array($sect, $hiddenSections))
$arDisplayedNowSPSections[] = $sect;
}
self::$userMeetingSection = CCalendar::GetCurUserMeetingSection();
// **** GET SECTIONS ****
$sections = self::GetSectionList(array(
'ADDITIONAL_IDS' => $arDisplayedSPSections
));
$readOnly = !self::$perm['edit'] && !self::$perm['section_edit'];
if (self::$type == 'user' && self::$ownerId != self::$userId)
$readOnly = true;
if (self::$bAnonym)
$readOnly = true;
$bCreateDefault = !self::$bAnonym;
if (self::$type == 'user')
$bCreateDefault = self::$ownerId == self::$userId;
$additonalMeetingsId = array();
$groupOrUser = self::$type == 'user' || self::$type == 'group';
if ($groupOrUser)
{
$noEditAccessedCalendars = true;
}
$trackingUsers = array();
$trackingGroups = array();
foreach ($sections as $i => $section)
{
$sections[$i]['~IS_MEETING_FOR_OWNER'] = $section['CAL_TYPE'] == 'user' && $section['OWNER_ID'] != self::$userId && CCalendar::GetMeetingSection($section['OWNER_ID']) == $section['ID'];
if (!in_array($section['ID'], $hiddenSections) && $section['ACTIVE'] !== 'N')
{
$arSectionIds[] = $section['ID'];
// It's superposed calendar of the other user and it's need to show user's meetings
if ($sections[$i]['~IS_MEETING_FOR_OWNER'])
$additonalMeetingsId[] = array('ID' => $section['OWNER_ID'], 'SECTION_ID' => $section['ID']);
}
// We check access only for main sections because we can't edit superposed section
if ($groupOrUser && $sections[$i]['CAL_TYPE'] == self::$type &&
$sections[$i]['OWNER_ID'] == self::$ownerId)
{
if ($noEditAccessedCalendars && $section['PERM']['edit'])
$noEditAccessedCalendars = false;
if ($readOnly && ($section['PERM']['edit'] || $section['PERM']['edit_section']) && !self::$isArchivedGroup)
$readOnly = false;
}
if (self::$bSuperpose && in_array($section['ID'], $arAddSections))
$sections[$i]['SUPERPOSED'] = true;
if ($bCreateDefault && $section['CAL_TYPE'] == self::$type && $section['OWNER_ID'] == self::$ownerId)
$bCreateDefault = false;
if ($sections[$i]['SUPERPOSED'])
{
$type = $sections[$i]['CAL_TYPE'];
if ($type == 'user')
{
$path = self::$pathesForSite['path_to_user_calendar'];
$path = CComponentEngine::MakePathFromTemplate($path, array("user_id" => $sections[$i]['OWNER_ID']));
$trackingUsers[] = $sections[$i]['OWNER_ID'];
}
elseif($type == 'group')
{
$path = self::$pathesForSite['path_to_group_calendar'];
$path = CComponentEngine::MakePathFromTemplate($path, array("group_id" => $sections[$i]['OWNER_ID']));
$trackingGroups[] = $sections[$i]['OWNER_ID'];
}
else
{
$path = self::$pathesForSite['path_to_type_'.$type];
}
$sections[$i]['LINK'] = $path;
}
}
if ($groupOrUser && $noEditAccessedCalendars && !$bCreateDefault)
$readOnly = true;
self::$readOnly = $readOnly;
if (!$readOnly && $showNewEventDialog)
{
$JSConfig['showNewEventDialog'] = true;
$JSConfig['bChooseMR'] = isset($_GET['CHOOSE_MR']) && $_GET['CHOOSE_MR'] == "Y";
}
if (!in_array($JSConfig['lastSection'], $arSectionIds))
{
$JSConfig['lastSection'] = $arSectionIds[0];
}
$JSConfig = array_merge($JSConfig, Array(
'trackingUsersList' => CCalendarUserSettings::getTrackingUsers(false, array('userList' => $trackingUsers)),
'trackingGroupList' => CCalendarUserSettings::getTrackingGroups(false, array('groupList' => $trackingGroups))
));
// **** GET TASKS ****
if (self::$showTasks)
{
$JSConfig['viewTaskPath'] = self::$viewTaskPath;
$JSConfig['editTaskPath'] = self::$editTaskPath;
}
// We don't have any section
if ($bCreateDefault)
{
$fullSectionsList = $groupOrUser ? self::GetSectionList(array('checkPermissions' => false, 'getPermissions' => false)) : array();
// Section exists but it closed to this user (Ref. mantis:#64037)
if (count($fullSectionsList) > 0)
{
$readOnly = true;
}
else
{
$defCalendar = CCalendarSect::CreateDefault(array(
'type' => CCalendar::GetType(),
'ownerId' => CCalendar::GetOwnerId()
));
$arSectionIds[] = $defCalendar['ID'];
$sections[] = $defCalendar;
self::$userMeetingSection = $defCalendar['ID'];
}
}
if (CCalendarType::CanDo('calendar_type_edit', self::$type))
$JSConfig['new_section_access'] = CCalendarSect::GetDefaultAccess(self::$type, self::$ownerId);
$colors = array(
'#9dcf00','#2FC6F6','#56D1E0','#FFA900','#47E4C2','#F87396','#9985DD','#A8ADB4','#AF7E00'
);
$JSConfig['hiddenSections'] = $hiddenSections;
$JSConfig['readOnly'] = $readOnly;
// access
$JSConfig['accessNames'] = self::GetAccessNames();
$JSConfig['sectionAccessTasks'] = self::GetAccessTasks('calendar_section');
$JSConfig['typeAccessTasks'] = self::GetAccessTasks('calendar_type');
$JSConfig['bSuperpose'] = self::$bSuperpose;
$JSConfig['additonalMeetingsId'] = $additonalMeetingsId;
$selectedUserCodes = array('U'.self::$userId);
if (self::$type == 'user')
{
$selectedUserCodes[] = 'U'.self::$ownerId;
}
$additionalParams = array(
'socnetDestination' => CCalendar::GetSocNetDestination(false, $selectedUserCodes),
'locationList' => CCalendarLocation::GetList(),
'timezoneList' => CCalendar::GetTimezoneList(),
'defaultColorsList' => $colors,
'formSettings' => array(
'slider_main' => CCalendarUserSettings::getFormSettings('slider_main')
)
);
// Append Javascript files and CSS files, and some base configs
CCalendarSceleton::InitJS(
$JSConfig,
array(
'sections' => $sections
),
$additionalParams
);
}
public static function GetUserGroups($userId = 0)
{
if (!$userId || !class_exists('CSocNetUserToGroup') || !class_exists('CSocNetFeatures'))
return;
$dbGroups = CSocNetUserToGroup::GetList(
array("GROUP_NAME" => "ASC"),
array(
"USER_ID" => $userId,
"<=ROLE" => SONET_ROLES_USER,
"GROUP_SITE_ID" => SITE_ID,
"GROUP_ACTIVE" => "Y"
),
false,
false,
array("GROUP_ID", "GROUP_NAME")
);
$arRes = array();
if ($dbGroups)
{
$arGroupIds = array();
$arGroups = array();
while ($g = $dbGroups->GetNext())
{
$arGroups[] = $g;
$arGroupIds[] = $g['GROUP_ID'];
}
if (count($arGroupIds) > 0)
{
$arFeaturesActive = CSocNetFeatures::IsActiveFeature(SONET_ENTITY_GROUP, $arGroupIds, "calendar");
$arView = CSocNetFeaturesPerms::CanPerformOperation($userId, SONET_ENTITY_GROUP, $arGroupIds, "calendar", 'view');
$arWrite = CSocNetFeaturesPerms::CanPerformOperation($userId, SONET_ENTITY_GROUP, $arGroupIds, "calendar", 'write');
foreach($arGroups as $group)
{
$groupId = intVal($group['~GROUP_ID']);
// Calendar is disabled as feature or user can't even view it
if (!$arFeaturesActive[$groupId] || !$arView[$groupId])
continue;
$arRes[$groupId] = array(
'ID' => $groupId,
'NAME' => $group['~GROUP_NAME'],
'READONLY' => !$arWrite[$groupId] // Can't write to group's calendars
);
}
}
}
return $arRes;
}
public static function SetDisplayedSuperposed($userId = false, $arIds = array())
{
if (!class_exists('CUserOptions') || !$userId)
return false;
$res = array();
if (is_array($arIds))
{
foreach($arIds as $id)
{
if (intVal($id) > 0)
{
$res[] = intVal($id);
}
}
}
CUserOptions::SetOption("calendar", "superpose_displayed", serialize($res));
return true;
}
public static function DeleteSection($id)
{
if (CCalendar::IsExchangeEnabled(self::GetCurUserId()) && self::$type == 'user')
{
$oSect = CCalendarSect::GetById($id);
// For exchange we change only calendar name
if ($oSect && $oSect['IS_EXCHANGE'] && $oSect['DAV_EXCH_CAL'])
{
$exchRes = CDavExchangeCalendar::DoDeleteCalendar($oSect['OWNER_ID'], $oSect['DAV_EXCH_CAL']);
if ($exchRes !== true)
return CCalendar::CollectExchangeErrors($exchRes);
}
}
$pushChannels = PushTable::getById(array('ENTITY_TYPE' => 'SECTION', 'ENTITY_ID' => $id));
if ($row = $pushChannels->fetch())
{
\Bitrix\Calendar\Sync\GoogleApiPush::stopChannel($row);
}
return CCalendarSect::Delete($id);
}
public static function CollectExchangeErrors($arErrors = array())
{
if (count($arErrors) == 0 || !is_array($arErrors))
return '[EC_NO_EXCH] '.Loc::getMessage('EC_NO_EXCHANGE_SERVER');
$str = "";
$errorCount = count($arErrors);
for($i = 0; $i < $errorCount; $i++)
$str .= "[".$arErrors[$i][0]."] ".$arErrors[$i][1]."\n";
return $str;
}
public static function DeleteEvent($id, $doExternalSync = true, $params = array())
{
global $CACHE_MANAGER;
$id = intVal($id);
if (!$id)
{
return false;
}
$checkPermissions = isset($params['checkPermissions']) ? $params['checkPermissions'] : true;
if (!isset(self::$userId))
{
self::$userId = CCalendar::GetCurUserId();
}
CCalendar::SetOffset(false, 0);
$res = CCalendarEvent::GetList(
array(
'arFilter' => array("ID" => $id),
'parseRecursion' => false,
'setDefaultLimit' => false,
'fetchAttendees' => true,
'checkPermissions' => $checkPermissions
)
);
if ($event = $res[0])
{
if (!isset(self::$type))
{
self::$type = $event['CAL_TYPE'];
}
if (!isset(self::$ownerId))
{
self::$ownerId = $event['OWNER_ID'];
}
if ($checkPermissions && !self::IsPersonal($event['CAL_TYPE'], $event['OWNER_ID'], self::$userId) && !CCalendarSect::CanDo('calendar_edit', $event['SECT_ID'], self::$userId))
{
return Loc::getMessage('EC_ACCESS_DENIED');
}
if ($doExternalSync !== false && $event['SECT_ID'])
{
$bGoogleApi = CCalendar::isGoogleApiEnabled() && $event['CAL_TYPE'] == 'user';
$bCalDav = CCalendar::IsCalDAVEnabled() && $event['CAL_TYPE'] == 'user';
$bExchangeEnabled = CCalendar::IsExchangeEnabled() && $event['CAL_TYPE'] == 'user';
if ($bExchangeEnabled || $bCalDav || $bGoogleApi)
{
$res = CCalendarSync::DoDeleteToDav(array(
'bCalDav' => $bCalDav,
'bExchangeEnabled' => $bExchangeEnabled,
'sectionId' => $event['SECT_ID']
), $event);
if ($res !== true)
return $res;
}
}
$sendNotification = isset($params['sendNotification']) ? $params['sendNotification'] : ($params['recursionMode'] !== 'all');
$res = CCalendarEvent::Delete(array(
'id' => $id,
'Event' => $event,
'bMarkDeleted' => true,
'userId' => self::$userId,
'sendNotification' => $sendNotification
));
if ($params['recursionMode'] != 'this' && $event['RECURRENCE_ID'])
{
self::DeleteEvent($event['RECURRENCE_ID'], $doExternalSync, array('sendNotification' => $sendNotification));
}
if (CCalendarEvent::CheckRecurcion($event))
{
$events = CCalendarEvent::GetEventsByRecId($id);
foreach($events as $ev)
{
self::DeleteEvent($ev['ID'], $doExternalSync, array('sendNotification' => $sendNotification));
}
}
if($params['recursionMode'] == 'all')
{
foreach($event['~ATTENDEES'] as $attendee)
{
if ($attendee['STATUS'] != 'N')
{
$CACHE_MANAGER->ClearByTag('calendar_user_'.$attendee["USER_ID"]);
CCalendarNotify::Send(array(
"mode" => 'cancel_all',
"name" => $event['NAME'],
"from" => $event['DATE_FROM'],
"guestId" => $attendee["USER_ID"],
"eventId" => $event['PARENT_ID'],
"userId" => $event['MEETING_HOST'],
"fields" => $event
));
}
}
}
return $res;
}
return false;
}
public static function SetOffset($userId = false, $value = 0)
{
if ($userId === false)
self::$offset = $value;
else
self::$arTimezoneOffsets[$userId] = $value;
}
public static function CollectCalDAVErros($arErrors = array())
{
if (count($arErrors) == 0 || !is_array($arErrors))
return '[EC_NO_EXCH] '.Loc::getMessage('EC_NO_CAL_DAV');
$str = "";
$errorCount = count($arErrors);
for($i = 0; $i < $errorCount; $i++)
{
$str .= "[".$arErrors[$i][0]."] ".$arErrors[$i][1]."\n";
}
return $str;
}
public static function GetPathForCalendarEx($userId = 0)
{
$bExtranet = \Bitrix\Main\Loader::includeModule('extranet');
// It's extranet user
if ($bExtranet && self::IsExtranetUser($userId))
{
$siteId = CExtranet::GetExtranetSiteID();
}
else
{
if ($bExtranet && !self::IsExtranetUser($userId))
$siteId = CSite::GetDefSite();
else
$siteId = self::GetSiteId();
if (self::$siteId == $siteId && isset(self::$pathesForSite) && is_array(self::$pathesForSite))
self::$pathes[$siteId] = self::$pathesForSite;
}
if (!isset(self::$pathes[$siteId]) || !is_array(self::$pathes[$siteId]))
self::$pathes[$siteId] = self::GetPathes($siteId);
$calendarUrl = self::$pathes[$siteId]['path_to_user_calendar'];
$calendarUrl = str_replace(array('#user_id#', '#USER_ID#'), $userId, $calendarUrl);
$calendarUrl = CCalendar::GetServerPath().$calendarUrl;
return $calendarUrl;
}
public static function IsExtranetUser($userId = 0)
{
return !count(self::GetUserDepartment($userId));
}
public static function GetUserDepartment($userId = 0)
{
if (!isset(self::$arUserDepartment[$userId]))
{
$rsUser = CUser::GetByID($userId);
if($arUser = $rsUser->Fetch())
self::SetUserDepartment($userId, $arUser["UF_DEPARTMENT"]);
}
return self::$arUserDepartment[$userId];
}
public static function SetUserDepartment($userId = 0, $dep = array())
{
if (!is_array($dep))
$dep = array();
self::$arUserDepartment[$userId] = $dep;
}
public static function HandleImCallback($module, $tag, $value, $arNotify)
{
$userId = CCalendar::GetCurUserId();
if ($module == "calendar" && $userId)
{
$arTag = explode("|", $tag);
$eventId = intVal($arTag[2]);
if ($arTag[0] == "CALENDAR" && $arTag[1] == "INVITE" && $eventId > 0 && $userId)
{
CCalendarEvent::SetMeetingStatus(array(
'userId' => $userId,
'eventId' => $eventId,
'status' => $value == 'Y' ? 'Y' : 'N',
'personalNotification' => true
));
return $value == 'Y' ? Loc::getMessage('EC_PROP_CONFIRMED_TEXT_Y') : Loc::getMessage('EC_PROP_CONFIRMED_TEXT_N');
}
}
}
public static function ClearSettings()
{
self::SetSettings(array(), true);
}
public static function SetSettings($settings = array(), $bClear = false)
{
$arPathes = self::GetPathesList();
$arOpt = array('work_time_start', 'work_time_end', 'year_holidays', 'year_workdays', 'week_holidays', 'week_start', 'user_name_template', 'sync_by_push', 'user_show_login', 'rm_iblock_type', 'rm_iblock_id', 'denied_superpose_types', 'pathes_for_sites', 'pathes', 'dep_manager_sub', 'forum_id', 'rm_for_sites');
$arOpt = array_merge($arOpt, $arPathes);
if ($settings['rm_iblock_ids'] && !$settings['rm_for_sites'])
{
foreach($settings['rm_iblock_ids'] as $site => $value)
{
COption::SetOptionString("calendar", 'rm_iblock_id', $value, false, $site);
}
}
foreach($arOpt as $opt)
{
if ($bClear)
{
COption::RemoveOption("calendar", $opt);
}
elseif (isset($settings[$opt]))
{
if ($opt == 'rm_iblock_id' && !$settings['rm_for_sites'])
{
continue;
}
elseif ($opt == 'sync_by_push' && self::isGoogleApiEnabled())
{
if ($settings[$opt])
{
// start push agents
\CAgent::RemoveAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::clearPushChannels();", "calendar");
\CAgent::AddAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::createWatchChannels(0);", "calendar", "N", 60);
\CAgent::AddAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::processPush();", "calendar", "N", 180);
\CAgent::AddAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::renewWatchChannels();", "calendar", "N", 14400);
}
else
{
// start clear push channels agent
\CAgent::AddAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::clearPushChannels();", "calendar", "N", 60);
\CAgent::RemoveAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::processPush();", "calendar");
\CAgent::RemoveAgent("\\Bitrix\\Calendar\\Sync\\GoogleApiPush::renewWatchChannels();", "calendar");
}
}
elseif ($opt == 'pathes' && is_array($settings[$opt]))
{
$sitesPathes = $settings[$opt];
$ar = array();
$arAffectedSites = array();
foreach($sitesPathes as $s => $pathes)
{
$affect = false;
foreach($arPathes as $path)
{
if ($pathes[$path] != $settings[$path])
{
$ar[$path] = $pathes[$path];
$affect = true;
}
}
if ($affect && !in_array($s, $arAffectedSites))
{
$arAffectedSites[] = $s;
COption::SetOptionString("calendar", 'pathes_'.$s, serialize($ar));
}
else
{
COption::RemoveOption("calendar", 'pathes_'.$s);
}
}
COption::SetOptionString("calendar", 'pathes_sites', serialize($arAffectedSites));
continue;
}
elseif ($opt == 'denied_superpose_types' && is_array($settings[$opt]))
{
$settings[$opt] = serialize($settings[$opt]);
}
COption::SetOptionString("calendar", $opt, $settings[$opt]);
}
}
}
public static function IsBitrix24()
{
return \Bitrix\Main\ModuleManager::isModuleInstalled('bitrix24');
}
public static function SearchAttendees($name = '', $Params = array())
{
if (!isset($Params['arFoundUsers']))
$Params['arFoundUsers'] = CSocNetUser::SearchUser($name);
$arUsers = array();
if (!is_array($Params['arFoundUsers']) || count($Params['arFoundUsers']) <= 0)
{
if ($Params['addExternal'] !== false)
{
if (check_email($name, true))
{
$arUsers[] = array(
'type' => 'ext',
'email' => htmlspecialcharsex($name)
);
}
else
{
$arUsers[] = array(
'type' => 'ext',
'name' => htmlspecialcharsex($name)
);
}
}
}
else
{
foreach ($Params['arFoundUsers'] as $userId => $userName)
{
$userId = intVal($userId);
$by = "id";
$order = "asc";
$r = CUser::GetList($by, $order, array("ID_EQUAL_EXACT" => $userId, "ACTIVE" => "Y"));
if (!$User = $r->Fetch())
continue;
$name = trim($User['NAME'].' '.$User['LAST_NAME']);
if ($name == '')
$name = trim($User['LOGIN']);
$arUsers[] = array(
'type' => 'int',
'id' => $userId,
'name' => $name,
'status' => 'Q',
'busy' => 'free'
);
}
}
return $arUsers;
}
public static function GetGroupMembers($groupId)
{
$dbMembers = CSocNetUserToGroup::GetList(
array("RAND" => "ASC"),
array(
"GROUP_ID" => $groupId,
"<=ROLE" => SONET_ROLES_USER,
"USER_ACTIVE" => "Y"
),
false,
false,
array("USER_ID", "USER_NAME", "USER_LAST_NAME", "USER_SECOND_NAME", "USER_LOGIN")
);
$arMembers = array();
if ($dbMembers)
{
while ($Member = $dbMembers->GetNext())
{
$name = trim($Member['USER_NAME'].' '.$Member['USER_LAST_NAME']);
if ($name == '')
$name = trim($Member['USER_LOGIN']);
$arMembers[] = array('id' => $Member["USER_ID"],'name' => $name);
}
}
return $arMembers;
}
public static function ReminderAgent($eventId = 0, $userId = 0, $viewPath = '', $calendarType = '', $ownerId = 0)
{
CCalendarReminder::ReminderAgent($eventId, $userId, $viewPath, $calendarType, $ownerId);
}
public static function GetMaxTimestamp()
{
return self::CALENDAR_MAX_TIMESTAMP;
}
public static function GetOwnerName($type = '', $ownerId = '')
{
$type = strtolower($type);
$key = $type.'_'.$ownerId;
if (isset(self::$ownerNames[$key]))
return self::$ownerNames[$key];
$ownerName = '';
if($type == 'user')
{
$ownerName = CCalendar::GetUserName($ownerId);
}
elseif($type == 'group')
{
// Get group name
if (!\Bitrix\Main\Loader::includeModule("socialnetwork"))
return $ownerName;
if ($arGroup = CSocNetGroup::GetByID($ownerId))
$ownerName = $arGroup["~NAME"];
}
else
{
// Get type name
$arTypes = CCalendarType::GetList(array("arFilter" => array("XML_ID" => $type)));
$ownerName = $arTypes[0]['NAME'];
}
self::$ownerNames[$key] = $ownerName;
$ownerName = trim($ownerName);
return $ownerName;
}
public static function GetTimezoneOffset($timezoneId, $dateTimestamp = false)
{
$offset = 0;
if ($timezoneId)
{
try
{
$oTz = new DateTimeZone($timezoneId);
if ($oTz)
{
$offset = $oTz->getOffset(new DateTime($dateTimestamp ? "@$dateTimestamp" : "now", $oTz));
}
}
catch(Exception $e){}
}
return $offset;
}
public static function GetAbsentEvents($params)
{
if (!isset($params['arUserIds']))
return false;
return CCalendarEvent::GetAbsent($params['arUserIds'], $params);
}
public static function GetAccessibilityForUsers($params)
{
if (!isset($params['checkPermissions']))
$params['checkPermissions'] = true;
$res = CCalendarEvent::GetAccessibilityForUsers(array(
'users' => $params['users'],
'from' => $params['from'],
'to' => $params['to'],
'curEventId' => $params['curEventId'],
'checkPermissions' => $params['checkPermissions']
));
// Fetch absence from intranet
if ($params['getFromHR'] && CCalendar::IsIntranetEnabled())
{
$resHR = CIntranetUtils::GetAbsenceData(
array(
'DATE_START' => $params['from'],
'DATE_FINISH' => $params['to'],
'USERS' => $params['users'],
'PER_USER' => true,
'SELECT' => array('ID', 'DATE_ACTIVE_FROM', 'DATE_ACTIVE_TO')
),
BX_INTRANET_ABSENCE_HR
);
foreach($resHR as $userId => $forUser)
{
if (!isset($res[$userId]) || !is_array($res[$userId]))
$res[$userId] = array();
foreach($forUser as $event)
{
$res[$userId][] = array(
'FROM_HR' => true,
'ID' => $event['ID'],
'DT_FROM' => $event['DATE_ACTIVE_FROM'],
'DT_TO' => $event['DATE_ACTIVE_TO'],
'ACCESSIBILITY' => 'absent',
'IMPORTANCE' => 'normal',
"FROM" => CCalendar::Timestamp($event['DATE_ACTIVE_FROM']),
"TO" => CCalendar::Timestamp($event['DATE_ACTIVE_TO'])
);
}
}
}
return $res;
}
public static function GetNearestEventsList($params = array())
{
$type = $params['bCurUserList'] ? 'user' : $params['type'];
// Get current user id
if (!isset($params['userId']) || $params['userId'] <= 0)
$curUserId = CCalendar::GetCurUserId();
else
$curUserId = intval($params['userId']);
if (!CCalendarType::CanDo('calendar_type_view', $type, $curUserId))
return 'access_denied';
if ($params['bCurUserList'] && ($curUserId <= 0 || (class_exists('CSocNetFeatures') && !CSocNetFeatures::IsActiveFeature(SONET_ENTITY_USER, $curUserId, "calendar"))))
return 'inactive_feature';
$arFilter = array(
'CAL_TYPE' => $type,
'FROM_LIMIT' => $params['fromLimit'],
'TO_LIMIT' => $params['toLimit'],
'DELETED' => 'N',
'ACTIVE_SECTION' => 'Y'
);
if ($params['bCurUserList'])
$arFilter['OWNER_ID'] = $curUserId;
if (isset($params['sectionId']) && $params['sectionId'])
$arFilter["SECTION"] = $params['sectionId'];
if ($type == 'user')
unset($arFilter['CAL_TYPE']);
$arEvents = CCalendarEvent::GetList(
array(
'arFilter' => $arFilter,
'parseRecursion' => true,
'fetchAttendees' => true,
'userId' => $curUserId,
'fetchMeetings' => $type == 'user',
'preciseLimits' => true,
'skipDeclined' => true
)
);
if (CCalendar::Date(time(), false) == $params['fromLimit'])
$limitTime = time();
else
$limitTime = CCalendar::Timestamp($params['fromLimit']);
$arResult = array();
$serverOffset = intVal(date("Z"));
foreach($arEvents as $event)
{
if ($event['IS_MEETING'] && $event["MEETING_STATUS"] == 'N')
continue;
if ($type == 'user' && !$event['IS_MEETING'] && $event['CAL_TYPE'] != 'user')
continue;
// $serverToTs = timestamp in utc + server offset;
$serverToTs = (CCalendar::Timestamp($event['DATE_TO']) - $event['TZ_OFFSET_TO']) + $serverOffset;
if ($event['DT_SKIP_TIME'] == 'Y')
{
$serverToTs += self::DAY_LENGTH;
}
if ($serverToTs >= $limitTime)
{
$fromTs = CCalendar::Timestamp($event['DATE_FROM']);
$toTs = CCalendar::Timestamp($event['DATE_TO']);
if ($event['DT_SKIP_TIME'] !== "Y")
{
$fromTs -= $event['~USER_OFFSET_FROM'];
$toTs -= $event['~USER_OFFSET_TO'];
}
$event['DATE_FROM'] = CCalendar::Date($fromTs, $event['DT_SKIP_TIME'] != 'Y');
$event['DATE_TO'] = CCalendar::Date($toTs, $event['DT_SKIP_TIME'] != 'Y');
unset($event['TZ_FROM'], $event['TZ_TO'], $event['TZ_OFFSET_FROM'], $event['TZ_OFFSET_TO']);
$event['DT_FROM_TS'] = $fromTs;
$event['DT_TO_TS'] = $toTs;
$arResult[] = $event;
}
}
// Sort by DATE_FROM_TS
usort($arResult, array('CCalendar', '_NearestSort'));
return $arResult;
}
public static function _NearestSort($a, $b)
{
if ($a['DT_FROM_TS'] == $b['DT_FROM_TS'])
return 0;
if ($a['DT_FROM_TS'] < $b['DT_FROM_TS'])
return -1;
return 1;
}
public static function GetAccessibilityForMeetingRoom($params)
{
$allowReserveMeeting = isset($params['allowReserveMeeting']) ? $params['allowReserveMeeting'] : self::$allowReserveMeeting;
$RMiblockId = isset($params['RMiblockId']) ? $params['RMiblockId'] : self::$settings['rm_iblock_id'];
$curEventId = $params['curEventId'] > 0 ? $params['curEventId'] : false;
$arResult = array();
$offset = CCalendar::GetOffset();
if ($allowReserveMeeting)
{
$arSelect = array("ID", "NAME", "IBLOCK_SECTION_ID", "IBLOCK_ID", "ACTIVE_FROM", "ACTIVE_TO");
$arFilter = array(
"IBLOCK_ID" => $RMiblockId,
"SECTION_ID" => $params['id'],
"INCLUDE_SUBSECTIONS" => "Y",
"ACTIVE" => "Y",
"CHECK_PERMISSIONS" => 'N',
">=DATE_ACTIVE_TO" => $params['from'],
"<=DATE_ACTIVE_FROM" => $params['to']
);
if(IntVal($curEventId) > 0)
{
$arFilter["!ID"] = IntVal($curEventId);
}
$rsElement = CIBlockElement::GetList(Array('ACTIVE_FROM' => 'ASC'), $arFilter, false, false, $arSelect);
while($obElement = $rsElement->GetNextElement())
{
$arItem = $obElement->GetFields();
$arItem["DISPLAY_ACTIVE_FROM"] = CIBlockFormatProperties::DateFormat(self::DFormat(true), MakeTimeStamp($arItem["ACTIVE_FROM"]));
$arItem["DISPLAY_ACTIVE_TO"] = CIBlockFormatProperties::DateFormat(self::DFormat(true), MakeTimeStamp($arItem["ACTIVE_TO"]));
$arResult[] = array(
"ID" => intVal($arItem['ID']),
"NAME" => $arItem['~NAME'],
"DT_FROM" => CCalendar::CutZeroTime($arItem['DISPLAY_ACTIVE_FROM']),
"DT_TO" => CCalendar::CutZeroTime($arItem['DISPLAY_ACTIVE_TO']),
"DT_FROM_TS" => (CCalendar::Timestamp($arItem['DISPLAY_ACTIVE_FROM']) - $offset) * 1000,
"DT_TO_TS" => (CCalendar::Timestamp($arItem['DISPLAY_ACTIVE_TO']) - $offset) * 1000
);
}
}
return $arResult;
}
public static function GetMeetingRoomById($Params)
{
if (IntVal($Params['RMiblockId']) > 0 && CIBlock::GetPermission($Params['RMiblockId']) >= "R")
{
$arFilter = array("IBLOCK_ID" => $Params['RMiblockId'], "ACTIVE" => "Y", "ID" => $Params['id']);
$arSelectFields = array("NAME");
$res = CIBlockSection::GetList(array(), $arFilter, false, array("NAME"));
if ($arMeeting = $res->GetNext())
return $arMeeting;
}
if(IntVal($Params['VMiblockId']) > 0 && CIBlock::GetPermission($Params['VMiblockId']) >= "R")
{
$arFilter = array("IBLOCK_ID" => $Params['VMiblockId'], "ACTIVE" => "Y");
$arSelectFields = array("ID", "NAME", "DESCRIPTION", "IBLOCK_ID");
$res = CIBlockSection::GetList(Array(), $arFilter, false, $arSelectFields);
if($arMeeting = $res->GetNext())
{
return array(
'ID' => $Params['VMiblockId'],
'NAME' => $arMeeting["NAME"],
'DESCRIPTION' => $arMeeting['DESCRIPTION'],
);
}
}
return false;
}
public static function ReleaseLocation($loc)
{
$set = CCalendar::GetSettings(array('request' => false));
if($set['rm_iblock_id'])
{
CCalendar::ReleaseMeetingRoom(array(
'mrevid' => $loc['mrevid'],
'mrid' => $loc['mrid'],
'RMiblockId' => $set['rm_iblock_id']
));
}
if ($loc['room_id'] && $loc['room_event_id'] !== false)
{
CCalendarLocation::releaseRoom(array(
'room_id' => $loc['room_id'],
'room_event_id' => $loc['room_event_id']
));
}
}
public static function ReleaseMeetingRoom($Params)
{
$Params['RMiblockId'] = isset($Params['RMiblockId']) ? $Params['RMiblockId'] : self::$settings['rm_iblock_id'];
$arFilter = array(
"ID" => $Params['mrevid'],
"IBLOCK_ID" => $Params['RMiblockId'],
"IBLOCK_SECTION_ID" => $Params['mrid'],
"SECTION_ID" => array($Params['mrid'])
);
$res = CIBlockElement::GetList(array(), $arFilter, false, false, array("ID"));
if($arElement = $res->Fetch())
{
$obElement = new CIBlockElement;
$obElement->Delete($Params['mrevid']);
}
// Hack: reserve meeting calendar based on old calendar's cache
$cache = new CPHPCache;
$cache->CleanDir('event_calendar/');
$cache->CleanDir('event_calendar/events/');
$cache->CleanDir('event_calendar/events/'.$Params['RMiblockId']);
}
public static function GetCalendarList($calendarId, $params = array())
{
self::SetSilentErrorMode();
list($sectionId, $entityType, $entityId) = $calendarId;
$arFilter = array(
'CAL_TYPE' => $entityType,
'OWNER_ID' => $entityId
);
if (!is_array($params))
$params = array();
if ($sectionId > 0)
$arFilter['ID'] = $sectionId;
if (isset($params['active']))
{
$arFilter['ACTIVE'] = $params['active'] ? 'Y' : 'N';
}
$res = CCalendarSect::GetList(array('arFilter' => $arFilter));
$arCalendars = array();
foreach($res as $calendar)
{
if ($params['skipExchange'] == true && strlen($calendar['DAV_EXCH_CAL']) > 0)
{
continue;
}
$arCalendars[] = array(
'ID' => $calendar['ID'],
'~NAME' => $calendar['NAME'],
'NAME' => htmlspecialcharsbx($calendar['NAME']),
'DESCRIPTION' => htmlspecialcharsbx($calendar['DESCRIPTION']),
'COLOR' => htmlspecialcharsbx($calendar['COLOR'])
//"DATE_CREATE" => date("d.m.Y H:i", self::Timestamp($arSection['DATE_CREATE']))
);
}
self::SetSilentErrorMode(false);
return $arCalendars;
}
/*
* $params['from'], $params['from'] - datetime in UTC
* */
public static function GetDavCalendarEventsList($calendarId, $arFilter = array())
{
list($sectionId, $entityType, $entityId) = $calendarId;
CCalendar::SetOffset(false, 0);
$arFilter1 = array(
'OWNER_ID' => $entityId,
'DELETED' => 'N'
);
if (isset($arFilter['DAV_XML_ID']))
{
unset($arFilter['DATE_START'], $arFilter['FROM_LIMIT'], $arFilter['DATE_END'], $arFilter['TO_LIMIT']);
}
else
{
if (isset($arFilter['DATE_START']))
{
$arFilter['FROM_LIMIT'] = $arFilter['DATE_START'];
unset($arFilter['DATE_START']);
}
if (isset($arFilter['DATE_END']))
{
$arFilter['TO_LIMIT'] = $arFilter['DATE_END'];
unset($arFilter['DATE_END']);
}
}
$fetchMeetings = true;
if ($sectionId > 0)
{
$arFilter['SECTION'] = $sectionId;
$fetchMeetings = false;
if ($entityType == 'user')
$fetchMeetings = self::GetMeetingSection($entityId) == $sectionId;
}
$arFilter = array_merge($arFilter1, $arFilter);
$arEvents = CCalendarEvent::GetList(
array(
'arFilter' => $arFilter,
'getUserfields' => false,
'parseRecursion' => false,
'fetchAttendees' => false,
'fetchMeetings' => $fetchMeetings,
'userId' => CCalendar::GetCurUserId()
)
);
$result = array();
foreach ($arEvents as $event)
{
if ($event['IS_MEETING'] && $event["MEETING_STATUS"] == 'N')
continue;
// Skip events from where owner is host of the meeting and it's meeting from other section
if ($entityType == 'user' && $event['IS_MEETING'] && $event['MEETING_HOST'] == $entityId && $event['SECT_ID'] != $sectionId)
continue;
$event['XML_ID'] = $event['DAV_XML_ID'];
if ($event['LOCATION'] !== '')
$event['LOCATION'] = CCalendar::GetTextLocation($event['LOCATION']);
$event['RRULE'] = CCalendarEvent::ParseRRULE($event['RRULE']);
$result[] = $event;
}
return $result;
}
public static function GetTextLocation($loc = '')
{
$location = self::ParseLocation($loc);
$result = $loc;
if ($location['mrid'] === false && $location['room_id'] === false)
{
$result = $location['str'];
}
elseif($location['room_id'] > 0)
{
$room = CCalendarLocation::getById($location['room_id']);
$result = $room ? $room['NAME'] : '';
}
else
{
$MRList = CCalendar::GetMeetingRoomList();
foreach($MRList as $MR)
{
if ($MR['ID'] == $location['mrid'])
{
$result = $MR['NAME'];
break;
}
}
}
return $result;
}
public static function ParseLocation($location = '')
{
$res = array(
'mrid' => false,
'mrevid' => false,
'room_id' => false,
'room_event_id' => false,
'str' => $location
);
if (strlen($location) > 5 && substr($location, 0, 5) == 'ECMR_')
{
$location = explode('_', $location);
if (count($location) >= 2)
{
if (intVal($location[1]) > 0)
$res['mrid'] = intVal($location[1]);
if (intVal($location[2]) > 0)
$res['mrevid'] = intVal($location[2]);
}
}
elseif (strlen($location) > 9 && substr($location, 0, 9) == 'calendar_')
{
$location = explode('_', $location);
if (count($location) >= 2)
{
if (intVal($location[1]) > 0)
$res['room_id'] = intVal($location[1]);
if (intVal($location[2]) > 0)
$res['room_event_id'] = intVal($location[2]);
}
}
return $res;
}
/* * * * RESERVE MEETING ROOMS * * * */
public static function GetUserPermissionsForCalendar($calendarId, $userId)
{
list($sectionId, $entityType, $entityId) = $calendarId;
$entityType = strtolower($entityType);
if ($sectionId == 0)
{
$res = array(
'bAccess' => CCalendarType::CanDo('calendar_type_view', $entityType, $userId),
'bReadOnly' => !CCalendarType::CanDo('calendar_type_edit', $entityType, $userId)
);
}
$bOwner = $entityType == 'user' && $entityId == $userId;
$res = array(
'bAccess' => $bOwner || CCalendarSect::CanDo('calendar_view_time', $sectionId, $userId),
'bReadOnly' => !$bOwner && !CCalendarSect::CanDo('calendar_edit', $sectionId, $userId)
);
if ($res['bReadOnly'] && !$bOwner)
{
if (CCalendarSect::CanDo('calendar_view_time', $sectionId, $userId))
$res['privateStatus'] = 'time';
if (CCalendarSect::CanDo('calendar_view_title', $sectionId, $userId))
$res['privateStatus'] = 'title';
}
return $res;
}
public static function GetDayLen()
{
return self::DAY_LENGTH;
}
public static function UnParseTextLocation($loc = '')
{
$result = array('NEW' => $loc);
if ($loc != "")
{
$location = self::ParseLocation($loc);
if ($location['mrid'] === false)
{
$MRList = CCalendar::GetMeetingRoomList();
$loc_ = trim(strtolower($loc));
foreach($MRList as $MR)
{
if (trim(strtolower($MR['NAME'])) == $loc_)
{
$result['NEW'] = 'ECMR_'.$MR['ID'];
break;
}
}
}
}
return $result;
}
public static function ClearExchangeHtml($html = "")
{
// Echange in chrome puts chr(13) instead of \n
$html = str_replace(chr(13), "\n", trim($html, chr(13)));
$html = preg_replace("/(\s|\S)*<a\s*name=\"bm_begin\"><\/a>/is".BX_UTF_PCRE_MODIFIER,"", $html);
$html = preg_replace("/<br>(\n|\r)+/is".BX_UTF_PCRE_MODIFIER,"<br>", $html);
return self::ParseHTMLToBB($html);
}
public static function ParseHTMLToBB($html = "")
{
$id = AddEventHandler("main", "TextParserBeforeTags", Array("CCalendar", "_ParseHack"));
$TextParser = new CTextParser();
$TextParser->allow = array("HTML" => "N", "ANCHOR" => "Y", "BIU" => "Y", "IMG" => "Y", "QUOTE" => "Y", "CODE" => "Y", "FONT" => "N", "LIST" => "Y", "SMILES" => "Y", "NL2BR" => "Y", "VIDEO" => "Y", "TABLE" => "Y", "CUT_ANCHOR" => "Y", "ALIGN" => "Y");
$html = $TextParser->convertText($html);
$html = htmlspecialcharsback($html);
// Replace BR
$html = preg_replace("/\<br\s*\/*\>/is".BX_UTF_PCRE_MODIFIER,"\n", $html);
// Kill
$html = preg_replace("/ /is".BX_UTF_PCRE_MODIFIER,"", $html);
// Kill tags
$html = preg_replace("/\<([^>]*?)>/is".BX_UTF_PCRE_MODIFIER,"", $html);
$html = htmlspecialcharsbx($html);
RemoveEventHandler("main", "TextParserBeforeTags", $id);
return $html;
}
public static function WeekDayByInd($i, $binv = true)
{
if ($binv)
$arDays = array('SU','MO','TU','WE','TH','FR','SA');
else
$arDays = array('MO','TU','WE','TH','FR','SA','SU');
return isset($arDays[$i]) ? $arDays[$i] : false;
}
public static function SaveEvent($params = array())
{
$res = self::SaveEventEx($params);
if (is_array($res) && isset($res['id']))
{
return $res['id'];
}
else
{
return $res;
}
}
public static function SaveEventEx($params = array())
{
$arFields = $params['arFields'];
if (self::$type && !isset($arFields['CAL_TYPE']))
$arFields['CAL_TYPE'] = self::$type;
if (self::$bOwner && !isset($arFields['OWNER_ID']))
$arFields['OWNER_ID'] = self::$ownerId;
if (!isset($arFields['SKIP_TIME']) && isset($arFields['DT_SKIP_TIME']))
$arFields['SKIP_TIME'] = $arFields['DT_SKIP_TIME'] == 'Y';
$result = array();
$userId = isset($params['userId']) ? $params['userId'] : self::GetCurUserId();
$sectionId = (is_array($arFields['SECTIONS']) && count($arFields['SECTIONS']) > 0) ? $arFields['SECTIONS'][0] : intval($arFields['SECTIONS']);
$bPersonal = self::IsPersonal($arFields['CAL_TYPE'], $arFields['OWNER_ID'], $userId);
$checkPermission = !isset($params['checkPermission']) || $params['checkPermission'] !== false;
$silentErrorMode = isset($params['silentErrorMode']) ? $params['silentErrorMode'] : true;
$silentErrorModePrev = self::$silentErrorMode;
self::SetSilentErrorMode();
if (!isset($arFields['DATE_FROM']) &&
!isset($arFields['DATE_TO']) &&
isset($arFields['DT_FROM']) &&
isset($arFields['DT_TO']))
{
$arFields['DATE_FROM'] = $arFields['DT_FROM'];
$arFields['DATE_TO'] = $arFields['DT_TO'];
unset($arFields['DT_FROM']);
unset($arFields['DT_TO']);
}
// Fetch current event
$curEvent = false;
$bNew = !isset($arFields['ID']) || !$arFields['ID'];
if (!$bNew)
{
$curEvent = CCalendarEvent::GetList(
array(
'arFilter' => array(
"ID" => intVal($arFields['ID']),
"DELETED" => "N"
),
'parseRecursion' => false,
'fetchAttendees' => true,
'fetchMeetings' => false,
'userId' => $userId
)
);
if ($curEvent)
$curEvent = $curEvent[0];
$bPersonal = $bPersonal && self::IsPersonal($curEvent['CAL_TYPE'], $curEvent['OWNER_ID'], $userId);
$arFields['CAL_TYPE'] = $curEvent['CAL_TYPE'];
$arFields['OWNER_ID'] = $curEvent['OWNER_ID'];
$arFields['CREATED_BY'] = $curEvent['CREATED_BY'];
$arFields['ACTIVE'] = $curEvent['ACTIVE'];
$bChangeMeeting = !$checkPermission || CCalendarSect::CanDo('calendar_edit', $curEvent['SECT_ID'], $userId);
if (!isset($arFields['NAME']))
$arFields['NAME'] = $curEvent['NAME'];
if (!isset($arFields['DESCRIPTION']))
$arFields['DESCRIPTION'] = $curEvent['DESCRIPTION'];
if (!isset($arFields['COLOR']) && $curEvent['COLOR'])
$arFields['COLOR'] = $curEvent['COLOR'];
if (!isset($arFields['TEXT_COLOR']) && $curEvent['TEXT_COLOR'])
$arFields['TEXT_COLOR'] = $curEvent['TEXT_COLOR'];
if (!isset($arFields['SECTIONS']))
{
$arFields['SECTIONS'] = array($curEvent['SECT_ID']);
$sectionId = (is_array($arFields['SECTIONS']) && count($arFields['SECTIONS']) > 0) ? $arFields['SECTIONS'][0] : 0;
}
if (!isset($arFields['IS_MEETING']))
$arFields['IS_MEETING'] = $curEvent['IS_MEETING'];
if (!isset($arFields['ACTIVE']))
$arFields['ACTIVE'] = $curEvent['ACTIVE'];
if (!isset($arFields['PRIVATE_EVENT']))
$arFields['PRIVATE_EVENT'] = $curEvent['PRIVATE_EVENT'];
if (!isset($arFields['ACCESSIBILITY']))
$arFields['ACCESSIBILITY'] = $curEvent['ACCESSIBILITY'];
if (!isset($arFields['IMPORTANCE']))
$arFields['IMPORTANCE'] = $curEvent['IMPORTANCE'];
if (!isset($arFields['SKIP_TIME']))
$arFields['SKIP_TIME'] = $curEvent['DT_SKIP_TIME'] == 'Y';
if (!isset($arFields['DATE_FROM']) && isset($curEvent['DATE_FROM']))
$arFields['DATE_FROM'] = $curEvent['DATE_FROM'];
if (!isset($arFields['DATE_TO']) && isset($curEvent['DATE_TO']))
$arFields['DATE_TO'] = $curEvent['DATE_TO'];
if (!isset($arFields['TZ_FROM']))
$arFields['TZ_FROM'] = $curEvent['TZ_FROM'];
if (!isset($arFields['TZ_TO']))
$arFields['TZ_TO'] = $curEvent['TZ_TO'];
if (!isset($arFields['MEETING']) && $arFields['IS_MEETING'])
$arFields['MEETING'] = $curEvent['MEETING'];
if (!isset($arFields['MEETING']) && $arFields['IS_MEETING'])
$arFields['MEETING'] = $curEvent['MEETING'];
if (!isset($arFields['ATTENDEES']) && !isset($arFields['ATTENDEES_CODES'])
&& $arFields['IS_MEETING'] && isset($curEvent['~ATTENDEES']))
{
$arFields['ATTENDEES'] = array();
foreach($curEvent['~ATTENDEES'] as $att)
{
$arFields['ATTENDEES'][] = $att['USER_ID'];
}
}
if (!isset($arFields['ATTENDEES_CODES']) && $arFields['IS_MEETING'])
{
$arFields['ATTENDEES_CODES'] = $curEvent['ATTENDEES_CODES'];
}
if (!isset($arFields['LOCATION']) && $curEvent['LOCATION'] != "")
{
$arFields['LOCATION'] = Array(
"OLD" => $curEvent['LOCATION'],
"NEW" => $curEvent['LOCATION']
);
}
if (!$bChangeMeeting)
{
$arFields['IS_MEETING'] = $curEvent['IS_MEETING'];
}
if ($arFields['IS_MEETING'] && !$bPersonal && $arFields['CAL_TYPE'] == 'user')
{
$arFields['SECTIONS'] = array($curEvent['SECT_ID']);
}
if ($curEvent['IS_MEETING'])
{
$arFields['MEETING_HOST'] = $curEvent['MEETING_HOST'];
}
// If it's attendee and but modifying called from CalDav methods
if (($params['bSilentAccessMeeting'] || $params['fromWebservice'] === true)
&& $curEvent['IS_MEETING'] && $curEvent['PARENT_ID'] != $curEvent['ID'])
{
$params['recursionEditMode'] = 'skip';
$params['sendInvitations'] = false;
$params['sendEditNotification'] = false;
$params['significantChanges'] = false;
$params['arFields'] = array(
"ID" => $arFields["ID"],
"PARENT_ID" => $arFields["PARENT_ID"],
"OWNER_ID" => $arFields["OWNER_ID"],
"DAV_XML_ID" => $arFields['DAV_XML_ID'],
"CAL_DAV_LABEL" => $arFields['CAL_DAV_LABEL'],
"DAV_EXCH_LABEL" => $arFields['DAV_EXCH_LABEL']
);
$params['userId'] = $userId;
CCalendarEvent::Edit($params);
return true; // CalDav will return 204
}
if (!isset($arFields["RRULE"]) && $curEvent["RRULE"] != '' && $params['fromWebservice'] !== true)
{
$arFields["RRULE"] = CCalendarEvent::ParseRRULE($curEvent["RRULE"]);
}
if ($params['fromWebservice'] === true)
{
if ($arFields["RRULE"] == -1 && CCalendarEvent::CheckRecurcion($curEvent))
{
$arFields["RRULE"] = CCalendarEvent::ParseRRULE($curEvent['RRULE']);
}
}
if (!isset($arFields['EXDATE']) && $arFields["RRULE"])
$arFields['EXDATE'] = $curEvent['EXDATE'];
if ($curEvent)
$params['currentEvent'] = $curEvent;
if ($checkPermission && !$bPersonal && !CCalendarSect::CanDo('calendar_edit', $curEvent['SECT_ID'], $userId))
{
return Loc::getMessage('EC_ACCESS_DENIED');
}
}
elseif ($sectionId > 0 && $checkPermission && !$bPersonal && !CCalendarSect::CanDo('calendar_add', $sectionId, $userId))
{
return CCalendar::ThrowError(Loc::getMessage('EC_ACCESS_DENIED'));
}
if ($params['autoDetectSection'] && $sectionId <= 0)
{
$sectionId = false;
if ($arFields['CAL_TYPE'] == 'user')
{
$sectionId = CCalendarSect::GetLastUsedSection('user', $arFields['OWNER_ID'], $userId);
if ($sectionId)
{
$res = CCalendarSect::GetList(array('arFilter' => array('CAL_TYPE' => $arFields['CAL_TYPE'],'OWNER_ID' => $arFields['OWNER_ID'], 'ID'=> $sectionId)));
if (!$res || !$res[0])
$sectionId = false;
}
else
{
$sectionId = false;
}
if ($sectionId)
$arFields['SECTIONS'] = array($sectionId);
}
if (!$sectionId)
{
$sectRes = self::GetSectionForOwner($arFields['CAL_TYPE'], $arFields['OWNER_ID'], $params['autoCreateSection']);
if ($sectRes['sectionId'] > 0)
{
$arFields['SECTIONS'] = array($sectRes['sectionId']);
if ($sectRes['autoCreated'])
$params['bAffectToDav'] = false;
}
else
{
return false;
}
}
}
if (isset($arFields["RRULE"]))
{
$arFields["RRULE"] = CCalendarEvent::CheckRRULE($arFields["RRULE"]);
}
// Set version
if (!isset($arFields['VERSION']) || $arFields['VERSION'] <= $curEvent['VERSION'])
$arFields['VERSION'] = $curEvent['VERSION'] ? $curEvent['VERSION'] + 1 : 1;
if ($params['autoDetectSection'] && $sectionId <= 0 && $arFields['OWNER_ID'] > 0)
{
$res = CCalendarSect::GetList(array('arFilter' => array('CAL_TYPE' => $arFields['CAL_TYPE'],'OWNER_ID' => $arFields['OWNER_ID']), 'checkPermissions' => false));
if ($res && is_array($res) && isset($res[0]))
{
$sectionId = $res[0]['ID'];
}
elseif ($params['autoCreateSection'])
{
$defCalendar = CCalendarSect::CreateDefault(array(
'type' => $arFields['CAL_TYPE'],
'ownerId' => $arFields['OWNER_ID']
));
$sectionId = $defCalendar['ID'];
$params['bAffectToDav'] = false;
}
if ($sectionId > 0)
$arFields['SECTIONS'] = array($sectionId);
else
return false;
}
$bExchange = CCalendar::IsExchangeEnabled() && $arFields['CAL_TYPE'] == 'user';
$bCalDav = CCalendar::IsCalDAVEnabled() && $arFields['CAL_TYPE'] == 'user';
$bGoogleApi = CCalendar::isGoogleApiEnabled();
if ($params['bAffectToDav'] !== false && ($bExchange || $bCalDav || $bGoogleApi) && $sectionId > 0)
{
$res = CCalendarSync::DoSaveToDav(array(
'bCalDav' => $bCalDav,
'bExchange' => $bExchange,
'sectionId' => $sectionId
), $arFields, $curEvent);
if ($res !== true)
{
return CCalendar::ThrowError($res);
}
}
$params['arFields'] = $arFields;
$params['userId'] = $userId;
if (self::$ownerId != $arFields['OWNER_ID'] && self::$type != $arFields['CAL_TYPE'])
$params['path'] = self::GetPath($arFields['CAL_TYPE'], $arFields['OWNER_ID'], 1);
else
$params['path'] = self::$path;
if ($curEvent && in_array($params['recursionEditMode'], array('this', 'next')) &&
CCalendarEvent::CheckRecurcion($curEvent))
{
// Edit only current instance of the set of reccurent events
if ($params['recursionEditMode'] == 'this')
{
// 1. Edit current reccurent event: exclude current date
$excludeDates = CCalendarEvent::GetExDate($curEvent['EXDATE']);
$excludeDate = self::Date(self::Timestamp($params['currentEventDateFrom']), false);
$excludeDates[] = $excludeDate;
// Save current event
$id = CCalendar::SaveEvent(array(
'arFields' => array(
"ID" => $curEvent["ID"],
'EXDATE' => CCalendarEvent::SetExDate($excludeDates)
),
'recursionEditMode' => 'skip',
'silentErrorMode' => $params['silentErrorMode'],
'sendInvitations' => false,
'sendEditNotification' => false,
'userId' => $userId
));
// 2. Copy event with new changes, but without reccursion
$newParams = $params;
$newParams['sendEditNotification'] = false;
if (!$newParams['arFields']['MEETING']['REINVITE'])
{
$newParams['saveAttendeesStatus'] = true;
}
$newParams['arFields']['RECURRENCE_ID'] = $curEvent['RECURRENCE_ID'] ? $curEvent['RECURRENCE_ID'] : $newParams['arFields']['ID'];
unset($newParams['arFields']['ID']);
unset($newParams['arFields']['DAV_XML_ID']);
unset($newParams['arFields']['RRULE']);
unset($newParams['recursionEditMode']);
$newParams['arFields']['REMIND'] = $params['currentEvent']['REMIND'];
$fromTs = self::Timestamp($newParams['currentEventDateFrom']);
$currentFromTs = self::Timestamp($newParams['arFields']['DATE_FROM']);
$length = self::Timestamp($newParams['arFields']['DATE_TO']) - self::Timestamp($newParams['arFields']['DATE_FROM']);
if (!isset($newParams['arFields']['DATE_FROM']) || !isset($newParams['arFields']['DATE_TO']))
{
$length = $curEvent['DT_LENGTH'];
$currentFromTs = self::Timestamp($curEvent['DATE_FROM']);
}
$instanceDate = !isset($newParams['arFields']['DATE_FROM']) ||self::Date(self::Timestamp($curEvent['DATE_FROM']), false) == self::Date($currentFromTs, false);
if ($newParams['arFields']['SKIP_TIME'])
{
if ($instanceDate)
{
$newParams['arFields']['DATE_FROM'] = self::Date($fromTs, false);
$newParams['arFields']['DATE_TO'] = self::Date($fromTs + $length - CCalendar::GetDayLen(), false);
}
else
{
$newParams['arFields']['DATE_FROM'] = self::Date($currentFromTs, false);
$newParams['arFields']['DATE_TO'] = self::Date($currentFromTs + $length - CCalendar::GetDayLen(), false);
}
}
else
{
if ($instanceDate)
{
$newFromTs = self::DateWithNewTime($currentFromTs, $fromTs);
$newParams['arFields']['DATE_FROM'] = self::Date($newFromTs);
$newParams['arFields']['DATE_TO'] = self::Date($newFromTs + $length);
}
}
$eventMod = $curEvent;
$eventMod['DATE_FROM'] = $newParams['currentEventDateFrom'];
$commentXmlId = CCalendarEvent::GetEventCommentXmlId($eventMod);
$newParams['arFields']['RELATIONS'] = array('COMMENT_XML_ID' => $commentXmlId);
$result['recEventId'] = CCalendar::SaveEvent($newParams);
}
// Edit all next instances of the set of reccurent events
elseif($params['recursionEditMode'] == 'next')
{
$currentDateTimestamp = self::Timestamp($params['currentEventDateFrom']);
// Copy event with new changes
$newParams = $params;
$recId = $newParams['arFields']['RECURRENCE_ID'] = $curEvent['RECURRENCE_ID'] ? $curEvent['RECURRENCE_ID'] : $newParams['arFields']['ID'];
// Check if it's first instance of the series, so we shoudn't create another event
if (CCalendar::Date(self::Timestamp($curEvent['DATE_FROM']), false) == CCalendar::Date($currentDateTimestamp, false))
{
$newParams['recursionEditMode'] = 'skip';
}
else
{
// 1. Edit current reccurent event - finish it
$arFieldsCurrent = array(
"ID" => $curEvent["ID"],
"RRULE" => CCalendarEvent::ParseRRULE($curEvent['RRULE'])
);
$arFieldsCurrent['RRULE']['UNTIL'] = self::Date($currentDateTimestamp - self::GetDayLen(), false);
unset($arFieldsCurrent['RRULE']['~UNTIL']);
unset($arFieldsCurrent['RRULE']['COUNT']);
// Save current event
$id = CCalendar::SaveEvent(array(
'arFields' => $arFieldsCurrent,
'silentErrorMode' => $params['silentErrorMode'],
'recursionEditMode' => 'skip',
'sendInvitations' => false,
'sendEditNotification' => false,
'userId' => $userId
));
unset($newParams['arFields']['ID']);
unset($newParams['arFields']['DAV_XML_ID']);
unset($newParams['recursionEditMode']);
}
if (!$newParams['arFields']['MEETING']['REINVITE'])
{
$newParams['saveAttendeesStatus'] = true;
}
$currentFromTs = self::Timestamp($newParams['arFields']['DATE_FROM']);
$length = self::Timestamp($newParams['arFields']['DATE_TO']) - self::Timestamp($newParams['arFields']['DATE_FROM']);
if (!isset($newParams['arFields']['DATE_FROM']) || !isset($newParams['arFields']['DATE_TO']))
{
$length = $curEvent['DT_LENGTH'];
$currentFromTs = self::Timestamp($curEvent['DATE_FROM']);
}
$instanceDate = !isset($newParams['arFields']['DATE_FROM']) ||self::Date(self::Timestamp($curEvent['DATE_FROM']), false) == self::Date($currentFromTs, false);
if ($newParams['arFields']['SKIP_TIME'])
{
if ($instanceDate)
{
$newParams['arFields']['DATE_FROM'] = self::Date($currentDateTimestamp, false);
$newParams['arFields']['DATE_TO'] = self::Date($currentDateTimestamp + $length, false);
}
else
{
$newParams['arFields']['DATE_FROM'] = self::Date($currentFromTs, false);
$newParams['arFields']['DATE_TO'] = self::Date($currentFromTs + $length, false);
}
}
else
{
if ($instanceDate)
{
$newFromTs = self::DateWithNewTime($currentFromTs, $currentDateTimestamp);
$newParams['arFields']['DATE_FROM'] = self::Date($newFromTs);
$newParams['arFields']['DATE_TO'] = self::Date($newFromTs + $length);
}
}
if (isset($curEvent['EXDATE']) && $curEvent['EXDATE'] != '')
$newParams['arFields']['EXDATE'] = $curEvent['EXDATE'];
$result['recEventId'] = CCalendar::SaveEvent($newParams);
if ($recId)
{
$recRelatedEvents = CCalendarEvent::GetEventsByRecId($recId, false);
foreach($recRelatedEvents as $ev)
{
$evFromTs = CCalendar::Timestamp($ev['DATE_FROM']);
if($evFromTs > $currentDateTimestamp)
{
$newParams['arFields']['ID'] = $ev['ID'];
$newParams['arFields']['RRULE'] = CCalendarEvent::ParseRRULE($ev['RRULE']);
if ($newParams['arFields']['SKIP_TIME'])
{
$newParams['arFields']['DATE_FROM'] = self::Date($evFromTs, false);
$newParams['arFields']['DATE_TO'] = self::Date(CCalendar::Timestamp($ev['DATE_TO']), false);
}
else
{
$newFromTs = self::DateWithNewTime($currentFromTs, $evFromTs);
$newParams['arFields']['DATE_FROM'] = self::Date($newFromTs);
$newParams['arFields']['DATE_TO'] = self::Date($newFromTs + $length);
}
CCalendar::SaveEvent($newParams);
}
}
}
}
}
else
{
if ($params['recursionEditMode'] !== 'all')
$params['recursionEditMode'] = 'skip';
else
$params['recursionEditMode'] = '';
$id = CCalendarEvent::Edit($params);
if($id)
{
$UFs = $params['UF'];
if(isset($UFs) && count($UFs) > 0)
{
CCalendarEvent::UpdateUserFields($id, $UFs);
if($arFields['IS_MEETING'])
{
if(!empty($UFs['UF_WEBDAV_CAL_EVENT']))
{
$UF = $GLOBALS['USER_FIELD_MANAGER']->GetUserFields("CALENDAR_EVENT", $id, LANGUAGE_ID);
CCalendar::UpdateUFRights($UFs['UF_WEBDAV_CAL_EVENT'], $arFields['ATTENDEES_CODES'], $UF['UF_WEBDAV_CAL_EVENT']);
}
}
}
}
// Here we should select all events connected with edited via RECURRENCE_ID:
// It could be original source event (without RECURRENCE_ID) or sibling events
if ($curEvent && CCalendarEvent::CheckRecurcion($curEvent)
&& !$params['recursionEditMode']
&& !$params['arFields']['RECURRENCE_ID']
)
{
$events = array();
$recId = $curEvent['RECURRENCE_ID'] ? $curEvent['RECURRENCE_ID'] : $curEvent['ID'];
if ($curEvent['RECURRENCE_ID'] && $curEvent['RECURRENCE_ID'] !== $curEvent['ID'])
{
$topEvent = CCalendarEvent::GetById($curEvent['RECURRENCE_ID']);
if ($topEvent)
{
$events[] = $topEvent;
}
}
if ($recId)
{
$events_1 = CCalendarEvent::GetList(array('arFilter' => array('RECURRENCE_ID' => $recId), 'parseRecursion' => false, 'setDefaultLimit' => false));
if ($events_1)
$events = array_merge($events, $events_1);
}
foreach($events as $ev)
{
if ($ev['ID'] !== $curEvent['ID'])
{
$newParams = $params;
$newParams['arFields']['ID'] = $ev['ID'];
$newParams['arFields']['RECURRENCE_ID'] = $ev['RECURRENCE_ID'];
$newParams['arFields']['DAV_XML_ID'] = $ev['DAV_XML_ID'];
$newParams['arFields']['CAL_DAV_LABEL'] = $ev['CAL_DAV_LABEL'];
$newParams['arFields']['RRULE'] = CCalendarEvent::ParseRRULE($ev['RRULE']);
$newParams['recursionEditMode'] = 'skip';
$newParams['currentEvent'] = $ev;
$eventFromTs = self::Timestamp($ev['DATE_FROM']);
$currentFromTs = self::Timestamp($newParams['arFields']['DATE_FROM']);
$length = self::Timestamp($newParams['arFields']['DATE_TO']) - self::Timestamp($newParams['arFields']['DATE_FROM']);
if ($newParams['arFields']['SKIP_TIME'])
{
$newParams['arFields']['DATE_FROM'] = $ev['DATE_FROM'];
$newParams['arFields']['DATE_TO'] = self::Date($eventFromTs + $length, false);
}
else
{
$newFromTs = self::DateWithNewTime($currentFromTs, $eventFromTs);
$newParams['arFields']['DATE_FROM'] = self::Date($newFromTs);
$newParams['arFields']['DATE_TO'] = self::Date($newFromTs + $length);
}
if (isset($ev['EXDATE']) && $ev['EXDATE'] != '')
$newParams['arFields']['EXDATE'] = $ev['EXDATE'];
CCalendar::SaveEvent($newParams);
}
}
}
$arFields['ID'] = $id;
foreach(GetModuleEvents("calendar", "OnAfterCalendarEventEdit", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array('arFields' => $arFields, 'bNew' => $bNew, 'userId' => $userId));
}
self::SetSilentErrorMode($silentErrorModePrev);
$result['id'] = $id;
return $result;
}
public static function ThrowError($str)
{
if (self::$silentErrorMode)
return false;
global $APPLICATION;
echo '<!-- BX_EVENT_CALENDAR_ACTION_ERROR:'.$str.'-->';
return $APPLICATION->ThrowException($str);
}
public static function GetSectionForOwner($calType, $ownerId, $autoCreate = true)
{
return CCalendarSect::GetSectionForOwner($calType, $ownerId, $autoCreate);
}
public static function UpdateUFRights($files, $rights, $ufEntity = array())
{
global $USER;
static $arTasks = null;
if (!is_array($rights) || sizeof($rights) <= 0)
return false;
if ($files===null || $files===false)
return false;
if (!is_array($files))
$files = array($files);
if (sizeof($files) <= 0)
return false;
if (!\Bitrix\Main\Loader::includeModule('iblock') || !\Bitrix\Main\Loader::includeModule('webdav'))
return false;
$arFiles = array();
foreach($files as $id)
{
$id = intval($id);
if (intval($id) > 0)
$arFiles[] = $id;
}
if (sizeof($arFiles) <= 0)
return false;
if ($arTasks == null)
$arTasks = CWebDavIblock::GetTasks();
$arCodes = array();
foreach($rights as $value)
{
if (substr($value, 0, 2) === 'SG')
$arCodes[] = $value.'_K';
$arCodes[] = $value;
}
$arCodes = array_unique($arCodes);
$i=0;
$arViewRights = $arEditRights = array();
$curUserID = 'U'.$USER->GetID();
foreach($arCodes as $right)
{
if ($curUserID == $right) // do not override owner's rights
continue;
$key = 'n' . $i++;
$arViewRights[$key] = array(
'GROUP_CODE' => $right,
'TASK_ID' => $arTasks['R'],
);
}
$ibe = new CIBlockElement();
$dbWDFile = $ibe->GetList(array(), array('ID' => $arFiles, 'SHOW_NEW' => 'Y'), false, false, array('ID', 'NAME', 'SECTION_ID', 'IBLOCK_ID', 'WF_NEW'));
$iblockIds = array();
if ($dbWDFile)
{
while ($arWDFile = $dbWDFile->Fetch())
{
$id = $arWDFile['ID'];
if ($arWDFile['WF_NEW'] == 'Y')
$ibe->Update($id, array('BP_PUBLISHED' => 'Y'));
if (CIBlock::GetArrayByID($arWDFile['IBLOCK_ID'], "RIGHTS_MODE") === "E")
{
$ibRights = CWebDavIblock::_get_ib_rights_object('ELEMENT', $id, $arWDFile['IBLOCK_ID']);
$ibRights->SetRights(CWebDavTools::appendRights($ibRights, $arViewRights, $arTasks));
if(empty($iblockIds[$arWDFile['IBLOCK_ID']]))
$iblockIds[$arWDFile['IBLOCK_ID']] = $arWDFile['IBLOCK_ID'];
}
}
global $CACHE_MANAGER;
foreach ($iblockIds as $iblockId)
$CACHE_MANAGER->ClearByTag('iblock_id_' . $iblockId);
unset($iblockId);
}
}
public static function TempUser($TmpUser = false, $create = true, $ID = false)
{
global $USER;
if ($create && $TmpUser === false && (!$USER || !is_object($USER)))
{
$USER = new CUser;
if ($ID && intVal($ID) > 0)
$USER->Authorize(intVal($ID));
return $USER;
}
elseif (!$create && $USER && is_object($USER))
{
unset($USER);
return false;
}
return false;
}
public static function SaveSection($Params)
{
$type = isset($Params['arFields']['CAL_TYPE']) ? $Params['arFields']['CAL_TYPE'] : self::$type;
// Exchange
if ($Params['bAffectToDav'] !== false && CCalendar::IsExchangeEnabled(self::$ownerId) && $type == 'user')
{
$exchRes = true;
$ownerId = isset($Params['arFields']['OWNER_ID']) ? $Params['arFields']['OWNER_ID'] : self::$ownerId;
if(isset($Params['arFields']['ID']) && $Params['arFields']['ID'] > 0)
{
// Fetch section
//$oSect = CCalendarSect::GetById($Params['arFields']['ID']);
// For exchange we change only calendar name
//if ($oSect && $oSect['IS_EXCHANGE'] && $oSect['DAV_EXCH_CAL'] && $oSect["NAME"] != $Params['arFields']['NAME'])
// $exchRes = CDavExchangeCalendar::DoUpdateCalendar($ownerId, $oSect['DAV_EXCH_CAL'], $oSect['DAV_EXCH_MOD'], $Params['arFields']);
}
elseif($Params['arFields']['IS_EXCHANGE'])
{
$exchRes = CDavExchangeCalendar::DoAddCalendar($ownerId, $Params['arFields']);
}
if ($exchRes !== true)
{
if (!is_array($exchRes) || !array_key_exists("XML_ID", $exchRes))
return CCalendar::ThrowError(CCalendar::CollectExchangeErrors($exchRes));
// // It's ok, we successfuly save event to exchange calendar - and save it to DB
$Params['arFields']['DAV_EXCH_CAL'] = $exchRes['XML_ID'];
$Params['arFields']['DAV_EXCH_MOD'] = $exchRes['MODIFICATION_LABEL'];
}
}
// Save here
$ID = CCalendarSect::Edit($Params);
CCalendar::ClearCache(array('section_list', 'event_list'));
return $ID;
}
public static function ClearCache($arPath = false)
{
global $CACHE_MANAGER;
$CACHE_MANAGER->ClearByTag("CALENDAR_EVENT_LIST");
if ($arPath === false)
$arPath = array(
'access_tasks',
'type_list',
'section_list',
'attendees_list',
'event_list'
);
elseif (!is_array($arPath))
$arPath = array($arPath);
if (is_array($arPath) && count($arPath) > 0)
{
$cache = new CPHPCache;
foreach($arPath as $path)
if ($path != '')
$cache->CleanDir(CCalendar::CachePath().$path);
}
}
public static function CachePath()
{
return self::$cachePath;
}
// * * * * * * * * * * * * CalDAV + Exchange * * * * * * * * * * * * * * * *
public static function SyncCalendarItems($connectionType, $calendarId, $arCalendarItems)
{
self::$silentErrorMode = true;
// $arCalendarItems:
//Array(
// [0] => Array(
// [XML_ID] => AAATAGFudGlfYn...
// [MODIFICATION_LABEL] => DwAAABYAAA...
// )
// [1] => Array(
// [XML_ID] => AAATAGFudGlfYnVn...
// [MODIFICATION_LABEL] => DwAAABYAAAAQ...
// )
//)
list($sectionId, $entityType, $entityId) = $calendarId;
$entityType = strtolower($entityType);
if ($connectionType == 'exchange')
$xmlIdField = "DAV_EXCH_LABEL";
elseif ($connectionType == 'caldav')
$xmlIdField = "CAL_DAV_LABEL";
else
return array();
$arCalendarItemsMap = array();
foreach ($arCalendarItems as $value)
$arCalendarItemsMap[$value["XML_ID"]] = $value["MODIFICATION_LABEL"];
$arModified = array();
$eventsList = CCalendarEvent::GetList(
array(
'arFilter' => array(
'CAL_TYPE' => $entityType,
'OWNER_ID' => $entityId,
'SECTION' => $sectionId
),
'getUserfields' => false,
'parseRecursion' => false,
'fetchAttendees' => false,
'fetchMeetings' => false,
'userId' => $entityType == 'user' ? $entityId : '0'
)
);
foreach ($eventsList as $event)
{
if (isset($arCalendarItemsMap[$event["DAV_XML_ID"]]))
{
if ($event[$xmlIdField] != $arCalendarItemsMap[$event["DAV_XML_ID"]])
$arModified[$event["DAV_XML_ID"]] = $event["ID"];
unset($arCalendarItemsMap[$event["DAV_XML_ID"]]);
}
else
{
if ($connectionType == 'exchange')
{
if ($event['ID'] == $event['PARENT_ID'])
{
self::DeleteCalendarEvent($calendarId, $event["ID"], self::$userId, $event);
}
}
else
{
self::DeleteCalendarEvent($calendarId, $event["ID"], self::$userId, $event);
}
}
}
$arResult = array();
foreach ($arCalendarItems as $value)
{
if (array_key_exists($value["XML_ID"], $arModified))
{
$arResult[] = array(
"XML_ID" => $value["XML_ID"],
"ID" => $arModified[$value["XML_ID"]]
);
}
}
foreach ($arCalendarItemsMap as $key => $value)
{
$arResult[] = array(
"XML_ID" => $key,
"ID" => 0
);
}
self::$silentErrorMode = false;
return $arResult;
}
public static function DeleteCalendarEvent($calendarId, $eventId, $userId, $oEvent = false)
{
self::$silentErrorMode = true;
list($sectionId, $entityType, $entityId) = $calendarId;
$res = CCalendarEvent::Delete(array(
'id' => $eventId,
'userId' => $userId,
'bMarkDeleted' => true,
'Event' => $oEvent
));
self::$silentErrorMode = false;
return $res;
}
// Called from CalDav sync functions and from CCalendar::SyncCalendarItems
public static function SyncClearCache()
{
}
public static function Color($color = '', $defaultColor = true)
{
if ($color != '')
{
$color = ltrim(trim(preg_replace('/[^\d|\w]/', '', $color)), "#");
if (strlen($color) > 6)
$color = substr($color, 0, 6);
elseif(strlen($color) < 6)
$color = '';
}
$color = '#'.$color;
// Default color
$DEFAULT_COLOR = '#9dcf00';
if ($color == '#')
{
if ($defaultColor === true)
$color = $DEFAULT_COLOR;
elseif($defaultColor)
$color = $defaultColor;
else
$color = '';
}
return $color;
}
public static function ConvertDayInd($i)
{
return $i == 0 ? 6 : $i - 1;
}
// return array('bAccess' => true/false, 'bReadOnly' => true/false, 'privateStatus' => 'time'/'title');
public static function _fixTimestamp($timestamp)
{
if (date("Z") !== date("Z", $timestamp))
{
$timestamp += (date("Z") - date("Z", $timestamp));
}
return $timestamp;
}
// Called from CalDav, Exchange methods
public static function FormatTime($h = 0, $m = 0)
{
$m = intVal($m);
if ($m > 59)
$m = 59;
elseif ($m < 0)
$m = 0;
if ($m < 10)
$m = '0'.$m;
$h = intVal($h);
if ($h > 24)
$h = 24;
if ($h < 0)
$h = 0;
if (IsAmPmMode())
{
$ampm = 'am';
if ($h == 0)
{
$h = 12;
}
else if ($h == 12)
{
$ampm = 'pm';
}
else if ($h > 12)
{
$ampm = 'pm';
$h -= 12;
}
$res = $h.':'.$m.' '.$ampm;
}
else
{
$res = (($h < 10) ? '0' : '').$h.':'.$m;
}
return $res;
}
// Called from SaveEvent: try to save event in Exchange or to Dav Server and if it's Ok, return true
public static function GetUserId()
{
if (!self::$userId)
self::$userId = self::GetCurUserId();
return self::$userId;
}
public static function GetReadonlyMode()
{
return self::$readOnly;
}
// Called from CalDav sync methods
public static function GetUserAvatarSrc($user = array(), $params = array())
{
if (!is_array($user) && intVal($user) > 0)
$user = self::GetUser($user);
$avatar_src = self::GetUserAvatar($user, $params);
if ($avatar_src === false)
$avatar_src = '/bitrix/images/1.gif';
return $avatar_src;
}
public static function GetUserAvatar($user = array(), $params = array())
{
if (!is_array($user) && intVal($user) > 0)
$user = self::GetUser($user);
if (!empty($user["PERSONAL_PHOTO"]))
{
if (empty($params['AVATAR_SIZE']))
{
$params['AVATAR_SIZE'] = 42;
}
$arFileTmp = CFile::ResizeImageGet(
$user["PERSONAL_PHOTO"],
array('width' => $params['AVATAR_SIZE'], 'height' => $params['AVATAR_SIZE']),
BX_RESIZE_IMAGE_EXACT,
false
);
$avatar_src = $arFileTmp['src'];
}
else
{
$avatar_src = false;
}
return $avatar_src;
}
public static function GetUserUrl($userId = 0, $pathToUser = "")
{
if ($pathToUser == '')
{
if (self::$pathToUser == '')
{
if (empty(self::$pathesForSite))
self::$pathesForSite = self::GetPathes(SITE_ID);
self::$pathToUser = self::$pathesForSite['path_to_user'];
}
$pathToUser = self::$pathToUser;
}
return CUtil::JSEscape(CComponentEngine::MakePathFromTemplate($pathToUser, array("user_id" => $userId, "USER_ID" => $userId)));
}
public static function GetAccessTasksByName($binging = 'calendar_section', $name = 'calendar_denied')
{
$arTasks = CCalendar::GetAccessTasks($binging);
foreach($arTasks as $id => $task)
if ($task['name'] == $name)
return $id;
return false;
}
public static function GetAccessTasks($binging = 'calendar_section')
{
\Bitrix\Main\Localization\Loc::loadLanguageFile($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/calendar/admin/task_description.php");
if (is_array(self::$arAccessTask[$binging]))
return self::$arAccessTask[$binging];
$bIntranet = self::IsIntranetEnabled();
$arTasks = Array();
$res = CTask::GetList(Array('ID' => 'asc'), Array('MODULE_ID' => 'calendar', 'BINDING' => $binging));
while($arRes = $res->Fetch())
{
if (!$bIntranet && (strtolower($arRes['NAME']) == 'calendar_view_time' || strtolower($arRes['NAME']) == 'calendar_view_title'))
continue;
$name = '';
if ($arRes['SYS'])
$name = Loc::getMessage('TASK_NAME_'.strtoupper($arRes['NAME']));
if (strlen($name) == 0)
$name = $arRes['NAME'];
$arTasks[$arRes['ID']] = array(
'name' => $arRes['NAME'],
'title' => $name
);
}
self::$arAccessTask[$binging] = $arTasks;
return $arTasks;
}
public static function PushAccessNames($arCodes = array())
{
foreach($arCodes as $code)
{
if (!array_key_exists($code, self::$accessNames))
{
self::$accessNames[$code] = null;
}
}
}
public static function SetLocation($old = '', $new = '', $params = array())
{
$tzEnabled = CTimeZone::Enabled();
if ($tzEnabled)
{
CTimeZone::Disable();
}
// *** ADD MEETING ROOM ***
$locOld = CCalendar::ParseLocation($old);
$locNew = CCalendar::ParseLocation($new);
CCalendar::GetSettings(array('request' => false));
$res = $locNew['mrid'] ? $locNew['str'] : $new;
$RMiblockId = isset($params['RMiblockId']) ? $params['RMiblockId'] : self::$settings['rm_iblock_id'];
// If not allowed
if ($RMiblockId && $locOld['mrid'] !== false && $locOld['mrevid'] !== false) // Release MR
{
CCalendar::ReleaseMeetingRoom(array(
'mrevid' => $locOld['mrevid'],
'mrid' => $locOld['mrid'],
'RMiblockId' => $RMiblockId
));
}
if ($locOld['room_id'] !== false && $locOld['room_event_id'] !== false) // Release MR
{
CCalendar::ReleaseLocation($locOld);
}
if ($locNew['mrid'] !== false) // Reserve MR
{
$mrevid = false;
if ($params['bRecreateReserveMeetings'])
{
$mrevid = CCalendar::ReserveMeetingRoom(array(
'RMiblockId' => $RMiblockId,
'mrid' => $locNew['mrid'],
'dateFrom' => $params['dateFrom'],
'dateTo' => $params['dateTo'],
'name' => $params['name'],
'description' => Loc::getMessage('EC_RESERVE_FOR_EVENT').': '.$params['name'],
'persons' => $params['persons'],
'members' => $params['attendees']
));
}
elseif(is_array($locNew) && $locNew['mrevid'] !== false)
{
$mrevid = $locNew['mrevid'];
}
$locNew = ($mrevid && $mrevid != 'reserved' && $mrevid != 'expire' && $mrevid > 0) ? 'ECMR_'.$locNew['mrid'].'_'.$mrevid : '';
}
elseif($locNew['room_id'])
{
$roomEventId = CCalendarLocation::reserveRoom(array(
'room_id' => $locNew['room_id'],
'room_event_id' => false,
'parentParams' => $params['parentParams']
));
$locNew = $roomEventId ? 'calendar_'.$locNew['room_id'].'_'.$roomEventId : '';
}
else
{
$locNew = $locNew['str'];
}
if ($locNew)
{
$res = $locNew;
}
if ($tzEnabled)
{
CTimeZone::Enable();
}
return $res;
}
public static function ReserveMeetingRoom($params)
{
$tst = MakeTimeStamp($params['dateTo']);
if (date("H:i", $tst) == '00:00')
$params['dateTo'] = CIBlockFormatProperties::DateFormat(self::DFormat(true), $tst + (23 * 60 + 59) * 60);
CCalendar::GetSettings(array('request' => false));
$params['RMiblockId'] = (isset($params['RMiblockId']) && $params['RMiblockId']) ? $params['RMiblockId'] : self::$settings['rm_iblock_id'];
$check = CCalendar::CheckMeetingRoom($params);
if ($check !== true)
return $check;
$arFields = array(
"IBLOCK_ID" => $params['RMiblockId'],
"IBLOCK_SECTION_ID" => $params['mrid'],
"NAME" => $params['name'],
"DATE_ACTIVE_FROM" => $params['dateFrom'],
"DATE_ACTIVE_TO" => $params['dateTo'],
"CREATED_BY" => CCalendar::GetCurUserId(),
"DETAIL_TEXT" => $params['description'],
"PROPERTY_VALUES" => array(
"UF_PERSONS" => $params['persons'],
"PERIOD_TYPE" => 'NONE'
),
"ACTIVE" => "Y"
);
$bs = new CIBlockElement;
$id = $bs->Add($arFields);
// Hack: reserve meeting calendar based on old calendar's cache
$cache = new CPHPCache;
$cache->CleanDir('event_calendar/');
$cache->CleanDir('event_calendar/events/');
$cache->CleanDir('event_calendar/events/'.$params['RMiblockId']);
return $id;
}
public static function CheckMeetingRoom($Params)
{
$fromDateTime = MakeTimeStamp($Params['dateFrom']);
$toDateTime = MakeTimeStamp($Params['dateTo']);
$arFilter = array(
"ACTIVE" => "Y",
"IBLOCK_ID" => $Params['RMiblockId'],
"SECTION_ID" => $Params['mrid'],
"<DATE_ACTIVE_FROM" => $Params['dateTo'],
">DATE_ACTIVE_TO" => $Params['dateFrom'],
"PROPERTY_PERIOD_TYPE" => "NONE",
);
if ($Params['mrevid_old'] > 0)
$arFilter["!=ID"] = $Params['mrevid_old'];
$dbElements = CIBlockElement::GetList(array("DATE_ACTIVE_FROM" => "ASC"), $arFilter, false, false, array('ID'));
if ($arElements = $dbElements->GetNext())
return 'reserved';
include_once($_SERVER['DOCUMENT_ROOT']."/bitrix/components/bitrix/intranet.reserve_meeting/init.php");
$arPeriodicElements = __IRM_SearchPeriodic($fromDateTime, $toDateTime, $Params['RMiblockId'], $Params['mrid']);
for ($i = 0, $l = count($arPeriodicElements); $i < $l; $i++)
if (!$Params['mrevid_old'] || $arPeriodicElements[$i]['ID'] != $Params['mrevid_old'])
return 'reserved';
return true;
}
public static function GetOuterUrl()
{
return self::$outerUrl;
}
public static function ManageConnections($arConnections = array())
{
global $APPLICATION;
$bSync = false;
$l = count($arConnections);
for ($i = 0; $i < $l; $i++)
{
$con = $arConnections[$i];
$conId = intVal($con['id']);
if ($conId <= 0) // It's new connection
{
if ($con['del'] != 'Y')
{
if(!CCalendar::CheckCalDavUrl($con['link'], $con['user_name'], $con['pass']))
return Loc::getMessage("EC_CALDAV_URL_ERROR");
CDavConnection::Add(array(
"ENTITY_TYPE" => 'user',
"ENTITY_ID" => self::$ownerId,
"ACCOUNT_TYPE" => 'caldav',
"NAME" => $con['name'],
"SERVER" => $con['link'],
"SERVER_USERNAME" => $con['user_name'],
"SERVER_PASSWORD" => $con['pass'])
);
$bSync = true;
}
}
elseif ($con['del'] != 'Y') // Edit connection
{
$arFields = array(
"NAME" => $con['name'],
"SERVER" => $con['link'],
"SERVER_USERNAME" => $con['user_name']
);
if ($con['pass'] !== 'bxec_not_modify_pass')
$arFields["SERVER_PASSWORD"] = $con['pass'];
$resCon = CDavConnection::GetList(array("ID" => "ASC"), array("ID" => $conId));
if ($arCon = $resCon->Fetch())
{
if($arCon['ACCOUNT_TYPE'] !== 'caldav_google_oauth' && $arCon['ACCOUNT_TYPE'] !== 'google_api_oauth')
{
CDavConnection::Update($conId, $arFields);
}
}
if (is_array($con['sections']))
{
foreach ($con['sections'] as $sectId => $active)
{
$sectId = intVal($sectId);
if(CCalendar::IsPersonal() || CCalendarSect::CanDo('calendar_edit_section', $sectId, self::$userId))
{
CCalendarSect::Edit(array('arFields' => array("ID" => $sectId, "ACTIVE" => $active == "Y" ? "Y" : "N")));
}
}
}
$bSync = true;
}
else
{
CCalendar::RemoveConnection(array('id' => $conId, 'del_calendars' => $con['del_calendars']));
}
}
if($err = $APPLICATION->GetException())
{
return $err->GetString();
}
if ($bSync)
CDavGroupdavClientCalendar::DataSync("user", self::$ownerId);
$res = CDavConnection::GetList(
array("ID" => "DESC"),
array(
"ENTITY_TYPE" => "user",
"ENTITY_ID" => self::$ownerId
),
false,
false
);
while($arCon = $res->Fetch())
{
if ($arCon['ACCOUNT_TYPE'] == 'caldav_google_oauth' || $arCon['ACCOUNT_TYPE'] == 'caldav')
{
if(strpos($arCon['LAST_RESULT'], "[200]") === false)
return Loc::getMessage('EC_CALDAV_CONNECTION_ERROR', array('#CONNECTION_NAME#' => $arCon['NAME'], '#ERROR_STR#' => $arCon['LAST_RESULT']));
}
}
return true;
}
public static function CheckCalDavUrl($url, $username, $password)
{
$arServer = parse_url($url);
// Mantis #71074
if (strpos(strtolower($_SERVER['SERVER_NAME']), strtolower($arServer['host'])) !== false || strpos(strtolower($_SERVER['HTTP_HOST']), strtolower($arServer['host'])) !== false)
return false;
return CDavGroupdavClientCalendar::DoCheckCalDAVServer($arServer["scheme"], $arServer["host"], $arServer["port"], $username, $password, $arServer["path"]);
}
public static function RemoveConnection($connection = array())
{
// Clean sections
$res = CCalendarSect::GetList(array('arFilter' => array('CAL_TYPE' => 'user', 'OWNER_ID' => self::$ownerId, 'CAL_DAV_CON' => $connection['id'])));
$pushChannelResult = PushTable::getList(array(
'select' => array('*'),
'filter' => array('ENTITY_TYPE' => 'CONNECTION', 'ENTITY_ID' => $connection['id'])
));
if ($row = $pushChannelResult->fetch())
{
\Bitrix\Calendar\Sync\GoogleApiPush::stopChannel($row, $connection['ENTITY_ID']);
}
foreach ($res as $sect)
{
if ($connection['del_calendars'] == 'Y') // Delete all callendars from this connection
{
$pushChannelResult = PushTable::getList(array(
'select' => array('*'),
'filter' => array('ENTITY_TYPE' => 'SECTION', 'ENTITY_ID' => $sect['ID'])
));
if ($row = $pushChannelResult->fetch())
{
\Bitrix\Calendar\Sync\GoogleApiPush::stopChannel($row, $sect['OWNER_ID']);
}
CCalendarSect::Delete($sect['ID'], false);
}
else
CCalendarSect::Edit(array('arFields' => array("ID" => $sect['ID'], "CAL_DAV_CON" => '', 'CAL_DAV_CAL' => '', 'CAL_DAV_MOD' => '')));
}
// Delete Google oauth token if it's google oauth caldav connection
$resCon = CDavConnection::GetList(array("ID" => "ASC"), array("ID" => $connection['id']));
if ($arCon = $resCon->Fetch())
{
$googleCalDavStatus = CCalendarSync::GetGoogleCalendarConnection();
if($googleCalDavStatus['googleCalendarPrimaryId'] && $arCon['ACCOUNT_TYPE'] == 'caldav_google_oauth')
{
$serverPath = 'https://apidata.googleusercontent.com/caldav/v2/' . $googleCalDavStatus['googleCalendarPrimaryId'] . '/user';
}
elseif ($googleCalDavStatus['googleCalendarPrimaryId'] && $arCon['ACCOUNT_TYPE'] == 'google_api_oauth')
{
$serverPath = 'https://www.googleapis.com/calendar/v3';
}
if ($arCon['SERVER'] == $serverPath)
{
if (\Bitrix\Main\Loader::includeModule('socialservices'))
{
$client = new CSocServGoogleOAuth(CCalendar::GetCurUserId());
$client->getEntityOAuth()->addScope(array('https://www.googleapis.com/auth/calendar', 'https://www.googleapis.com/auth/calendar.readonly'));
// Delete stored tokens
$client->getEntityOAuth()->deleteStorageTokens();
}
}
}
// Delete dav connections
CDavConnection::Delete($connection['id']);
}
public static function GetTypeByExternalId($externalId = false)
{
if ($externalId)
{
$res = CCalendarType::GetList(array('arFilter' => array('EXTERNAL_ID' => $externalId)));
if ($res && $res[0])
return $res[0]['XML_ID'];
}
return false;
}
public static function SetCurUserMeetingSection($userMeetingSection)
{
self::$userMeetingSection = $userMeetingSection;
}
public static function CacheTime($time = false)
{
if ($time !== false)
self::$cacheTime = $time;
return self::$cacheTime;
}
public static function _ParseHack(&$text, &$TextParser)
{
$text = preg_replace(array("/\</is".BX_UTF_PCRE_MODIFIER, "/\>/is".BX_UTF_PCRE_MODIFIER),array('<', '>'),$text);
$text = preg_replace("/\<br\s*\/*\>/is".BX_UTF_PCRE_MODIFIER,"", $text);
$text = preg_replace("/\<(\w+)[^>]*\>(.+?)\<\/\\1[^>]*\>/is".BX_UTF_PCRE_MODIFIER,"\\2",$text);
$text = preg_replace("/\<*\/li\>/is".BX_UTF_PCRE_MODIFIER,"", $text);
$text = str_replace(array("<", ">"),array("<", ">"),$text);
$TextParser->allow = array();
return true;
}
public static function IsSocnetAdmin()
{
if (!isset(self::$bCurUserSocNetAdmin))
self::$bCurUserSocNetAdmin = self::IsSocNet() && CSocNetUser::IsCurrentUserModuleAdmin();
return self::$bCurUserSocNetAdmin;
}
public static function GetMaxDate()
{
if (!self::$CALENDAR_MAX_DATE)
{
$date = new DateTime();
$date->setDate(2038, 1, 1);
self::$CALENDAR_MAX_DATE = self::Date($date->getTimestamp(), false);
}
return self::$CALENDAR_MAX_DATE;
}
public static function GetMinDate()
{
if (!self::$CALENDAR_MIN_DATE)
{
$date = new DateTime();
$date->setDate(1970, 1, 1);
self::$CALENDAR_MIN_DATE = self::Date($date->getTimestamp(), false);
}
return self::$CALENDAR_MIN_DATE;
}
public static function GetDestinationUsers($codes, $fetchUsers = false)
{
if (!Main\Loader::includeModule('socialnetwork'))
{
return array();
}
$users = \CSocNetLogDestination::getDestinationUsers($codes, $fetchUsers);
if ($fetchUsers)
{
for ($i = 0, $l = count($users); $i < $l; $i++)
{
$users[$i]['FORMATTED_NAME'] = CCalendar::GetUserName($users[$i]);
}
}
return $users;
}
public static function GetAttendeesMessage($cnt = 0)
{
if (
($cnt % 100) > 10
&& ($cnt % 100) < 20
)
$suffix = 5;
else
$suffix = $cnt % 10;
return Loc::getMessage("EC_ATTENDEE_".$suffix, Array("#NUM#" => $cnt));
}
public static function GetMoreAttendeesMessage($cnt = 0)
{
if (
($cnt % 100) > 10
&& ($cnt % 100) < 20
)
$suffix = 5;
else
$suffix = $cnt % 10;
return Loc::getMessage("EC_ATTENDEE_MORE_".$suffix, Array("#NUM#" => $cnt));
}
public static function GetFormatedDestination($codes = array())
{
$ac = CSocNetLogTools::FormatDestinationFromRights($codes, array(
"CHECK_PERMISSIONS_DEST" => "Y",
"DESTINATION_LIMIT" => 100000,
"NAME_TEMPLATE" => "#NAME# #LAST_NAME#",
"PATH_TO_USER" => "/company/personal/user/#user_id#/",
));
return $ac;
}
public static function GetFromToHtml($fromTs = false, $toTs = false, $skipTime = false, $dtLength = 0, $forRrule = false)
{
if (intVal($fromTs) != $fromTs)
{
$fromTs = self::Timestamp($fromTs);
}
if (intVal($toTs) != $toTs)
{
$toTs = self::Timestamp($toTs);
}
if ($toTs < $fromTs)
{
$toTs = $fromTs;
}
// Formats
$formatShort = CCalendar::DFormat(false);
$formatFull = CCalendar::DFormat(true);
$formatTime = str_replace($formatShort, '', $formatFull);
$formatTime = $formatTime == $formatFull ? "H:i" : str_replace(':s', '', $formatTime);
$html = '';
$formatFull = str_replace(':s', '', $formatFull);
if ($skipTime)
{
if ($dtLength == self::DAY_LENGTH || !$dtLength) // One full day event
{
if (!$forRrule)
{
$html = FormatDate(array(
"tommorow" => "tommorow",
"today" => "today",
"yesterday" => "yesterday",
"-" => $formatShort,
"" => $formatShort,
), $fromTs, time() + CTimeZone::GetOffset());
$html .= ', ';
}
$html .= Loc::getMessage('EC_VIEW_FULL_DAY');
}
else // Event for several days
{
$from = FormatDate(array(
"tommorow" => "tommorow",
"today" => "today",
"yesterday" => "yesterday",
"-" => $formatShort,
"" => $formatShort,
), $fromTs, time() + CTimeZone::GetOffset());
$to = FormatDate(array(
"tommorow" => "tommorow",
"today" => "today",
"yesterday" => "yesterday",
"-" => $formatShort,
"" => $formatShort,
), $toTs - self::DAY_LENGTH, time() + CTimeZone::GetOffset());
$html = Loc::getMessage('EC_VIEW_DATE_FROM_TO', array('#DATE_FROM#' => $from, '#DATE_TO#' => $to));
}
}
else
{
// Event during one day
if(date('dmY', $fromTs) == date('dmY', $toTs))
{
if (!$forRrule)
{
$html = FormatDate(array(
"tommorow" => "tommorow",
"today" => "today",
"yesterday" => "yesterday",
"-" => $formatShort,
"" => $formatShort,
), $fromTs, time() + CTimeZone::GetOffset());
$html .= ', ';
}
$html .= Loc::getMessage('EC_VIEW_TIME_FROM_TO_TIME', array('#TIME_FROM#' => FormatDate($formatTime, $fromTs), '#TIME_TO#' => FormatDate($formatTime, $toTs)));
}
else
{
$html = Loc::getMessage('EC_VIEW_DATE_FROM_TO', array('#DATE_FROM#' => FormatDate($formatFull, $fromTs, time() + CTimeZone::GetOffset()), '#DATE_TO#' => FormatDate($formatFull, $toTs, time() + CTimeZone::GetOffset())));
}
}
return $html;
}
public static function GetSocNetDestination($user_id = false, $selected = array(), $userList = array())
{
if (!\Bitrix\Main\Loader::includeModule("socialnetwork"))
{
return false;
}
global $CACHE_MANAGER;
if (!is_array($selected))
{
$selected = array();
}
if (method_exists('CSocNetLogDestination','GetDestinationSort'))
{
$DESTINATION = array(
'LAST' => array(),
'DEST_SORT' => CSocNetLogDestination::GetDestinationSort(array("DEST_CONTEXT" => "CALENDAR"))
);
CSocNetLogDestination::fillLastDestination($DESTINATION['DEST_SORT'], $DESTINATION['LAST']);
}
else
{
$DESTINATION = array(
'LAST' => array(
'SONETGROUPS' => CSocNetLogDestination::GetLastSocnetGroup(),
'DEPARTMENT' => CSocNetLogDestination::GetLastDepartment(),
'USERS' => CSocNetLogDestination::GetLastUser()
)
);
}
if (!$user_id)
$user_id = CCalendar::GetCurUserId();
$cacheTtl = defined("BX_COMP_MANAGED_CACHE") ? 3153600 : 3600*4;
$cacheId = 'calendar_dest_'.$user_id;
$cacheDir = '/calendar/socnet_destination/'.SITE_ID.'/'.$user_id;
$obCache = new CPHPCache;
if($obCache->InitCache($cacheTtl, $cacheId, $cacheDir))
{
$DESTINATION['SONETGROUPS'] = $obCache->GetVars();
}
else
{
$obCache->StartDataCache();
$DESTINATION['SONETGROUPS'] = CSocNetLogDestination::GetSocnetGroup(Array('features' => array("calendar", array("view"))));
if(defined("BX_COMP_MANAGED_CACHE"))
{
$CACHE_MANAGER->StartTagCache($cacheDir);
foreach($DESTINATION['SONETGROUPS'] as $val)
{
$CACHE_MANAGER->RegisterTag("sonet_features_G_".$val["entityId"]);
$CACHE_MANAGER->RegisterTag("sonet_group_".$val["entityId"]);
}
$CACHE_MANAGER->RegisterTag("sonet_user2group_U".$user_id);
$CACHE_MANAGER->EndTagCache();
}
$obCache->EndDataCache($DESTINATION['SONETGROUPS']);
}
$destinationUserList = Array();
$DESTINATION['SELECTED'] = Array();
if (!empty($userList))
{
foreach ($userList as $userId)
{
$DESTINATION['SELECTED']['U'.$userId] = "users";
$DESTINATION['LAST']['USERS']['U'.$userId] = 'U'.$userId;
}
}
foreach ($selected as $ind => $code)
{
if (substr($code, 0 , 2) == 'DR')
{
$DESTINATION['SELECTED'][$code] = "department";
}
elseif (substr($code, 0 , 2) == 'UA')
{
$DESTINATION['SELECTED'][$code] = "groups";
}
elseif (substr($code, 0 , 2) == 'SG')
{
$DESTINATION['SELECTED'][$code] = "sonetgroups";
}
elseif (substr($code, 0 , 1) == 'U')
{
$DESTINATION['SELECTED'][$code] = "users";
$destinationUserList[] = intVal(str_replace('U', '', $code));
}
}
// intranet structure
$arStructure = CSocNetLogDestination::GetStucture();
$DESTINATION['DEPARTMENT'] = $arStructure['department'];
$DESTINATION['DEPARTMENT_RELATION'] = $arStructure['department_relation'];
$DESTINATION['DEPARTMENT_RELATION_HEAD'] = $arStructure['department_relation_head'];
if (\Bitrix\Main\Loader::includeModule('extranet') && !CExtranet::IsIntranetUser())
{
$DESTINATION['EXTRANET_USER'] = 'Y';
$DESTINATION['USERS'] = CSocNetLogDestination::GetExtranetUser();
}
else
{
if (is_array($DESTINATION['LAST']['USERS']))
{
foreach ($DESTINATION['LAST']['USERS'] as $value)
{
$destinationUserList[] = intVal(str_replace('U', '', $value));
}
}
if (!empty($userList))
{
$destinationUserList = array_unique(array_merge($destinationUserList, $userList));
}
$DESTINATION['EXTRANET_USER'] = 'N';
$DESTINATION['USERS'] = CSocNetLogDestination::GetUsers(Array('id' => $destinationUserList));
}
$users = array();
foreach ($DESTINATION['USERS'] as $key => $entry)
{
if ($entry['isExtranet'] == 'N')
$users[$key] = $entry;
}
$DESTINATION['USERS'] = $users;
return $DESTINATION;
}
public static function SaveUserTimezoneName($user, $tzName = '')
{
if (!is_array($user) && intVal($user) > 0)
$user = self::GetUser($user, true);
CUserOptions::SetOption("calendar", "timezone".self::GetCurrentOffsetUTC($user['ID']), $tzName, false, $user['ID']);
}
public static function CheckOffsetForTimezone($timezone, $offset, $date = false)
{
return true;
}
public static function GetOffsetUTC($userId = false, $dateTimestamp)
{
if (!$userId && self::$userId)
$userId = self::$userId;
$tzName = self::GetUserTimezoneName($userId);
if ($tzName)
{
$offset = self::GetTimezoneOffset($tzName, $dateTimestamp);
}
else
{
$offset = date("Z", $dateTimestamp) + CCalendar::GetOffset($userId);
}
return intVal($offset);
}
public static function OnSocNetGroupDelete($groupId)
{
$groupId = intVal($groupId);
if ($groupId > 0)
{
$res = CCalendarSect::GetList(
array(
'arFilter' => array(
'CAL_TYPE' => 'group',
'OWNER_ID' => $groupId
),
'checkPermissions' => false
)
);
foreach($res as $sect)
{
CCalendarSect::Delete($sect['ID'], false);
}
}
return true;
}
/**
* Handles last caldav activity from mobile devices
*
* @param \Bitrix\Main\Event $event Event.
* @return null
*/
public static function OnDavCalendarSync(\Bitrix\Main\Event $event)
{
$calendarId = $event->getParameter('id');
$userAgent = strtolower($event->getParameter('agent'));
$agent = false;
list($sectionId, $entityType, $entityId) = $calendarId;
static $arAgentsMap = array(
'android' => 'android', // Android/iOS CardDavBitrix24
'iphone' => 'iphone', // Apple iPhone iCal
'davkit' => 'mac', // Apple iCal
'mac os' => 'mac', // Apple iCal (Mac Os X > 10.8)
'mac_os_x' => 'mac', // Apple iCal (Mac Os X > 10.8)
'mac+os+x' => 'mac', // Apple iCal (Mac Os X > 10.10)
'dataaccess' => 'iphone', // Apple addressbook iPhone
//'sunbird' => 'sunbird', // Mozilla Sunbird
'ios' => 'iphone'
);
foreach ($arAgentsMap as $pattern => $name)
{
if (strpos($userAgent, $pattern) !== false)
{
$agent = $name;
break;
}
}
if ($entityType == 'user' && $agent)
{
self::SaveSyncDate($entityId, $agent);
}
}
/**
* Saves date of last successful sync
*
* @param int $userId User Id
* @param string $syncType Type of synchronization.
* @param string $date Date of synchronization.
* @return null
*/
public static function SaveSyncDate($userId, $syncType, $date = false)
{
if ($date === false)
$date = self::Date(time());
$syncTypes = array('iphone', 'android', 'mac', 'exchange', 'outlook', 'office365');
if (in_array($syncType, $syncTypes))
{
CUserOptions::SetOption("calendar", "last_sync_".$syncType, $date, false, $userId);
}
}
public static function OnExchangeCalendarSync(\Bitrix\Main\Event $event)
{
self::SaveSyncDate($event->getParameter('userId'), 'exchange');
}
public static function ClearSyncInfo($userId, $syncType)
{
$syncTypes = array('iphone', 'android', 'mac', 'exchange', 'outlook', 'office365');
if (in_array($syncType, $syncTypes))
{
CUserOptions::DeleteOption("calendar", "last_sync_".$syncType, false, $userId);
}
}
/**
* Updates counter in left menu in b24, sets amount of requests for meeting for current user or
* set of users
*
* @param int|array $users array of user's ids or user id as an int
* @return null
*/
public static function UpdateCounter($users = false)
{
if ($users == false)
$users = array(self::GetCurUserId());
elseif(!is_array($users))
$users = array($users);
$ids = array();
foreach($users as $user)
{
if (intVal($user) > 0)
$ids[] = intVal($user);
}
$users = $ids;
if (count($users) > 0)
{
$events = CCalendarEvent::GetList(array(
'arFilter' => array(
'CAL_TYPE' => 'user',
'OWNER_ID' => $users,
'FROM_LIMIT' => self::Date(time(), false),
'TO_LIMIT' => self::Date(time() + self::DAY_LENGTH * 90, false),
'IS_MEETING' => 1,
'MEETING_STATUS' => 'Q',
'DELETED' => 'N'
),
'parseRecursion' => false,
'checkPermissions' => false)
);
$counters = array();
foreach($events as $event)
{
if(!isset($counters[$event['OWNER_ID']]))
$counters[$event['OWNER_ID']] = 0;
$counters[$event['OWNER_ID']]++;
}
foreach($users as $user)
{
if($user > 0)
{
if(isset($counters[$user]) && $counters[$user] > 0)
CUserCounter::Set($user, 'calendar', $counters[$user], '**', '', false);
else
CUserCounter::Set($user, 'calendar', 0, '**', '', false);
}
}
}
}
// TODO: cache it!!!!!!
private static function __tzsort($a, $b)
{
if($a['offset'] == $b['offset'])
return strcmp($a['timezone_id'], $b['timezone_id']);
return ($a['offset'] < $b['offset']? -1 : 1);
}
private static function GetInstance()
{
if (!isset(self::$instance))
{
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public static function IsIntranetEnabled()
{
if (!isset(self::$bIntranet))
{
self::$bIntranet = IsModuleInstalled('intranet');
}
return self::$bIntranet;
}
public static function IsSocNet()
{
if (!isset(self::$bSocNet))
{
\Bitrix\Main\Loader::includeModule("socialnetwork");
self::$bSocNet = class_exists('CSocNetUserToGroup') && CBXFeatures::IsFeatureEnabled("Calendar") && self::IsIntranetEnabled();
}
return self::$bSocNet;
}
public static function GetCurUserId($refresh = false)
{
global $USER;
if (!isset(self::$curUserId) || $refresh || !self::$curUserId)
{
if (is_object($USER) && $USER->IsAuthorized())
self::$curUserId = $USER->GetId();
else
self::$curUserId = 0;
}
return self::$curUserId;
}
public static function GetSettings($params = array())
{
if (!is_array($params))
$params = array();
if (isset(self::$settings) && count(self::$settings) > 0 && $params['request'] === false)
return self::$settings;
$pathes_for_sites = COption::GetOptionString('calendar', 'pathes_for_sites', true);
if ($params['forseGetSitePathes'] || !$pathes_for_sites)
$pathes = self::GetPathes(isset($params['site']) ? $params['site'] : false);
else
$pathes = array();
if (!isset($params['getDefaultForEmpty']) || $params['getDefaultForEmpty'] !== false)
$params['getDefaultForEmpty'] = true;
$siteId = isset($params['site']) ? $params['site'] : SITE_ID;
$resMeetingCommonForSites = COption::GetOptionString('calendar', 'rm_for_sites', true);
$siteIdForResMeet = !$resMeetingCommonForSites && $siteId ? $siteId : false;
self::$settings = array(
'work_time_start' => COption::GetOptionString('calendar', 'work_time_start', 9),
'work_time_end' => COption::GetOptionString('calendar', 'work_time_end', 19),
'year_holidays' => COption::GetOptionString('calendar', 'year_holidays', Loc::getMessage('EC_YEAR_HOLIDAYS_DEFAULT')),
'year_workdays' => COption::GetOptionString('calendar', 'year_workdays', Loc::getMessage('EC_YEAR_WORKDAYS_DEFAULT')),
'week_holidays' => explode('|', COption::GetOptionString('calendar', 'week_holidays', 'SA|SU')),
'week_start' => COption::GetOptionString('calendar', 'week_start', 'MO'),
'user_name_template' => self::GetUserNameTemplate($params['getDefaultForEmpty']),
'sync_by_push' => COption::GetOptionString('calendar', 'sync_by_push', false),
'user_show_login' => COption::GetOptionString('calendar', 'user_show_login', true),
'path_to_user' => COption::GetOptionString('calendar', 'path_to_user', "/company/personal/user/#user_id#/"),
'path_to_user_calendar' => COption::GetOptionString('calendar', 'path_to_user_calendar', "/company/personal/user/#user_id#/calendar/"),
'path_to_group' => COption::GetOptionString('calendar', 'path_to_group', "/workgroups/group/#group_id#/"),
'path_to_group_calendar' => COption::GetOptionString('calendar', 'path_to_group_calendar', "/workgroups/group/#group_id#/calendar/"),
'path_to_vr' => COption::GetOptionString('calendar', 'path_to_vr', ""),
'path_to_rm' => COption::GetOptionString('calendar', 'path_to_rm', ""),
'rm_iblock_type' => COption::GetOptionString('calendar', 'rm_iblock_type', ""),
'rm_iblock_id' => COption::GetOptionString('calendar', 'rm_iblock_id', "", $siteIdForResMeet, !!$siteIdForResMeet),
'dep_manager_sub' => COption::GetOptionString('calendar', 'dep_manager_sub', true),
'denied_superpose_types' => unserialize(COption::GetOptionString('calendar', 'denied_superpose_types', serialize(array()))),
'pathes_for_sites' => $pathes_for_sites,
'pathes' => $pathes,
'forum_id' => COption::GetOptionString('calendar', 'forum_id', ""),
'rm_for_sites' => COption::GetOptionString('calendar', 'rm_for_sites', true)
);
$arPathes = self::GetPathesList();
foreach($arPathes as $pathName)
{
if (!isset(self::$settings[$pathName]))
self::$settings[$pathName] = COption::GetOptionString('calendar', $pathName, "");
}
if(self::$settings['work_time_start'] > 23)
self::$settings['work_time_start'] = 23;
if (self::$settings['work_time_end'] <= self::$settings['work_time_start'])
self::$settings['work_time_end'] = self::$settings['work_time_start'] + 1;
if (self::$settings['work_time_end'] > 23.30)
self::$settings['work_time_end'] = 23.30;
if (self::$settings['forum_id'] == "")
{
self::$settings['forum_id'] = COption::GetOptionString("tasks", "task_forum_id", "");
if (self::$settings['forum_id'] == "" && \Bitrix\Main\Loader::includeModule("forum"))
{
$db = CForumNew::GetListEx();
if ($ar = $db->GetNext())
self::$settings['forum_id'] = $ar["ID"];
}
COption::SetOptionString("calendar", "forum_id", self::$settings['forum_id']);
}
return self::$settings;
}
public static function GetPathes($forSite = false)
{
$pathes = array();
$pathes_for_sites = COption::GetOptionString('calendar', 'pathes_for_sites', true);
if ($forSite === false)
{
$arAffectedSites = COption::GetOptionString('calendar', 'pathes_sites', false);
if ($arAffectedSites != false && CheckSerializedData($arAffectedSites))
$arAffectedSites = unserialize($arAffectedSites);
}
else
{
if (is_array($forSite))
$arAffectedSites = $forSite;
else
$arAffectedSites = array($forSite);
}
if(is_array($arAffectedSites) && count($arAffectedSites) > 0)
{
foreach($arAffectedSites as $s)
{
$ar = COption::GetOptionString("calendar", 'pathes_'.$s, false);
if ($ar != false && CheckSerializedData($ar))
{
$ar = unserialize($ar);
if(is_array($ar))
$pathes[$s] = $ar;
}
}
}
if ($forSite !== false)
{
$result = array();
if (isset($pathes[$forSite]) && is_array($pathes[$forSite]))
$result = $pathes[$forSite];
$arPathes = self::GetPathesList();
foreach($arPathes as $pathName)
{
$val = $result[$pathName];
if (!isset($val) || empty($val) || $pathes_for_sites)
{
if (!isset($SET))
$SET = self::GetSettings();
$val = $SET[$pathName];
$result[$pathName] = $val;
}
}
return $result;
}
return $pathes;
}
public static function GetPathesList()
{
if (!self::$pathesListEx)
{
self::$pathesListEx = self::$pathesList;
$arTypes = CCalendarType::GetList(array('checkPermissions' => false));
for ($i = 0, $l = count($arTypes); $i < $l; $i++)
{
if ($arTypes[$i]['XML_ID'] !== 'user' && $arTypes[$i]['XML_ID'] !== 'group')
{
self::$pathesList[] = 'path_to_type_'.$arTypes[$i]['XML_ID'];
}
}
}
return self::$pathesList;
}
public static function GetUserNameTemplate($fromSite = true)
{
$user_name_template = COption::GetOptionString('calendar', 'user_name_template', '');
if ($fromSite && empty($user_name_template))
$user_name_template = CSite::GetNameFormat(false);
return $user_name_template;
}
public static function SetUserSettings($settings = array(), $userId = false)
{
CCalendarUserSettings::Set($settings, $userId);
}
public static function GetUserSettings($userId = false)
{
return CCalendarUserSettings::Get($userId);
}
public static function GetPermissions($Params = array())
{
global $USER;
$type = isset($Params['type']) ? $Params['type'] : self::$type;
$ownerId = isset($Params['ownerId']) ? $Params['ownerId'] : self::$ownerId;
$userId = isset($Params['userId']) ? $Params['userId'] : self::$userId;
$bView = true;
$bEdit = true;
$bEditSection = true;
if ($type == 'user' && $ownerId != $userId)
{
$bEdit = false;
$bEditSection = false;
}
if ($type == 'group')
{
if (!$USER->CanDoOperation('edit_php'))
{
$keyOwner = 'SG'.$ownerId.'_A';
$keyMod = 'SG'.$ownerId.'_E';
$keyMember = 'SG'.$ownerId.'_K';
$arCodes = array();
$rCodes = CAccess::GetUserCodes($userId);
while($code = $rCodes->Fetch())
$arCodes[] = $code['ACCESS_CODE'];
if (\Bitrix\Main\Loader::includeModule("socialnetwork"))
{
$group = CSocNetGroup::getByID($ownerId);
if(!empty($group['CLOSED']) && $group['CLOSED'] === 'Y' &&
\Bitrix\Main\Config\Option::get('socialnetwork', 'work_with_closed_groups', 'N') === 'N')
{
self::$isArchivedGroup = true;
}
}
if (in_array($keyOwner, $arCodes))// Is owner
{
$bEdit = true;
$bEditSection = true;
}
elseif(in_array($keyMod, $arCodes) && !self::$isArchivedGroup)// Is moderator
{
$bEdit = true;
$bEditSection = true;
}
elseif(in_array($keyMember, $arCodes) && !self::$isArchivedGroup)// Is member
{
$bEdit = true;
$bEditSection = false;
}
else
{
$bEdit = false;
$bEditSection = false;
}
}
}
if ($type != 'user' && $type != 'group')
{
$bView = CCalendarType::CanDo('calendar_type_view', $type);
$bEdit = CCalendarType::CanDo('calendar_type_edit', $type);
$bEditSection = CCalendarType::CanDo('calendar_type_edit_section', $type);
}
if ($Params['setProperties'] !== false)
{
self::$perm['view'] = $bView;
self::$perm['edit'] = $bEdit;
self::$perm['section_edit'] = $bEditSection;
}
return array(
'view' => $bView,
'edit' => $bEdit,
'section_edit' => $bEditSection
);
}
public static function GetPath($type = '', $ownerId = '', $hard = false)
{
if (self::$path == '' || $hard)
{
$path = '';
if (empty($type))
$type = self::$type;
if (!empty($type))
{
if ($type == 'user')
{
$path = COption::GetOptionString(
'calendar',
'path_to_user_calendar',
COption::getOptionString('socialnetwork', 'user_page', "/company/personal/")."user/#user_id#/calendar/"
);
}
elseif($type == 'group')
{
$path = COption::GetOptionString(
'calendar',
'path_to_group_calendar',
COption::getOptionString('socialnetwork', 'workgroups_page', "/workgroups/")."group/#group_id#/calendar/"
);
}
if (!COption::GetOptionString('calendar', 'pathes_for_sites', true))
{
$siteId = self::GetSiteId();
$pathes = self::GetPathes();
if (isset($pathes[$siteId]))
{
if ($type == 'user' && isset($pathes[$siteId]['path_to_user_calendar']))
$path = $pathes[$siteId]['path_to_user_calendar'];
elseif($type == 'group' && isset($pathes[$siteId]['path_to_group_calendar']))
$path = $pathes[$siteId]['path_to_group_calendar'];
}
}
if (empty($ownerId))
$ownerId = self::$ownerId;
if (!empty($path) && !empty($ownerId))
{
if ($type == 'user')
$path = str_replace(array('#user_id#', '#USER_ID#'), $ownerId, $path);
elseif($type == 'group')
$path = str_replace(array('#group_id#', '#GROUP_ID#'), $ownerId, $path);
}
$path = CCalendar::GetServerPath().$path;
}
}
else
{
$path = self::$path;
}
return $path;
}
public static function GetSiteId()
{
if (!self::$siteId)
self::$siteId = SITE_ID;
return self::$siteId;
}
public static function GetServerPath()
{
if (!isset(self::$serverPath))
{
self::$serverPath = (CMain::IsHTTPS() ? "https://" : "http://").self::GetServerName();
}
return self::$serverPath;
}
public static function GetServerName()
{
if (defined("SITE_SERVER_NAME") && strlen(SITE_SERVER_NAME) > 0)
$server_name = SITE_SERVER_NAME;
if (!$server_name)
$server_name = COption::GetOptionString("main", "server_name", "");
if (!$server_name)
$server_name = $_SERVER['HTTP_HOST'];
$server_name = rtrim($server_name, '/');
if (!preg_match('/^[a-z0-9\.\-]+$/i', $server_name)) // cyrillic domain hack
{
$converter = new CBXPunycode(defined('BX_UTF') && BX_UTF === true ? 'UTF-8' : 'windows-1251');
$host = $converter->Encode($server_name);
if (!preg_match('#--p1ai$#', $host)) // trying to guess
$host = $converter->Encode(CharsetConverter::ConvertCharset($server_name, 'utf-8', 'windows-1251'));
$server_name = $host;
}
return $server_name;
}
public static function GetStartUpEvent($eventId = false)
{
if (!$eventId)
return false;
$res = CCalendarEvent::GetList(
array(
'arFilter' => array(
"PARENT_ID" => $eventId,
"OWNER_ID" => self::$userId,
"IS_MEETING" => 1,
"DELETED" => "N"
),
'parseRecursion' => false,
'fetchAttendees' => true,
'fetchMeetings' => true,
'checkPermissions' => true,
'setDefaultLimit' => false
)
);
if (!$res || !is_array($res[0]))
{
$res = CCalendarEvent::GetList(
array(
'arFilter' => array(
"ID" => $eventId,
"DELETED" => "N"
),
'parseRecursion' => false,
'userId' => self::$userId,
'fetchAttendees' => false,
'fetchMeetings' => true
)
);
}
if ($res && isset($res[0]) && ($event = $res[0]))
{
if ($event['MEETING_STATUS'] == 'Y' || $event['MEETING_STATUS'] == 'N' || $event['MEETING_STATUS'] == 'Q')
{
if ($event['IS_MEETING'] && self::$userId == self::$ownerId && self::$type == 'user' && ($_GET['CONFIRM'] == 'Y' || $_GET['CONFIRM'] == 'N'))
{
CCalendarEvent::SetMeetingStatus(array(
'userId' => self::$userId,
'eventId' => $event['ID'],
'status' => $_GET['CONFIRM'] == 'Y' ? 'Y' : 'N',
'personalNotification' => true
));
}
}
if ($event['RRULE'])
$event['RRULE'] = CCalendarEvent::ParseRRULE($event['RRULE']);
return $event;
}
else
{
CCalendarNotify::ClearNotifications($eventId);
}
return false;
}
public static function Timestamp($date, $bRound = true, $bTime = true)
{
$timestamp = MakeTimeStamp($date, self::TSFormat($bTime ? "FULL" : "SHORT"));
if ($bRound)
$timestamp = self::RoundTimestamp($timestamp);
return $timestamp;
}
public static function TSFormat($format = "FULL")
{
return CSite::GetDateFormat($format);
}
public static function RoundTimestamp($ts)
{
return round($ts / 60) * 60; // We don't need for seconds here
}
public static function IsPersonal($type = false, $ownerId = false, $userId = false)
{
if (!$type)
$type = self::$type;
if(!$ownerId)
$ownerId = self::$ownerId;
if(!$userId)
$userId = self::$userId;
return $type == 'user' && $ownerId == $userId;
}
public static function IsExchangeEnabled($userId = false)
{
if (isset(self::$arExchEnabledCache[$userId]))
return self::$arExchEnabledCache[$userId];
if (!IsModuleInstalled('dav') || COption::GetOptionString("dav", "agent_calendar") != "Y")
$res = false;
elseif (!\Bitrix\Main\Loader::includeModule('dav'))
$res = false;
elseif ($userId === false)
$res = CDavExchangeCalendar::IsExchangeEnabled();
else
$res = CDavExchangeCalendar::IsExchangeEnabled() && CDavExchangeCalendar::IsExchangeEnabledForUser($userId);
self::$arExchEnabledCache[$userId] = $res;
return $res;
}
public static function isGoogleApiEnabled()
{
if (!isset(self::$isGoogleApiEnabled))
{
self::$isGoogleApiEnabled = \Bitrix\Main\ModuleManager::isModuleInstalled('socialservices') &&
(is_null(\Bitrix\Main\Config\Configuration::getValue("calendar_integration")) || \Bitrix\Main\Config\Configuration::getValue("calendar_integration") === self::INTEGRATION_GOOGLE_API);
if (self::$isGoogleApiEnabled
&& !self::IsBitrix24()
&& \Bitrix\Main\Loader::includeModule('socialservices'))
{
self::$isGoogleApiEnabled = CSocServGoogleOAuth::GetOption('google_appid') !== '' && CSocServGoogleOAuth::GetOption('google_appsecret') !== '';
}
}
return self::$isGoogleApiEnabled;
}
public static function IsCalDAVEnabled()
{
if (!IsModuleInstalled('dav') || COption::GetOptionString("dav", "agent_calendar_caldav") != "Y")
return false;
return \Bitrix\Main\Loader::includeModule('dav') && CDavGroupdavClientCalendar::IsCalDAVEnabled();
}
public static function IsWebserviceEnabled()
{
if (!isset(self::$bWebservice))
self::$bWebservice = IsModuleInstalled('webservice');
return self::$bWebservice;
}
public static function IsExtranetEnabled()
{
if (!isset(self::$bExtranet))
self::$bExtranet = \Bitrix\Main\Loader::includeModule('extranet') && CExtranet::IsExtranetSite();
return self::$bExtranet;
}
public static function IsAbsenceEnabled()
{
return !self::IsBitrix24()
|| COption::GetOptionString("bitrix24", "absence_limits_enabled", "") != "Y"
|| \Bitrix\Bitrix24\Feature::isFeatureEnabled("absence");
}
public static function GetMeetingRoomList($Params = array())
{
if (isset(self::$meetingRoomList))
return self::$meetingRoomList;
if (!isset($Params['RMiblockId']) && !isset($Params['VMiblockId']))
{
if (!isset(self::$settings))
self::$settings = self::GetSettings();
if (!self::$pathesForSite)
self::$pathesForSite = self::GetSettings(array('forseGetSitePathes' => true,'site' =>self::GetSiteId()));
$RMiblockId = self::$settings['rm_iblock_id'];
$pathToMR = self::$pathesForSite['path_to_rm'];
}
else
{
$RMiblockId = $Params['RMiblockId'];
$pathToMR = $Params['pathToMR'];
}
$MRList = Array();
if (IntVal($RMiblockId) > 0 && CIBlock::GetPermission($RMiblockId) >= "R" && self::$allowReserveMeeting)
{
$arOrderBy = array("NAME" => "ASC", "ID" => "DESC");
$arFilter = array("IBLOCK_ID" => $RMiblockId, "ACTIVE" => "Y");
$arSelectFields = array("IBLOCK_ID","ID","NAME","DESCRIPTION","UF_FLOOR","UF_PLACE","UF_PHONE");
$res = CIBlockSection::GetList($arOrderBy, $arFilter, false, $arSelectFields );
while ($arMeeting = $res->GetNext())
{
$MRList[] = array(
'ID' => $arMeeting['ID'],
'NAME' => $arMeeting['~NAME'],
'DESCRIPTION' => $arMeeting['~DESCRIPTION'],
'UF_PLACE' => $arMeeting['UF_PLACE'],
'UF_PHONE' => $arMeeting['UF_PHONE'],
'URL' => str_replace(array("#id#", "#ID#"), $arMeeting['ID'], $pathToMR)
);
}
}
self::$meetingRoomList = $MRList;
return $MRList;
}
public static function GetCurrentOffsetUTC($userId = false)
{
if (!$userId && self::$userId)
$userId = self::$userId;
return intVal(date("Z") + self::GetOffset($userId));
}
public static function GetOffset($userId = false)
{
if ($userId > 0)
{
if (!isset(self::$arTimezoneOffsets[$userId]))
{
$offset = CTimeZone::GetOffset($userId, true);
self::$arTimezoneOffsets[$userId] = $offset;
}
else
{
$offset = self::$arTimezoneOffsets[$userId];
}
}
else
{
if (!isset(self::$offset))
{
$offset = CTimeZone::GetOffset(null, true);
self::$offset = $offset;
}
else
{
$offset = self::$offset;
}
}
return $offset;
}
public static function GetUserTimezoneName($user, $getDefault = true)
{
if (!is_array($user) && intVal($user) > 0)
{
$user = self::GetUser($user, true);
}
$offset = self::GetCurrentOffsetUTC($user['ID']);
$tzName = CUserOptions::GetOption("calendar", "timezone".$offset, false, $user['ID']);
if ($tzName === 'undefined' || $tzName === 'false')
$tzName = false;
if (!$tzName && $user['AUTO_TIME_ZONE'] !== 'Y' && $user['TIME_ZONE'])
{
$tzName = $user['TIME_ZONE'];
}
if (!$tzName && $getDefault)
{
$tzName = self::GetGoodTimezoneForOffset($offset);
}
return $tzName;
}
public static function GetUser($userId, $bPhoto = false)
{
global $USER;
if (is_object($USER) && intVal($userId) == $USER->GetId() && !$bPhoto)
{
$user = array(
'ID' => $USER->GetId(),
'NAME' => $USER->GetFirstName(),
'LAST_NAME' => $USER->GetLastName(),
'SECOND_NAME' => $USER->GetParam('SECOND_NAME'),
'LOGIN' => $USER->GetLogin(),
'PERSONAL_PHOTO' => $USER->GetParam('PERSONAL_PHOTO'),
);
}
else
{
$rsUser = CUser::GetByID(intVal($userId));
$user = $rsUser->Fetch();
}
return $user;
}
public static function GetGoodTimezoneForOffset($offset)
{
$timezones = self::GetTimezoneList();
$goodTz = array();
$result = false;
foreach($timezones as $tz)
{
if ($tz['offset'] == $offset)
{
$goodTz[] = $tz;
if (LANGUAGE_ID == 'ru')
{
if (preg_match('/(kaliningrad|moscow|samara|yekaterinburg|novosibirsk|krasnoyarsk|irkutsk|yakutsk|vladivostok)/i', $tz['timezone_id']))
{
$result = $tz['timezone_id'];
break;
}
}
elseif (strpos($tz['timezone_id'], 'Europe') !== false)
{
$result = $tz['timezone_id'];
break;
}
}
}
if (!$result && count($goodTz) > 0)
{
$result = $goodTz[0]['timezone_id'];
}
return $result;
}
public static function GetTimezoneList()
{
if (empty(self::$timezones))
{
self::$timezones = array();
static $aExcept = array("Etc/", "GMT", "UTC", "UCT", "HST", "PST", "MST", "CST", "EST", "CET", "MET", "WET", "EET", "PRC", "ROC", "ROK", "W-SU");
foreach(DateTimeZone::listIdentifiers() as $tz)
{
foreach($aExcept as $ex)
if(strpos($tz, $ex) === 0)
continue 2;
try
{
$oTz = new DateTimeZone($tz);
self::$timezones[$tz] = array('timezone_id' => $tz, 'offset' => $oTz->getOffset(new DateTime("now", $oTz)));
}
catch(Exception $e){}
}
uasort(self::$timezones, array('CCalendar', '__tzsort'));
foreach(self::$timezones as $k => $z)
{
self::$timezones[$k]['title'] = '(UTC'.($z['offset'] <> 0? ' '.($z['offset'] < 0? '-':'+').sprintf("%02d", ($h = floor(abs($z['offset'])/3600))).':'.sprintf("%02d", abs($z['offset'])/60 - $h*60) : '').') '.$z['timezone_id'];
}
}
return self::$timezones;
}
public static function GetUserName($user)
{
if (!is_array($user) && intVal($user) > 0)
$user = self::GetUser($user);
if(!$user || !is_array($user))
return '';
return CUser::FormatName(self::$userNameTemplate, $user, self::$showLogin, false);
}
public static function GetWeekStart()
{
if (!isset(self::$weekStart))
{
$days = array('1' => 'MO', '2' => 'TU', '3' => 'WE', '4' => 'TH', '5' => 'FR', '6' => 'SA', '0' => 'SU');
self::$weekStart = $days[CSite::GetWeekStart()];
if (!in_array(self::$weekStart, $days))
self::$weekStart = 'MO';
}
return self::$weekStart;
}
public static function InitExternalCalendarsSyncParams(&$JSConfig)
{
$isGoogleApiEnabled = CCalendar::isGoogleApiEnabled() && self::$type == "user";
$googleCalDavStatus = array();
$googleApiStatus = array();
$JSConfig['bCalDAV'] = true;
$JSConfig['caldav_link_all'] = CCalendar::GetServerPath();
if (self::$type == 'user' && self::IsPersonal() && \Bitrix\Main\Loader::includeModule('dav'))
{
$tzEnabled = CTimeZone::Enabled();
if ($tzEnabled)
CTimeZone::Disable();
$connectionList = array();
$res = CDavConnection::GetList(
array("ID" => "DESC"),
array(
"ENTITY_TYPE" => "user",
"ENTITY_ID" => self::$ownerId,
'ACCOUNT_TYPE' => array('caldav_google_oauth', 'google_api_oauth', 'caldav')
), false, false);
if ($isGoogleApiEnabled)
{
$googleApiConnection = new GoogleApiSync(self::getCurUserId());
$transportErrors = $googleApiConnection->getTransportErrors();
if (!$transportErrors)
{
$googleApiStatus['googleCalendarPrimaryId'] = $googleApiConnection->getPrimaryId();
}
if (empty($googleApiStatus['googleCalendarPrimaryId']))
{
$curPath = CCalendar::GetPath();
if($curPath)
$curPath = CHTTP::urlDeleteParams($curPath, array("action", "sessid", "bx_event_calendar_request", "EVENT_ID"));
$client = new CSocServGoogleOAuth(self::$ownerId);
$client->getEntityOAuth()->addScope(array(
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/calendar.readonly'
));
$googleApiStatus['authLink'] = $client->getUrl('opener', null, array('BACKURL' => $curPath));
}
}
else
{
$googleCalDavStatus = CCalendarSync::GetGoogleCalendarConnection();
}
$googleApiConnections = array();
while($connection = $res->Fetch())
{
$connectionListItem = array(
'id' => $connection['ID'],
'server_host' => $connection['SERVER_HOST'],
'account_type' => $connection['ACCOUNT_TYPE'],
'name' => $connection['NAME'],
'link' => $connection['SERVER'],
'user_name' => $connection['SERVER_USERNAME'],
'last_result' => $connection['LAST_RESULT'],
'sync_date' => $connection['SYNCHRONIZED']
);
$connectionList[] = $connectionListItem;
if ($connection['ACCOUNT_TYPE'] == 'caldav_google_oauth' || $connection['ACCOUNT_TYPE'] == 'google_api_oauth')
{
$googleApiConnections[] = $connectionListItem;
}
}
$addConnection = true;
if ($isGoogleApiEnabled)
{
if (empty($googleApiConnections))
{
$googleApiConnection = new GoogleApiSync(self::getCurUserId());
$transportErrors = $googleApiConnection->getTransportErrors();
if (!$transportErrors)
{
$googleApiStatus['googleCalendarPrimaryId'] = $googleApiConnection->getPrimaryId();
}
if (empty($googleApiStatus['googleCalendarPrimaryId']))
{
$curPath = CCalendar::GetPath();
if($curPath)
$curPath = CHTTP::urlDeleteParams($curPath, array("action", "sessid", "bx_event_calendar_request", "EVENT_ID"));
$client = new CSocServGoogleOAuth(self::$ownerId);
$client->getEntityOAuth()->addScope(array(
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/calendar.readonly'
));
$googleApiStatus['authLink'] = $client->getUrl('opener', null, array('BACKURL' => $curPath));
}
}
if ($googleApiStatus['googleCalendarPrimaryId'] || !empty($googleApiConnections))
{
$serverPath = 'https://www.googleapis.com/calendar/v3';
foreach ($googleApiConnections as $connection)
{
if (($connection['link'] == $serverPath || $connection['account_type'] == 'caldav_google_oauth') || $connection['account_type'] == 'google_api_oauth')
{
$googleApiStatus['last_result'] = $connection['last_result'];
$googleApiStatus['sync_date'] = CCalendar::Date(self::Timestamp($connection['sync_date']) + CCalendar::GetOffset(self::$ownerId), true, true, true);
$googleApiStatus['connection_id'] = $connection['id'];
$addConnection = false;
break;
}
}
if ($addConnection)
{
$sAccountType = 'google_api_oauth';
$sServer = 'https://www.googleapis.com/calendar/v3';
$connectionData = array(
"ENTITY_TYPE" => 'user',
"ENTITY_ID" => self::$ownerId,
"ACCOUNT_TYPE" => $sAccountType,
"NAME" => 'Google Calendar ('.$googleApiStatus['googleCalendarPrimaryId'].')',
"SERVER" => $sServer,
"SYNC_TOKEN" => NULL,
);
$conId = CDavConnection::Add($connectionData);
if ($conId)
{
CCalendarSync::dataSync(array_merge($connectionData, array('ID' => $conId)));
$pushOptionEnabled = COption::GetOptionString('calendar', 'sync_by_push', false);
if ($pushOptionEnabled || CCalendar::IsBitrix24())
{
$googleApiConnection = new GoogleApiSync($connectionData['ENTITY_ID']);
$channelInfo = $googleApiConnection->startWatchCalendarList($connectionData['NAME']);
if ($channelInfo)
{
PushTable::delete(array("ENTITY_TYPE" => 'CONNECTION', 'ENTITY_ID' => $conId));
PushTable::add(array(
'ENTITY_TYPE' => 'CONNECTION',
'ENTITY_ID' => $conId,
'CHANNEL_ID' => $channelInfo['id'],
'RESOURCE_ID' => $channelInfo['resourceId'],
'EXPIRES' => $channelInfo['expiration'],
'NOT_PROCESSED' => 'N'
));
}
}
$res = CDavConnection::GetList(array("ID" => "DESC"), array("ID" => $conId), false, false);
if ($connection = $res->Fetch())
{
$connectionList[] = array(
'id' => $connection['ID'],
'server_host' => $connection['SERVER_HOST'],
'account_type' => $connection['ACCOUNT_TYPE'],
'name' => $connection['NAME'],
'link' => $connection['SERVER'],
'user_name' => $connection['SERVER_USERNAME'],
'last_result' => $connection['LAST_RESULT'],
'sync_date' => $connection['SYNCHRONIZED']
);
$googleApiStatus['connection_id'] = $connection['ID'];
$googleApiStatus['last_result'] = $googleApiConnections['LAST_RESULT'];
$googleApiStatus['sync_date'] = CCalendar::Date(self::Timestamp($connection['SYNCHRONIZED']) + CCalendar::GetOffset(self::$ownerId), true, true, true);
}
}
}
}
$JSConfig['googleCalDavStatus'] = $googleApiStatus;
}
else if ($googleCalDavStatus && $googleCalDavStatus['googleCalendarPrimaryId'])
{
$serverPath = 'https://apidata.googleusercontent.com/caldav/v2/'.$googleCalDavStatus['googleCalendarPrimaryId'].'/user';
foreach($connectionList as $connection)
{
if ($connection['link'] == $serverPath)
{
$googleCalDavStatus['last_result'] = $connection['last_result'];
$googleCalDavStatus['sync_date'] = CCalendar::Date(self::Timestamp($connection['sync_date']) + CCalendar::GetOffset(self::$ownerId), true, true, true);
$googleCalDavStatus['connection_id'] = $connection['id'];
$addConnection = false;
break;
}
}
if ($addConnection)
{
$conId = CDavConnection::Add(array(
"ENTITY_TYPE" => 'user',
"ENTITY_ID" => self::$ownerId,
"ACCOUNT_TYPE" => 'caldav_google_oauth',
"NAME" => 'Google Calendar ('.$googleCalDavStatus['googleCalendarPrimaryId'].')',
"SERVER" => 'https://apidata.googleusercontent.com/caldav/v2/'.$googleCalDavStatus['googleCalendarPrimaryId'].'/user'
));
if ($conId)
{
CDavGroupdavClientCalendar::DataSync("user", self::$ownerId);
$res = CDavConnection::GetList(array("ID" => "DESC"), array("ID" => $conId), false, false);
if($connection = $res->Fetch())
{
$connectionList[] = array(
'id' => $connection['ID'],
'server_host' => $connection['SERVER_HOST'],
'account_type' => $connection['ACCOUNT_TYPE'],
'name' => $connection['NAME'],
'link' => $connection['SERVER'],
'user_name' => $connection['SERVER_USERNAME'],
'last_result' => $connection['LAST_RESULT'],
'sync_date' => $connection['SYNCHRONIZED']
);
$googleCalDavStatus['connection_id'] = $connection['ID'];
$googleCalDavStatus['last_result'] = $connection['LAST_RESULT'];
$googleCalDavStatus['sync_date'] = CCalendar::Date(self::Timestamp($googleApiConnections['SYNCHRONIZED']) + CCalendar::GetOffset(self::$ownerId), true, true, true);
}
}
}
$JSConfig['googleCalDavStatus'] = $googleCalDavStatus;
}
$JSConfig['connections'] = $connectionList;
if ($tzEnabled)
CTimeZone::Enable();
}
}
// public static function InitGoogleApiParams(&$JSConfig)
// {
// if (!\Bitrix\Main\Loader::includeModule('socialservices') || !\Bitrix\Main\Loader::includeModule('dav'))
// {
// return;
// }
// $googleApiStatus = array();
//
// if (self::$type != 'user')
// {
// return;
// }
//
// $connectionList = array();
// $res = CDavConnection::GetList(
// array("ID" => "DESC"),
// array(
// "ENTITY_TYPE" => "user",
// "ENTITY_ID" => self::$ownerId,
// 'ACCOUNT_TYPE' => array('caldav_google_oauth', 'google_api_oauth')
// ), false, false);
//
// while ($arCon = $res->Fetch())
// {
// $connectionList[] = array(
// 'id' => $arCon['ID'],
// 'server_host' => $arCon['SERVER_HOST'],
// 'account_type' => $arCon['ACCOUNT_TYPE'],
// 'name' => $arCon['NAME'],
// 'link' => $arCon['SERVER'],
// 'user_name' => $arCon['SERVER_USERNAME'],
// 'last_result' => $arCon['LAST_RESULT'],
// 'sync_date' => $arCon['SYNCHRONIZED']
// );
// }
//
// if (self::IsPersonal())
// {
// if (!$connectionList)
// {
// $googleApiConnection = new GoogleApiSync(self::getCurUserId());
// $transportErrors = $googleApiConnection->getTransportErrors();
// if (!$transportErrors)
// {
// $googleApiStatus['googleCalendarPrimaryId'] = $googleApiConnection->getPrimaryId();
// }
//
// if (empty($googleApiStatus['googleCalendarPrimaryId']))
// {
// $curPath = CCalendar::GetPath();
// if($curPath)
// $curPath = CHTTP::urlDeleteParams($curPath, array("action", "sessid", "bx_event_calendar_request", "EVENT_ID"));
// $client = new CSocServGoogleOAuth(self::$ownerId);
// $client->getEntityOAuth()->addScope(array(
// 'https://www.googleapis.com/auth/calendar',
// 'https://www.googleapis.com/auth/calendar.readonly'
// ));
// $googleApiStatus['authLink'] = $client->getUrl('opener', null, array('BACKURL' => $curPath));
// }
// }
//
// if ($googleApiStatus['googleCalendarPrimaryId'] || $connectionList)
// {
// $serverPath = 'https://www.googleapis.com/calendar/v3';
// $addConnection = true;
//
// foreach ($connectionList as $arCon)
// {
// if (($arCon['link'] == $serverPath || $arCon['account_type'] == 'caldav_google_oauth') || $arCon['account_type'] == 'google_api_oauth')
// {
// $googleApiStatus['last_result'] = $arCon['last_result'];
// $googleApiStatus['sync_date'] = CCalendar::Date(self::Timestamp($arCon['sync_date']) + CCalendar::GetOffset(self::$ownerId), true, true, true);
// $googleApiStatus['connection_id'] = $arCon['id'];
//
// $addConnection = false;
// break;
// }
//
// }
//
// if ($addConnection && !$connectionList)
// {
// $sAccountType = 'google_api_oauth';
// $sServer = 'https://www.googleapis.com/calendar/v3';
// $connectionData = array(
// "ENTITY_TYPE" => 'user',
// "ENTITY_ID" => self::$ownerId,
// "ACCOUNT_TYPE" => $sAccountType,
// "NAME" => 'Google Calendar ('.$googleApiStatus['googleCalendarPrimaryId'].')',
// "SERVER" => $sServer,
// "SYNC_TOKEN" => NULL,
// );
// $conId = CDavConnection::Add($connectionData);
//
// if ($conId)
// {
// CCalendarSync::dataSync(array_merge($connectionData, array('ID' => $conId)));
//
// $pushOptionEnabled = COption::GetOptionString('calendar', 'sync_by_push', false);
// if ($pushOptionEnabled || CCalendar::IsBitrix24())
// {
// $googleApiConnection = new GoogleApiSync($connectionData['ENTITY_ID']);
// $channelInfo = $googleApiConnection->startWatchCalendarList($connectionData['NAME']);
// if ($channelInfo)
// {
// PushTable::delete(array("ENTITY_TYPE" => 'CONNECTION', 'ENTITY_ID' => $conId));
// PushTable::add(array(
// 'ENTITY_TYPE' => 'CONNECTION',
// 'ENTITY_ID' => $conId,
// 'CHANNEL_ID' => $channelInfo['id'],
// 'RESOURCE_ID' => $channelInfo['resourceId'],
// 'EXPIRES' => $channelInfo['expiration'],
// 'NOT_PROCESSED' => 'N'
// ));
// }
// }
// $res = CDavConnection::GetList(array("ID" => "DESC"), array("ID" => $conId), false, false);
// if ($arCon = $res->Fetch())
// {
// $connectionList[] = array(
// 'id' => $arCon['ID'],
// 'server_host' => $arCon['SERVER_HOST'],
// 'account_type' => $arCon['ACCOUNT_TYPE'],
// 'name' => $arCon['NAME'],
// 'link' => $arCon['SERVER'],
// 'user_name' => $arCon['SERVER_USERNAME'],
// 'last_result' => $arCon['LAST_RESULT'],
// 'sync_date' => $arCon['SYNCHRONIZED']
// );
// $googleApiStatus['connection_id'] = $arCon['ID'];
// $googleApiStatus['last_result'] = $arCon['LAST_RESULT'];
// $googleApiStatus['sync_date'] = CCalendar::Date(self::Timestamp($arCon['SYNCHRONIZED']) + CCalendar::GetOffset(self::$ownerId), true, true, true);
// }
// }
// }
// }
// }
//
// $JSConfig['googleCalDavStatus'] = $googleApiStatus;
// $JSConfig['connections'] = $connectionList;
// }
public static function Date($timestamp, $bTime = true, $bRound = true, $bCutSeconds = false)
{
if ($bRound)
$timestamp = self::RoundTimestamp($timestamp);
$format = self::DFormat($bTime);
if ($bTime && $bCutSeconds)
$format = str_replace(':s', '', $format);
return FormatDate($format, $timestamp);
}
public static function DFormat($bTime = true)
{
return CDatabase::DateFormatToPHP(CSite::GetDateFormat($bTime ? "FULL" : "SHORT", SITE_ID));
}
public static function DateWithNewTime($timestampTime, $timestampDate)
{
return mktime(date("H", $timestampTime), date("i", $timestampTime), 0, date("m", $timestampDate), date("d", $timestampDate), date("Y", $timestampDate));
}
public static function GetSyncInfo($userId, $syncType)
{
$activeSyncPeriod = 604800; // 3600 * 24 * 7 - one week
$syncTypes = array('iphone', 'android', 'mac', 'exchange', 'outlook', 'office365');
$result = array('connected' => false);
if (in_array($syncType, $syncTypes))
{
$result['date'] = CUserOptions::GetOption("calendar", "last_sync_".$syncType, false, $userId);
}
if ($result['date'])
{
$period = time() - self::Timestamp($result['date']);
if ($period >= 0 && $period <= $activeSyncPeriod)
{
$result['date'] = CCalendar::Date(self::Timestamp($result['date']) + CCalendar::GetOffset($userId), true, true, true);
$result['connected'] = true;
}
}
return $result;
}
public static function GetDisplayedSuperposed($userId = false)
{
if (!class_exists('CUserOptions') || !$userId)
return false;
$res = array();
$def = CUserOptions::GetOption("calendar", "superpose_displayed_default", false, $userId);
$saveOption = false;
if (intval($def) > 0)
{
$saveOption = true;
$res[] = intVal($def);
}
$str = CUserOptions::GetOption("calendar", "superpose_displayed", false, $userId);
if (CheckSerializedData($str))
{
$arIds = unserialize($str);
if (is_array($arIds) && count($arIds) > 0)
{
foreach($arIds as $id)
{
if (intVal($id) > 0)
{
$res[] = intVal($id);
}
}
}
}
if ($saveOption)
{
CUserOptions::SetOption("calendar", "superpose_displayed", serialize($res));
CUserOptions::SetOption("calendar", "superpose_displayed_default", false);
}
return $res;
}
public static function GetCurUserMeetingSection($bCreate = false)
{
if (!isset(self::$userMeetingSection) || !self::$userMeetingSection)
self::$userMeetingSection = CCalendar::GetMeetingSection(self::$userId, $bCreate);
return self::$userMeetingSection;
}
public static function GetMeetingSection($userId, $autoCreate = false)
{
if (isset(self::$meetingSections[$userId]))
return self::$meetingSections[$userId];
$result = false;
if ($userId > 0)
{
$set = CCalendarUserSettings::Get($userId);
$result = $set['meetSection'];
$section = false;
if ($result)
{
$section = CCalendarSect::GetList(
array('arFilter' => array('ID' => $result),
'checkPermissions' => false,
'getPermissions' => false
));
if($section && is_array($section) && is_array($section[0]))
{
$section = $section[0];
}
}
if($result && !$section)
$result = false;
if (!$result)
{
$res = CCalendarSect::GetList(array(
'arFilter' => array(
'CAL_TYPE' => 'user',
'OWNER_ID' => $userId
),
'checkPermissions' => false,
'getPermissions' => false
));
if ($res && count($res) > 0 && $res[0]['ID'])
$result = $res[0]['ID'];
if (!$result && $autoCreate)
{
$defCalendar = CCalendarSect::CreateDefault(array(
'type' => 'user',
'ownerId' => $userId
));
if ($defCalendar && $defCalendar['ID'] > 0)
$result = $defCalendar['ID'];
}
if($result)
{
$set['meetSection'] = $result;
CCalendarUserSettings::Set($set, $userId);
}
}
}
$actualResult = $result;
foreach(\Bitrix\Main\EventManager::getInstance()->findEventHandlers("calendar", "OnGetMeetingSectionForUser") as $event)
{
ExecuteModuleEventEx($event, array($userId, &$result));
}
if ($actualResult != $result)
{
$set['meetSection'] = $result;
CCalendarUserSettings::Set($set, $userId);
}
self::$meetingSections[$userId] = $result;
return $result;
}
public static function GetCrmSection($userId, $autoCreate = false)
{
if (isset(self::$crmSections[$userId]))
return self::$crmSections[$userId];
$result = false;
if ($userId > 0)
{
$set = CCalendarUserSettings::Get($userId);
$result = $set['crmSection'];
$section = false;
if ($result)
{
$section = CCalendarSect::GetList(
array('arFilter' => array('ID' => $result),
'checkPermissions' => false,
'getPermissions' => false
));
if($section && is_array($section) && is_array($section[0]))
{
$section = $section[0];
}
}
if($result && !$section)
$result = false;
if (!$result)
{
$res = CCalendarSect::GetList(array(
'arFilter' => array(
'CAL_TYPE' => 'user',
'OWNER_ID' => $userId
),
'checkPermissions' => false,
'getPermissions' => false
));
if ($res && count($res) > 0 && $res[0]['ID'])
$result = $res[0]['ID'];
if (!$result && $autoCreate)
{
$defCalendar = CCalendarSect::CreateDefault(array(
'type' => 'user',
'ownerId' => $userId
));
if ($defCalendar && $defCalendar['ID'] > 0)
$result = $defCalendar['ID'];
}
if($result)
{
$set['crmSection'] = $result;
CCalendarUserSettings::Set($set, $userId);
}
}
}
self::$crmSections[$userId] = $result;
return $result;
}
public static function GetSectionList($params = array())
{
$type = isset($params['CAL_TYPE']) ? $params['CAL_TYPE'] : self::$type;
$arFilter = array(
'CAL_TYPE' => $type,
);
if (isset($params['OWNER_ID']))
$arFilter['OWNER_ID'] = $params['OWNER_ID'];
elseif ($type == 'user' || $type == 'group')
$arFilter['OWNER_ID'] = self::GetOwnerId();
if (isset($params['ACTIVE']))
$arFilter['ACTIVE'] = $params['ACTIVE'];
if (isset($params['ADDITIONAL_IDS']) && count($params['ADDITIONAL_IDS']) > 0)
$arFilter['ADDITIONAL_IDS'] = $params['ADDITIONAL_IDS'];
$res = CCalendarSect::GetList(
array(
'arFilter' => $arFilter,
'checkPermissions' => $params['checkPermissions'],
'getPermissions' => $params['getPermissions']
)
);
return $res;
}
public static function GetOwnerId()
{
return self::$ownerId;
}
public static function GetEventList($params = array(), &$arAttendees)
{
$type = isset($params['type']) ? $params['type'] : self::$type;
$ownerId = isset($params['ownerId']) ? $params['ownerId'] : self::$ownerId;
$userId = isset($params['userId']) ? $params['userId'] : self::$userId;
if ($type != 'user' && !isset($params['section']) || count($params['section']) <= 0)
return array();
$arFilter = array();
CCalendarEvent::SetLastAttendees(false);
if (isset($params['fromLimit']))
$arFilter["FROM_LIMIT"] = $params['fromLimit'];
if (isset($params['toLimit']))
$arFilter["TO_LIMIT"] = $params['toLimit'];
$arFilter["OWNER_ID"] = $ownerId;
if ($type == 'user')
{
$fetchMeetings = in_array(self::GetMeetingSection($ownerId), $params['section']);
}
else
{
$fetchMeetings = in_array(self::GetCurUserMeetingSection(), $params['section']);
if ($type)
{
$arFilter['CAL_TYPE'] = $type;
}
}
$res = CCalendarEvent::GetList(
array(
'arFilter' => $arFilter,
'parseRecursion' => true,
'fetchAttendees' => true,
'userId' => $userId,
'fetchMeetings' => $fetchMeetings,
'setDefaultLimit' => false,
'limit' => $params['limit']
)
);
if (count($params['section']) > 0)
{
$NewRes = array();
foreach($res as $event)
{
if (in_array($event['SECT_ID'], $params['section']))
{
unset($event['DESCRIPTION'], $event['~DESCRIPTION']);
$NewRes[] = $event;
}
}
$res = $NewRes;
}
$arAttendees = CCalendarEvent::GetLastAttendees();
return $res;
}
public static function getTaskList($params = array())
{
$res = array();
$arFilter = array(
'!STATUS' => array(
CTasks::STATE_DEFERRED,
),
'CHECK_PERMISSIONS' => 'Y'
);
if (self::$userSettings['showCompletedTasks'] == 'N')
{
$arFilter['!STATUS'][] = CTasks::STATE_COMPLETED;
}
if ($params['type'] == 'user')
{
$arFilter['DOER'] = $params['ownerId'];
}
elseif ($params['type'] == 'group')
{
$arFilter['GROUP_ID'] = $params['ownerId'];
}
$tzEnabled = CTimeZone::Enabled();
if($tzEnabled)
CTimeZone::Disable();
$mgrResult = \Bitrix\Tasks\Manager\Task::getList(
\Bitrix\Tasks\Util\User::getId(),
array(
'order' => array("START_DATE_PLAN" => "ASC"),
'select' => array("ID", "TITLE", "DESCRIPTION", "CREATED_DATE", "DEADLINE", "START_DATE_PLAN", "END_DATE_PLAN", "CLOSED_DATE", "STATUS_CHANGED_DATE", "STATUS", "REAL_STATUS"),
'legacyFilter' => $arFilter,
),
array()
);
$offset = CCalendar::GetOffset();
foreach ($mgrResult['DATA'] as $task)
{
$dtFrom = NULL;
$dtTo = NULL;
$skipFromOffset = false;
$skipToOffset = false;
if(isset($task["START_DATE_PLAN"]) && $task["START_DATE_PLAN"])
$dtFrom = CCalendar::CutZeroTime($task["START_DATE_PLAN"]);
if(isset($task["END_DATE_PLAN"]) && $task["END_DATE_PLAN"])
$dtTo = CCalendar::CutZeroTime($task["END_DATE_PLAN"]);
if(!isset($dtTo) && isset($task["CLOSED_DATE"]))
$dtTo = CCalendar::CutZeroTime($task["CLOSED_DATE"]);
//Task statuses: 1 - New, 2 - Pending, 3 - In Progress, 4 - Supposedly completed, 5 - Completed, 6 - Deferred, 7 - Declined
if(!isset($dtTo) && isset($task["STATUS_CHANGED_DATE"]) && in_array($task["REAL_STATUS"], array('4', '5', '6', '7')))
$dtTo = CCalendar::CutZeroTime($task["STATUS_CHANGED_DATE"]);
if(isset($dtTo))
{
$ts = CCalendar::Timestamp($dtTo); // Correction display logic for harmony with Tasks interfaces
if(date("H:i", $ts) == '00:00')
$dtTo = CCalendar::Date($ts - 24 * 60 * 60);
}
elseif(isset($task["DEADLINE"]))
{
$dtTo = CCalendar::CutZeroTime($task["DEADLINE"]);
$ts = CCalendar::Timestamp($dtTo); // Correction display logic for harmony with Tasks interfaces
if(date("H:i", $ts) == '00:00')
$dtTo = CCalendar::Date($ts - 24 * 60 * 60);
if(!isset($dtFrom))
{
$skipFromOffset = true;
$dtFrom = CCalendar::Date(time(), false);
}
}
if(!isset($dtTo))
$dtTo = CCalendar::Date(time(), false);
if(!isset($dtFrom))
$dtFrom = $dtTo;
$dtFromTS = CCalendar::Timestamp($dtFrom);
$dtToTS = CCalendar::Timestamp($dtTo);
if($dtToTS < $dtFromTS)
{
$dtToTS = $dtFromTS;
$dtTo = CCalendar::Date($dtToTS, true);
}
$skipTime = date("H:i", $dtFromTS) == '00:00' && date("H:i", $dtToTS) == '00:00';
if(!$skipTime && $offset != 0)
{
if(!$skipFromOffset)
{
$dtFromTS += $offset;
$dtFrom = CCalendar::Date($dtFromTS, true);
}
if(!$skipToOffset)
{
$dtToTS += $offset;
$dtTo = CCalendar::Date($dtToTS, true);
}
}
$res[] = array(
"ID" => $task["ID"],
"~TYPE" => "tasks",
"NAME" => $task["TITLE"],
"DATE_FROM" => $dtFrom,
"DATE_TO" => $dtTo,
"DT_SKIP_TIME" => $skipTime ? 'Y' : 'N',
"CAN_EDIT" => CTasks::CanCurrentUserEdit($task)
);
}
if($tzEnabled)
CTimeZone::Enable();
return $res;
}
public static function CutZeroTime($date)
{
if (preg_match('/.*\s\d\d:\d\d:\d\d/i', $date))
{
$date = trim($date);
if (substr($date, -9) == ' 00:00:00')
return substr($date, 0, -9);
if (substr($date, -3) == ':00')
return substr($date, 0, -3);
}
return $date;
}
public static function GetType()
{
return self::$type;
}
public static function GetAccessNames()
{
$arCodes = array();
foreach (self::$accessNames as $code => $name)
{
if ($name === null)
$arCodes[] = $code;
}
if ($arCodes)
{
$access = new CAccess();
$arNames = $access->GetNames($arCodes);
foreach($arNames as $code => $name)
{
self::$accessNames[$code] = trim(htmlspecialcharsbx($name['provider'].' '.$name['name']));
}
}
return self::$accessNames;
}
function TrimTime($strTime)
{
$strTime = trim($strTime);
$strTime = preg_replace("/:00$/", "", $strTime);
$strTime = preg_replace("/:00$/", "", $strTime);
$strTime = preg_replace("/\\s00$/", "", $strTime);
return rtrim($strTime);
}
public static function SetSilentErrorMode($silentErrorMode = true)
{
self::$silentErrorMode = $silentErrorMode;
}
public function GetId()
{
return self::$id ? self::$id : 'EC'.rand();
}
}
?>