ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilCalendarExport.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 +-----------------------------------------------------------------------------+
22*/
23
24include_once './Services/Calendar/classes/class.ilCalendarUserSettings.php';
25include_once './Services/Calendar/classes/iCal/class.ilICalWriter.php';
26include_once './Services/Calendar/classes/class.ilCalendarCategory.php';
27include_once './Services/Calendar/classes/class.ilCalendarEntry.php';
28include_once './Services/Calendar/classes/class.ilCalendarCategoryAssignments.php';
29
38{
39 protected const BYTE_LIMIT = 1000000;
42
50 protected $logger = null;
54 protected $il_user;
58 protected $calendars;
62 protected $user_settings;
66 protected $appointments;
75
79 public function __construct(array $a_calendar_ids = [], bool $is_export_limited = false)
80 {
81 global $DIC;
82 $this->il_user = $DIC->user();
83 $this->logger = $DIC->logger()->cal();
84 $this->calendars = $a_calendar_ids;
85 $this->is_export_limited = $is_export_limited;
86 $this->appointments = [];
87 $this->user_settings = ilCalendarUserSettings::_getInstanceByUserId($this->il_user->getId());
88 $this->str_writer_export = new ilICalWriter();
89 }
90
92 {
94 }
95
96 public function setAppointments($a_apps) : void
97 {
98 $this->appointments = $a_apps;
99 }
100
101 public function getAppointments() : array
102 {
103 return $this->appointments;
104 }
105
109 public function setCalendarIds(array $a_cal_ids) : void
110 {
111 $this->calendars = $a_cal_ids;
112 }
113
117 public function getCalendarIds() : array
118 {
119 return $this->calendars;
120 }
121
122 public function setExportType(int $a_type) : void
123 {
124 $this->export_type = $a_type;
125 }
126
127 public function getExportType() : int
128 {
129 return $this->export_type;
130 }
131
132 public function export() : void
133 {
134 $this->str_writer_export->clear();
135 $str_writer_prefix = new ilICalWriter();
136 $str_writer_prefix->addLine('BEGIN:VCALENDAR');
137 $str_writer_prefix->addLine('VERSION:2.0');
138 $str_writer_prefix->addLine('METHOD:PUBLISH');
139 $str_writer_prefix->addLine('PRODID:-//ilias.de/NONSGML ILIAS Calendar V4.4//EN');
140 $str_writer_prefix->append($this->createTimezones());
141 $str_writer_suffix = new ilICalWriter();
142 $str_writer_suffix->addLine('END:VCALENDAR');
143 $this->str_writer_export->append($str_writer_prefix);
144 switch ($this->getExportType()) {
146 $byte_sum = $str_writer_prefix->byteCount() + $str_writer_suffix->byteCount();
147 $remaining_bytes = self::BYTE_LIMIT - $byte_sum;
148 $str_builder_body = $this->addCategories($remaining_bytes);
149 $this->str_writer_export->append($str_builder_body);
150 break;
151
153 $str_builder_body = $this->addAppointments();
154 $this->str_writer_export->append($str_builder_body);
155 break;
156 }
157 $this->str_writer_export->append($str_writer_suffix);
158 }
159
160 protected function createTimezones() : ilICalWriter
161 {
162 $str_writer = new ilICalWriter();
163 if ($this->getUserSettings()->getExportTimeZoneType() == ilCalendarUserSettings::CAL_EXPORT_TZ_UTC) {
164 return $str_writer;
165 }
166
167 $str_writer->addLine('X-WR-TIMEZONE:' . $this->il_user->getTimeZone());
168
169 include_once './Services/Calendar/classes/class.ilCalendarUtil.php';
170 $tzid_file = ilCalendarUtil::getZoneInfoFile($this->il_user->getTimeZone());
171 if (!is_file($tzid_file)) {
172 $tzid_file = ilCalendarUtil::getZoneInfoFile('Europe/Berlin');
173 }
174 $reader = fopen($tzid_file, 'r');
175 while ($line = fgets($reader)) {
176 $line = str_replace("\n", '', $line);
177 $str_writer->addLine($line);
178 }
179 return $str_writer;
180 }
181
182 protected function addCategories(int $remaining_bytes) : ilICalWriter
183 {
184 $single_appointments = [];
185 $str_writer_appointments = new ilICalWriter();
186
187 foreach ($this->calendars as $category_id) {
188 foreach (ilCalendarCategoryAssignments::_getAssignedAppointments(array($category_id)) as $app_id) {
189 $appointment = new ilCalendarEntry($app_id);
190 if ($this->isRepeatingAppointment($appointment)) {
191 $str_writer_appointment = $this->createAppointment($appointment);
192 $str_writer_appointments->append($str_writer_appointment);
193 continue;
194 }
195 $single_appointments[] = $appointment;
196 }
197 }
198
199 usort($single_appointments, function (ilCalendarEntry $a, ilCalendarEntry $b) {
200 return $a->getStart() > $b->getStart();
201 });
202
203 // Apply a filter on limited exports only
204 if ($this->is_export_limited) {
205 $single_appointments = array_filter($single_appointments, function (ilCalendarEntry $a) {
206 $time_now = new ilDateTime(time(), IL_CAL_UNIX);
207 $str_time_now = $time_now->get(IL_CAL_FKT_DATE, 'Ymd', ilTimeZone::UTC);
208 $str_time_start = $a->getStart()->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
209 $start = new DateTimeImmutable($str_time_start);
210 $now = new DateTimeImmutable($str_time_now);
211 $lower_bound = $now->sub(new DateInterval('P30D'));
212 return $lower_bound <= $start;
213 });
214 }
215
216 foreach ($single_appointments as $appointment) {
217 $str_writer_appointment = $this->createAppointment($appointment);
218 // Check byte count for limited exports only
219 if (
220 $this->is_export_limited &&
221 ($str_writer_appointments->byteCount() + $str_writer_appointment->byteCount()) > $remaining_bytes
222 ) {
223 break;
224 }
225 $str_writer_appointments->append($str_writer_appointment);
226 }
227
228 return $str_writer_appointments;
229 }
230
231 protected function isRepeatingAppointment(ilCalendarEntry $appointment) : bool
232 {
233 return count(ilCalendarRecurrences::_getRecurrences($appointment->getEntryId())) > 0;
234 }
235
236 protected function addAppointments() : ilICalWriter
237 {
238 $str_builder_appointments = new ilICalWriter();
239 foreach ($this->getAppointments() as $app) {
240 $str_writer_appointment = $this->createAppointment($app);
241 $str_builder_appointments->append($str_writer_appointment);
242 }
243 return $str_builder_appointments;
244 }
245
246 protected function createAppointment(ilCalendarEntry $appointment) : ilICalWriter
247 {
248 if ($appointment->isMilestone()) {
249 return $this->createVTODO($appointment);
250 } else {
251 return $this->createVEVENT($appointment);
252 }
253 }
254
256 {
257 return new ilICalWriter();
258 }
259
261 {
262 $str_writer = new ilICalWriter();
263 if (!$app->getStart() instanceof ilDateTime) {
264 $this->logger->notice('Cannot create appointment for app_id: ' . $app->getEntryId());
265 return $str_writer;
266 }
267 $test_date = $app->getStart()->get(IL_CAL_FKT_DATE, 'Ymd');
268 if (!strlen((string) $test_date)) {
269 return $str_writer;
270 }
271 $now = new ilDateTime(time(), IL_CAL_UNIX);
272
273 $str_writer->addLine('BEGIN:VEVENT');
274 $str_writer->addLine('DTSTAMP:'
275 . $now->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC));
276 $str_writer->addLine('UID:' . ilICalWriter::escapeText(
277 $app->getEntryId() . '_' . CLIENT_ID . '@' . ILIAS_HTTP_PATH
278 ));
279
280 $last_mod = $app->getLastUpdate()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
281 $str_writer->addLine('LAST-MODIFIED:' . $last_mod);
282
283 $startInit = $app->getStart();
284 $endInit = $app->getEnd();
285
286 // begin-patch aptar
287 if ($app->isFullday()) {
288 // According to RFC 5545 3.6.1 DTEND is not inclusive.
289 // But ILIAS stores inclusive dates in the database.
290 $endInit->increment(IL_CAL_DAY, 1);
291 $start = $startInit->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
292 $end = $endInit->get(IL_CAL_FKT_DATE, 'Ymd', $this->il_user->getTimeZone());
293 $str_writer->addLine('DTSTART;VALUE=DATE:' . $start);
294 $str_writer->addLine('DTEND;VALUE=DATE:' . $end);
295 } else {
296 if ($this->getUserSettings()->getExportTimeZoneType() == ilCalendarUserSettings::CAL_EXPORT_TZ_UTC) {
297 $start = $app->getStart()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
298 $end = $app->getEnd()->get(IL_CAL_FKT_DATE, 'Ymd\THis\Z', ilTimeZone::UTC);
299 $str_writer->addLine('DTSTART:' . $start);
300 $str_writer->addLine('DTEND:' . $end);
301 } else {
302 $start = $startInit->get(IL_CAL_FKT_DATE, 'Ymd\THis', $this->il_user->getTimeZone());
303 $end = $endInit->get(IL_CAL_FKT_DATE, 'Ymd\THis', $this->il_user->getTimeZone());
304 $str_writer->addLine('DTSTART;TZID=' . $this->il_user->getTimezone() . ':' . $start);
305 $str_writer->addLine('DTEND;TZID=' . $this->il_user->getTimezone() . ':' . $end);
306 }
307 }
308 // end-patch aptar
309
310 $str_writer->append($this->createRecurrences($app));
311 $str_writer->addLine('SUMMARY:' . ilICalWriter::escapeText($app->getPresentationTitle(false)));
312 if (strlen($app->getDescription())) {
313 $str_writer->addLine('DESCRIPTION:' . ilICalWriter::escapeText($app->getDescription()));
314 }
315 if (strlen($app->getLocation())) {
316 $str_writer->addLine('LOCATION:' . ilICalWriter::escapeText($app->getLocation()));
317 }
318
319 // TODO: URL
320 $str_writer->append($this->buildAppointmentUrl($app));
321 $str_writer->addLine('END:VEVENT');
322 return $str_writer;
323 }
324
326 {
327 $str_writer = new ilICalWriter();
328 include_once './Services/Calendar/classes/class.ilCalendarRecurrences.php';
329 foreach (ilCalendarRecurrences::_getRecurrences($app->getEntryId()) as $rec) {
330 foreach (ilCalendarRecurrenceExclusions::getExclusionDates($app->getEntryId()) as $excl) {
331 $str_writer->addLine($excl->toICal());
332 }
333 $recurrence_ical = $rec->toICal($this->il_user->getId());
334 if (strlen($recurrence_ical)) {
335 $str_writer->addLine($recurrence_ical);
336 }
337 }
338 return $str_writer;
339 }
340
341 public function getExportString() : string
342 {
343 return $this->str_writer_export->__toString();
344 }
345
347 {
348 $str_writer = new ilICalWriter();
351 );
352 if ($cat->getType() != ilCalendarCategory::TYPE_OBJ) {
353 $str_writer->addLine('URL;VALUE=URI:' . ILIAS_HTTP_PATH);
354 } else {
355 $refs = ilObject::_getAllReferences($cat->getObjId());
356 include_once './Services/Link/classes/class.ilLink.php';
357 $str_writer->addLine('URL;VALUE=URI:' . ilLink::_getLink(current($refs)));
358 }
359 return $str_writer;
360 }
361}
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_UNIX
const IL_CAL_FKT_DATE
const IL_CAL_DAY
static _getAssignedAppointments($a_cat_id)
Get assigned apointments.
static _lookupCategories($a_cal_id)
lookup categories
static getInstanceByCategoryId($a_cat_id)
Get instance by category id.
Model for a calendar entry.
@classDescription Export calendar(s) to ical format
buildAppointmentUrl(ilCalendarEntry $entry)
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($a_cal_id)
get all recurrences of an appointment
static _getInstanceByUserId($a_user_id)
get singleton instance
static getZoneInfoFile($a_tz)
@classDescription Date and time handling
static escapeText($a_text)
static _getAllReferences($a_id)
get all reference ids of object
$app
Definition: cli.php:38
const CLIENT_ID
Definition: constants.php:39
global $DIC
Definition: goto.php:24
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples