403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/calendar/lib/rooms/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/calendar/lib/rooms/manager.php
<?php

namespace Bitrix\Calendar\Rooms;

use Bitrix\Calendar\Integration\Pull\PushCommand;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\Error;
use Bitrix\Calendar\Internals\AccessTable;
use Bitrix\Calendar\Internals\EventTable;
use Bitrix\Calendar\Internals\LocationTable;
use Bitrix\Calendar\Internals\SectionTable;
use Bitrix\Main\Localization\Loc;
use Bitrix\Calendar\UserSettings;
use Bitrix\Main\Entity\ReferenceField;
use Bitrix\Main\EventManager;
use Bitrix\Main\ObjectPropertyException;
use Bitrix\Main\ORM\Query;
use Bitrix\Main\SystemException;
use Bitrix\Main\Text\Emoji;

Loc::loadMessages(__FILE__);

class Manager
{
	public const TYPE = 'location';

	/** @var Room|null $room */
	private ?Room $room = null;
	/** @var Error|null $error */
	private ?Error $error = null;

	protected function __construct()
	{
	}

	/**
	 * @param Room $room
	 *
	 * @return Manager
	 */
	public static function createInstanceWithRoom(Room $room): Manager
	{
		return (new self())->setRoom($room);
	}

	/**
	 * @return Manager
	 */
	public static function createInstance(): Manager
	{
		return new self;
	}

	/**
	 * @param Room $room
	 *
	 * @return Manager
	 */
	private function setRoom(Room $room): Manager
	{
		$this->room = $room;

		return $this;
	}

	/**
	 * @param Error $error
	 *
	 * @return void
	 */
	private function addError(Error $error): void
	{
		$this->error = $error;
	}

	public function getError(): ?Error
	{
		return $this->error;
	}

	/**
	 * Creating Room in Location Calendar
	 *
	 * @return Manager
	 * @throws \Exception
	 */
	public function createRoom(): Manager
	{
		if ($this->error)
		{
			return $this;
		}

		$this->room->create();

		if ($this->room->getError())
		{
			$this->addError($this->room->getError());
		}

		return $this;
	}

	/**
	 * Updating data of room in Location calendar
	 *
	 * @return Manager
	 * @throws \Exception
	 */
	public function updateRoom(): Manager
	{
		if ($this->error)
		{
			return $this;
		}

		$this->room->update();

		if ($this->room->getError())
		{
			$this->addError($this->room->getError());
		}

		return $this;
	}

	/**
	 * Deleting room by id in Location calendar
	 *
	 * @return Manager
	 * @throws \Exception
	 */
	public function deleteRoom(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		if (!$this->room->getName())
		{
			$this->room->setName($this->getRoomName($this->room->getId()));
		}

		$this->room->delete();

		if ($this->room->getError())
		{
			$this->addError($this->room->getError());
		}

		return $this;
	}

