1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
manager.php
См. документацию.
1<?php
2
3namespace Bitrix\Calendar\Rooms;
4
5use Bitrix\Calendar\Integration\Pull\PushCommand;
6use Bitrix\Main\ArgumentException;
7use Bitrix\Main\Error;
8use Bitrix\Calendar\Internals\AccessTable;
9use Bitrix\Calendar\Internals\EventTable;
10use Bitrix\Calendar\Internals\LocationTable;
11use Bitrix\Calendar\Internals\SectionTable;
12use Bitrix\Main\Localization\Loc;
13use Bitrix\Calendar\UserSettings;
14use Bitrix\Main\Entity\ReferenceField;
15use Bitrix\Main\EventManager;
16use Bitrix\Main\ObjectPropertyException;
17use Bitrix\Main\ORM\Query;
18use Bitrix\Main\SystemException;
19use Bitrix\Main\Text\Emoji;
20
21Loc::loadMessages(__FILE__);
22
24{
25 public const TYPE = 'location';
26
28 private ?Room $room = null;
30 private ?Error $error = null;
31
32 protected function __construct()
33 {
34 }
35
41 public static function createInstanceWithRoom(Room $room): Manager
42 {
43 return (new self())->setRoom($room);
44 }
45
49 public static function createInstance(): Manager
50 {
51 return new self;
52 }
53
59 private function setRoom(Room $room): Manager
60 {
61 $this->room = $room;
62
63 return $this;
64 }
65
71 private function addError(Error $error): void
72 {
73 $this->error = $error;
74 }
75
76 public function getError(): ?Error
77 {
78 return $this->error;
79 }
80
87 public function createRoom(): Manager
88 {
89 if ($this->error)
90 {
91 return $this;
92 }
93
94 $this->room->create();
95
96 if ($this->room->getError())
97 {
98 $this->addError($this->room->getError());
99 }
100
101 return $this;
102 }
103
110 public function updateRoom(): Manager
111 {
112 if ($this->error)
113 {
114 return $this;
115 }
116
117 $this->room->update();
118
119 if ($this->room->getError())
120 {
121 $this->addError($this->room->getError());
122 }
123
124 return $this;
125 }
126
133 public function deleteRoom(): Manager
134 {
135 if ($this->getError())
136 {
137 return $this;
138 }
139
140 if (!$this->room->getName())
141 {
142 $this->room->setName($this->getRoomName($this->room->getId()));
143 }
144
145 $this->room->delete();
146
147 if ($this->room->getError())
148 {
149 $this->addError($this->room->getError());
150 }
151
152 return $this;
153 }
154
161 public static function getRoomsList(): ?array
162 {
163 $roomQuery = LocationTable::query()
164 ->setSelect([
165 'LOCATION_ID' => 'ID',
166 'NECESSITY',
167 'CAPACITY',
168 'SECTION_ID',
169 'CATEGORY_ID',
170 'NAME' => 'SECTION.NAME',
171 'COLOR' => 'SECTION.COLOR',
172 'OWNER_ID' => 'SECTION.OWNER_ID',
173 'CAL_TYPE' => 'SECTION.CAL_TYPE',
174 ])
175 ->registerRuntimeField('SECTION',
176 new ReferenceField(
177 'SECTION',
178 SectionTable::getEntity(),
179 Query\Join::on('ref.ID', 'this.SECTION_ID'),
180 ['join_type' => Query\Join::TYPE_INNER]
181 )
182 )
183 ->setOrder(['ID' => 'ASC'])
184 ->cacheJoins(true)
185 ->setCacheTtl(86400)
186 ->exec()
187 ;
188
189 [$roomsId, $result] = self::prepareRoomsQueryData($roomQuery);
190
191 if (empty($result))
192 {
193 \CCalendarSect::CreateDefault([
194 'type' => self::TYPE,
195 'ownerId' => 0
196 ]);
197 LocationTable::cleanCache();
198
199 return null;
200 }
201
202 $result = self::getRoomsAccess($roomsId, $result);
203
204 foreach ($result as $room)
205 {
206 \CCalendarSect::HandlePermission($room);
207 }
208
209 return \CCalendarSect::GetSectionPermission($result);
210 }
211
220 public static function getRoomById(int $id, array $params = []): array
221 {
222 $roomQuery = LocationTable::query()
223 ->setSelect([
224 'LOCATION_ID' => 'ID',
225 'NECESSITY',
226 'CAPACITY',
227 'SECTION_ID',
228 'CATEGORY_ID',
229 'NAME' => 'SECTION.NAME',
230 'COLOR' => 'SECTION.COLOR',
231 'OWNER_ID' => 'SECTION.OWNER_ID',
232 'CAL_TYPE' => 'SECTION.CAL_TYPE',
233 ])
234 ->where('SECTION.ID', $id)
235 ->registerRuntimeField('SECTION',
236 new ReferenceField(
237 'SECTION',
238 SectionTable::getEntity(),
239 Query\Join::on('ref.ID', 'this.SECTION_ID'),
240 ['join_type' => Query\Join::TYPE_INNER]
241 )
242 )
243 ->cacheJoins(true)
244 ->setCacheTtl(86400)
245 ->exec()
246 ;
247
248 [$roomsId, $result] = self::prepareRoomsQueryData($roomQuery);
249 $result = self::getRoomsAccess($roomsId, $result);
250
251 foreach ($result as $room)
252 {
253 \CCalendarSect::HandlePermission($room);
254 }
255
256 $applyPermission = $params['checkPermission'] ?? true;
257 if ($applyPermission !== false)
258 {
259 return \CCalendarSect::GetSectionPermission($result);
260 }
261
262 return [...$result];
263 }
264
274 public static function reserveRoom(array $params = []): ?int
275 {
276 $params['checkPermission'] = $params['checkPermission'] ?? null;
277 $params['room_id'] = $params['room_id'] ?? null;
278 $roomList = self::getRoomById((int)$params['room_id'], ['checkPermission' => $params['checkPermission']]);
279
280 if (
281 !$roomList || empty($roomList[0])
282 || empty($roomList[0]['NAME'])
283 || (
284 empty($roomList[0]['PERM']['view_full'])
285 && $params['checkPermission'] !== false
286 )
287 )
288 {
289 return null;
290 }
291
292 $createdBy = $params['parentParams']['arFields']['CREATED_BY']
293 ?? $params['parentParams']['arFields']['MEETING_HOST']
294 ?? null
295 ;
296
297 $arFields = [
298 'ID' => $params['room_event_id'] ?? null,
299 'SECTIONS' => $params['room_id'] ?? null,
300 'DATE_FROM' => $params['parentParams']['arFields']['DATE_FROM'] ?? null,
301 'DATE_TO' => $params['parentParams']['arFields']['DATE_TO'] ?? null,
302 'TZ_FROM' => $params['parentParams']['arFields']['TZ_FROM'] ?? null,
303 'TZ_TO' => $params['parentParams']['arFields']['TZ_TO'] ?? null,
304 'SKIP_TIME' => $params['parentParams']['arFields']['SKIP_TIME'] ?? null,
305 'RRULE' => $params['parentParams']['arFields']['RRULE'] ?? null,
306 'EXDATE' => $params['parentParams']['arFields']['EXDATE'] ?? null,
307 ];
308
309 if (!$params['room_event_id'])
310 {
311 $arFields['CREATED_BY'] = $createdBy;
312 $arFields['NAME'] = \CCalendar::GetUserName($createdBy);
313 $arFields['CAL_TYPE'] = self::TYPE;
314 }
315
316 return \CCalendarEvent::Edit([
317 'arFields' => $arFields,
318 ]);
319 }
320
329 public function cancelBooking(array $params = []): Manager
330 {
331 $params = [
332 'recursion_mode' => $params['recursion_mode'] ?? null,
333 'parent_event_id' => $params['parent_event_id'] ?? null,
334 'section_id' => $params['section_id'] ?? null,
335 'current_event_date_from' => $params['current_event_date_from'] ?? null,
336 'current_event_date_to' => $params['current_event_date_to'] ?? null,
337 'owner_id' => $params['owner_id'] ?? null,
338 ];
339
340 if($this->getError() !== null)
341 {
342 return $this;
343 }
344
345 if($params['recursion_mode'] === 'all' || $params['recursion_mode'] === 'next')
346 {
347 $event = \CCalendarEvent::GetById($params['parent_event_id']);
348
349 $params['frequency'] = $event['RRULE']['FREQ'] ?? null;
350 if($params['recursion_mode'] === 'all')
351 {
352 $params['current_event_date_from'] = $event['DATE_FROM'] ?? null;
353 $params['current_event_date_to'] = $event['DATE_TO'] ?? null;
354 }
355 }
356
357 $result = \CCalendar::SaveEventEx([
358 'recursionEditMode' => $params['recursion_mode'],
359 'currentEventDateFrom' => $params['current_event_date_from'],
360 'checkPermission' => false,
361 'sendInvitations' => false,
362 'userId' => $params['owner_id'],
363 'arFields' => [
364 'ID' => $params['parent_event_id'],
365 'DATE_FROM' => $params['current_event_date_from'],
366 'DATE_TO' => $params['current_event_date_to'],
367 'LOCATION' => '',
368 ],
369 ]);
370
371 $params['event_id'] = $result['recEventId'] ?? $result['id'] ?? null;
372
373 $this->sendCancelBookingNotification($params);
374 return $this;
375 }
376
377 private function sendCancelBookingNotification(array $params): void
378 {
379 $params = [
380 'section_id' => $params['section_id'],
381 'event_id' => $params['event_id'],
382 'owner_id' => $params['owner_id'],
383 'current_event_date_from' => $params['current_event_date_from'],
384 'recursion_mode' => $params['recursion_mode'],
385 ];
386
387 $section = \CCalendarSect::GetById($params['section_id']);
388 $userId = \CCalendar::GetCurUserId();
389 $event = \CCalendarEvent::GetById($params['event_id'], false);
390
391 \CCalendarNotify::Send([
392 'eventId' => $params['event_id'],
393 'mode' => 'cancel_booking',
394 'location' => $section['NAME'] ?? null,
395 'locationId' => $params['section_id'],
396 'guestId' => $params['owner_id'],
397 'userId' => $userId,
398 'from' => $params['current_event_date_from'],
399 'eventName' => $event['NAME'] ?? null,
400 'recursionMode' => $params['recursion_mode'],
401 'fields' => $event,
402 ]);
403 }
404
412 public static function releaseRoom(array $params = [])
413 {
414 return \CCalendar::DeleteEvent(
415 (int)($params['room_event_id'] ?? null),
416 false,
417 [
418 'checkPermissions' => false,
419 'markDeleted' => false
420 ]
421 );
422 }
423
429 public function clearCache(): Manager
430 {
431 if ($this->getError())
432 {
433 return $this;
434 }
435
436 \CCalendarSect::SetClearOperationCache(true);
437 \CCalendar::clearCache([
438 'section_list',
439 'event_list'
440 ]);
441 LocationTable::cleanCache();
442
443 return $this;
444 }
445
449 public function cleanAccessTable(): Manager
450 {
451 if ($this->getError())
452 {
453 return $this;
454 }
455
456 \CCalendarSect::CleanAccessTable($this->room->getId());
457
458 return $this;
459 }
460
472 public static function setEventIdForLocation(int $id, ?string $location = null): void
473 {
474 if (empty($location))
475 {
476 $event = EventTable::query()
477 ->setSelect(['LOCATION'])
478 ->where('ID', $id)
479 ->exec()->fetch()
480 ;
481
482 $location = $event['LOCATION'] ?? null;
483 }
484
485 if (!empty($location))
486 {
487 $parsedLocation = Util::parseLocation($location);
488 if ($parsedLocation['room_id'] && $parsedLocation['room_event_id'])
489 {
490 EventTable::update($parsedLocation['room_event_id'], [
491 'PARENT_ID' => $id,
492 ]);
493 }
494 }
495 }
496
505 public function prepareResponseData(): array
506 {
507 $result = [];
508
509 $result['rooms'] = self::getRoomsList();
510 $sectionList = \CCalendar::GetSectionList([
511 'CAL_TYPE' => self::TYPE,
512 'OWNER_ID' => 0,
513 'checkPermissions' => true,
514 'getPermissions' => true,
515 'getImages' => true
516 ]);
517 $sectionList = array_merge(
518 $sectionList,
519 \CCalendar::getSectionListAvailableForUser(\CCalendar::GetUserId())
520 );
521 $result['sections'] = $sectionList;
522
523 return $result;
524 }
525
532 public static function prepareRoomManagerData(): ?array
533 {
534 $userId = \CCalendar::GetUserId();
535 $result = [];
536
537 // here we collects permissions cache for rooms @see \CCalendarSect::HandlePermission,
538 // if it not collected here and further @see \CCalendar::GetSectionList called with getPermissions => false,
539 // then permissions will not be correct (would be just empty)
540 $result['rooms'] = self::getRoomsList();
541
542 $followedSectionList = UserSettings::getFollowedSectionIdList($userId);
543 $sectionList = \CCalendar::GetSectionList([
544 'CAL_TYPE' => self::TYPE,
545 'OWNER_ID' => 0,
546 'ADDITIONAL_IDS' => $followedSectionList,
547 'getPermissions' => false,
548 ]);
549 $sectionList = array_merge($sectionList, \CCalendar::getSectionListAvailableForUser($userId));
550
551 $sectionAccessTasks = \CCalendar::GetAccessTasks('calendar_section', 'location');
552 $hiddenSections = UserSettings::getHiddenSections(
553 $userId,
554 [
555 'type' => self::TYPE,
556 'ownerId' => 0,
557 ]
558 );
559 $defaultSectionAccess = \CCalendarSect::GetDefaultAccess(
560 self::TYPE,
561 $userId
562 );
563
564 $result['sections'] = $sectionList;
565 $result['config'] = [
566 'locationAccess' => Util::getLocationAccess($userId),
567 'hiddenSections' => $hiddenSections,
568 'type' => self::TYPE,
569 'ownerId' => 0,
570 'userId' => $userId,
571 'defaultSectionAccess' => $defaultSectionAccess,
572 'sectionAccessTasks' => $sectionAccessTasks,
573 'showTasks' => false,
574 'accessNames' => \CCalendar::GetAccessNames(),
575 ];
576
577 return $result;
578 }
579
585 public function eventHandler($handler): Manager
586 {
587 if ($this->getError())
588 {
589 return $this;
590 }
591
592 foreach(EventManager::getInstance()->findEventHandlers('calendar', $handler) as $event)
593 {
595 $this->room->getId(),
596 ]);
597 }
598
599 return $this;
600 }
601
603 {
604 if ($this->getError())
605 {
606 return $this;
607 }
608
610 $event,
611 $this->room->getCreatedBy(),
612 [
613 'ID' => $this->room->getId()
614 ]
615 );
616
617 return $this;
618 }
619
628 private function getRoomName(int $id): ?string
629 {
630 $section = SectionTable::query()
631 ->setSelect(['NAME'])
632 ->where('ID', $id)
633 ->exec()->fetch()
634 ;
635
636 return $section ? $section['NAME'] : null;
637 }
638
645 public static function checkRoomName(?string $name): ?string
646 {
647 if (!$name)
648 {
649 return '';
650 }
651
652 $name = trim($name);
653
654 if (empty($name))
655 {
656 return '';
657 }
658
659 return $name;
660 }
661
668 {
669 if ($this->getError())
670 {
671 return $this;
672 }
673
674 $guestsId = [];
675 $eventsId = [];
676 $id = $this->room->getId();
677 $locationName = $this->room->getName();
678 $locationId = 'calendar_' . $id;
679
680 $events = EventTable::query()
681 ->setSelect(['ID', 'PARENT_ID', 'OWNER_ID', 'CREATED_BY', 'LOCATION'])
682 ->whereLike('LOCATION', $locationId. '%')
683 ->exec()
684 ;
685
686 while ($event = $events->fetch())
687 {
688 if ($event['ID'] === $event['PARENT_ID'])
689 {
690 $guestsId[] = $event['OWNER_ID'];
691 }
692
693 $eventsId[] = $event['ID'];
694 }
695
696 if (!empty($eventsId))
697 {
698 EventTable::updateMulti($eventsId, ['LOCATION' => '']);
699
700 $guestsId = array_unique($guestsId);
701 $userId = \CCalendar::GetCurUserId();
702
703 foreach ($guestsId as $guestId)
704 {
705 \CCalendarNotify::Send([
706 'mode' => 'delete_location',
707 'location' => $locationName,
708 'locationId' => $id,
709 'guestId' => (int)$guestId,
710 'userId' => $userId,
711 ]);
712 }
713 }
714
715 return $this;
716 }
717
724 public function pullDeleteEvents(): Manager
725 {
726 if ($this->getError())
727 {
728 return $this;
729 }
730
731 $events = self::getLocationEventsId($this->room->getId());
732
733 foreach ($events as $event)
734 {
735 if ($this->room->getCreatedBy())
736 {
738 PushCommand::DeleteEvent,
739 $this->room->getCreatedBy(),
740 ['fields' => $event]
741 );
742 }
743 }
744
745 return $this;
746 }
747
751 public function deleteEmptyEvents(): Manager
752 {
753 if ($this->getError())
754 {
755 return $this;
756 }
757
758 \CCalendarEvent::DeleteEmpty($this->room->getId());
759
760 return $this;
761 }
762
771 private static function getLocationEventsId(int $roomId): array
772 {
773 return EventTable::query()
774 ->setSelect([
775 'ID',
776 'CREATED_BY',
777 'PARENT_ID',
778 ])
779 ->where('SECTION_ID', $roomId)
780 ->where('DELETED', 'N')
781 ->exec()->fetchAll()
782 ;
783 }
784
788 public function saveAccess(): Manager
789 {
790 if ($this->getError())
791 {
792 return $this;
793 }
794
795 $access = $this->room->getAccess();
796 $id = $this->room->getId();
797
798 if (!empty($access))
799 {
800 \CCalendarSect::SavePermissions(
801 $id,
802 $access
803 );
804 }
805 else
806 {
807 \CCalendarSect::SavePermissions(
808 $id,
809 \CCalendarSect::GetDefaultAccess(
810 $this->room->getType(),
811 $this->room->getCreatedBy()
812 )
813 );
814 }
815
816 return $this;
817 }
818
824 private static function prepareRoomsQueryData(Query\Result $query): array
825 {
826 $roomsId = [];
827 $result = [];
828
829 while ($room = $query->fetch())
830 {
831 $room['ID'] = $room['SECTION_ID'];
832 unset($room['SECTION_ID']);
833
834 if (!empty($room['NAME']))
835 {
836 $room['NAME'] = Emoji::decode($room['NAME']);
837 }
838 $roomId = (int)$room['ID'];
839 $roomsId[] = $roomId;
840 $result[$roomId] = $room;
841 }
842
843 return [$roomsId, $result];
844 }
845
855 private static function getRoomsAccess(array $roomsId, array $rooms): array
856 {
857 if (empty($roomsId))
858 {
859 return [];
860 }
861
862 $accessQuery = AccessTable::query()
863 ->setSelect([
864 'ACCESS_CODE',
865 'TASK_ID',
866 'SECT_ID'
867 ])
868 ->whereIn('SECT_ID', $roomsId)
869 ->exec()
870 ;
871
872 while ($access = $accessQuery->fetch())
873 {
874 if (!isset($rooms[$access['SECT_ID']]['ACCESS']))
875 {
876 $rooms[$access['SECT_ID']]['ACCESS'] = [];
877 }
878 $rooms[$access['SECT_ID']]['ACCESS'][$access['ACCESS_CODE']] = (int)$access['TASK_ID'];
879 }
880
881 return $rooms;
882 }
883}
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static getRoomsList()
Определения manager.php:161
eventHandler($handler)
Определения manager.php:585
addPullEvent(PushCommand $event)
Определения manager.php:602
static createInstanceWithRoom(Room $room)
Определения manager.php:41
const TYPE
Определения manager.php:25
deleteLocationFromEvents()
Определения manager.php:667
cancelBooking(array $params=[])
Определения manager.php:329
deleteEmptyEvents()
Определения manager.php:751
static checkRoomName(?string $name)
Определения manager.php:645
static getRoomById(int $id, array $params=[])
Определения manager.php:220
pullDeleteEvents()
Определения manager.php:724
prepareResponseData()
Определения manager.php:505
cleanAccessTable()
Определения manager.php:449
static prepareRoomManagerData()
Определения manager.php:532
static setEventIdForLocation(int $id, ?string $location=null)
Определения manager.php:472
static createInstance()
Определения manager.php:49
static releaseRoom(array $params=[])
Определения manager.php:412
static reserveRoom(array $params=[])
Определения manager.php:274
static getFollowedSectionIdList($userId=false)
Определения usersettings.php:330
static getHiddenSections($userId=false, $options=[])
Определения usersettings.php:254
static addPullEvent(PushCommand $command, int $userId, array $params=[])
Определения util.php:385
Определения error.php:15
static getInstance()
Определения eventmanager.php:31
$arFields
Определения dblapprove.php:5
</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
$query
Определения get_search.php:11
if(!is_array($deviceNotifyCodes)) $access
Определения options.php:174
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
$name
Определения menu_edit.php:35
Определения chain.php:3
$event
Определения prolog_after.php:141
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$locationName
Определения options.php:2799
$location
Определения options.php:2729
$error
Определения subscription_card_product.php:20