ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
24 include_once './Services/Calendar/classes/class.ilCalendarUserSettings.php';
25 include_once './Services/Calendar/classes/iCal/class.ilICalWriter.php';
26 include_once './Services/Calendar/classes/class.ilCalendarCategory.php';
27 include_once './Services/Calendar/classes/class.ilCalendarEntry.php';
28 include_once './Services/Calendar/classes/class.ilCalendarCategoryAssignments.php';
29 
38 {
39  protected const BYTE_LIMIT = 1000000;
40  const EXPORT_CALENDARS = 1;
42 
46  protected $export_type = self::EXPORT_CALENDARS;
50  protected $logger = null;
54  protected $il_user;
58  protected $calendars;
62  protected $user_settings;
66  protected $appointments;
70  protected $str_writer_export;
74  protected $is_export_limited;
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  {
93  return $this->user_settings;
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()) {
145  case self::EXPORT_CALENDARS:
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 
152  case self::EXPORT_APPOINTMENTS:
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) {
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 
346  protected function buildAppointmentUrl(ilCalendarEntry $entry) : ilICalWriter
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 }
$app
Definition: cli.php:38
static _getRecurrences($a_cal_id)
get all recurrences of an appointment
Model for a calendar entry.
getPresentationTitle($a_shorten=true)
get title for presentation.
static _getInstanceByUserId($a_user_id)
get singleton instance
getEntryId()
get entry id
static getZoneInfoFile($a_tz)
static _lookupCategories($a_cal_id)
lookup categories
const IL_CAL_UNIX
static _getAllReferences($a_id)
get all reference ids of object
isMilestone()
is milestone
createAppointment(ilCalendarEntry $appointment)
const IL_CAL_DAY
getDescription()
get description
getEnd()
get end public
createRecurrences(ilCalendarEntry $app)
buildAppointmentUrl(ilCalendarEntry $entry)
Export calendar(s) to ical format
const CLIENT_ID
Definition: constants.php:39
global $DIC
Definition: goto.php:24
const IL_CAL_FKT_DATE
static getInstanceByCategoryId($a_cat_id)
Get instance by category id.
addCategories(int $remaining_bytes)
createVEVENT(ilCalendarEntry $app)
createVTODO(ilCalendarEntry $app)
static _getAssignedAppointments($a_cat_id)
Get assigned apointments.
static getExclusionDates($a_cal_id)
Read exclusion dates.
getLocation()
get location
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
isRepeatingAppointment(ilCalendarEntry $appointment)
__construct(array $a_calendar_ids=[], bool $is_export_limited=false)
static escapeText($a_text)
getLastUpdate()
get last update
setCalendarIds(array $a_cal_ids)