ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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 return $this->createVEVENT($appointment);
232 }
233
234 protected function createVTODO(ilCalendarEntry $app): ilICalWriter
235 {
236 return new ilICalWriter();
237 }
238
239 protected function createVEVENT(ilCalendarEntry $app): ilICalWriter
240 {
241 $str_writer = new ilICalWriter();
242 if (!$app->getStart() instanceof ilDateTime) {
243 $this->logger->notice('Cannot create appointment for app_id: ' . $app->getEntryId());
244 return $str_writer;
245 }
246 $test_date = $app->getStart()->get(IL_CAL_FKT_DATE, 'Ymd');
247 if (!strlen((string) $test_date)) {
248 return $str_writer;
249 }
250 $now = new ilDateTime(time(), IL_CAL_UNIX);
251
252 $str_writer->addLine('BEGIN:VEVENT');
253 $str_writer->addLine('DTSTAMP:'
254 . $now->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC));
255 $str_writer->addLine('UID:' . ilICalWriter::escapeText(
256 $app->getEntryId() . '_' . CLIENT_ID . '@' . ILIAS_HTTP_PATH
257 ));
258
259 $last_mod = $app->getLastUpdate()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
260 $str_writer->addLine('LAST-MODIFIED:' . $last_mod);
261
262 $startInit = $app->getStart();
263 $endInit = $app->getEnd();
264
265 // begin-patch aptar
266 if ($app->isFullday()) {
267 // According to RFC 5545 3.6.1 DTEND is not inclusive.
268 // But ILIAS stores inclusive dates in the database.
269 $endInit->increment(IL_CAL_DAY, 1);
270 $start = $startInit->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
271 $end = $endInit->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
272 $str_writer->addLine('DTSTART;VALUE=DATE:' . $start);
273 $str_writer->addLine('DTEND;VALUE=DATE:' . $end);
274 } else {
275 if ($this->getUserSettings()->getExportTimeZoneType() == ilCalendarUserSettings::CAL_EXPORT_TZ_UTC) {
276 $start = $app->getStart()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
277 $end = $app->getEnd()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
278 $str_writer->addLine('DTSTART:' . $start);
279 $str_writer->addLine('DTEND:' . $end);
280 } else {
281 $start = $startInit->get(IL_CAL_FKT_DATE, 'Ymd\THis', $this->il_user->getTimeZone());
282 $end = $endInit->get(IL_CAL_FKT_DATE, 'Ymd\THis', $this->il_user->getTimeZone());
283 $str_writer->addLine('DTSTART;TZID=' . $this->il_user->getTimezone() . ':' . $start);
284 $str_writer->addLine('DTEND;TZID=' . $this->il_user->getTimezone() . ':' . $end);
285 }
286 }
287 // end-patch aptar
288
289 $str_writer->append($this->createRecurrences($app));
290 $str_writer->addLine('SUMMARY:' . ilICalWriter::escapeText($app->getPresentationTitle(false)));
291 if (strlen($app->getDescription())) {
292 $str_writer->addLine('DESCRIPTION:' . ilICalWriter::escapeText($app->getDescription()));
293 }
294 if (strlen($app->getLocation())) {
295 $str_writer->addLine('LOCATION:' . ilICalWriter::escapeText($app->getLocation()));
296 }
297
298 // TODO: URL
299 $str_writer->append($this->buildAppointmentUrl($app));
300 $str_writer->addLine('END:VEVENT');
301 return $str_writer;
302 }
303
305 {
306 $str_writer = new ilICalWriter();
307 foreach (ilCalendarRecurrences::_getRecurrences($app->getEntryId()) as $rec) {
309 $str_writer->addLine($excl->toICal());
310 }
311 $recurrence_ical = $rec->toICal($this->il_user->getId());
312 if (strlen($recurrence_ical)) {
313 $str_writer->addLine($recurrence_ical);
314 }
315 }
316 return $str_writer;
317 }
318
319 public function getExportString(): string
320 {
321 return $this->str_writer_export->__toString();
322 }
323
325 {
326 $str_writer = new ilICalWriter();
329 );
330 if ($cat->getType() != ilCalendarCategory::TYPE_OBJ) {
331 $str_writer->addLine('URL;VALUE=URI:' . ILIAS_HTTP_PATH);
332 } else {
333 $refs = ilObject::_getAllReferences($cat->getObjId());
334 $str_writer->addLine('URL;VALUE=URI:' . ilLink::_getLink(current($refs)));
335 }
336 return $str_writer;
337 }
338}
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)
Model for a calendar entry.
getEnd()
Get end of period.
getStart()
Get start of date period.
isFullday()
is event a fullday period
getPresentationTitle(bool $a_shorten=true)
@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
const CLIENT_ID
Definition: constants.php:41
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
global $DIC
Definition: shib_login.php:26