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/ilovecveti.ru/bitrix/modules/calendar/lib/sync/icloud/ |
Upload File : |
<?php namespace Bitrix\Calendar\Sync\Icloud; use Bitrix\Calendar\Core\Builders\EventBuilderFromEntityObject; use Bitrix\Calendar\Core\Builders\EventCloner; use Bitrix\Calendar\Core\Event\Event; use Bitrix\Calendar\Core\Section\Section; use Bitrix\Calendar\Core\Base\Date; use Bitrix\Calendar\Internals\EventTable; use Bitrix\Calendar\Sync\Entities\SyncEvent; use Bitrix\Dav\Integration\Calendar\RecurrenceEventBuilder; use Bitrix\Main\ORM\Query\Query; class ApiService { /** @var ?ApiClient $apiClient */ protected ?ApiClient $apiClient = null; /** @var ?\CDavGroupdavClientCalendar $davClient */ protected ?\CDavGroupdavClientCalendar $davClient = null; /** @var Helper $helper */ protected Helper $helper; /** @var ?array $error */ protected ?array $error = null; /** * @param array $server * @param int|null $userId * * @throws \Bitrix\Main\ArgumentNullException */ public function __construct(array $server = [], int $userId = null) { $this->helper = new Helper(); if ($server) { $this->davClient = $this->createDavInstance( $server['SERVER_SCHEME'], $server['SERVER_HOST'], $server['SERVER_PORT'], $server['SERVER_USERNAME'], $server['SERVER_PASSWORD'] ); $this->apiClient = new ApiClient($this->davClient, $userId); } } /** * @param $connection * @param $server * * @return string|null * @throws \Bitrix\Main\ArgumentNullException */ public function getPrinciples($connection, $server): ?string { $userId = \CCalendar::GetUserId(); $davClient = $this->createDavInstance( $server['scheme'], $server['host'], $server['port'], $connection['SERVER_USERNAME'], $connection['SERVER_PASSWORD'] ); $this->apiClient = new ApiClient($davClient, $userId); $principlesXml = $this->apiClient->propfind( $server['path'], ['current-user-principal'], null, 0 ); if ($principlesXml) { return $this->getXmlStringData( $principlesXml, '/response/propstat/prop/current-user-principal/href' ); } return null; } /** * @param $connection * @param $server * * @return string|null * @throws \Bitrix\Main\ArgumentNullException */ public function getCalendarPath($connection, $server): ?string { $userId = \CCalendar::GetUserId(); $davClient = $this->createDavInstance( $server['scheme'], $server['host'], $server['port'], $connection['SERVER_USERNAME'], $connection['SERVER_PASSWORD'] ); $this->apiClient = new ApiClient($davClient, $userId); $calendarXml = $this->apiClient->propfind( $server['path'], [['calendar-home-set', 'urn:ietf:params:xml:ns:caldav']], null, 0 ); if ($calendarXml) { return $this->getXmlStringData( $calendarXml, '/response/propstat/prop/calendar-home-set/href' ); } return null; } /** * @param $connection * @param $server * * @return array|null */ public function getCalendarList($connection, $server): ?array { $davClient = $this->createDavInstance( $server['scheme'], $server['host'], $server['port'], $connection['SERVER_USERNAME'], $connection['SERVER_PASSWORD'] ); $calendars = $davClient->GetCalendarList($server['path']); if (!is_array($calendars) || empty($calendars)) { return null; } return $calendars; } /** * @param string $path * @param Event $event * * @return array|null * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ public function createEvent(string $path, Event $event): ?array { $event->setUid(VendorSyncService::generateUuid()); $xmlId = $event->getUid(); return $this->editEvent($path, $xmlId, $event); } /** * @param string $path * @param Event $event * @param array|null $data * * @return array|null * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ public function updateEvent(string $path, Event $event, ?array $data): ?array { $xmlId = $event->getUid(); if (!$xmlId) { return null; } if ($event->getExcludedDateCollection()->getCollection()) { return $this->saveInstance($path, $event, $data); } $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId); return $this->editEvent($eventPath, $xmlId, $event, $data); } /** * @param string $path * @param Event $event * * @return bool|null * @throws \Bitrix\Main\LoaderException */ public function deleteEvent(string $path, Event $event): ?bool { $xmlId = $event->getUid(); $acceptCodes = [200, 201, 204, 404]; if (!$xmlId) { return null; } $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId); $result = (int)$this->apiClient->delete($eventPath); if ($this->davClient->getError()) { $this->addError($this->davClient->getError()); } if (in_array($result, $acceptCodes)) { return true; } return null; } /** * @param string $path * @param Event $event * @param array|null $data * @param Date|null $excludeDate * * @return array|null * * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ public function saveInstance(string $path, Event $event, ?array $data, Date $excludeDate = null): ?array { $xmlId = $event->getUid(); if (!$xmlId) { return null; } $event = (new EventCloner($event))->build(); [$eventPath, $calendarData] = $this->prepareInstanceData($event, $path, $xmlId, $data, $excludeDate); return $this->sendPutAction($eventPath, $calendarData); } /** * @param string $path * @param SyncEvent $recurrenceEvent * * @return array|null * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ public function saveRecurrence(string $path, SyncEvent $recurrenceEvent): ?array { if (!$recurrenceEvent->getEvent()->getUid()) { $recurrenceEvent->getEvent()->setUid(VendorSyncService::generateUuid()); } $xmlId = $recurrenceEvent->getEvent()->getUid(); [$eventPath, $calendarData] = $this->prepareRecurrenceData($recurrenceEvent, $path, $xmlId); return $this->sendPutAction($eventPath, $calendarData); } /** * @param string $path * @param Section $section * * @return array|null * @throws \Bitrix\Main\LoaderException */ public function createSection(string $path, Section $section): ?array { $content = SectionBuilder::getInstance()->getCreateSectionContent($section); $result = (int)$this->apiClient->mkcol($path, $content); if ($this->davClient->getError()) { $this->addError($this->davClient->getError()); } if ($result === 200 || $result === 201) { $result = $this->davClient->GetCalendarList($path); if ($result && is_array($result)) { return [ 'XML_ID' => $result[0]['href'], 'MODIFICATION_LABEL' => $result[0]['getctag'], ]; } } return null; } /** * @param string $path * @param Section $section * * @return array|int[]|null * @throws \Bitrix\Main\LoaderException */ public function updateSection(string $path, Section $section): ?array { $content = SectionBuilder::getInstance()->getUpdateSectionContent($section); $result = (int)$this->apiClient->proppatch($path, $content); if ($this->davClient->getError()) { $this->addError($this->davClient->getError()); } if ($result === 207) { $result = $this->davClient->GetCalendarList($path); if ($result && is_array($result)) { return [ 'XML_ID' => $result[0]['href'], 'MODIFICATION_LABEL' => $result[0]['getctag'], ]; } } else { return [ 'ERROR' => $result, ]; } return null; } /** * @param string $path * * @return bool|null * @throws \Bitrix\Main\LoaderException */ public function deleteSection(string $path): ?bool { $result = (int)$this->apiClient->delete($path); if ($this->davClient->getError()) { $this->addError($this->davClient->getError()); } $acceptCodes = [200, 201, 204, 404]; if (in_array($result, $acceptCodes)) { return true; } return null; } public function getSectionsList($path) { return $this->davClient->GetCalendarList($path); } public function getEventsList($path, $syncToken): ?array { return $this->davClient->GetCalendarItemsBySyncToken($path, $syncToken); } public function getEventsListWithHref($path, $hrefs): ?array { return $this->davClient->GetCalendarItemsList($path, $hrefs, true); } public function prepareUrl(string $url): array { $parsed = parse_url($url); if (empty($parsed['port'])) { $parsed['port'] = ($parsed['scheme'] === 'https' ? 443 : 80 ); } return $parsed; } /** * @param $xml * @param $path * * @return string */ private function getXmlStringData($xml, $path): string { $data = ''; $responsePath = $xml->GetPath('/*/response'); foreach ($responsePath as $response) { if (!$data) { $dataXml = $response->GetPath($path); if (!empty($dataXml)) { $data = urldecode($dataXml[0]->GetContent()); } } } return $data; } /** * @param string $scheme * @param string $host * @param string $port * @param string $username * @param string $password * * @return \CDavGroupdavClientCalendar */ private function createDavInstance( string $scheme, string $host, string $port, string $username, string $password ): \CDavGroupdavClientCalendar { $davClient = new \CDavGroupdavClientCalendar( $scheme, $host, $port, $username, $password, ); $davClient->SetPrivateIp(false); return $davClient; } /** * @param string $path * @param string|null $xmlId * * @return string */ private function getPath(string $path, ?string $xmlId): string { if (mb_substr($path, -mb_strlen('/' . $xmlId . '.ics')) != '/' . $xmlId . '.ics') { $path = rtrim($path, '/'); $path .= '/' . $xmlId . '.ics'; } return $path; } /** * @param string $path * @param string|null $xmlId * @param Event $event * @param array|null $data * * @return array|null * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ private function editEvent( string $path, ?string $xmlId, Event $event, ?array $data = null ): ?array { $path = $this->getPath($path, $xmlId); $calendarData = EventBuilder::getInstance()->getContent($event, $data); if ($calendarData) { $calendarData = (new \CDavICalendar($calendarData))->Render(); } return $this->sendPutAction($path, $calendarData); } /** * @param Event $event * @param string $path * @param string $xmlId * @param array|null $data * @param Date|null $excludeDate * * @return array * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ private function prepareInstanceData( Event $event, string $path, string $xmlId, ?array $data, Date $excludeDate = null ): array { $instancesOriginalDate = []; $exDates = $event->getExcludedDateCollection(); $excludedInstance = $excludeDate?->format('Ymd'); $instances = EventTable::query() ->setSelect(['*']) ->where('RECURRENCE_ID', $event->getParentId()) ->where('DELETED', 'N') ->where('OWNER_ID', $event->getOwner()->getId()) ->where(Query::filter() // TODO: it's better to optimize it and don't use 'OR' logic here ->logic('or') ->whereNot('MEETING_STATUS', 'N') ->whereNull('MEETING_STATUS') ) ->exec()->fetchCollection() ; foreach ($instances as $instance) { $originalDate = $instance->getOriginalDateFrom() ? $instance->getOriginalDateFrom()->format('Ymd') : $instance->getDateFrom()->format('Ymd') ; if ($originalDate === $excludedInstance) { $instances->remove($instance); continue; } $instancesOriginalDate[] = $originalDate; } if ($exDates) { /** * @var int $key * @var Date $exDate */ foreach ($exDates->getCollection() as $key => $exDate) { if (in_array($exDate->format('Ymd'), $instancesOriginalDate, true)) { $exDates->remove($key); } } $event->setExcludedDateCollection($exDates); } $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId); $eventPath = $this->getPath($eventPath, $xmlId); $calendarData[] = EventBuilder::getInstance()->getContent($event, $data); foreach ($instances as $instance) { $instanceObject = (new EventBuilderFromEntityObject($instance))->build(); $instanceObject->setUid($xmlId); $calendarData[] = EventBuilder::getInstance()->getContent($instanceObject, $data); } if ($calendarData) { $calendarData = (new RecurrenceEventBuilder($calendarData))->Render(); } return [$eventPath, $calendarData]; } /** * @param SyncEvent $recurrenceEvent * @param string $path * @param $xmlId * * @return array * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException * @throws \Bitrix\Main\ObjectPropertyException * @throws \Bitrix\Main\SystemException */ private function prepareRecurrenceData(SyncEvent $recurrenceEvent, string $path, $xmlId): array { $instanceDates = []; $exDates = $recurrenceEvent->getEvent()->getExcludedDateCollection(); /** @var SyncEvent $instance */ foreach ($recurrenceEvent->getInstanceMap()->getCollection() as $instance) { $instanceDates[] = $instance->getEvent()->getOriginalDateFrom() ? $instance->getEvent()->getOriginalDateFrom()->format('Ymd') : $instance->getEvent()->getStart()->format('Ymd') ; } if ($exDates) { /** * @var int $key * @var Date $date */ foreach ($exDates->getCollection() as $key => $date) { if (in_array($date->format('Ymd'), $instanceDates, true)) { $exDates->remove($key); } } $recurrenceEvent->getEvent()->setExcludedDateCollection($exDates); } $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId); $eventPath = $this->getPath($eventPath, $xmlId); $calendarData[] = EventBuilder::getInstance()->getContent($recurrenceEvent->getEvent()); foreach ($recurrenceEvent->getInstanceMap()->getCollection() as $instance) { $instance->getEvent()->setUid($xmlId); $calendarData[] = EventBuilder::getInstance()->getContent($instance->getEvent()); } if ($calendarData) { $calendarData = (new RecurrenceEventBuilder($calendarData))->Render(); } return [$eventPath, $calendarData]; } /** * @param string $path * @param $calendarData * * @return array|null * @throws \Bitrix\Main\LoaderException */ private function sendPutAction(string $path, $calendarData): ?array { $result = (int)$this->apiClient->put($path, $calendarData); if ($this->davClient->getError()) { $this->addError($this->davClient->getError()); } if ($result === 201 || $result === 204) { $result = $this->davClient->GetCalendarItemsList( $path, null, false, 2 ); if ($result && is_array($result)) { return [ 'XML_ID' => $this->davClient::getBasenameWithoutExtension($result[0]['href']), 'MODIFICATION_LABEL' => $result[0]['getetag'], ]; } } return null; } /** * @param array $error * @return void */ private function addError(array $error) { $this->error = $error; } /** * @return array|null */ public function getError(): ?array { return $this->error; } }