1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
updateeventhandler.php
См. документацию.
1<?php
2
3namespace Bitrix\Calendar\Application\Command;
4
5use Bitrix\Calendar\Access\ActionDictionary;
6use Bitrix\Calendar\Access\EventAccessController;
7use Bitrix\Calendar\Access\Model\EventModel;
8use Bitrix\Calendar\Application\AttendeeService;
9use Bitrix\Calendar\Core\Builders\EventBuilderFromArray;
10use Bitrix\Calendar\Core\Event\Event;
11use Bitrix\Calendar\Core\Event\Tools\Dictionary;
12use Bitrix\Calendar\Core\Mappers\Factory;
13use Bitrix\Calendar\Core\Section\Section;
14use Bitrix\Calendar\Event\Event\AfterCalendarEventEdited;
15use Bitrix\Calendar\Integration\Intranet\UserService;
16use Bitrix\Calendar\Internals\Exception\EditException;
17use Bitrix\Calendar\Internals\Exception\EventNotFound;
18use Bitrix\Calendar\Internals\Exception\ExtranetPermissionDenied;
19use Bitrix\Calendar\Internals\Exception\LocationBusy;
20use Bitrix\Calendar\Internals\Exception\PermissionDenied;
21use Bitrix\Calendar\Internals\Exception\SectionNotFound;
22use Bitrix\Calendar\Rooms\AccessibilityManager;
23use Bitrix\Calendar\Util;
24use Bitrix\Main\DI\ServiceLocator;
25
27{
28 private bool $canEdit;
29 private bool $canEditAttendees;
30 private bool $canEditLocation;
31
32 public function __invoke(UpdateEventCommand $command): Event
33 {
35 $mapperFactory = ServiceLocator::getInstance()->get('calendar.service.mappers.factory');
36
37 // check if the current user has access to edit event operation
38 $this->checkPermissions($command->getId(), $command->getUserId());
39
40 $section = $this->getSection($mapperFactory, $command);
41 $event = $this->getEvent($mapperFactory, $command->getId());
42 $entryFields = $this->convertToArray($event, $mapperFactory);
43 $currentFields = $entryFields;
44
45 // base fields
46 $entryFields = ($this->canEdit)
47 ? $this->editBaseFields($entryFields, $command, $event, $section)
48 : $this->editPersonalFields($entryFields, $command);
49
50 // attendees
51 $entryFields = ($this->canEdit || $this->canEditAttendees)
52 ? $this->editAttendees($entryFields, $command, $event->getId(), $section)
53 : $entryFields;
54
55 // location
56 $entryFields = ($this->canEdit || $this->canEditLocation)
57 ? $this->editLocation($entryFields, $command, $event->getId())
58 : $entryFields;
59
60 // update event
61 $event = (new EventBuilderFromArray($entryFields))->build();
62 $updatedEvent = $mapperFactory->getEvent()->update($event, [
63 'checkPermission' => false,
64 'UF' => $command->getUfFields(),
65 'silentErrorMode' => false,
66 'recursionEditMode' => $this->getRecursionEditMode($command),
67 'currentEventDateFrom' => $command->getCurrentDateFrom(),
68 'sendInvitesToDeclined' => $command->isSendInvitesAgain(),
69 'requestUid' => $command->getRequestUid(),
70 'checkLocationOccupancy' => $command->isCheckLocationOccupancy(),
71 'userId' => \CCalendar::GetUserId(),
72 ]);
73
74 if ($updatedEvent === null)
75 {
76 throw new EditException();
77 }
78
79 if ($updatedEvent && $updatedEvent->isMeeting())
80 {
81 $this->notifyEventAuthor($mapperFactory, $updatedEvent, $command->getUserId(), $currentFields);
82 }
83
84 (new AfterCalendarEventEdited($event->getId(), $command))->emit();
85
86 return $updatedEvent;
87 }
88
89 private function editBaseFields(array $entryFields, UpdateEventCommand $command, Event $event, Section $section): array
90 {
91 $meetingHostId = $command->getMeetingHost() ? : $command->getUserId();
92 $sectionId = $event->getSection()->getId();
93 if ($event->getCalendarType() === $section->getType())
94 {
95 $sectionId = $command->getSectionId();
96 }
97
98 return array_merge($entryFields, [
99 'DATE_FROM' => $command->getDateFrom(),
100 'DATE_TO' => $command->getDateTo(),
101 'SKIP_TIME' => $command->isSkipTime(),
102 'DT_SKIP_TIME' => $command->isSkipTime() ? 'Y' : 'N',
103 'TZ_FROM' => $command->getTimeZoneFrom(),
104 'TZ_TO' => $command->getTimeZoneTo(),
105 'NAME' => $command->getName(),
106 'DESCRIPTION' => $command->getDescription(),
107 'SECTIONS' => [$sectionId],
108 'COLOR' => $command->getColor(),
109 'ACCESSIBILITY' => $command->getAccessibility(),
110 'IMPORTANCE' => $command->getImportance(),
111 'PRIVATE_EVENT' => $command->isPrivate(),
112 'RRULE' => $command->getRrule(),
113 'REMIND' => $command->getRemindList(),
114 'MEETING_HOST' => $meetingHostId,
115 'OWNER_ID' => $command->getUserId(),
116 'MEETING' => [
117 'HOST_NAME' => \CCalendar::GetUserName($meetingHostId),
118 'NOTIFY' => $command->isMeetingNotify(),
119 'REINVITE' => $command->isMeetingReinvite(),
120 'ALLOW_INVITE' => $command->isAllowInvite(),
121 'MEETING_CREATOR' => $meetingHostId,
122 'HIDE_GUESTS' => $command->isHideGuests(),
123 'CHAT_ID' => $command->getChatId(),
124 ],
125 ]);
126 }
127
128 private function editPersonalFields(array $entryFields, UpdateEventCommand $command): array
129 {
130 return array_merge($entryFields, [
131 'REMIND' => $command->getRemindList(),
132 ]);
133 }
134
135 private function editAttendees(array $entryFields, UpdateEventCommand $command, int $eventId, Section $section): array
136 {
137 $attendeeService = new AttendeeService();
138 $attendeeCodes = $attendeeService->getAttendeeAccessCodes($command->getAttendeesEntityList(), $command->getUserId());
139 $attendees = \CCalendar::GetDestinationUsers($attendeeCodes);
140 $isMeeting = $attendeeService->isMeeting($attendeeCodes, $section, $command->getUserId());
141 $attendeesAndCodes = $attendeeService->excludeAttendees($attendees, $attendeeCodes, $command->getExcludeUsers());
142
143 $entryFields['ATTENDEES_CODES'] = $attendeesAndCodes['codes'];
144 $entryFields['ATTENDEES'] = $attendeesAndCodes['attendees'];
145 $entryFields['IS_MEETING'] = $isMeeting;
146
147 $additionalExcludeUsers = [];
148 if (
149 $section->getType() === Dictionary::CALENDAR_TYPE['user']
150 && $section->getOwner()?->getId()
151 && $section->getOwner()?->getId() !== (int)$entryFields['MEETING_HOST']
152 )
153 {
154 $additionalExcludeUsers[] = $section->getOwner()?->getId();
155 }
156
157
158 if ($isMeeting && $command->isPlannerFeatureEnabled())
159 {
160 $attendeesToCheck = array_diff($attendeesAndCodes['attendees'], [$entryFields['MEETING_HOST']]);
161 $attendeeService->checkBusyAttendees($command, $attendeesToCheck, $eventId, $additionalExcludeUsers);
162 }
163
164 return $entryFields;
165 }
166
167 private function editLocation(array $entryFields, UpdateEventCommand $command, int $eventId): array
168 {
169 $entryFields['LOCATION'] = $command->getLocation();
170
171 $params = [
172 'ID' => $eventId,
173 'SKIP_TIME' => $entryFields['SKIP_TIME'] ?? ($entryFields['DT_SKIP_TIME'] === 'Y'),
174 'DATE_FROM' => $entryFields['DATE_FROM'],
175 'DATE_TO' => $entryFields['DATE_TO'],
176 'TZ_FROM' => $entryFields['TZ_FROM'],
177 'TZ_TO' => $entryFields['TZ_TO'],
178 ];
179 $isLocationBusy = !AccessibilityManager::checkAccessibility($command->getLocation(), ['fields' => $params]);
180 if ($isLocationBusy)
181 {
182 throw new LocationBusy();
183 }
184
185 return $entryFields;
186 }
187
188 private function checkPermissions(int $eventId, int $userId): void
189 {
190 $controller = new EventAccessController($userId);
191 $model = $this->getEventAccessModel($eventId, $userId);
192 $this->canEdit = $controller->check(ActionDictionary::ACTION_EVENT_EDIT, $model);
193 $this->canEditAttendees = $controller->check(ActionDictionary::ACTION_EVENT_EDIT_ATTENDEES, $model);
194 $this->canEditLocation = $controller->check(ActionDictionary::ACTION_EVENT_EDIT_LOCATION, $model);
195
196 if (!($this->canEdit || $this->canEditAttendees || $this->canEditLocation))
197 {
198 throw new PermissionDenied();
199 }
200 }
201
202 private function getEvent(Factory $factoryMapper, int $eventId, $isParent = false): Event
203 {
204 $event = $factoryMapper->getEvent()->getById($eventId);
205 if (!$event)
206 {
207 throw new EventNotFound();
208 }
209
210 return ($event->getId() !== $event->getParentId() && !$isParent)
211 ? $this->getEvent($factoryMapper, $event->getParentId(), true)
212 : $event;
213 }
214
215 private function convertToArray(Event $event, Factory $mapper): array
216 {
217 $entryFields = $mapper->getEvent()->convertToArray($event);
218
219 unset($entryFields['SECTION_ID']);
220 unset($entryFields['RECURRENCE_ID']);
221
222 return $entryFields;
223 }
224
225 private function getEventAccessModel(int $eventId, int $userId): EventModel
226 {
227 return \CCalendarEvent::getEventModelForPermissionCheck(
228 eventId: $eventId,
229 userId: $userId
230 );
231 }
232
233 private function getSection(Factory $mapperFactory, UpdateEventCommand $command): Section
234 {
235 $section = $mapperFactory->getSection()->getById($command->getSectionId());
236 if (!$section)
237 {
238 throw new SectionNotFound();
239 }
240
241 if (!in_array($section->getType(), ['user', 'group'], true) && (new UserService())->isNotIntranetUser($command->getUserId()))
242 {
243 throw new ExtranetPermissionDenied();
244 }
245
246 if (Util::isCollabUser($command->getUserId()) && !$section->isCollab())
247 {
248 throw new PermissionDenied();
249 }
250
251 return $section;
252 }
253
254 private function notifyEventAuthor(Factory $mapperFactory, Event $updatedEvent, int $userId, array $currentFields): void
255 {
256 $isMeeting = $updatedEvent->isMeeting();
257 $meetingHostId = $updatedEvent->getEventHost()?->getId();
258 $type = $updatedEvent->getCalendarType();
259
260 if (!($isMeeting && $meetingHostId && $userId !== $meetingHostId && $type === 'user'))
261 {
262 return;
263 }
264
265 // TODO: refactor all this crap in the future
266 $entryFields = $mapperFactory->getEvent()->convertToArray($updatedEvent);
267 $entryChanges = \CCalendarEvent::CheckEntryChanges($entryFields, $currentFields);
268 if (empty($entryChanges))
269 {
270 return;
271 }
272
273 $fromTo = \CCalendarEvent::GetEventFromToForUser($entryFields, $userId);
274 \CCalendarNotify::Send([
275 'mode' => 'change_notify',
276 'name' => $entryFields['NAME'] ?? null,
277 "from" => $fromTo['DATE_FROM'] ?? null,
278 "to" => $fromTo['DATE_TO'] ?? null,
279 "location" => \CCalendar::GetTextLocation($entryFields["LOCATION"] ?? null),
280 "guestId" => $meetingHostId,
281 "eventId" => $updatedEvent->getId(),
282 "userId" => $userId,
283 "fields" => $entryFields,
284 "isSharing" => $updatedEvent->getCalendarType() === Dictionary::EVENT_TYPE['shared'],
285 "entryChanges" => $entryChanges,
286 ]);
287 }
288
292 private function getRecursionEditMode(UpdateEventCommand $command): ?string
293 {
294 $recursionEditMode = $command->getRecEditMode();
295 $canEditOnlyThis = $this->canEditAttendees && $this->canEditLocation && !$this->canEdit;
296
297 if ($canEditOnlyThis && in_array($recursionEditMode, ['next', 'all']))
298 {
299 throw new PermissionDenied();
300 }
301
302 return $recursionEditMode;
303 }
304}
$type
Определения options.php:106
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static isCollabUser(int $userId)
Определения util.php:337
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$event
Определения prolog_after.php:141
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799