	/**
	 * @return array|null
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public static function getRoomsList(): ?array
	{
		$roomQuery = LocationTable::query()
			->setSelect([
				'LOCATION_ID' => 'ID',
				'NECESSITY',
	            'CAPACITY',
				'SECTION_ID',
				'CATEGORY_ID',
				'NAME' => 'SECTION.NAME',
				'COLOR' => 'SECTION.COLOR',
				'OWNER_ID' => 'SECTION.OWNER_ID',
				'CAL_TYPE' => 'SECTION.CAL_TYPE',
            ])
			->registerRuntimeField('SECTION',
               new ReferenceField(
                   'SECTION',
                   SectionTable::getEntity(),
                   Query\Join::on('ref.ID', 'this.SECTION_ID'),
                   ['join_type' => Query\Join::TYPE_INNER]
               )
			)
			->setOrder(['ID' => 'ASC'])
			->cacheJoins(true)
			->setCacheTtl(86400)
			->exec()
		;

		[$roomsId, $result] = self::prepareRoomsQueryData($roomQuery);

		if (empty($result))
		{
			\CCalendarSect::CreateDefault([
				'type' => self::TYPE,
				'ownerId' => 0
			]);
			LocationTable::cleanCache();

			return null;
		}

		$result = self::getRoomsAccess($roomsId, $result);

		foreach ($result as $room)
		{
			\CCalendarSect::HandlePermission($room);
		}

		return \CCalendarSect::GetSectionPermission($result);
	}

	/**
	 * @param int $id
	 * @param array $params
	 * @return array
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public static function getRoomById(int $id, array $params = []): array
	{
		$roomQuery = LocationTable::query()
			->setSelect([
				'LOCATION_ID' => 'ID',
				'NECESSITY',
				'CAPACITY',
				'SECTION_ID',
				'CATEGORY_ID',
				'NAME' => 'SECTION.NAME',
				'COLOR' => 'SECTION.COLOR',
				'OWNER_ID' => 'SECTION.OWNER_ID',
				'CAL_TYPE' => 'SECTION.CAL_TYPE',
			])
			->where('SECTION.ID', $id)
			->registerRuntimeField('SECTION',
				new ReferenceField(
					'SECTION',
					SectionTable::getEntity(),
					Query\Join::on('ref.ID', 'this.SECTION_ID'),
					['join_type' => Query\Join::TYPE_INNER]
				)
			)
			->cacheJoins(true)
			->setCacheTtl(86400)
			->exec()
		;

		[$roomsId, $result] = self::prepareRoomsQueryData($roomQuery);
		$result = self::getRoomsAccess($roomsId, $result);

		foreach ($result as $room)
		{
			\CCalendarSect::HandlePermission($room);
		}

		$applyPermission = $params['checkPermission'] ?? true;
		if ($applyPermission !== false)
		{
			return \CCalendarSect::GetSectionPermission($result);
		}

		return [...$result];
	}

	/**
	 * @param array $params
	 *
	 * @return int|null
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 * @throws \Bitrix\Main\LoaderException
	 */
	public static function reserveRoom(array $params = []): ?int
	{
		$params['checkPermission'] = $params['checkPermission'] ?? null;
		$params['room_id'] = $params['room_id'] ?? null;
		$roomList = self::getRoomById((int)$params['room_id'], ['checkPermission' => $params['checkPermission']]);

		if (
			!$roomList || empty($roomList[0])
			|| empty($roomList[0]['NAME'])
			|| (
				empty($roomList[0]['PERM']['view_full'])
				&& $params['checkPermission'] !== false
			)
		)
		{
			return null;
		}

		$createdBy = $params['parentParams']['arFields']['CREATED_BY']
			?? $params['parentParams']['arFields']['MEETING_HOST']
			?? null
		;

		$arFields = [
			'ID' => $params['room_event_id'] ?? null,
			'SECTIONS' => $params['room_id'] ?? null,
			'DATE_FROM' => $params['parentParams']['arFields']['DATE_FROM'] ?? null,
			'DATE_TO' => $params['parentParams']['arFields']['DATE_TO'] ?? null,
			'TZ_FROM' => $params['parentParams']['arFields']['TZ_FROM'] ?? null,
			'TZ_TO' => $params['parentParams']['arFields']['TZ_TO'] ?? null,
			'SKIP_TIME' => $params['parentParams']['arFields']['SKIP_TIME'] ?? null,
			'RRULE' => $params['parentParams']['arFields']['RRULE'] ?? null,
			'EXDATE' => $params['parentParams']['arFields']['EXDATE'] ?? null,
		];

		if (!$params['room_event_id'])
		{
			$arFields['CREATED_BY'] = $createdBy;
			$arFields['NAME'] = \CCalendar::GetUserName($createdBy);
			$arFields['CAL_TYPE'] = self::TYPE;
		}

		return \CCalendarEvent::Edit([
			'arFields' => $arFields,
		]);
	}

