11 PRODID =
'-//Bitrix//Bitrix Calendar//EN',
33 $availableProperties = [
74 if (in_array(
$key, $this->availableProperties) && !empty($value))
76 $this->properties[
$key] = $this->prepareValue($value,
$key);
86 if (isset(
$config[
'timezoneFrom']))
88 $this->timezoneFrom =
$config[
'timezoneFrom'];
90 if (isset(
$config[
'timezoneTo']))
92 $this->timezoneTo =
$config[
'timezoneTo'];
99 $this->fullDayMode = $value;
104 $this->organizer = [
'name' =>
$name,
'email' =>
$email,
'phone' => $phone];
109 if (is_array($attendeeDataList))
111 foreach($attendeeDataList as $attendeeData)
113 $this->attendees[] = $attendeeData;
130 return implode(
"\r\n", $this->buildBody());
133 private function buildBody()
138 'PRODID:'.self::PRODID,
140 'CALSCALE:GREGORIAN',
141 'METHOD:'.self::$METHOD,
148 if (isset($this->organizer[
'email']))
150 $props[self::formatOrganizerKey($this->organizer)] = self::formatEmailValue($this->organizer[
'email']);
152 else if (isset($this->organizer[
'phone']))
154 $props[self::formatOrganizerKey($this->organizer)] = self::formatPhoneValue($this->organizer[
'phone']);
158 if (is_array($this->attendees))
160 foreach($this->attendees as
$k => $attendee)
162 $props[self::formatAttendeeKey($attendee)] = self::formatEmailValue($attendee[
'email']);
167 foreach($this->properties as
$k => $v)
172 $props[
'DTSTAMP'] = self::formatDateTimeValue($v);
175 $props[
'URL;VALUE=URI'] = $v;
179 if ($this->fullDayMode)
181 $props[mb_strtoupper(
$k).
';VALUE=DATE'] = self::formatDateValue($v);
185 $tzid = (
$k ===
'dtstart') ? $this->timezoneFrom : $this->timezoneTo;
186 $props[mb_strtoupper(
$k).
';TZID='.$tzid] = self::formatDateTimeValue($v);
190 case 'last-modified':
191 $props[mb_strtoupper(
$k)] = self::formatDateTimeValue($v);
194 $priority = match ($v)
200 $props[mb_strtoupper(
$k)] = $priority;
207 if ($this->rrule !==
null)
212 if ($this->excludeDates && $this->rrule)
214 $props[
'EXDATE'] = $this->formatExcludedDates($this->prepareExcludedDates());
223 $ics_props[] =
'BEGIN:VALARM';
224 $ics_props[] =
'TRIGGER:-PT' .
$props[
'ALARM'];
225 $ics_props[] =
'ACTION:DISPLAY';
226 $ics_props[] =
'END:VALARM';
229 $ics_props[] =
$k . $v;
232 $ics_props[] =
"$k:$v";
237 $ics_props[] =
'END:VEVENT';
238 $ics_props[] =
'END:VCALENDAR';
243 private function prepareExcludedDates():
array
246 $exDate = $this->excludeDates->getCollection();
248 foreach ($exDate as $date)
250 $formattedDate = date(
'Ymd',
MakeTimeStamp($date->getFields()[
'date']));
251 if ($this->fullDayMode)
254 'VALUE' => $formattedDate,
255 'PARAMETERS' => [
'VALUE' =>
'DATE'],
264 $this->formatDateTimeValue($this->properties[
'dtstart'], self::TIME_FORMAT)
266 'PARAMETERS' => [
'TZID' => $this->prepareTimeZone($this->timezoneFrom)],
274 private function prepareTimeZone(?DateTimeZone $timeZone): string
278 return $timeZone->getTimeZone()->getName();
284 private function formatExcludedDates(
array $preparedExDate): string
289 foreach ($preparedExDate as $date)
291 $timezone = $date[
'PARAMETERS'][
'TZID'] ??
null;
292 $dates[] = $date[
'VALUE'];
295 $timezone = $timezone ?
';TZID=' . $timezone :
';VALUE=DATE';
297 return $timezone .
':' . implode(
',', $dates);
300 private function prepareValue(
$val,
$key =
false)
315 private static function formatDateValue($timestamp)
317 $dt = new \DateTime();
318 $dt->setTimestamp($timestamp);
319 return $dt->format(self::DATE_FORMAT);
322 private static function formatDateTimeValue($timestamp,
string $format = self::DATETIME_FORMAT)
324 $dt = new \DateTime();
327 $dt->setTimestamp($timestamp);
329 return $dt->format($format);
332 private static function formatEmailValue(
$email)
334 return 'mailto:'.$email;
337 private static function formatPhoneValue($phone): string
339 return 'tel:'.$phone;
343 private static function formatAttendeeKey($attendee)
346 $key .=
';CUTYPE=INDIVIDUAL';
348 $key .=
';RSVP=TRUE';
349 $key .=
';CN='.$attendee[
'email'];
353 private static function formatOrganizerKey(
$organizer)
358 $key .=
';CN='.$organizer[
'name'];
366 if (
$rrule->getInterval())
380 &&
$rrule->getUntil()->getDate()->getTimestamp()
381 &&
$rrule->getUntil()->getDate()->getTimestamp() < 2145830400
390 $untilTimestamp =
$rrule->getUntil()->getDate()->getTimestamp() + (self::DAY_LENGTH - 1) - $offset;
391 $result .=
';UNTIL=' . date(
'Ymd\\THis\\Z', $untilTimestamp);
397 private static function escapeString(
$str)
399 return preg_replace(
'/([\,;])/',
'\\\$1',
$str);