ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.ilCalendarSchedule.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2006 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
37{
38 const TYPE_DAY = 1;
39 const TYPE_WEEK = 2;
40 const TYPE_MONTH = 3;
41 const TYPE_INBOX = 4;
42 const TYPE_HALF_YEAR = 6;
43
44 // @deprecated
46
47 protected $limit_events = -1;
48 protected $schedule = array();
49 protected $timezone;
50 protected $weekstart;
51 protected $type = 0;
52
53 protected $subitems_enabled = false;
54
55 protected $start = null;
56 protected $end = null;
57 protected $user = null;
58 protected $user_settings = null;
59 protected $db = null;
60 protected $filters = array();
61
65 protected $strict_period;
66
77 public function __construct(ilDate $seed, $a_type, $a_user_id = 0, $a_strict_period = false)
78 {
79 global $ilUser,$ilDB;
80
81 $this->db = $ilDB;
82
83 $this->type = $a_type;
84
85 //this strict period is just to avoid possible side effects.
86 //I there are none, we can get rid of this strict period control and remove it from the constructor
87 //and from the calls in ilCalendarView getEvents.
88 $this->strict_period = $a_strict_period;
89
90 if (!$a_user_id || $a_user_id == $ilUser->getId()) {
91 $this->user = $ilUser;
92 } else {
93 $this->user = new ilObjUser($a_user_id);
94 }
95 $this->user_settings = ilCalendarUserSettings::_getInstanceByUserId($this->user->getId());
96 $this->weekstart = $this->user_settings->getWeekStart();
97 $this->timezone = $this->user->getTimeZone();
98
99 $this->initPeriod($seed);
100
101
102 // category / event filters
103 // portfolio does custom filter handling (booking group ids)
105 // consultation hour calendar views do not mind calendar category visibility
107 // this is the "default" filter which handles currently hidden categories for the user
108 $this->addFilter(new ilCalendarScheduleFilterHidden($this->user->getId()));
109 } else {
110 // handle booking visibility (target object, booked out)
111 //this filter deals with consultation hours
112 $this->addFilter(new ilCalendarScheduleFilterBookings($this->user->getId()));
113 }
114
116 //this filter deals with booking pool reservations
117 $this->addFilter(new ilCalendarScheduleFilterBookingPool($this->user->getId()));
118 }
119
120 // exercise
121 include_once './Services/Calendar/classes/class.ilCalendarScheduleFilterExercise.php';
122 $this->addFilter(new ilCalendarScheduleFilterExercise($this->user->getId()));
123 }
124 }
125
130 protected function areEventsLimited()
131 {
132 return $this->limit_events != -1;
133 }
134
139 public function getEventsLimit()
140 {
141 return $this->limit_events;
142 }
143
148 public function setEventsLimit($a_limit)
149 {
150 $this->limit_events = $a_limit;
151 }
152
158 public function addSubitemCalendars($a_status)
159 {
160 $this->subitems_enabled = $a_status;
161 }
162
167 public function enabledSubitemCalendars()
168 {
169 return (bool) $this->subitems_enabled;
170 }
171
177 public function addFilter(ilCalendarScheduleFilter $a_filter)
178 {
179 $this->filters[] = $a_filter;
180 }
181
189 public function getByDay(ilDate $a_start, $a_timezone)
190 {
191 $start = new ilDateTime($a_start->get(IL_CAL_DATETIME), IL_CAL_DATETIME, $this->timezone);
192 $fstart = new ilDate($a_start->get(IL_CAL_UNIX), IL_CAL_UNIX);
193 $fend = clone $fstart;
194
195 $f_unix_start = $fstart->get(IL_CAL_UNIX);
196 $fend->increment(ilDateTime::DAY, 1);
197 $f_unix_end = $fend->get(IL_CAL_UNIX);
198
199 $unix_start = $start->get(IL_CAL_UNIX);
200 $start->increment(ilDateTime::DAY, 1);
201 $unix_end = $start->get(IL_CAL_UNIX);
202
203 $counter = 0;
204
205 $tmp_date = new ilDateTime($unix_start, IL_CAL_UNIX, $this->timezone);
206 $tmp_schedule = array();
207 $tmp_schedule_fullday = array();
208 foreach ($this->schedule as $schedule) {
209 if ($schedule['fullday']) {
210 if (($f_unix_start == $schedule['dstart']) or
211 $f_unix_start == $schedule['dend'] or
212 ($f_unix_start > $schedule['dstart'] and $f_unix_end <= $schedule['dend'])) {
213 $tmp_schedule_fullday[] = $schedule;
214 }
215 } elseif (($schedule['dstart'] == $unix_start) or
216 (($schedule['dstart'] <= $unix_start) and ($schedule['dend'] > $unix_start)) or
217 (($schedule['dstart'] >= $unix_start) and ($schedule['dstart'] < $unix_end))) {
218 $tmp_schedule[] = $schedule;
219 }
220 }
221
222 //order non full day events by starting date;
223 array_multisort(array_column($tmp_schedule, 'dstart'), SORT_ASC, $tmp_schedule);
224
225 //merge both arrays keeping the full day events first and then rest ordered by starting date.
226 $schedules = array_merge($tmp_schedule_fullday, $tmp_schedule);
227
228 return $schedules;
229 }
230
231
237 public function calculate()
238 {
239 $events = $this->getEvents();
240
241 // we need category type for booking handling
242 $ids = array();
243 foreach ($events as $event) {
244 $ids[] = $event->getEntryId();
245 }
246
247 include_once('Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
249 include_once('Services/Calendar/classes/class.ilCalendarCategory.php');
250 $cat_types = array();
251 foreach (array_unique($cat_map) as $cat_id) {
252 $cat = new ilCalendarCategory($cat_id);
253 $cat_types[$cat_id] = $cat->getType();
254 }
255
256 $counter = 0;
257 foreach ($events as $event) {
258 // Calculdate recurring events
259 include_once('Services/Calendar/classes/class.ilCalendarRecurrences.php');
260 if ($recs = ilCalendarRecurrences::_getRecurrences($event->getEntryId())) {
261 $duration = $event->getEnd()->get(IL_CAL_UNIX) - $event->getStart()->get(IL_CAL_UNIX);
262 foreach ($recs as $rec) {
263 $calc = new ilCalendarRecurrenceCalculator($event, $rec);
264 foreach ($calc->calculateDateList($this->start, $this->end)->get() as $rec_date) {
265 if ($this->type == self::TYPE_PD_UPCOMING &&
266 $rec_date->get(IL_CAL_UNIX) < time()) {
267 continue;
268 }
269
270 $this->schedule[$counter]['event'] = $event;
271 $this->schedule[$counter]['dstart'] = $rec_date->get(IL_CAL_UNIX);
272 $this->schedule[$counter]['dend'] = $this->schedule[$counter]['dstart'] + $duration;
273 $this->schedule[$counter]['fullday'] = $event->isFullday();
274 $this->schedule[$counter]['category_id'] = $cat_map[$event->getEntryId()];
275 $this->schedule[$counter]['category_type'] = $cat_types[$cat_map[$event->getEntryId()]];
276
277 switch ($this->type) {
278 case self::TYPE_DAY:
279 case self::TYPE_WEEK:
280 // store date info (used for calculation of overlapping events)
281 $tmp_date = new ilDateTime($this->schedule[$counter]['dstart'], IL_CAL_UNIX, $this->timezone);
282 $this->schedule[$counter]['start_info'] = $tmp_date->get(IL_CAL_FKT_GETDATE, '', $this->timezone);
283
284 $tmp_date = new ilDateTime($this->schedule[$counter]['dend'], IL_CAL_UNIX, $this->timezone);
285 $this->schedule[$counter]['end_info'] = $tmp_date->get(IL_CAL_FKT_GETDATE, '', $this->timezone);
286 break;
287
288 default:
289 break;
290 }
291 $counter++;
292 if ($this->type != self::TYPE_PD_UPCOMING &&
293 $this->areEventsLimited() && $counter >= $this->getEventsLimit()) {
294 break;
295 }
296 }
297 }
298 } else {
299 $this->schedule[$counter]['event'] = $event;
300 $this->schedule[$counter]['dstart'] = $event->getStart()->get(IL_CAL_UNIX);
301 $this->schedule[$counter]['dend'] = $event->getEnd()->get(IL_CAL_UNIX);
302 $this->schedule[$counter]['fullday'] = $event->isFullday();
303 $this->schedule[$counter]['category_id'] = $cat_map[$event->getEntryId()];
304 $this->schedule[$counter]['category_type'] = $cat_types[$cat_map[$event->getEntryId()]];
305
306 if (!$event->isFullday()) {
307 switch ($this->type) {
308 case self::TYPE_DAY:
309 case self::TYPE_WEEK:
310 // store date info (used for calculation of overlapping events)
311 $tmp_date = new ilDateTime($this->schedule[$counter]['dstart'], IL_CAL_UNIX, $this->timezone);
312 $this->schedule[$counter]['start_info'] = $tmp_date->get(IL_CAL_FKT_GETDATE, '', $this->timezone);
313
314 $tmp_date = new ilDateTime($this->schedule[$counter]['dend'], IL_CAL_UNIX, $this->timezone);
315 $this->schedule[$counter]['end_info'] = $tmp_date->get(IL_CAL_FKT_GETDATE, '', $this->timezone);
316 break;
317
318 default:
319 break;
320 }
321 }
322 $counter++;
323 if ($this->type != self::TYPE_PD_UPCOMING &&
324 $this->areEventsLimited() && $counter >= $this->getEventsLimit()) {
325 break;
326 }
327 }
328 }
329
330 if ($this->type == self::TYPE_PD_UPCOMING) {
331 $this->schedule = ilUtil::sortArray($this->schedule, "dstart", "asc", true);
332 if ($this->areEventsLimited() && sizeof($this->schedule) >= $this->getEventsLimit()) {
333 $this->schedule = array_slice($this->schedule, 0, $this->getEventsLimit());
334 }
335 }
336 }
337
338 public function getScheduledEvents()
339 {
340 return (array) $this->schedule;
341 }
342
343 protected function filterCategories(array $a_cats)
344 {
345 if (!sizeof($a_cats)) {
346 return $a_cats;
347 }
348
349 foreach ($this->filters as $filter) {
350 if (sizeof($a_cats)) {
351 $a_cats = $filter->filterCategories($a_cats);
352 }
353 }
354
355 return $a_cats;
356 }
357
358 protected function modifyEventByFilters(ilCalendarEntry $event)
359 {
360 foreach ($this->filters as $filter) {
361 $res = $filter->modifyEvent($event);
362 if (!$res) {
363 ilLoggerFactory::getLogger('crs')->debug('filtering failed for ' . get_class($filter));
364 return false;
365 }
366 $event = $res;
367 }
368 return $event;
369 }
370
371 protected function addCustomEvents(ilDate $start, ilDate $end, array $categories)
372 {
373 $new_events = array();
374 foreach ($this->filters as $filter) {
375 $events_by_filter = $filter->addCustomEvents($start, $end, $categories);
376 if ($events_by_filter) {
377 $new_events = array_merge($new_events, $events_by_filter);
378 }
379 }
380 return $new_events;
381 }
382
391 public function getChangedEvents($a_include_subitem_calendars = false)
392 {
393 global $ilDB;
394
395 include_once('./Services/Calendar/classes/class.ilCalendarCategories.php');
396 $cats = ilCalendarCategories::_getInstance($this->user->getId())->getCategories($a_include_subitem_calendars);
397 $cats = $this->filterCategories($cats);
398
399 if (!count($cats)) {
400 return array();
401 }
402
403 $start = new ilDate(date('Y-m-d', time()), IL_CAL_DATE);
404 $start->increment(IL_CAL_MONTH, -1);
405
406 $query = "SELECT ce.cal_id cal_id FROM cal_entries ce " .
407 "JOIN cal_cat_assignments ca ON ca.cal_id = ce.cal_id " .
408 "WHERE last_update > " . $ilDB->quote($start->get(IL_CAL_DATETIME), 'timestamp') . " " .
409 "AND " . $ilDB->in('ca.cat_id', $cats, false, 'integer') . ' ' .
410 "ORDER BY last_update";
411 $res = $this->db->query($query);
412
413 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
414 $event = new ilCalendarEntry($row->cal_id);
415 $valid_event = $this->modifyEventByFilters($event);
416 if ($valid_event) {
417 $events[] = $valid_event;
418 }
419 }
420
421 foreach ($this->addCustomEvents($this->start, $this->end, $cats) as $event) {
422 $events[] = $event;
423 }
424
425 return $events ? $events : array();
426 }
427
428
434 public function getEvents()
435 {
436 global $ilDB;
437
438 include_once('./Services/Calendar/classes/class.ilCalendarCategories.php');
439 $cats = ilCalendarCategories::_getInstance($this->user->getId())->getCategories($this->enabledSubitemCalendars());
440 $cats = $this->filterCategories($cats);
441
442 if (!count($cats)) {
443 return array();
444 }
445
446 // TODO: optimize
447 $query = "SELECT ce.cal_id cal_id" .
448 " FROM cal_entries ce" .
449 " LEFT JOIN cal_recurrence_rules crr ON (ce.cal_id = crr.cal_id)" .
450 " JOIN cal_cat_assignments ca ON (ca.cal_id = ce.cal_id)";
451
452 if ($this->type != self::TYPE_INBOX) {
453 $query .= " WHERE ((starta <= " . $this->db->quote($this->end->get(IL_CAL_DATETIME, '', 'UTC'), 'timestamp') .
454 " AND enda >= " . $this->db->quote($this->start->get(IL_CAL_DATETIME, '', 'UTC'), 'timestamp') . ")" .
455 " OR (starta <= " . $this->db->quote($this->end->get(IL_CAL_DATETIME, '', 'UTC'), 'timestamp') .
456 " AND NOT rule_id IS NULL))";
457 } else {
458 $date = new ilDateTime(mktime(0, 0, 0), IL_CAL_UNIX);
459 $query .= " WHERE starta >= " . $this->db->quote($date->get(IL_CAL_DATETIME, '', 'UTC'), 'timestamp');
460 }
461
462 $query .= " AND " . $ilDB->in('ca.cat_id', $cats, false, 'integer') .
463 " ORDER BY starta";
464
465 $res = $this->db->query($query);
466
467 $events = array();
468 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
469 $event = new ilCalendarEntry($row->cal_id);
470 $valid_event = $this->modifyEventByFilters($event);
471 if ($valid_event) {
472 $events[] = $valid_event;
473 }
474 }
475
476 foreach ($this->addCustomEvents($this->start, $this->end, $cats) as $event) {
477 $events[] = $event;
478 }
479
480 return $events;
481 }
482
490 protected function initPeriod(ilDate $seed)
491 {
492 switch ($this->type) {
493 case self::TYPE_DAY:
494 $this->start = clone $seed;
495 $this->end = clone $seed;
496 //this strict period is just to avoid possible side effects.
497 if (!$this->strict_period) {
498 $this->start->increment(IL_CAL_DAY, -2);
499 $this->end->increment(IL_CAL_DAY, 2);
500 } else {
501 $this->end->increment(IL_CAL_DAY, 1);
502 }
503 break;
504
505 case self::TYPE_WEEK:
506 $this->start = clone $seed;
507 $start_info = $this->start->get(IL_CAL_FKT_GETDATE, '', 'UTC');
508 $day_diff = $this->weekstart - $start_info['isoday'];
509
510 if ($day_diff == 7) {
511 $day_diff = 0;
512 }
513
514 //this strict period is just to avoid possible side effects.
515 if ($this->strict_period) {
516 $this->start->increment(IL_CAL_DAY, $day_diff);
517 $this->end = clone $this->start;
518 $this->end->increment(IL_CAL_WEEK);
519 } else {
520 $this->start->increment(IL_CAL_DAY, $day_diff);
521 $this->start->increment(IL_CAL_DAY, -1);
522 $this->end = clone $this->start;
523 $this->end->increment(IL_CAL_DAY, 9);
524 }
525 break;
526
527 case self::TYPE_MONTH:
528 if ($this->strict_period) {
529 $this->start = clone $seed;
530 $this->end = clone $seed;
531 $this->end->increment(IL_CAL_MONTH, 1);
532 } else {
533 //todo: previous implementation still taking more days than represented in the view.
534 $year_month = $seed->get(IL_CAL_FKT_DATE, 'Y-m', 'UTC');
535 list($year, $month) = explode('-', $year_month);
536
537 $this->start = new ilDate($year_month . '-01', IL_CAL_DATE);
538 $this->start->increment(IL_CAL_DAY, -6);
539
540 $this->end = new ilDate($year_month . '-' . ilCalendarUtil::_getMaxDayOfMonth($year, $month), IL_CAL_DATE);
541 $this->end->increment(IL_CAL_DAY, 6);
542 }
543
544 break;
545
547 $this->start = clone $seed;
548 $this->end = clone $this->start;
549 $this->end->increment(IL_CAL_MONTH, 6);
550 break;
551
553 case self::TYPE_INBOX:
554 $this->start = $seed;
555 $this->end = clone $this->start;
556 $this->end->increment(IL_CAL_MONTH, 12);
557 break;
558 }
559
560 return true;
561 }
562
569 public function setPeriod(ilDate $a_start, ilDate $a_end)
570 {
571 $this->start = $a_start;
572 $this->end = $a_end;
573 }
574}
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
user()
Definition: user.php:4
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
const IL_CAL_WEEK
const IL_CAL_UNIX
const IL_CAL_DATETIME
const IL_CAL_MONTH
const IL_CAL_FKT_DATE
const IL_CAL_DAY
static _getInstance($a_usr_id=0)
get singleton instance
static _getAppointmentCalendars($a_cal_ids)
lookup calendars for appointment ids
Stores calendar categories.
Model for a calendar entry.
Calculates an ilDateList for a given calendar entry and recurrence rule.
static _getRecurrences($a_cal_id)
get all recurrences of an appointment
Calendar schedule filter for booking pool reservations.
Calendar schedule filter for consultation hour bookings.
Calendar schedule filter for hidden categories.
Represents a list of calendar appointments (including recurring events) for a specific user in a give...
enabledSubitemCalendars()
Are subitem calendars enabled.
areEventsLimited()
Check if events are limited.
setEventsLimit($a_limit)
Set events limit.
__construct(ilDate $seed, $a_type, $a_user_id=0, $a_strict_period=false)
Constructor.
modifyEventByFilters(ilCalendarEntry $event)
getChangedEvents($a_include_subitem_calendars=false)
get new/changed events
getEvents()
Read events (will be moved to another class, since only active and/or visible calendars are shown)
addCustomEvents(ilDate $start, ilDate $end, array $categories)
addFilter(ilCalendarScheduleFilter $a_filter)
Add filter.
setPeriod(ilDate $a_start, ilDate $a_end)
Set period.
addSubitemCalendars($a_status)
Enable subitem calendars (session calendars for courses)
getByDay(ilDate $a_start, $a_timezone)
get byday
getEventsLimit()
get current limit of events
initPeriod(ilDate $seed)
init period of events
static _getInstanceByUserId($a_user_id)
get singleton instance
static _getMaxDayOfMonth($a_year, $a_month)
get max day of month 2008,2 => 29
@classDescription Date and time handling
increment($a_type, $a_count=1)
increment
Class for single dates.
get($a_format, $a_format_str='', $a_tz='')
get formatted date
static getLogger($a_component_id)
Get component logger.
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
$counter
Calendar schedule filter interface.
$query
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92