	/**
	 * @param array $params
	 *
	 * Cancel booking of room
	 *
	 * @return Manager
	 * @throws \Bitrix\Main\ObjectException
	 */
	public function cancelBooking(array $params = []): Manager
	{
		$params = [
			'recursion_mode' => $params['recursion_mode'] ?? null,
			'parent_event_id' => $params['parent_event_id'] ?? null,
			'section_id' => $params['section_id'] ?? null,
			'current_event_date_from' => $params['current_event_date_from'] ?? null,
			'current_event_date_to' => $params['current_event_date_to'] ?? null,
			'owner_id' => $params['owner_id'] ?? null,
		];

		if($this->getError() !== null)
		{
			return $this;
		}

		if($params['recursion_mode'] === 'all' || $params['recursion_mode'] === 'next')
		{
			$event = \CCalendarEvent::GetById($params['parent_event_id']);

			$params['frequency'] = $event['RRULE']['FREQ'] ?? null;
			if($params['recursion_mode'] === 'all')
			{
				$params['current_event_date_from'] = $event['DATE_FROM'] ?? null;
				$params['current_event_date_to'] = $event['DATE_TO'] ?? null;
			}
		}

		$result = \CCalendar::SaveEventEx([
			'recursionEditMode' => $params['recursion_mode'],
			'currentEventDateFrom' => $params['current_event_date_from'],
			'checkPermission' => false,
			'sendInvitations' => false,
			'userId' => $params['owner_id'],
			'arFields' => [
				'ID' => $params['parent_event_id'],
				'DATE_FROM' => $params['current_event_date_from'],
				'DATE_TO' => $params['current_event_date_to'],
				'LOCATION' => '',
			],
		]);

		$params['event_id'] = $result['recEventId'] ?? $result['id'] ?? null;

		$this->sendCancelBookingNotification($params);
		return $this;
	}

	private function sendCancelBookingNotification(array $params): void
	{
		$params = [
			'section_id' => $params['section_id'],
			'event_id' => $params['event_id'],
			'owner_id' => $params['owner_id'],
			'current_event_date_from' => $params['current_event_date_from'],
			'recursion_mode' => $params['recursion_mode'],
		];

		$section = \CCalendarSect::GetById($params['section_id']);
		$userId = \CCalendar::GetCurUserId();
		$event = \CCalendarEvent::GetById($params['event_id'], false);

		\CCalendarNotify::Send([
			'eventId' => $params['event_id'],
			'mode' => 'cancel_booking',
			'location' => $section['NAME'] ?? null,
			'locationId' => $params['section_id'],
			'guestId' => $params['owner_id'],
			'userId' => $userId,
			'from' => $params['current_event_date_from'],
			'eventName' => $event['NAME'] ?? null,
			'recursionMode' => $params['recursion_mode'],
			'fields' => $event,
		]);
	}

	/**
	 * @param array $params
	 *
	 * Deleting event from calendar location
	 *
	 * @return bool|string
	 */
	public static function releaseRoom(array $params = [])
	{
		return \CCalendar::DeleteEvent(
			(int)($params['room_event_id'] ?? null),
			false,
			[
				'checkPermissions' => false,
				'markDeleted' => false
			]
		);
	}

	/**
	 * @return Manager
	 *
	 * Clears cache for updating list of rooms on the page
	 */
	public function clearCache(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		\CCalendarSect::SetClearOperationCache(true);
		\CCalendar::clearCache([
			'section_list',
			'event_list'
		]);
		LocationTable::cleanCache();

		return $this;
	}

	/**
	 * @return Manager
	 */
	public function cleanAccessTable(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		\CCalendarSect::CleanAccessTable($this->room->getId());

		return $this;
	}

	/**
	 * @param int $id
	 *
	 * Setting id of new event in user calendar
	 * for event in location calendar
	 * @param string|null $location
	 * @return void
	 * @throws ArgumentException
	 * @throws ObjectPropertyException
	 * @throws SystemException
	 */
	public static function setEventIdForLocation(int $id, ?string $location = null): void
	{
		if (empty($location))
		{
			$event = EventTable::query()
				->setSelect(['LOCATION'])
				->where('ID', $id)
				->exec()->fetch()
			;

			$location = $event['LOCATION'] ?? null;
		}

		if (!empty($location))
		{
			$parsedLocation = Util::parseLocation($location);
			if ($parsedLocation['room_id'] && $parsedLocation['room_event_id'])
			{
				EventTable::update($parsedLocation['room_event_id'], [
					'PARENT_ID' => $id,
				]);
			}
		}
	}

