1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
EventProvider.php
См. документацию.
1<?php
2
3namespace Bitrix\Calendar\OpenEvents\Provider;
4
5use Bitrix\Calendar\Core\Common;
6use Bitrix\Calendar\Core\Event\Tools\Dictionary;
7use Bitrix\Calendar\EventOption\Dto\EventOptionsDto;
8use Bitrix\Calendar\Internals\Counter;
9use Bitrix\Calendar\Internals\EO_Event_Collection;
10use Bitrix\Calendar\Internals\EventAttendeeTable;
11use Bitrix\Calendar\Internals\EventTable;
12use Bitrix\Calendar\Internals\SectionTable;
13use Bitrix\Calendar\OpenEvents\Internals\Entity\OpenEventOption;
14use Bitrix\Calendar\OpenEvents\Internals\OpenEventCategoryAttendeeTable;
15use Bitrix\Calendar\OpenEvents\Internals\OpenEventOptionTable;
16use Bitrix\Calendar\OpenEvents\Item\OpenEvent;
17use Bitrix\Calendar\OpenEvents\Provider\Event\Filter;
18use Bitrix\Calendar\Util;
19use Bitrix\Calendar\Integration\Im;
20use Bitrix\Main\Engine\CurrentUser;
21use Bitrix\Main\Entity\ReferenceField;
22use Bitrix\Main\ORM\Query\Join;
23use Bitrix\Main\ORM\Query\Query;
24use Bitrix\Main\Text\Emoji;
25use Bitrix\Main\Type\DateTime;
26
27final class EventProvider
28{
29 protected int $userId;
30
31 public function __construct(?int $userId = null)
32 {
33 $this->userId = $userId ?? (int)CurrentUser::get()->getId();
34 }
35
36 public function getTsRange(Filter $filter): array
37 {
38 $filter->fromDate = null;
39 $filter->toDate = null;
40
41 $query = EventTable::query()
42 ->setSelect([
43 Query::expr('MIN_TS')->min('DATE_FROM_TS_UTC'),
44 Query::expr('MAX_TS')->max('DATE_TO_TS_UTC'),
45 ])
46 ;
47
49
50 $result = $query->fetch();
51
52 if (empty($result['MAX_TS']))
53 {
54 return [
55 'from' => gmmktime(0, 0, 0, 1, 1, 2038),
56 'to' => 0,
57 ];
58 }
59
60 return [
61 'from' => $result['MIN_TS'],
62 'to' => $result['MAX_TS'],
63 ];
64 }
65
66 public function list(Filter $filter): array
67 {
68 $query = EventTable::query();
69
70 $this->prepareSelect($query);
72
73 $eventCollection = $query->fetchCollection();
74
75 return $this->prepareResult($eventCollection, $filter);
76 }
77
78 protected function prepareSelect(Query $query): void
79 {
80 $query->setSelect([
81 'ID',
82 'NAME',
83 'DATE_FROM',
84 'DATE_TO',
85 'TZ_FROM',
86 'TZ_TO',
87 'DT_LENGTH',
88 'DT_SKIP_TIME',
89 'COLOR',
90 'SECTION_ID',
91 'RRULE',
92 'EXDATE',
93 'CREATED_BY',
94 'EVENT_OPTIONS.*',
95 ]);
96 }
97
98 protected function prepareFilter(Query $query, Filter $filter): void
99 {
100 $query->where('CAL_TYPE', Dictionary::CALENDAR_TYPE['open_event']);
101
102 if (!empty($filter->categoriesIds))
103 {
104 $query->registerRuntimeField(
105 (new ReferenceField(
106 'EVENT_OPTIONS',
107 OpenEventOptionTable::getEntity(),
108 Join::on('this.ID', 'ref.EVENT_ID')
109 ->whereIn('ref.CATEGORY_ID', $filter->categoriesIds),
110 ))
111 ->configureJoinType(Join::TYPE_INNER),
112 );
113 }
114 else
115 {
116 $query->registerRuntimeField(
117 new ReferenceField(
118 'EVENT_OPTIONS',
119 OpenEventOptionTable::getEntity(),
120 Join::on('this.ID', 'ref.EVENT_ID'),
121 ),
122 );
123 }
124
125 $query->registerRuntimeField(
126 (new ReferenceField(
127 'CATEGORY_ATTENDEE',
128 OpenEventCategoryAttendeeTable::getEntity(),
129 Join::on('this.EVENT_OPTIONS.CATEGORY_ID', 'ref.CATEGORY_ID')
130 ->whereIn('ref.USER_ID', [Common::SYSTEM_USER_ID, $this->userId])
131 ))
132 ->configureJoinType(Join::TYPE_INNER)
133 );
134
135 if (!empty($filter->fromDate))
136 {
137 $query->where(
138 'DATE_TO_TS_UTC',
139 '>=',
140 (int)\CCalendar::Timestamp($filter->fromDate, false) - $this->getUserOffset()
141 );
142 }
143
144 if (!empty($filter->toDate))
145 {
146 $query->where(
147 'DATE_FROM_TS_UTC',
148 '<=',
149 (int)\CCalendar::Timestamp($filter->toDate, false) - $this->getUserOffset()
150 );
151 }
152
153 if (!empty($filter->creatorId))
154 {
155 $query->where('CREATED_BY', $filter->creatorId);
156 }
157
158 if ($filter->iAmAttendee === true)
159 {
160 $query->registerRuntimeField(
161 (new ReferenceField(
162 'ATTENDEE',
163 EventAttendeeTable::getEntity(),
164 Join::on('this.ID', 'ref.EVENT_ID')
165 ->where('ref.OWNER_ID', $this->userId)
166 ->where('ref.MEETING_STATUS', 'Y')
167 ,
168 ))
169 ->configureJoinType(Join::TYPE_INNER)
170 ,
171 );
172 }
173
174 if ($filter->iAmAttendee === false)
175 {
176 $query->registerRuntimeField(
177 new ReferenceField(
178 'ATTENDEE',
179 EventAttendeeTable::getEntity(),
180 Join::on('this.ID', 'ref.EVENT_ID')
181 ->where('ref.OWNER_ID', $this->userId)
182 ->where('ref.MEETING_STATUS', 'Y')
183 ,
184 ),
185 );
186 $query->whereNull('ATTENDEE.EVENT_ID');
187 }
188
189 if (!empty($filter->query))
190 {
191 $value = \CCalendarEvent::prepareToken(Emoji::encode($filter->query));
192
193 if (\CCalendarEvent::isFullTextIndexEnabled())
194 {
196 $query->whereMatch('SEARCHABLE_CONTENT', $searchText);
197 }
198 else
199 {
200 $query->whereLike('SEARCHABLE_CONTENT', '%' . $value . '%');
201 }
202 }
203
204 $query->where('DELETED', $filter->deleted ? 'Y' : 'N');
205 }
206
207 protected function getUserOffset(): int
208 {
209 return Util::getTimezoneOffsetUTC(\CCalendar::GetUserTimezoneName($this->userId));
210 }
211
212 protected function prepareResult(EO_Event_Collection $eventCollection, Filter $filter): array
213 {
214 if ($eventCollection->isEmpty())
215 {
216 return [];
217 }
218
219 $eventIds = $eventCollection->getIdList();
220 $sectionIds = array_unique($eventCollection->getSectionIdList());
221 $categoryIds = array_unique(
222 array_map(fn ($event) => $event->get('EVENT_OPTIONS')?->getCategoryId(), $eventCollection->getAll()),
223 );
224 $threadIds = array_unique(
225 array_map(fn ($event) => $event->get('EVENT_OPTIONS')?->getThreadId(), $eventCollection->getAll()),
226 );
227
228 $attendedEventIds = $this->getAttendedEventIds($eventIds, $filter);
229
230 $sectionColors = $this->getSectionColors($sectionIds);
231
232 $categories = (new CategoryProvider())->getCategoryCollection($categoryIds);
233 $categoriesChannelIds = array_combine($categories->getIdList(), $categories->getChannelIdList());
234 $categoriesNames = array_combine($categories->getIdList(), $categories->getNameList());
235
236 $commentsCounts = Im\Comments::getCounts($threadIds);
237
238 $counter = Counter::getInstance($this->userId);
239
240 $events = [];
241 foreach ($eventCollection as $event)
242 {
243 $eventId = $event->getId();
244
248 $eventOptions = $event->get('EVENT_OPTIONS');
249 if (!$eventOptions)
250 {
251 continue;
252 }
253
254 $eventCommentsCount = isset($commentsCounts[$eventOptions->getThreadId()])
255 ? (int)$commentsCounts[$eventOptions->getThreadId()] - 1
256 : 0
257 ;
258
259 $dateFrom = $event->getDateFrom()->format('d.m.Y');
260 $dateTo = $event->getDateTo()->format('d.m.Y');
261 $dateFromTs = (new DateTime($dateFrom, 'd.m.Y', new \DateTimeZone('UTC')))->getTimestamp();
262 $dateToTs = (new DateTime($dateTo, 'd.m.Y', new \DateTimeZone('UTC')))->getTimestamp();
263 if (!$event->getDtSkipTime())
264 {
265 $dateFromTs = Util::getDateTimestampUtc($event->getDateFrom(), $event->getTzFrom());
266 $dateToTs = Util::getDateTimestampUtc($event->getDateTo(), $event->getTzTo());
267 }
268
269 $events[] = new OpenEvent(
270 id: $eventId,
271 name: $event->getName(),
272 dateFromTs: $dateFromTs,
273 dateToTs: $dateToTs,
274 isFullDay: $event->getDtSkipTime(),
275 isAttendee: in_array($eventId, $attendedEventIds, true),
276 attendeesCount: $eventOptions->getAttendeesCount(),
277 creatorId: $event->getCreatedBy(),
278 eventOptions: EventOptionsDto::fromArray(json_decode($eventOptions->getOptions(), true)),
279 categoryId: $eventOptions->getCategoryId(),
280 categoryName: $categoriesNames[$eventOptions->getCategoryId()],
281 categoryChannelId: $categoriesChannelIds[$eventOptions->getCategoryId()],
282 color: $event->getColor() ?: $sectionColors[$event->getSectionId()] ?: null,
283 commentsCount: $eventCommentsCount,
284 threadId: $eventOptions->getThreadId(),
285 isNew: (bool)$counter->get(Counter\CounterDictionary::COUNTER_NEW_EVENT, $eventId),
286 rrule: $event->getRrule(),
287 rruleDescription: \CCalendarEvent::GetRRULEDescription([
288 'RRULE' => $event->getRrule(),
289 'DATE_FROM' => $event->getDateFrom()->toString(),
290 'DT_SKIP_TIME' => $event->getDtSkipTime() ? 'Y' : 'N',
291 ]),
292 exdate: $event->getExdate(),
293 );
294 }
295
296 return $events;
297 }
298
299 protected function getAttendedEventIds(array $eventIds, Filter $filter): array
300 {
301 if ($filter->iAmAttendee === true)
302 {
303 return $eventIds;
304 }
305
306 if ($filter->iAmAttendee === false)
307 {
308 return [];
309 }
310
311 $attendees = EventAttendeeTable::query()
312 ->setSelect(['OWNER_ID', 'EVENT_ID'])
313 ->where('OWNER_ID', $this->userId)
314 ->whereIn('EVENT_ID', $eventIds)
315 ->where('MEETING_STATUS', 'Y')
316 ->fetchCollection()
317 ;
318
319 return $attendees->getEventIdList();
320 }
321
322 protected function getSectionColors(array $sectionIds): array
323 {
324 $sectionsQuery = SectionTable::query()
325 ->setSelect(['ID', 'COLOR'])
326 ->whereIn('ID', $sectionIds)
327 ;
328
329 $sections = $sectionsQuery->fetchCollection();
330
331 return array_combine($sections->getIdList(), $sections->getColorList());
332 }
333}
prepareFilter(Query $query, Filter $filter)
Определения EventProvider.php:98
getSectionColors(array $sectionIds)
Определения EventProvider.php:322
getAttendedEventIds(array $eventIds, Filter $filter)
Определения EventProvider.php:299
static getTimezoneOffsetUTC(string $timezoneName)
Определения util.php:767
static getDateTimestampUtc(DateTime $date, ?string $eventTimezone=null)
Определения util.php:774
static getInstance()
Определения application.php:98
static matchAgainstWildcard($phrase, $wildcard=' *', $minTokenSize=null)
Определения helper.php:32
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
background color
Определения file_new.php:745
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$filter
Определения iblock_catalog_list.php:54
Определения chain.php:3
$counter
Определения options.php:5
$event
Определения prolog_after.php:141