Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
manager.php
1<?php
2
4
13use Bitrix\Main\Entity\ReferenceField;
17
18Loc::loadMessages(__FILE__);
19
21{
22 public const TYPE = 'location';
23
25 private ?Room $room = null;
27 private ?Error $error = null;
28
29 protected function __construct()
30 {
31 }
32
38 public static function createInstanceWithRoom(Room $room): Manager
39 {
40 return (new self())->setRoom($room);
41 }
42
46 public static function createInstance(): Manager
47 {
48 return new self;
49 }
50
56 private function setRoom(Room $room): Manager
57 {
58 $this->room = $room;
59
60 return $this;
61 }
62
68 private function addError(Error $error): void
69 {
70 $this->error = $error;
71 }
72
73 public function getError(): ?Error
74 {
75 return $this->error;
76 }
77
84 public function createRoom(): Manager
85 {
86 if ($this->error)
87 {
88 return $this;
89 }
90
91 $this->room->create();
92
93 if ($this->room->getError())
94 {
95 $this->addError($this->room->getError());
96 }
97
98 return $this;
99 }
100
107 public function updateRoom(): Manager
108 {
109 if ($this->error)
110 {
111 return $this;
112 }
113
114 $this->room->update();
115
116 if ($this->room->getError())
117 {
118 $this->addError($this->room->getError());
119 }
120
121 return $this;
122 }
123
130 public function deleteRoom(): Manager
131 {
132 if ($this->getError())
133 {
134 return $this;
135 }
136
137 if (!$this->room->getName())
138 {
139 $this->room->setName($this->getRoomName($this->room->getId()));
140 }
141
142 $this->room->delete();
143
144 if ($this->room->getError())
145 {
146 $this->addError($this->room->getError());
147 }
148
149 return $this;
150 }
151
158 public static function getRoomsList(): ?array
159 {
160 $roomQuery = LocationTable::query()
161 ->setSelect([
162 'LOCATION_ID' => 'ID',
163 'NECESSITY',
164 'CAPACITY',
165 'SECTION_ID',
166 'CATEGORY_ID',
167 'NAME' => 'SECTION.NAME',
168 'COLOR' => 'SECTION.COLOR',
169 'OWNER_ID' => 'SECTION.OWNER_ID',
170 'CAL_TYPE' => 'SECTION.CAL_TYPE',
171 ])
172 ->registerRuntimeField('SECTION',
173 new ReferenceField(
174 'SECTION',
175 SectionTable::getEntity(),
176 Query\Join::on('ref.ID', 'this.SECTION_ID'),
177 ['join_type' => Query\Join::TYPE_INNER]
178 )
179 )
180 ->setOrder(['ID' => 'ASC'])
181 ->cacheJoins(true)
182 ->setCacheTtl(86400)
183 ->exec()
184 ;
185
186 [$roomsId, $result] = self::prepareRoomsQueryData($roomQuery);
187
188 if (empty($result))
189 {
190 \CCalendarSect::CreateDefault([
191 'type' => self::TYPE,
192 'ownerId' => 0
193 ]);
194 LocationTable::cleanCache();
195
196 return null;
197 }
198
199 $result = self::getRoomsAccess($roomsId, $result);
200
201 foreach ($result as $room)
202 {
203 \CCalendarSect::HandlePermission($room);
204 }
205
206 return \CCalendarSect::GetSectionPermission($result);
207 }
208
217 public static function getRoomById(int $id, array $params = []): array
218 {
219 $roomQuery = LocationTable::query()
220 ->setSelect([
221 'LOCATION_ID' => 'ID',
222 'NECESSITY',
223 'CAPACITY',
224 'SECTION_ID',
225 'CATEGORY_ID',
226 'NAME' => 'SECTION.NAME',
227 'COLOR' => 'SECTION.COLOR',
228 'OWNER_ID' => 'SECTION.OWNER_ID',
229 'CAL_TYPE' => 'SECTION.CAL_TYPE',
230 ])
231 ->where('SECTION.ID', $id)
232 ->registerRuntimeField('SECTION',
233 new ReferenceField(
234 'SECTION',
235 SectionTable::getEntity(),
236 Query\Join::on('ref.ID', 'this.SECTION_ID'),
237 ['join_type' => Query\Join::TYPE_INNER]
238 )
239 )
240 ->cacheJoins(true)
241 ->setCacheTtl(86400)
242 ->exec()
243 ;
244
245 [$roomsId, $result] = self::prepareRoomsQueryData($roomQuery);
246 $result = self::getRoomsAccess($roomsId, $result);
247
248 foreach ($result as $room)
249 {
250 \CCalendarSect::HandlePermission($room);
251 }
252
253 $applyPermission = $params['checkPermission'] ?? true;
254 if ($applyPermission !== false)
255 {
256 return \CCalendarSect::GetSectionPermission($result);
257 }
258
259 return [...$result];
260 }
261
271 public static function reserveRoom(array $params = []): ?int
272 {
273 $params['checkPermission'] = $params['checkPermission'] ?? null;
274 $params['room_id'] = $params['room_id'] ?? null;
275 $roomList = self::getRoomById((int)$params['room_id'], ['checkPermission' => $params['checkPermission']]);
276
277 if (
278 !$roomList || empty($roomList[0])
279 || empty($roomList[0]['NAME'])
280 || (
281 empty($roomList[0]['PERM']['view_full'])
282 && $params['checkPermission'] !== false
283 )
284 )
285 {
286 return null;
287 }
288
289 $createdBy = $params['parentParams']['arFields']['CREATED_BY']
290 ?? $params['parentParams']['arFields']['MEETING_HOST']
291 ?? null
292 ;
293
294 $arFields = [
295 'ID' => $params['room_event_id'] ?? null,
296 'SECTIONS' => $params['room_id'] ?? null,
297 'DATE_FROM' => $params['parentParams']['arFields']['DATE_FROM'] ?? null,
298 'DATE_TO' => $params['parentParams']['arFields']['DATE_TO'] ?? null,
299 'TZ_FROM' => $params['parentParams']['arFields']['TZ_FROM'] ?? null,
300 'TZ_TO' => $params['parentParams']['arFields']['TZ_TO'] ?? null,
301 'SKIP_TIME' => $params['parentParams']['arFields']['SKIP_TIME'] ?? null,
302 'RRULE' => $params['parentParams']['arFields']['RRULE'] ?? null,
303 'EXDATE' => $params['parentParams']['arFields']['EXDATE'] ?? null,
304 ];
305
306 if (!$params['room_event_id'])
307 {
308 $arFields['CREATED_BY'] = $createdBy;
309 $arFields['NAME'] = \CCalendar::GetUserName($createdBy);
310 $arFields['CAL_TYPE'] = self::TYPE;
311 }
312
313 return \CCalendarEvent::Edit([
314 'arFields' => $arFields,
315 ]);
316 }
317
326 public function cancelBooking(array $params = []): Manager
327 {
328 $params = [
329 'recursion_mode' => $params['recursion_mode'] ?? null,
330 'parent_event_id' => $params['parent_event_id'] ?? null,
331 'section_id' => $params['section_id'] ?? null,
332 'current_event_date_from' => $params['current_event_date_from'] ?? null,
333 'current_event_date_to' => $params['current_event_date_to'] ?? null,
334 'owner_id' => $params['owner_id'] ?? null,
335 ];
336
337 if($this->getError() !== null)
338 {
339 return $this;
340 }
341
342 if($params['recursion_mode'] === 'all' || $params['recursion_mode'] === 'next')
343 {
344 $event = \CCalendarEvent::GetById($params['parent_event_id']);
345
346 $params['frequency'] = $event['RRULE']['FREQ'] ?? null;
347 if($params['recursion_mode'] === 'all')
348 {
349 $params['current_event_date_from'] = $event['DATE_FROM'] ?? null;
350 $params['current_event_date_to'] = $event['DATE_TO'] ?? null;
351 }
352 }
353
354 $result = \CCalendar::SaveEventEx([
355 'recursionEditMode' => $params['recursion_mode'],
356 'currentEventDateFrom' => $params['current_event_date_from'],
357 'checkPermission' => false,
358 'sendInvitations' => false,
359 'userId' => $params['owner_id'],
360 'arFields' => [
361 'ID' => $params['parent_event_id'],
362 'DATE_FROM' => $params['current_event_date_from'],
363 'DATE_TO' => $params['current_event_date_to'],
364 'LOCATION' => '',
365 ],
366 ]);
367
368 $params['event_id'] = $result['recEventId'] ?? $result['id'] ?? null;
369
370 $this->sendCancelBookingNotification($params);
371 return $this;
372 }
373
374 private function sendCancelBookingNotification(array $params): void
375 {
376 $params = [
377 'section_id' => $params['section_id'],
378 'event_id' => $params['event_id'],
379 'owner_id' => $params['owner_id'],
380 'current_event_date_from' => $params['current_event_date_from'],
381 'recursion_mode' => $params['recursion_mode'],
382 ];
383
384 $section = \CCalendarSect::GetById($params['section_id']);
385 $userId = \CCalendar::GetCurUserId();
386 $event = \CCalendarEvent::GetById($params['event_id'], false);
387
388 \CCalendarNotify::Send([
389 'eventId' => $params['event_id'],
390 'mode' => 'cancel_booking',
391 'location' => $section['NAME'] ?? null,
392 'locationId' => $params['section_id'],
393 'guestId' => $params['owner_id'],
394 'userId' => $userId,
395 'from' => $params['current_event_date_from'],
396 'eventName' => $event['NAME'] ?? null,
397 'recursionMode' => $params['recursion_mode'],
398 'fields' => $event,
399 ]);
400 }
401
409 public static function releaseRoom(array $params = [])
410 {
411 return \CCalendar::DeleteEvent(
412 (int)($params['room_event_id'] ?? null),
413 false,
414 [
415 'checkPermissions' => false,
416 'markDeleted' => false
417 ]
418 );
419 }
420
426 public function clearCache(): Manager
427 {
428 if ($this->getError())
429 {
430 return $this;
431 }
432
433 \CCalendarSect::SetClearOperationCache(true);
434 \CCalendar::clearCache([
435 'section_list',
436 'event_list'
437 ]);
438 LocationTable::cleanCache();
439
440 return $this;
441 }
442
446 public function cleanAccessTable(): Manager
447 {
448 if ($this->getError())
449 {
450 return $this;
451 }
452
453 \CCalendarSect::CleanAccessTable();
454
455 return $this;
456 }
457
469 public static function setEventIdForLocation(int $id): void
470 {
471 $event = EventTable::query()
472 ->setSelect(['LOCATION'])
473 ->where('ID', $id)
474 ->exec()->fetch()
475 ;
476
477 if (!empty($event['LOCATION']))
478 {
479 $location = Util::parseLocation($event['LOCATION']);
480 if ($location['room_id'] && $location['room_event_id'])
481 {
482 EventTable::update($location['room_event_id'], [
483 'PARENT_ID' => $id,
484 ]);
485 }
486 }
487 }
488
497 public function prepareResponseData(): array
498 {
499 $result = [];
500
501 $result['rooms'] = self::getRoomsList();
502 $sectionList = \CCalendar::GetSectionList([
503 'CAL_TYPE' => self::TYPE,
504 'OWNER_ID' => 0,
505 'checkPermissions' => true,
506 'getPermissions' => true,
507 'getImages' => true
508 ]);
509 $sectionList = array_merge(
510 $sectionList,
511 \CCalendar::getSectionListAvailableForUser(\CCalendar::GetUserId())
512 );
513 $result['sections'] = $sectionList;
514
515 return $result;
516 }
517
524 public static function prepareRoomManagerData(): ?array
525 {
526 $userId = \CCalendar::GetUserId();
527 $result = [];
528
529 $followedSectionList = UserSettings::getFollowedSectionIdList($userId);
530 $sectionList = \CCalendar::GetSectionList([
531 'CAL_TYPE' => self::TYPE,
532 'OWNER_ID' => 0,
533 'ADDITIONAL_IDS' => $followedSectionList,
534 ]);
535 $sectionList = array_merge($sectionList, \CCalendar::getSectionListAvailableForUser($userId));
536
537 $sectionAccessTasks = \CCalendar::GetAccessTasks('calendar_section', 'location');
538 $hiddenSections = UserSettings::getHiddenSections(
539 $userId,
540 [
541 'type' => self::TYPE,
542 'ownerId' => 0,
543 ]
544 );
545 $defaultSectionAccess = \CCalendarSect::GetDefaultAccess(
546 self::TYPE,
547 $userId
548 );
549
550 $result['rooms'] = self::getRoomsList();
551 $result['sections'] = $sectionList;
552 $result['config'] = [
553 'locationAccess' => Util::getLocationAccess($userId),
554 'hiddenSections' => $hiddenSections,
555 'type' => self::TYPE,
556 'ownerId' => 0,
557 'userId' => $userId,
558 'defaultSectionAccess' => $defaultSectionAccess,
559 'sectionAccessTasks' => $sectionAccessTasks,
560 'showTasks' => false,
561 'accessNames' => \CCalendar::GetAccessNames(),
562 ];
563
564 return $result;
565 }
566
572 public function eventHandler($handler): Manager
573 {
574 if ($this->getError())
575 {
576 return $this;
577 }
578
579 foreach(EventManager::getInstance()->findEventHandlers('calendar', $handler) as $event)
580 {
581 ExecuteModuleEventEx($event, [
582 $this->room->getId(),
583 ]);
584 }
585
586 return $this;
587 }
588
589 public function addPullEvent($event): Manager
590 {
591 if ($this->getError())
592 {
593 return $this;
594 }
595
596 \Bitrix\Calendar\Util::addPullEvent(
597 $event,
598 $this->room->getCreatedBy(),
599 [
600 'ID' => $this->room->getId()
601 ]
602 );
603
604 return $this;
605 }
606
615 private function getRoomName(int $id): ?string
616 {
617 $section = SectionTable::query()
618 ->setSelect(['NAME'])
619 ->where('ID', $id)
620 ->exec()->fetch()
621 ;
622
623 return $section ? $section['NAME'] : null;
624 }
625
632 public static function checkRoomName(?string $name): ?string
633 {
634 if (!$name)
635 {
636 return '';
637 }
638
639 $name = trim($name);
640
641 if (empty($name))
642 {
643 return '';
644 }
645
646 return $name;
647 }
648
655 {
656 if ($this->getError())
657 {
658 return $this;
659 }
660
661 global $DB;
662 $guestsId = [];
663 $idTemp = "(#ID#, ''),";
664 $updateString = '';
665 $id = $this->room->getId();
666 $locationName = $this->room->getName();
667 $locationId = 'calendar_' . $id;
668
669 $events = $DB->Query("
670 SELECT ID, PARENT_ID, OWNER_ID, CREATED_BY, LOCATION
671 FROM b_calendar_event
672 WHERE LOCATION LIKE '" . $locationId . "%';
673 ");
674
675 while ($event = $events->Fetch())
676 {
677 if ($event['ID'] === $event['PARENT_ID'])
678 {
679 $guestsId[] = $event['OWNER_ID'];
680 }
681 $updateString .= str_replace('#ID#', $event['ID'], $idTemp);
682 }
683
684 if ($updateString)
685 {
686 $updateString = substr($updateString, 0, -1);
687 $DB->Query("
688 INSERT INTO b_calendar_event (ID, LOCATION)
689 VALUES ".$updateString."
690 ON DUPLICATE KEY UPDATE LOCATION = VALUES(LOCATION)
691 ");
692 $guestsId = array_unique($guestsId);
693 $userId = \CCalendar::GetCurUserId();
694
695 foreach ($guestsId as $guestId)
696 {
697 \CCalendarNotify::Send([
698 'mode' => 'delete_location',
699 'location' => $locationName,
700 'locationId' => $id,
701 'guestId' => (int)$guestId,
702 'userId' => $userId,
703 ]);
704 }
705 }
706
707 return $this;
708 }
709
716 public function pullDeleteEvents(): Manager
717 {
718 if ($this->getError())
719 {
720 return $this;
721 }
722
723 $events = self::getLocationEventsId($this->room->getId());
724
725 foreach ($events as $event)
726 {
727 if ($this->room->getCreatedBy())
728 {
729 \Bitrix\Calendar\Util::addPullEvent(
730 'delete_event',
731 $this->room->getCreatedBy(),
732 ['fields' => $event]
733 );
734 }
735 }
736
737 return $this;
738 }
739
743 public function deleteEmptyEvents(): Manager
744 {
745 if ($this->getError())
746 {
747 return $this;
748 }
749
750 \CCalendarEvent::DeleteEmpty($this->room->getId());
751
752 return $this;
753 }
754
763 private static function getLocationEventsId(int $roomId): array
764 {
765 return EventTable::query()
766 ->setSelect([
767 'ID',
768 'CREATED_BY',
769 'PARENT_ID',
770 ])
771 ->where('SECTION_ID', $roomId)
772 ->where('DELETED', 'N')
773 ->exec()->fetchAll()
774 ;
775 }
776
780 public function saveAccess(): Manager
781 {
782 if ($this->getError())
783 {
784 return $this;
785 }
786
787 $access = $this->room->getAccess();
788 $id = $this->room->getId();
789
790 if (!empty($access))
791 {
792 \CCalendarSect::SavePermissions(
793 $id,
794 $access
795 );
796 }
797 else
798 {
799 \CCalendarSect::SavePermissions(
800 $id,
801 \CCalendarSect::GetDefaultAccess(
802 $this->room->getType(),
803 $this->room->getCreatedBy()
804 )
805 );
806 }
807
808 return $this;
809 }
810
816 private static function prepareRoomsQueryData(Query\Result $query): array
817 {
818 $roomsId = [];
819 $result = [];
820
821 while ($room = $query->fetch())
822 {
823 $room['ID'] = $room['SECTION_ID'];
824 unset($room['SECTION_ID']);
825
826 if (!empty($room['NAME']))
827 {
828 $room['NAME'] = Emoji::decode($room['NAME']);
829 }
830 $roomId = (int)$room['ID'];
831 $roomsId[] = $roomId;
832 $result[$roomId] = $room;
833 }
834
835 return [$roomsId, $result];
836 }
837
847 private static function getRoomsAccess(array $roomsId, array $rooms): array
848 {
849 if (empty($roomsId))
850 {
851 return [];
852 }
853
854 $accessQuery = AccessTable::query()
855 ->setSelect([
856 'ACCESS_CODE',
857 'TASK_ID',
858 'SECT_ID'
859 ])
860 ->whereIn('SECT_ID', $roomsId)
861 ->exec()
862 ;
863
864 while ($access = $accessQuery->fetch())
865 {
866 if (!isset($rooms[$access['SECT_ID']]['ACCESS']))
867 {
868 $rooms[$access['SECT_ID']]['ACCESS'] = [];
869 }
870 $rooms[$access['SECT_ID']]['ACCESS'][$access['ACCESS_CODE']] = (int)$access['TASK_ID'];
871 }
872
873 return $rooms;
874 }
875}
static setEventIdForLocation(int $id)
Definition manager.php:469
static createInstanceWithRoom(Room $room)
Definition manager.php:38
cancelBooking(array $params=[])
Definition manager.php:326
static checkRoomName(?string $name)
Definition manager.php:632
static getRoomById(int $id, array $params=[])
Definition manager.php:217
static releaseRoom(array $params=[])
Definition manager.php:409
static reserveRoom(array $params=[])
Definition manager.php:271
static getFollowedSectionIdList($userId=false)
static getHiddenSections($userId=false, $options=[])
static loadMessages($file)
Definition loc.php:64