	/**
	 * Preparing data with rooms and sections for ajax-actions
	 *
	 * @return array
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public function prepareResponseData(): array
	{
		$result = [];

		$result['rooms'] = self::getRoomsList();
		$sectionList = \CCalendar::GetSectionList([
			'CAL_TYPE' => self::TYPE,
			'OWNER_ID' => 0,
			'checkPermissions' => true,
			'getPermissions' => true,
			'getImages' => true
		]);
		$sectionList = array_merge(
			$sectionList,
			\CCalendar::getSectionListAvailableForUser(\CCalendar::GetUserId())
		);
		$result['sections'] = $sectionList;

		return $result;
	}

	/**
	 * @return array|null
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public static function prepareRoomManagerData(): ?array
	{
		$userId = \CCalendar::GetUserId();
		$result = [];

		// here we collects permissions cache for rooms @see \CCalendarSect::HandlePermission,
		// if it not collected here and further @see \CCalendar::GetSectionList called with getPermissions => false,
		// then permissions will not be correct (would be just empty)
		$result['rooms'] = self::getRoomsList();

		$followedSectionList = UserSettings::getFollowedSectionIdList($userId);
		$sectionList = \CCalendar::GetSectionList([
			'CAL_TYPE' => self::TYPE,
			'OWNER_ID' => 0,
			'ADDITIONAL_IDS' => $followedSectionList,
			'getPermissions' => false,
		]);
		$sectionList = array_merge($sectionList, \CCalendar::getSectionListAvailableForUser($userId));

		$sectionAccessTasks = \CCalendar::GetAccessTasks('calendar_section', 'location');
		$hiddenSections = UserSettings::getHiddenSections(
			$userId,
			[
				'type' => self::TYPE,
				'ownerId' => 0,
			]
		);
		$defaultSectionAccess = \CCalendarSect::GetDefaultAccess(
			self::TYPE,
			$userId
		);

		$result['sections'] = $sectionList;
		$result['config'] = [
			'locationAccess' => Util::getLocationAccess($userId),
			'hiddenSections' => $hiddenSections,
			'type' => self::TYPE,
			'ownerId' => 0,
			'userId' => $userId,
			'defaultSectionAccess' => $defaultSectionAccess,
			'sectionAccessTasks' => $sectionAccessTasks,
			'showTasks' => false,
			'accessNames' => \CCalendar::GetAccessNames(),
		];

		return $result;
	}

	/**
	 * @param $handler
	 *
	 * @return Manager
	 */
	public function eventHandler($handler): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		foreach(EventManager::getInstance()->findEventHandlers('calendar', $handler) as $event)
		{
			ExecuteModuleEventEx($event, [
				$this->room->getId(),
			]);
		}

