Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
eventconverter.php
1<?php
2
4
15use CCalendar;
16
18{
19 public const ACCESSIBILITY_IMPORT_MAP = [
20 'busy' => 'busy',
21 'free' => 'free',
22 'workingElsewhere' => 'absent',
23 'tentative' => 'quest',
24 'oof' => 'absent', // Away
25 ];
26 public const ACCESSIBILITY_EXPORT_MAP = [
27 'busy' => 'busy',
28 'free' => 'free',
29 'quest' => 'tentative',
30 'absent' => 'oof', // Away
31 ];
32
33 public function __construct()
34 {
35 }
36
42 public function eventToDto(Event $event): EventDto
43 {
44 $endDate = $event->isFullDayEvent()
45 ? (clone $event->getEnd())->add('1 day')
46 : $event->getEnd();
47
48 $data = [
49 'subject' => $event->getName(),
50 'body' => [
51 'contentType' => 'HTML',
52 'content' => $this->prepareDescription($event),
53 ],
54 'isAllDay' => $event->isFullDayEvent(),
55 'start' => [
56 'dateTime' => $event->getStart()->getDate()->format(Helper::TIME_FORMAT_LONG),
57 'timeZone' => $this->prepareTimeZone(
58 $event->getStart(),
59 $event->getStartTimeZone(),
60 $event->isFullDayEvent()
61 ),
62 ],
63 'end' => [
64 'dateTime' => $endDate->getDate()->format(Helper::TIME_FORMAT_LONG),
65 'timeZone' => $this->prepareTimeZone(
66 $endDate,
67 $event->getEndTimeZone(),
68 $event->isFullDayEvent()
69 ),
70 ],
71 'isCancelled' => $event->isDeleted(),
72 'location' => [
73 'displayName' => $this->prepareLocation($event->getLocation()),
74 ],
75 ];
76
77 if ($event->isRecurrence())
78 {
79 $data['recurrence'] = $this->prepareRecurringForDto($event->getRecurringRule(), $event->getStart()->getDate());
80 }
81
82 if ($event->getRemindCollection())
83 {
84 $this->prepareReminders($event, $data);
85 }
86
87 if ($accessibility = $this->convertAccessibility($event->getAccessibility()))
88 {
89 $data['showAs'] = $accessibility;
90 }
91
92 return new EventDto($data);
93 }
94
100 private function convertAccessibility(?string $ourValue): ?string
101 {
102 return self::ACCESSIBILITY_EXPORT_MAP[$ourValue] ?? null;
103 }
104
111 private function prepareRecurringForDto(RecurringEventRules $rule, Type\Date $startDate): array
112 {
113 $result = [
114 'pattern' => [
115 'interval' => $rule->getInterval(),
116 ],
117 'range' => [],
118 ];
119 $dayMap = [
120 'MO' => 'monday',
121 'TU' => 'tuesday',
122 'WE' => 'wednesday',
123 'TH' => 'thursday',
124 'FR' => 'friday',
125 'SA' => 'saturday',
126 'SU' => 'sunday',
127 ];
128 if ($rule->getFrequency() === 'WEEKLY')
129 {
130 $result['pattern']['type'] = 'weekly';
131
132 $firstDayOfWeek = \COption::GetOptionString('calendar', 'week_start', 'MO');
133 $result['pattern']['firstDayOfWeek'] = $dayMap[$firstDayOfWeek];
134
135 if ($rule->getByday())
136 {
137 $result['pattern']['daysOfWeek'] = array_map(function ($val) use ($dayMap) {
138 return $dayMap[$val] ?? '';
139 }, array_values($rule->getByday()));
140 }
141 }
142 elseif ($rule->getFrequency() === 'DAILY')
143 {
144 $result['pattern']['type'] = 'daily';
145 }
146 elseif ($rule->getFrequency() === 'MONTHLY')
147 {
148 $result['pattern']['type'] = 'absoluteMonthly';
149 $result['pattern']['interval'] = $rule->getInterval();
150 $result['pattern']['dayOfMonth'] = (int) $startDate->format('d');
151
152 }
153 elseif ($rule->getFrequency() === 'YEARLY')
154 {
155 $result['pattern']['type'] = 'absoluteYearly';
156 $result['pattern']['dayOfMonth'] = (int) $startDate->format('d');
157 $result['pattern']['month'] = (int) $startDate->format('m');
158 }
159 $result['range']['startDate'] = $startDate->format('Y-m-d');
160
161 if ($rule->getCount())
162 {
163 $result['range']['type'] = 'numbered';
164 $result['range']['numberOfOccurrences'] = $rule->getCount();
165 $result['range']['endDate'] = '0001-01-01';
166 }
167 elseif ($rule->getUntil())
168 {
169 $result['range']['type'] = 'endDate';
170 $result['range']['endDate'] = $rule->getUntil()->format('Y-m-d');
171 }
172 else
173 {
174 $result['range']['type'] = 'noEnd';
175 $result['range']['endDate'] = $this->getFarFarAwayDate();
176 }
177
178 return $result;
179 }
180
184 private function getFarFarAwayDate(): string
185 {
186 return '01.01.2038';
187 }
188
195 private function prepareReminders(Event $event, array &$data): void
196 {
197 $remindCollection = $event->getRemindCollection();
198 $delta = null;
199
201 foreach ($remindCollection as $remind)
202 {
203 if (!$remind->isBeforeEventStart() && !$event->isFullDayEvent())
204 {
205 continue;
206 }
207
208 $newDelta = $remind->getTimeBeforeStartInMinutes();
209
210 if ($newDelta < -1440)
211 {
212 continue;
213 }
214
215 $delta = $delta === null ? $newDelta : min($delta, $newDelta);
216 }
217
218 if ($delta !== null)
219 {
220 $delta = (int)$delta;
221 $data['isReminderOn'] = true;
222 $data['reminderMinutesBeforeStart'] = $delta;
223 }
224 else
225 {
226 $data['isReminderOn'] = false;
227 $data['reminderMinutesBeforeStart'] = 0;
228 }
229
230 }
231
237 private function prepareLocation(?Location $location)
238 {
239 if ($location)
240 {
241 return CCalendar::GetTextLocation($location->getActualLocation());
242 }
243
244 return null;
245 }
246
254 private function prepareTimeZone(
255 Base\Date $date,
256 ?Base\DateTimeZone $timeZone,
257 bool $fullDay
258 ): string
259 {
260 if ($timeZone)
261 {
262 return $timeZone->getTimeZone()->getName();
263 }
264
265 if (!$fullDay)
266 {
267 $coreDate = $date->getDate();
268 if ($coreDate instanceof Type\DateTime)
269 {
270 return $coreDate->getTimeZone()->getName();
271 }
272 }
273
274 return $this->getDefaultTimezone();
275 }
276
280 private function getDefaultTimezone(): string
281 {
282 return 'UTC';
283 }
284
290 private function prepareDescription(Event $event): string
291 {
292 $description = (new EventDescription())->prepareForExport($event);
293
294 return $description ? \CCalendarEvent::ParseText($this->parseImagesInDescription($description)) : '';
295 }
296
302 private function parseImagesInDescription(string $description): string
303 {
304 return preg_replace(
305 "#\[img]((cid):[.\\-_:a-z0-9@]+)*\[/img]#is".BX_UTF_PCRE_MODIFIER,
306 "<img src='\\1'>",
307 $description
308 );
309 }
310}