1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
apiservice.php
См. документацию.
1<?php
2
3namespace Bitrix\Calendar\Sync\Icloud;
4
5use Bitrix\Calendar\Core\Builders\EventBuilderFromEntityObject;
6use Bitrix\Calendar\Core\Builders\EventCloner;
7use Bitrix\Calendar\Core\Event\Event;
8use Bitrix\Calendar\Core\Section\Section;
9use Bitrix\Calendar\Core\Base\Date;
10use Bitrix\Calendar\Internals\EventTable;
11use Bitrix\Calendar\Sync\Entities\SyncEvent;
12use Bitrix\Dav\Integration\Calendar\RecurrenceEventBuilder;
13use Bitrix\Main\ORM\Query\Query;
14
16{
18 protected ?ApiClient $apiClient = null;
20 protected ?\CDavGroupdavClientCalendar $davClient = null;
22 protected Helper $helper;
24 protected ?array $error = null;
25
32 public function __construct(array $server = [], int $userId = null)
33 {
34 $this->helper = new Helper();
35 if ($server)
36 {
37 $this->davClient = $this->createDavInstance(
38 $server['SERVER_SCHEME'],
39 $server['SERVER_HOST'],
40 $server['SERVER_PORT'],
41 $server['SERVER_USERNAME'],
42 $server['SERVER_PASSWORD']
43 );
44
45 $this->apiClient = new ApiClient($this->davClient, $userId);
46 }
47 }
48
56 public function getPrinciples($connection, $server): ?string
57 {
58 $userId = \CCalendar::GetUserId();
59 $davClient = $this->createDavInstance(
60 $server['scheme'],
61 $server['host'],
62 $server['port'],
63 $connection['SERVER_USERNAME'],
64 $connection['SERVER_PASSWORD']
65 );
66
67 $this->apiClient = new ApiClient($davClient, $userId);
68 $principlesXml = $this->apiClient->propfind(
69 $server['path'],
70 ['current-user-principal'],
71 null,
72 0
73 );
74 if ($principlesXml)
75 {
76 return $this->getXmlStringData(
77 $principlesXml,
78 '/response/propstat/prop/current-user-principal/href'
79 );
80 }
81
82 return null;
83 }
84
92 public function getCalendarPath($connection, $server): ?string
93 {
94 $userId = \CCalendar::GetUserId();
95 $davClient = $this->createDavInstance(
96 $server['scheme'],
97 $server['host'],
98 $server['port'],
99 $connection['SERVER_USERNAME'],
100 $connection['SERVER_PASSWORD']
101 );
102
103 $this->apiClient = new ApiClient($davClient, $userId);
104 $calendarXml = $this->apiClient->propfind(
105 $server['path'],
106 [['calendar-home-set', 'urn:ietf:params:xml:ns:caldav']],
107 null,
108 0
109 );
110
111 if ($calendarXml)
112 {
113 return $this->getXmlStringData(
114 $calendarXml,
115 '/response/propstat/prop/calendar-home-set/href'
116 );
117 }
118
119 return null;
120 }
121
128 public function getCalendarList($connection, $server): ?array
129 {
130 $davClient = $this->createDavInstance(
131 $server['scheme'],
132 $server['host'],
133 $server['port'],
134 $connection['SERVER_USERNAME'],
135 $connection['SERVER_PASSWORD']
136 );
137
138 $calendars = $davClient->GetCalendarList($server['path']);
139 if (!is_array($calendars) || empty($calendars))
140 {
141 return null;
142 }
143
144 return $calendars;
145 }
146
157 public function createEvent(string $path, Event $event): ?array
158 {
160 $xmlId = $event->getUid();
161
162 return $this->editEvent($path, $xmlId, $event);
163 }
164
176 public function updateEvent(string $path, Event $event, ?array $data): ?array
177 {
178 $xmlId = $event->getUid();
179 if (!$xmlId)
180 {
181 return null;
182 }
183
184 if ($event->getExcludedDateCollection()->getCollection())
185 {
186 return $this->saveInstance($path, $event, $data);
187 }
188
189 $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId);
190
191 return $this->editEvent($eventPath, $xmlId, $event, $data);
192 }
193
201 public function deleteEvent(string $path, Event $event): ?bool
202 {
203 $xmlId = $event->getUid();
204 $acceptCodes = [200, 201, 204, 404];
205
206 if (!$xmlId)
207 {
208 return null;
209 }
210
211 $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId);
212
213 $result = (int)$this->apiClient->delete($eventPath);
214
215 if ($this->davClient->getError())
216 {
217 $this->addError($this->davClient->getError());
218 }
219
220 if (in_array($result, $acceptCodes))
221 {
222 return true;
223 }
224
225 return null;
226 }
227
241 public function saveInstance(string $path, Event $event, ?array $data, Date $excludeDate = null): ?array
242 {
243 $xmlId = $event->getUid();
244 if (!$xmlId)
245 {
246 return null;
247 }
248
249 $event = (new EventCloner($event))->build();
250 [$eventPath, $calendarData] = $this->prepareInstanceData($event, $path, $xmlId, $data, $excludeDate);
251
252 return $this->sendPutAction($eventPath, $calendarData);
253 }
254
265 public function saveRecurrence(string $path, SyncEvent $recurrenceEvent): ?array
266 {
267 if (!$recurrenceEvent->getEvent()->getUid())
268 {
269 $recurrenceEvent->getEvent()->setUid(VendorSyncService::generateUuid());
270 }
271 $xmlId = $recurrenceEvent->getEvent()->getUid();
272
273 [$eventPath, $calendarData] = $this->prepareRecurrenceData($recurrenceEvent, $path, $xmlId);
274
275 return $this->sendPutAction($eventPath, $calendarData);
276 }
277
285 public function createSection(string $path, Section $section): ?array
286 {
287 $content = SectionBuilder::getInstance()->getCreateSectionContent($section);
288 $result = (int)$this->apiClient->mkcol($path, $content);
289
290 if ($this->davClient->getError())
291 {
292 $this->addError($this->davClient->getError());
293 }
294
295 if ($result === 200 || $result === 201)
296 {
297 $result = $this->davClient->GetCalendarList($path);
298 if ($result && is_array($result))
299 {
300 return [
301 'XML_ID' => $result[0]['href'],
302 'MODIFICATION_LABEL' => $result[0]['getctag'],
303 ];
304 }
305 }
306
307 return null;
308 }
309
317 public function updateSection(string $path, Section $section): ?array
318 {
319 $content = SectionBuilder::getInstance()->getUpdateSectionContent($section);
320 $result = (int)$this->apiClient->proppatch($path, $content);
321
322 if ($this->davClient->getError())
323 {
324 $this->addError($this->davClient->getError());
325 }
326
327 if ($result === 207)
328 {
329 $result = $this->davClient->GetCalendarList($path);
330 if ($result && is_array($result))
331 {
332 return [
333 'XML_ID' => $result[0]['href'],
334 'MODIFICATION_LABEL' => $result[0]['getctag'],
335 ];
336 }
337 }
338 else
339 {
340 return [
341 'ERROR' => $result,
342 ];
343 }
344
345 return null;
346 }
347
354 public function deleteSection(string $path): ?bool
355 {
356 $result = (int)$this->apiClient->delete($path);
357
358 if ($this->davClient->getError())
359 {
360 $this->addError($this->davClient->getError());
361 }
362
363 $acceptCodes = [200, 201, 204, 404];
364
365 if (in_array($result, $acceptCodes))
366 {
367 return true;
368 }
369
370 return null;
371 }
372
373 public function getSectionsList($path)
374 {
375 return $this->davClient->GetCalendarList($path);
376 }
377
378 public function getEventsList($path, $syncToken): ?array
379 {
380 return $this->davClient->GetCalendarItemsBySyncToken($path, $syncToken);
381 }
382
383 public function getEventsListWithHref($path, $hrefs): ?array
384 {
385 return $this->davClient->GetCalendarItemsList($path, $hrefs, true);
386 }
387
388 public function prepareUrl(string $url): array
389 {
390 $parsed = parse_url($url);
391 if (empty($parsed['port']))
392 {
393 $parsed['port'] = ($parsed['scheme'] === 'https'
394 ? 443
395 : 80
396 );
397 }
398
399 return $parsed;
400 }
401
408 private function getXmlStringData($xml, $path): string
409 {
410 $data = '';
411 $responsePath = $xml->GetPath('/*/response');
412 foreach ($responsePath as $response)
413 {
414 if (!$data)
415 {
416 $dataXml = $response->GetPath($path);
417 if (!empty($dataXml))
418 {
419 $data = urldecode($dataXml[0]->GetContent());
420 }
421 }
422 }
423
424 return $data;
425 }
426
436 private function createDavInstance(
437 string $scheme,
438 string $host,
439 string $port,
440 string $username,
441 string $password
442 ): \CDavGroupdavClientCalendar
443 {
444 $davClient = new \CDavGroupdavClientCalendar(
445 $scheme,
446 $host,
447 $port,
448 $username,
449 $password,
450 );
451 $davClient->SetPrivateIp(false);
452
453 return $davClient;
454 }
455
462 private function getPath(string $path, ?string $xmlId): string
463 {
464 if (mb_substr($path, -mb_strlen('/' . $xmlId . '.ics')) != '/' . $xmlId . '.ics')
465 {
466 $path = rtrim($path, '/');
467 $path .= '/' . $xmlId . '.ics';
468 }
469
470 return $path;
471 }
472
485 private function editEvent(
486 string $path,
487 ?string $xmlId,
488 Event $event,
489 ?array $data = null
490 ): ?array
491 {
492 $path = $this->getPath($path, $xmlId);
493 $calendarData = EventBuilder::getInstance()->getContent($event, $data);
494 if ($calendarData)
495 {
496 $calendarData = (new \CDavICalendar($calendarData))->Render();
497 }
498
499 return $this->sendPutAction($path, $calendarData);
500 }
501
515 private function prepareInstanceData(
516 Event $event,
517 string $path,
518 string $xmlId,
519 ?array $data,
520 Date $excludeDate = null
521 ): array
522 {
523 $instancesOriginalDate = [];
524 $exDates = $event->getExcludedDateCollection();
525 $excludedInstance = $excludeDate?->format('Ymd');
526
527 $instances = EventTable::query()
528 ->setSelect(['*'])
529 ->where('RECURRENCE_ID', $event->getParentId())
530 ->where('DELETED', 'N')
531 ->where('OWNER_ID', $event->getOwner()->getId())
532 ->where(Query::filter() // TODO: it's better to optimize it and don't use 'OR' logic here
533 ->logic('or')
534 ->whereNot('MEETING_STATUS', 'N')
535 ->whereNull('MEETING_STATUS')
536 )
537 ->exec()->fetchCollection()
538 ;
539
540 foreach ($instances as $instance)
541 {
542 $originalDate = $instance->getOriginalDateFrom()
543 ? $instance->getOriginalDateFrom()->format('Ymd')
544 : $instance->getDateFrom()->format('Ymd')
545 ;
546 if ($originalDate === $excludedInstance)
547 {
548 $instances->remove($instance);
549 continue;
550 }
551
552 $instancesOriginalDate[] = $originalDate;
553 }
554
555 if ($exDates)
556 {
561 foreach ($exDates->getCollection() as $key => $exDate)
562 {
563 if (in_array($exDate->format('Ymd'), $instancesOriginalDate, true))
564 {
565 $exDates->remove($key);
566 }
567 }
568 $event->setExcludedDateCollection($exDates);
569 }
570
571 $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId);
572 $eventPath = $this->getPath($eventPath, $xmlId);
573 $calendarData[] = EventBuilder::getInstance()->getContent($event, $data);
574
575 foreach ($instances as $instance)
576 {
577 $instanceObject = (new EventBuilderFromEntityObject($instance))->build();
578 $instanceObject->setUid($xmlId);
579 $calendarData[] = EventBuilder::getInstance()->getContent($instanceObject, $data);
580 }
581 if ($calendarData)
582 {
583 $calendarData = (new RecurrenceEventBuilder($calendarData))->Render();
584 }
585
586 return [$eventPath, $calendarData];
587 }
588
600 private function prepareRecurrenceData(SyncEvent $recurrenceEvent, string $path, $xmlId): array
601 {
602 $instanceDates = [];
603 $exDates = $recurrenceEvent->getEvent()->getExcludedDateCollection();
604
606 foreach ($recurrenceEvent->getInstanceMap()->getCollection() as $instance)
607 {
608 $instanceDates[] = $instance->getEvent()->getOriginalDateFrom()
609 ? $instance->getEvent()->getOriginalDateFrom()->format('Ymd')
610 : $instance->getEvent()->getStart()->format('Ymd')
611 ;
612 }
613
614 if ($exDates)
615 {
620 foreach ($exDates->getCollection() as $key => $date)
621 {
622 if (in_array($date->format('Ymd'), $instanceDates, true))
623 {
624 $exDates->remove($key);
625 }
626 }
627
628 $recurrenceEvent->getEvent()->setExcludedDateCollection($exDates);
629 }
630
631 $eventPath = $this->davClient->GetRequestEventPath($path, $xmlId);
632 $eventPath = $this->getPath($eventPath, $xmlId);
633 $calendarData[] = EventBuilder::getInstance()->getContent($recurrenceEvent->getEvent());
634
635 foreach ($recurrenceEvent->getInstanceMap()->getCollection() as $instance)
636 {
637 $instance->getEvent()->setUid($xmlId);
638 $calendarData[] = EventBuilder::getInstance()->getContent($instance->getEvent());
639 }
640
641 if ($calendarData)
642 {
643 $calendarData = (new RecurrenceEventBuilder($calendarData))->Render();
644 }
645
646 return [$eventPath, $calendarData];
647 }
648
656 private function sendPutAction(string $path, $calendarData): ?array
657 {
658 $result = (int)$this->apiClient->put($path, $calendarData);
659
660 if ($this->davClient->getError())
661 {
662 $this->addError($this->davClient->getError());
663 }
664
665 if ($result === 201 || $result === 204)
666 {
667 $result = $this->davClient->GetCalendarItemsList(
668 $path,
669 null,
670 false,
671 2
672 );
673
674 if ($result && is_array($result))
675 {
676 return [
677 'XML_ID' => $this->davClient::getBasenameWithoutExtension($result[0]['href']),
678 'MODIFICATION_LABEL' => $result[0]['getetag'],
679 ];
680 }
681 }
682
683 return null;
684 }
685
690 private function addError(array $error)
691 {
692 $this->error = $error;
693 }
694
698 public function getError(): ?array
699 {
700 return $this->error;
701 }
702}
$path
Определения access_edit.php:21
$connection
Определения actionsdefinitions.php:38
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
updateSection(string $path, Section $section)
Определения apiservice.php:317
saveInstance(string $path, Event $event, ?array $data, Date $excludeDate=null)
Определения apiservice.php:241
createEvent(string $path, Event $event)
Определения apiservice.php:157
deleteEvent(string $path, Event $event)
Определения apiservice.php:201
__construct(array $server=[], int $userId=null)
Определения apiservice.php:32
getEventsListWithHref($path, $hrefs)
Определения apiservice.php:383
getPrinciples($connection, $server)
Определения apiservice.php:56
getEventsList($path, $syncToken)
Определения apiservice.php:378
updateEvent(string $path, Event $event, ?array $data)
Определения apiservice.php:176
createSection(string $path, Section $section)
Определения apiservice.php:285
CDavGroupdavClientCalendar $davClient
Определения apiservice.php:20
prepareUrl(string $url)
Определения apiservice.php:388
getCalendarList($connection, $server)
Определения apiservice.php:128
saveRecurrence(string $path, SyncEvent $recurrenceEvent)
Определения apiservice.php:265
deleteSection(string $path)
Определения apiservice.php:354
getCalendarPath($connection, $server)
Определения apiservice.php:92
Определения date.php:9
$content
Определения commerceml.php:144
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$host
Определения .description.php:9
$event
Определения prolog_after.php:141
$instance
Определения ps_b24_final.php:14
if(empty($signedUserToken)) $key
Определения quickway.php:257
$password
Определения result.php:7
$response
Определения result.php:21
$url
Определения iframe.php:7