		return $this;
	}

	public function addPullEvent(PushCommand $event): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		\Bitrix\Calendar\Util::addPullEvent(
			$event,
			$this->room->getCreatedBy(),
			[
				'ID' => $this->room->getId()
			]
		);

		return $this;
	}

	/**
	 * @param int $id
	 *
	 * @return string|null
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	private function getRoomName(int $id): ?string
	{
		$section = SectionTable::query()
			->setSelect(['NAME'])
			->where('ID', $id)
			->exec()->fetch()
		;

		return $section ? $section['NAME'] : null;
	}

	/**
	 * @param $name
	 * Validation for name of room
	 *
	 * @return string|null
	 */
	public static function checkRoomName(?string $name): ?string
	{
		if (!$name)
		{
			return '';
		}

		$name = trim($name);

		if (empty($name))
		{
			return '';
		}

		return $name;
	}

	/**
	 * Delete location value when deleting room
	 *
	 * @return $this
	 */
	public function deleteLocationFromEvents(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		$guestsId = [];
		$eventsId = [];
		$id = $this->room->getId();
		$locationName = $this->room->getName();
		$locationId = 'calendar_' . $id;

		$events = EventTable::query()
			->setSelect(['ID', 'PARENT_ID', 'OWNER_ID', 'CREATED_BY', 'LOCATION'])
			->whereLike('LOCATION', $locationId. '%')
			->exec()
		;

		while ($event = $events->fetch())
		{
			if ($event['ID'] === $event['PARENT_ID'])
			{
				$guestsId[] = $event['OWNER_ID'];
			}

			$eventsId[] = $event['ID'];
		}

		if (!empty($eventsId))
		{
			EventTable::updateMulti($eventsId, ['LOCATION' => '']);

			$guestsId = array_unique($guestsId);
			$userId = \CCalendar::GetCurUserId();

			foreach ($guestsId as $guestId)
			{
				\CCalendarNotify::Send([
					'mode' => 'delete_location',
					'location' => $locationName,
					'locationId' => $id,
					'guestId' => (int)$guestId,
					'userId' => $userId,
				]);
			}
		}

		return $this;
	}

	/**
	 * @return $this
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public function pullDeleteEvents(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		$events = self::getLocationEventsId($this->room->getId());

		foreach ($events as $event)
		{
			if ($this->room->getCreatedBy())
			{
				\Bitrix\Calendar\Util::addPullEvent(
					PushCommand::DeleteEvent,
					$this->room->getCreatedBy(),
					['fields' => $event]
				);
			}
		}

		return $this;
	}

	/**
	 * @return Manager
	 */
	public function deleteEmptyEvents(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		\CCalendarEvent::DeleteEmpty($this->room->getId());

		return $this;
	}

	/**
	 * @param int $roomId
	 *
	 * @return array of location events id with a given id
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	private static function getLocationEventsId(int $roomId): array
	{
		return EventTable::query()
			->setSelect([
	            'ID',
	            'CREATED_BY',
	            'PARENT_ID',
			])
			->where('SECTION_ID', $roomId)
			->where('DELETED', 'N')
			->exec()->fetchAll()
		;
	}

	/**
	 * @return Manager
	 */
	public function saveAccess(): Manager
	{
		if ($this->getError())
		{
			return $this;
		}

		$access = $this->room->getAccess();
		$id = $this->room->getId();

		if (!empty($access))
		{
			\CCalendarSect::SavePermissions(
				$id,
				$access
			);
		}
		else
		{
			\CCalendarSect::SavePermissions(
				$id,
				\CCalendarSect::GetDefaultAccess(
					$this->room->getType(),
					$this->room->getCreatedBy()
				)
			);
		}

		return $this;
	}

	/**
	 * @param Query\Result $query
	 *
	 * @return array
	 */
	private static function prepareRoomsQueryData(Query\Result $query): array
	{
		$roomsId = [];
		$result = [];

		while ($room = $query->fetch())
		{
			$room['ID'] = $room['SECTION_ID'];
			unset($room['SECTION_ID']);

			if (!empty($room['NAME']))
			{
				$room['NAME'] = Emoji::decode($room['NAME']);
			}
			$roomId = (int)$room['ID'];
			$roomsId[] = $roomId;
			$result[$roomId] = $room;
		}

		return [$roomsId, $result];
	}

	/**
	 * @param array $roomsId
	 * @param array $rooms
	 *
	 * @return array
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	private static function getRoomsAccess(array $roomsId, array $rooms): array
	{
		if (empty($roomsId))
		{
			return [];
		}

		$accessQuery = AccessTable::query()
			->setSelect([
				'ACCESS_CODE',
				'TASK_ID',
				'SECT_ID'
			])
			->whereIn('SECT_ID', $roomsId)
			->exec()
		;

		while ($access = $accessQuery->fetch())
		{
			if (!isset($rooms[$access['SECT_ID']]['ACCESS']))
			{
				$rooms[$access['SECT_ID']]['ACCESS'] = [];
			}
			$rooms[$access['SECT_ID']]['ACCESS'][$access['ACCESS_CODE']] = (int)$access['TASK_ID'];
		}

		return $rooms;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit