ILIAS  release_8 Revision v8.24
class.ilCalendarExport.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
27{
28 public const EXPORT_CALENDARS = 1;
29 public const EXPORT_APPOINTMENTS = 2;
30
31 protected const BYTE_LIMIT = 1000000;
32
34
37
38 protected array $calendars = array();
40 protected array $appointments = array();
42
47
48 protected bool $is_export_limited;
49
53 public function __construct(array $a_calendar_ids = [], bool $is_export_limited = false)
54 {
55 global $DIC;
56 $this->il_user = $DIC->user();
57 $this->logger = $DIC->logger()->cal();
58 $this->calendars = $a_calendar_ids;
59 $this->is_export_limited = $is_export_limited;
60 $this->appointments = [];
61 $this->user_settings = ilCalendarUserSettings::_getInstanceByUserId($this->il_user->getId());
62 $this->str_writer_export = new ilICalWriter();
63 }
64
66 {
68 }
69
73 public function setAppointments(array $a_apps): void
74 {
75 $this->appointments = $a_apps;
76 }
77
81 public function getAppointments(): array
82 {
84 }
85
89 public function setCalendarIds(array $a_cal_ids): void
90 {
91 $this->calendars = $a_cal_ids;
92 }
93
97 public function getCalendarIds(): array
98 {
99 return $this->calendars;
100 }
101
102 public function setExportType(int $a_type): void
103 {
104 $this->export_type = $a_type;
105 }
106 public function getExportType(): int
107 {
108 return $this->export_type;
109 }
110
111 public function export(): void
112 {
113 $this->str_writer_export->clear();
114 $str_writer_prefix = new ilICalWriter();
115 $str_writer_prefix->addLine('BEGIN:VCALENDAR');
116 $str_writer_prefix->addLine('VERSION:2.0');
117 $str_writer_prefix->addLine('METHOD:PUBLISH');
118 $str_writer_prefix->addLine('PRODID:-//ilias.de/NONSGML ILIAS Calendar V4.4//EN');
119 $str_writer_prefix->append($this->createTimezones());
120 $str_writer_suffix = new ilICalWriter();
121 $str_writer_suffix->addLine('END:VCALENDAR');
122 $this->str_writer_export->append($str_writer_prefix);
123 switch ($this->getExportType()) {
125 $byte_sum = $str_writer_prefix->byteCount() + $str_writer_suffix->byteCount();
126 $remaining_bytes = self::BYTE_LIMIT - $byte_sum;
127 $str_builder_body = $this->addCategories($remaining_bytes);
128 $this->str_writer_export->append($str_builder_body);
129 break;
130
132 $str_builder_body = $this->addAppointments();
133 $this->str_writer_export->append($str_builder_body);
134 break;
135 }
136 $this->str_writer_export->append($str_writer_suffix);
137 }
138
139 protected function createTimezones(): ilICalWriter
140 {
141 $str_writer = new ilICalWriter();
142 if ($this->getUserSettings()->getExportTimeZoneType() == ilCalendarUserSettings::CAL_EXPORT_TZ_UTC) {
143 return $str_writer;
144 }
145
146 $str_writer->addLine('X-WR-TIMEZONE:' . $this->il_user->getTimeZone());
147 $tzid_file = ilCalendarUtil::getZoneInfoFile($this->il_user->getTimeZone());
148 if (!is_file($tzid_file)) {
149 $tzid_file = ilCalendarUtil::getZoneInfoFile('Europe/Berlin');
150 }
151 $reader = fopen($tzid_file, 'r');
152 while ($line = fgets($reader)) {
153 $line = str_replace("\n", '', $line);
154 $str_writer->addLine($line);
155 }
156 return $str_writer;
157 }
158
159 protected function addCategories(int $remaining_bytes): ilICalWriter
160 {
161 $single_appointments = [];
162 $str_writer_appointments = new ilICalWriter();
163
164 foreach ($this->calendars as $category_id) {
165 foreach (ilCalendarCategoryAssignments::_getAssignedAppointments(array($category_id)) as $app_id) {
166 $appointment = new ilCalendarEntry($app_id);
167 if ($this->isRepeatingAppointment($appointment)) {
168 $str_writer_appointment = $this->createAppointment($appointment);
169 $str_writer_appointments->append($str_writer_appointment);
170 continue;
171 }
172 $single_appointments[] = $appointment;
173 }
174 }
175
176 usort($single_appointments, function (ilCalendarEntry $a, ilCalendarEntry $b) {
177 if($a->getStart() === $b->getStart()) {
178 return 0;
179 }
180 return $a->getStart() > $b->getStart() ? 1 : -1;
181 });
182
183 // Apply a filter on limited exports only
184 if ($this->is_export_limited) {
185 $single_appointments = array_filter($single_appointments, function (ilCalendarEntry $a) {
186 $time_now = new ilDateTime(time(), IL_CAL_UNIX);
187 $str_time_now = $time_now->get(IL_CAL_FKT_DATE, 'Ymd', ilTimeZone::UTC);
188 $str_time_start = $a->getStart()->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
189 if ($str_time_start === null) {
190 return false;
191 }
192 $start = new DateTimeImmutable($str_time_start);
193 $now = new DateTimeImmutable($str_time_now);
194 $lower_bound = $now->sub(new DateInterval('P30D'));
195 return $lower_bound <= $start;
196 });
197 }
198
199 foreach ($single_appointments as $appointment) {
200 $str_writer_appointment = $this->createAppointment($appointment);
201 // Check byte count for limited exports only
202 if (
203 $this->is_export_limited &&
204 ($str_writer_appointments->byteCount() + $str_writer_appointment->byteCount()) > $remaining_bytes
205 ) {
206 break;
207 }
208 $str_writer_appointments->append($str_writer_appointment);
209 }
210
211 return $str_writer_appointments;
212 }
213
214 protected function isRepeatingAppointment(ilCalendarEntry $appointment): bool
215 {
216 return count(ilCalendarRecurrences::_getRecurrences($appointment->getEntryId())) > 0;
217 }
218
219 protected function addAppointments(): ilICalWriter
220 {
221 $str_builder_appointments = new ilICalWriter();
222 foreach ($this->getAppointments() as $app) {
223 $str_writer_appointment = $this->createAppointment(new ilCalendarEntry($app));
224 $str_builder_appointments->append($str_writer_appointment);
225 }
226 return $str_builder_appointments;
227 }
228
229 protected function createAppointment(ilCalendarEntry $appointment): ilICalWriter
230 {
231 if ($appointment->isMilestone()) {
232 return $this->createVTODO($appointment);
233 } else {
234 return $this->createVEVENT($appointment);
235 }
236 }
237
239 {
240 return new ilICalWriter();
241 }
242
244 {
245 $str_writer = new ilICalWriter();
246 if (!$app->getStart() instanceof ilDateTime) {
247 $this->logger->notice('Cannot create appointment for app_id: ' . $app->getEntryId());
248 return $str_writer;
249 }
250 $test_date = $app->getStart()->get(IL_CAL_FKT_DATE, 'Ymd');
251 if (!strlen((string) $test_date)) {
252 return $str_writer;
253 }
254 $now = new ilDateTime(time(), IL_CAL_UNIX);
255
256 $str_writer->addLine('BEGIN:VEVENT');
257 $str_writer->addLine('DTSTAMP:'
258 . $now->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC));
259 $str_writer->addLine('UID:' . ilICalWriter::escapeText(
260 $app->getEntryId() . '_' . CLIENT_ID . '@' . ILIAS_HTTP_PATH
261 ));
262
263 $last_mod = $app->getLastUpdate()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
264 $str_writer->addLine('LAST-MODIFIED:' . $last_mod);
265
266 $startInit = $app->getStart();
267 $endInit = $app->getEnd();
268
269 // begin-patch aptar
270 if ($app->isFullday()) {
271 // According to RFC 5545 3.6.1 DTEND is not inclusive.
272 // But ILIAS stores inclusive dates in the database.
273 $endInit->increment(IL_CAL_DAY, 1);
274 $start = $startInit->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
275 $end = $endInit->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
276 $str_writer->addLine('DTSTART;VALUE=DATE:' . $start);
277 $str_writer->addLine('DTEND;VALUE=DATE:' . $end);
278 } else {
279 if ($this->getUserSettings()->getExportTimeZoneType() == ilCalendarUserSettings::CAL_EXPORT_TZ_UTC) {
280 $start = $app->getStart()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
281 $end = $app->getEnd()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
282 $str_writer->addLine('DTSTART:' . $start);
283 $str_writer->addLine('DTEND:' . $end);
284 } else {
285 $start = $startInit->get(IL_CAL_FKT_DATE, 'Ymd\THis', $this->il_user->getTimeZone());
286 $end = $endInit->get(IL_CAL_FKT_DATE, 'Ymd\THis', $this->il_user->getTimeZone());
287 $str_writer->addLine('DTSTART;TZID=' . $this->il_user->getTimezone() . ':' . $start);
288 $str_writer->addLine('DTEND;TZID=' . $this->il_user->getTimezone() . ':' . $end);
289 }
290 }
291 // end-patch aptar
292
293 $str_writer->append($this->createRecurrences($app));
294 $str_writer->addLine('SUMMARY:' . ilICalWriter::escapeText($app->getPresentationTitle(false)));
295 if (strlen($app->getDescription())) {
296 $str_writer->addLine('DESCRIPTION:' . ilICalWriter::escapeText($app->getDescription()));
297 }
298 if (strlen($app->getLocation())) {
299 $str_writer->addLine('LOCATION:' . ilICalWriter::escapeText($app->getLocation()));
300 }
301
302 // TODO: URL
303 $str_writer->append($this->buildAppointmentUrl($app));
304 $str_writer->addLine('END:VEVENT');
305 return $str_writer;
306 }
307
309 {
310 $str_writer = new ilICalWriter();
311 include_once './Services/Calendar/classes/class.ilCalendarRecurrences.php';
312 foreach (ilCalendarRecurrences::_getRecurrences($app->getEntryId()) as $rec) {
313 foreach (ilCalendarRecurrenceExclusions::getExclusionDates($app->getEntryId()) as $excl) {
314 $str_writer->addLine($excl->toICal());
315 }
316 $recurrence_ical = $rec->toICal($this->il_user->getId());
317 if (strlen($recurrence_ical)) {
318 $str_writer->addLine($recurrence_ical);
319 }
320 }
321 return $str_writer;
322 }
323
324 public function getExportString(): string
325 {
326 return $this->str_writer_export->__toString();
327 }
328
330 {
331 $str_writer = new ilICalWriter();
334 );
335 if ($cat->getType() != ilCalendarCategory::TYPE_OBJ) {
336 $str_writer->addLine('URL;VALUE=URI:' . ILIAS_HTTP_PATH);
337 } else {
338 $refs = ilObject::_getAllReferences($cat->getObjId());
339 include_once './Services/Link/classes/class.ilLink.php';
340 $str_writer->addLine('URL;VALUE=URI:' . ilLink::_getLink(current($refs)));
341 }
342 return $str_writer;
343 }
344}
const IL_CAL_UNIX
const IL_CAL_FKT_DATE
const IL_CAL_DAY
static _getAssignedAppointments(array $a_cat_id)
Get assigned apointments.
static getInstanceByCategoryId(int $a_cat_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
@classDescription Export calendar(s) to ical format
ilICalWriter $str_writer_export
buildAppointmentUrl(ilCalendarEntry $entry)
setAppointments(array $a_apps)
ilCalendarUserSettings $user_settings
createAppointment(ilCalendarEntry $appointment)
createVTODO(ilCalendarEntry $app)
createVEVENT(ilCalendarEntry $app)
addCategories(int $remaining_bytes)
createRecurrences(ilCalendarEntry $app)
__construct(array $a_calendar_ids=[], bool $is_export_limited=false)
setCalendarIds(array $a_cal_ids)
isRepeatingAppointment(ilCalendarEntry $appointment)
static getExclusionDates($a_cal_id)
Read exclusion dates.
static _getRecurrences(int $a_cal_id)
get all recurrences of an appointment
static _getInstanceByUserId(int $a_user_id)
static getZoneInfoFile($a_tz)
@classDescription Date and time handling
static escapeText(string $a_text)
Component logger with individual log levels by component id.
User class.
static _getAllReferences(int $id)
get all reference ids for object ID
$app
Definition: cli.php:39
const CLIENT_ID
Definition: constants.php:41
global $DIC
Definition: feed.php:28
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples