ILIAS  release_8 Revision v8.24
ilCalendarRecurrenceCalculator Class Reference

This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Learning e.V. More...

+ Collaboration diagram for ilCalendarRecurrenceCalculator:

Public Member Functions

 __construct (ilDatePeriod $entry, ilCalendarRecurrenceCalculation $rec)
 
 calculateDateList (ilDateTime $a_start, ilDateTime $a_end, int $a_limit=-1)
 calculate date list More...
 

Protected Member Functions

 getDuration ()
 Get duration of event. More...
 
 applyDurationPeriod (ilDateList $list, ilDateTime $start, ilDateTime $end)
 Apply duration period. More...
 
 adjustTimeZones (ilDateTime $a_start, ilDateTime $a_end)
 Adjust timezone. More...
 
 optimizeStartingTime ()
 
 optimizeEndingTime ()
 
 incrementByFrequency (ilDateTime $start)
 
 applyBYMONTHRules (ilDateList $list)
 
 applyBYWEEKNORules (ilDateList $list)
 Apply BYWEEKNO rules (1 to 53 and -1 to -53). More...
 
 applyBYYEARDAYRules (ilDateList $list)
 
 applyBYMONTHDAYRules (ilDateList $list)
 
 applyBYDAYRules (ilDateList $list)
 
 getYearWeekDays (ilDateTime $seed)
 get a list of year week days according to the BYMONTH rule More...
 
 getMonthWeekDays (int $year, int $month)
 
 getWeekWeekDays (array $seed_info)
 get weedays of week More...
 
 applyBYSETPOSRules (ilDateList $list)
 Apply BYSETPOST rules. More...
 
 applyLimits (ilDateList $list)
 Apply limits (count or until) More...
 
 applyExclusionDates ()
 
 initDateList ()
 
 createDate ($a_date, $a_format_type=IL_CAL_UNIX)
 
 validateRecurrence ()
 

Protected Attributes

string $timezone = ilTimeZone::UTC
 
ilLogger $log
 
bool $limit_reached = false
 
ilDateList $valid_dates = null
 
ilDateTime $period_start = null
 
ilDateTime $period_end = null
 
ilDateTime $start = null
 
ilDatePeriod $event
 
ilCalendarRecurrenceCalculation $recurrence
 
int $duration = 0
 
string $frequence_context = ''
 

Detailed Description

This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Learning e.V.

ILIAS is licensed with the GPL-3.0, see https://www.gnu.org/licenses/gpl-3.0.en.html You should have received a copy of said license along with the source code, too.

If this is not the case or you just want to try ILIAS, you'll find us at: https://www.ilias.de https://github.com/ILIAS-eLearning Calculates an ilDateList for a given calendar entry and recurrence rule.

Author
Stefan Meyer meyer.nosp@m.@lei.nosp@m.fos.c.nosp@m.om @ilCtrl_Calls

Definition at line 27 of file class.ilCalendarRecurrenceCalculator.php.

Constructor & Destructor Documentation

◆ __construct()

ilCalendarRecurrenceCalculator::__construct ( ilDatePeriod  $entry,
ilCalendarRecurrenceCalculation  $rec 
)

Definition at line 43 of file class.ilCalendarRecurrenceCalculator.php.

44 {
45 $this->log = $GLOBALS['DIC']->logger()->cal();
46 $this->event = $entry;
47 $this->recurrence = $rec;
48
49 $this->duration = (int) $entry->getEnd()->get(IL_CAL_UNIX) - (int) $entry->getStart()->get(IL_CAL_UNIX);
50 }
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
const IL_CAL_UNIX
getEnd()
Get end of period.
getStart()
Get start of date period.

References $GLOBALS, ilDatePeriod\getEnd(), ilDatePeriod\getStart(), IL_CAL_UNIX, and ILIAS\Repository\int().

+ Here is the call graph for this function:

Member Function Documentation

◆ adjustTimeZones()

ilCalendarRecurrenceCalculator::adjustTimeZones ( ilDateTime  $a_start,
ilDateTime  $a_end 
)
protected

Adjust timezone.

Definition at line 179 of file class.ilCalendarRecurrenceCalculator.php.

179 : void
180 {
181 $this->timezone = $this->event->isFullday() ? ilTimeZone::UTC : $this->recurrence->getTimeZone();
182 ilTimeZone::_setDefaultTimeZone($this->timezone);
183
184 $this->period_start = clone $a_start;
185 $this->period_end = clone $a_end;
186 $this->start = clone $this->event->getStart();
187
188 try {
189 if ($this->event->isFullday()) {
190 $this->period_start->switchTimeZone(ilTimeZone::UTC);
191 $this->period_end->switchTimeZone(ilTimeZone::UTC);
192 $this->start->switchTimeZone(ilTimeZone::UTC);
193 } else {
194 $this->period_start->switchTimeZone($this->recurrence->getTimeZone());
195 $this->period_end->switchTimeZone($this->recurrence->getTimeZone());
196 $this->start->switchTimeZone($this->recurrence->getTimeZone());
197 }
198 return;
199 } catch (ilDateTimeException $e) {
200 $this->log->debug(': ' . $e->getMessage());
201 return;
202 }
203 }
Class for DateTime exceptions.
switchTimeZone(string $a_timezone_identifier='')
Switch timezone.
static _setDefaultTimeZone(string $a_tz)

References Vendor\Package\$e, ilTimeZone\_setDefaultTimeZone(), ILIAS\Repository\event(), ilDateTime\switchTimeZone(), and ilTimeZone\UTC.

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYDAYRules()

ilCalendarRecurrenceCalculator::applyBYDAYRules ( ilDateList  $list)
protected

Definition at line 480 of file class.ilCalendarRecurrenceCalculator.php.

480 : ilDateList
481 {
482 // return unmodified, if no byday rules are available
483 if (!$this->recurrence->getBYDAYList()) {
484 return $list;
485 }
486
487 $days_list = $this->initDateList();
488
489 // generate a list of e.g all Sundays for the given year
490 // or e.g a list of all week days in a give month (FREQ = MONTHLY,WEEKLY or DAILY)
491 $day_array = [];
492 foreach ($list->get() as $seed) {
493 $seed_info = $seed->get(IL_CAL_FKT_GETDATE);
494
495 // TODO: maybe not correct in dst cases
496 $date_info = $seed->get(IL_CAL_FKT_GETDATE);
497 $date_info['mday'] = 1;
498 $date_info['mon'] = 1;
499 $start = $this->createDate($date_info, IL_CAL_FKT_GETDATE);
500
501 switch ($this->frequence_context) {
503 $day_array = $this->getYearWeekDays($seed);
504 break;
505
507 $day_array = $this->getMonthWeekDays($seed_info['year'], $seed_info['mon']);
508 break;
509
511 // TODO or RFC bug: FREQ>WEEKLY;BYMONTH=1;BYDAY=FR returns FR 1.2.2008
512 // Ical says: apply BYMONTH rules and after that apply byday rules on that date list.
513 $day_array = $this->getWeekWeekDays($seed_info);
514 break;
515
517 $day_array[strtoupper(substr($seed->get(IL_CAL_FKT_DATE, 'D'), 0, 2))] = array($seed_info['yday']);
518 break;
519
520 }
521 foreach ($this->recurrence->getBYDAYList() as $byday) {
522 $year_day = array();
523 $day = strtoupper(substr($byday, -2));
524 $num_by_day = (int) $byday;
525
526 if ($num_by_day) {
527 if ($num_by_day > 0) {
528 if (isset($day_array[$day][$num_by_day - 1])) {
529 $year_day = array($day_array[$day][$num_by_day - 1]);
530 }
531 } elseif (isset($day_array[$day][count($day_array[$day]) + $num_by_day])) {
532 $year_day = array($day_array[$day][count($day_array[$day]) + $num_by_day]);
533 }
534 } elseif (isset($day_array[$day])) {
535 $year_day = $day_array[$day];
536 }
537 foreach ($year_day as $day) {
538 switch ($this->frequence_context) {
543 $tmp_date = clone $start;
544 $tmp_date->increment(IL_CAL_DAY, $day);
545 $days_list->add($tmp_date);
546 break;
547 }
548 }
549 }
550 }
551 return $days_list;
552 }
const IL_CAL_FKT_GETDATE
const IL_CAL_FKT_DATE
const IL_CAL_DAY
createDate($a_date, $a_format_type=IL_CAL_UNIX)
getYearWeekDays(ilDateTime $seed)
get a list of year week days according to the BYMONTH rule
getWeekWeekDays(array $seed_info)
get weedays of week
List of dates.
increment(string $a_type, int $a_count=1)

References $start, createDate(), ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), getMonthWeekDays(), getWeekWeekDays(), getYearWeekDays(), IL_CAL_DAY, IL_CAL_FKT_DATE, IL_CAL_FKT_GETDATE, ilDateTime\increment(), initDateList(), and ILIAS\Repository\int().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYMONTHDAYRules()

ilCalendarRecurrenceCalculator::applyBYMONTHDAYRules ( ilDateList  $list)
protected

Definition at line 399 of file class.ilCalendarRecurrenceCalculator.php.

399 : ilDateList
400 {
401 // return unmodified, if no byweekno rules are available
402 if (!$this->recurrence->getBYMONTHDAYList()) {
403 return $list;
404 }
405 $days_list = $this->initDateList();
406 foreach ($list->get() as $seed) {
408 (int) $seed->get(IL_CAL_FKT_DATE, 'Y', $this->timezone),
409 (int) $seed->get(IL_CAL_FKT_DATE, 'n', $this->timezone)
410 );
411 foreach ($this->recurrence->getBYMONTHDAYList() as $bymonth_no) {
412 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
413 if ($this->frequence_context != ilCalendarRecurrence::FREQ_YEARLY) {
414 if ($day_no < 1 or $day_no > $num_days) {
415 $this->log->debug(': Ignoring BYMONTHDAY rule: ' . $day_no . ' for month ' .
416 $seed->get(IL_CAL_FKT_DATE, 'M', $this->timezone));
417 continue;
418 }
419 }
420 $day_diff = $day_no - $seed->get(IL_CAL_FKT_DATE, 'j', $this->timezone);
421 $new_day = $this->createDate($seed->get(IL_CAL_UNIX, '', $this->timezone));
422 $new_day->increment(ilDateTime::DAY, $day_diff);
423
424 switch ($this->frequence_context) {
426 // Check if day matches
427 if ($seed->get(IL_CAL_FKT_DATE, 'j', $this->timezone) == $day_no) {
428 $days_list->add($new_day);
429 }
430 break;
431
433 // Check if week matches
434 if ($seed->get(IL_CAL_FKT_DATE, 'W', $this->timezone) == $new_day->get(
436 'W',
437 $this->timezone
438 )) {
439 $days_list->add($new_day);
440 }
441 break;
442
444 // seed and new day are in the same month.
445 $days_list->add($new_day);
446 break;
447
449 $h = (int) ($this->event->isFullday() ? 0 : $seed->get(IL_CAL_FKT_DATE, 'H', $this->timezone));
450 $i = (int) ($this->event->isFullday() ? 0 : $seed->get(IL_CAL_FKT_DATE, 'i', $this->timezone));
451 $s = (int) ($this->event->isFullday() ? 0 : $seed->get(IL_CAL_FKT_DATE, 's', $this->timezone));
452 $y = (int) $seed->get(IL_CAL_FKT_DATE, 'Y', $this->timezone);
453
454 // TODO: the chosen monthday has to added to all months
455 for ($month = 1; $month <= 12; $month++) {
457 $y,
458 $month
459 );
460 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
461 if ($day_no < 1 or $day_no > $num_days) {
462 $this->log->debug(': Ignoring BYMONTHDAY rule: ' . $day_no . ' for month ' . $month);
463 } else {
464 $tz_obj = ilTimeZone::_getInstance($this->timezone);
465 $tz_obj->switchTZ();
466 $unix = mktime($h, $i, $s, $month, $day_no, $y);
467 $tz_obj->restoreTZ();
468 $new_day = $this->createDate($unix);
469 $days_list->add($new_day);
470 }
471 }
472 break;
473 }
474 }
475 }
476 $this->frequence_context = ilCalendarRecurrence::FREQ_DAILY;
477 return $days_list;
478 }
static _getMaxDayOfMonth(int $a_year, int $a_month)
get max day of month 2008,2 => 29
static _getInstance(string $a_tz='')
get instance by timezone
$i
Definition: metadata.php:41

References $i, ilTimeZone\_getInstance(), ilCalendarUtil\_getMaxDayOfMonth(), createDate(), ilDateTime\DAY, ILIAS\Repository\event(), ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, initDateList(), and ILIAS\Repository\int().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYMONTHRules()

ilCalendarRecurrenceCalculator::applyBYMONTHRules ( ilDateList  $list)
protected

Definition at line 257 of file class.ilCalendarRecurrenceCalculator.php.

257 : ilDateList
258 {
259 // return unmodified, if no bymonth rules are available
260 if (!$this->recurrence->getBYMONTHList()) {
261 return $list;
262 }
263 $month_list = $this->initDateList();
264 foreach ($list->get() as $date) {
265 foreach ($this->recurrence->getBYMONTHList() as $month) {
266 // YEARLY rules extend the seed to every month given in the BYMONTH rule
267 // Rules < YEARLY must match the month of the seed
268 if ($this->recurrence->getFrequenceType() == ilCalendarRecurrence::FREQ_YEARLY) {
269 $month_date = $this->createDate($date->get(IL_CAL_UNIX, '', $this->timezone));
270 $month_date->increment(
272 -($date->get(IL_CAL_FKT_DATE, 'n', $this->timezone) - $month)
273 );
274
275 #echo "BYMONTH: ".$month_date;
276 $month_list->add($month_date);
277 } elseif ($date->get(IL_CAL_FKT_DATE, 'n', $this->timezone) == $month) {
278 $month_list->add($date);
279 }
280 }
281 }
282 // decrease the frequence_context for YEARLY rules
283 if ($this->recurrence->getFrequenceType() == ilCalendarRecurrence::FREQ_YEARLY) {
284 $this->frequence_context = ilCalendarRecurrence::FREQ_MONTHLY;
285 }
286 return $month_list;
287 }

References createDate(), ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, initDateList(), and ilDateTime\MONTH.

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYSETPOSRules()

ilCalendarRecurrenceCalculator::applyBYSETPOSRules ( ilDateList  $list)
protected

Apply BYSETPOST rules.

Definition at line 628 of file class.ilCalendarRecurrenceCalculator.php.

628 : ilDateList
629 {
630 // return unmodified, if no bysetpos rules are available
631 if (!$this->recurrence->getBYSETPOSList()) {
632 return $list;
633 }
634 $pos_list = $this->initDateList();
635 $list->sort();
636 $candidates = $list->get();
637 $candidates_count = count($candidates);
638 foreach ($this->recurrence->getBYSETPOSList() as $position) {
639 if ($position > 0 and $date = $list->getAtPosition($position)) {
640 $pos_list->add($date);
641 }
642 if ($position < 0 and $date = $list->getAtPosition($candidates_count + $position + 1)) {
643 $pos_list->add($date);
644 }
645 }
646 return $pos_list;
647 }
getAtPosition(int $a_pos)
get item at specific position
sort()
Sort list.

References ilDateList\get(), ilDateList\getAtPosition(), initDateList(), and ilDateList\sort().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYWEEKNORules()

ilCalendarRecurrenceCalculator::applyBYWEEKNORules ( ilDateList  $list)
protected

Apply BYWEEKNO rules (1 to 53 and -1 to -53).

This rule can only be applied to YEARLY rules (RFC 2445 4.3.10)

Definition at line 293 of file class.ilCalendarRecurrenceCalculator.php.

293 : ilDateList
294 {
295 if ($this->recurrence->getFrequenceType() != ilCalendarRecurrence::FREQ_YEARLY) {
296 return $list;
297 }
298 // return unmodified, if no byweekno rules are available
299 if (!$this->recurrence->getBYWEEKNOList()) {
300 return $list;
301 }
302 $weeks_list = $this->initDateList();
303 foreach ($list->get() as $seed) {
304 $weeks_in_year = date('W', mktime(0, 0, 0, 12, 28, $seed->get(IL_CAL_FKT_DATE, 'Y', $this->timezone)));
305 $this->log->debug(': Year ' . $seed->get(
307 'Y',
308 $this->timezone
309 ) . ' has ' . $weeks_in_year . ' weeks');
310 foreach ($this->recurrence->getBYWEEKNOList() as $week_no) {
311 $week_no = $week_no < 0 ? ((int) $weeks_in_year + $week_no + 1) : $week_no;
312
313 switch ($this->frequence_context) {
315 $this->log->debug(': Handling BYWEEKNO in MONTHLY context');
316 // Check if week matches
317 if ($seed->get(IL_CAL_FKT_DATE, 'W', $this->timezone) == $week_no) {
318 $weeks_list->add($seed);
319 }
320 break;
321
323 $this->log->debug(': Handling BYWEEKNO in YEARLY context');
324 $week_diff = $week_no - $seed->get(IL_CAL_FKT_DATE, 'W', $this->timezone);
325
326 // TODO: think about tz here
327 $new_week = $this->createDate($seed->get(IL_CAL_UNIX, '', $this->timezone));
328 $new_week->increment(ilDateTime::WEEK, $week_diff);
329 $weeks_list->add($new_week);
330 break;
331 }
332 }
333 }
334 $this->frequence_context = ilCalendarRecurrence::FREQ_WEEKLY;
335 return $weeks_list;
336 }

References createDate(), ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, initDateList(), ILIAS\Repository\int(), and ilDateTime\WEEK.

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYYEARDAYRules()

ilCalendarRecurrenceCalculator::applyBYYEARDAYRules ( ilDateList  $list)
protected

Definition at line 338 of file class.ilCalendarRecurrenceCalculator.php.

338 : ilDateList
339 {
340 // return unmodified, if no byweekno rules are available
341 if (!$this->recurrence->getBYYEARDAYList()) {
342 return $list;
343 }
344 $days_list = $this->initDateList();
345 foreach ($list->get() as $seed) {
346 $num_days = date('z', mktime(0, 0, 0, 12, 31, $seed->get(IL_CAL_FKT_DATE, 'Y', $this->timezone)));
347 $this->log->debug(': Year ' . $seed->get(
349 'Y',
350 $this->timezone
351 ) . ' has ' . $num_days . ' days.');
352
353 foreach ($this->recurrence->getBYYEARDAYList() as $day_no) {
354 $day_no = $day_no < 0 ? ((int) $num_days + $day_no + 1) : $day_no;
355
356 $day_diff = $day_no - $seed->get(IL_CAL_FKT_DATE, 'z', $this->timezone);
357 $new_day = $this->createDate($seed->get(IL_CAL_UNIX, '', $this->timezone));
358 $new_day->increment(ilDateTime::DAY, $day_diff);
359
360 switch ($this->frequence_context) {
362 // Check if day matches
363 if ($seed->get(IL_CAL_FKT_DATE, 'z', $this->timezone) == $day_no) {
364 $days_list->add($new_day);
365 }
366 break;
368 // Check if week matches
369 if ($seed->get(IL_CAL_FKT_DATE, 'W', $this->timezone) == $new_day->get(
371 'W',
372 $this->timezone
373 )) {
374 $days_list->add($new_day);
375 }
376 break;
378 // Check if month matches
379 if ($seed->get(IL_CAL_FKT_DATE, 'n', $this->timezone) == $new_day->get(
381 'n',
382 $this->timezone
383 )) {
384 $days_list->add($new_day);
385 }
386 break;
388 // Simply add
389 $days_list->add($new_day);
390 break;
391 }
392 }
393 }
394
395 $this->frequence_context = ilCalendarRecurrence::FREQ_DAILY;
396 return $days_list;
397 }

References createDate(), ilDateTime\DAY, ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, initDateList(), and ILIAS\Repository\int().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyDurationPeriod()

ilCalendarRecurrenceCalculator::applyDurationPeriod ( ilDateList  $list,
ilDateTime  $start,
ilDateTime  $end 
)
protected

Apply duration period.

Definition at line 155 of file class.ilCalendarRecurrenceCalculator.php.

155 : void
156 {
157 $list_copy = clone $list;
158 foreach ($list_copy as $start_date) {
159 $end_date = clone $start_date;
160 $end_date->increment(ilDateTime::MINUTE, $this->getDuration() / 60);
161
162 if (
163 (
164 ilDateTime::_after($start_date, $this->period_end)
165 ) ||
166 (
167 ilDateTime::_before($end_date, $this->period_start)
168 )
169 ) {
170 $this->log->debug('Removed invalid date ' . $start_date . ' <-> ' . $end_date);
171 $list->remove($start_date);
172 }
173 }
174 }
remove(ilDateTime $remove)
remove from list
static _after(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
static _before(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.

References ilDateTime\_after(), ilDateTime\_before(), getDuration(), ilDateTime\MINUTE, and ilDateList\remove().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyExclusionDates()

ilCalendarRecurrenceCalculator::applyExclusionDates ( )
protected

Definition at line 690 of file class.ilCalendarRecurrenceCalculator.php.

690 : void
691 {
692 if (!$this->recurrence->getExclusionDates()) {
693 return;
694 }
695 foreach ($this->recurrence->getExclusionDates() as $excl) {
696 $this->valid_dates->removeByDAY($excl->getDate());
697 }
698 }

Referenced by calculateDateList().

+ Here is the caller graph for this function:

◆ applyLimits()

ilCalendarRecurrenceCalculator::applyLimits ( ilDateList  $list)
protected

Apply limits (count or until)

Definition at line 652 of file class.ilCalendarRecurrenceCalculator.php.

652 : bool
653 {
654 $list->sort();
655 // Check valid dates before starting time
656 foreach ($list->get() as $check_date) {
657 if (ilDateTime::_before($check_date, $this->event->getStart(), IL_CAL_DAY)) {
658 $this->log->debug('Removed invalid date: ' . $check_date . ' before starting date: ' . $this->event->getStart());
659 $list->remove($check_date);
660 }
661 }
662
663 // Check count if given
664 if ($this->recurrence->getFrequenceUntilCount()) {
665 foreach ($list->get() as $res) {
666 // check smaller than since the start time counts as one
667 if (count($this->valid_dates->get()) < $this->recurrence->getFrequenceUntilCount()) {
668 $this->valid_dates->add($res);
669 } else {
670 $this->limit_reached = true;
671 return false;
672 }
673 }
674 return true;
675 } elseif ($this->recurrence->getFrequenceUntilDate()) {
676 $date = $this->recurrence->getFrequenceUntilDate();
677 foreach ($list->get() as $res) {
678 if (ilDateTime::_after($res, $date, IL_CAL_DAY)) {
679 $this->limit_reached = true;
680 return false;
681 }
682 $this->valid_dates->add($res);
683 }
684 return true;
685 }
686 $this->valid_dates->merge($list);
687 return true;
688 }
$res
Definition: ltiservices.php:69

References $res, ilDateTime\_after(), ilDateTime\_before(), ILIAS\Repository\event(), ilDateList\get(), IL_CAL_DAY, ilDateList\remove(), and ilDateList\sort().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calculateDateList()

ilCalendarRecurrenceCalculator::calculateDateList ( ilDateTime  $a_start,
ilDateTime  $a_end,
int  $a_limit = -1 
)

calculate date list

Parameters
ilDateTimeilDateTime start of period
ilDateTimeilDateTime end of period
intlimit number of returned dates
Returns
ilDateList List of recurring dates

Definition at line 67 of file class.ilCalendarRecurrenceCalculator.php.

68 {
69 $this->valid_dates = $this->initDateList();
70
71 // Check invalid settings: e.g no frequence given, invalid start/end dates ...
72 if (!$this->validateRecurrence()) {
73 $this->valid_dates->add($this->event->getStart());
74 return $this->valid_dates;
75 }
76
77 // Performance fix: Switching the timezone for many dates seems to be
78 // quite time consuming.
79 // Therfore we adjust the timezone of all input dates (start,end, event start)
80 // to the same tz (UTC for fullday events, Recurrence tz for all others).
81 $this->adjustTimeZones($a_start, $a_end);
82
83 // Add start of event if it is in the period
84 if ((ilDateTime::_after($this->event->getStart(), $this->period_start, IL_CAL_DAY) and
85 ilDateTime::_before($this->event->getStart(), $this->period_end, IL_CAL_DAY)) or
86 ilDateTime::_equals($this->event->getStart(), $this->period_start, IL_CAL_DAY)) {
87 // begin-patch aptar
88 $this->valid_dates->add($this->event->getStart());
89 #$this->valid_dates->add($this->event->getStart());
90 // end patch aptar
91 }
92
93 // Calculate recurrences based on frequency (e.g. MONTHLY)
94 $time = microtime(true);
95
97 $end = $this->optimizeEndingTime();
98
99 #echo "ZEIT: ADJUST: ".(microtime(true) - $time).'<br>';
100 $counter = 0;
101 do {
102 ++$counter;
103 // initialize context for applied rules
104 // E.g
105 // RRULE:FREQ=YEARLY;BYMONTH=1;BYWEEKNO=1,50 => context for BYWERKNO is monthly because it filters to the weeks in JAN
106 // RRULE:FREQ=YEARLY;BYWEEKNO=1,50 => context for BYWERKNO is yearly because it adds all weeks.
107 $this->frequence_context = $this->recurrence->getFrequenceType();
108
109 $freq_res = $this->initDateList();
110 $freq_res->add($start);
111
112 // Fixed sequence of applying rules (RFC 2445 4.3.10)
113 $freq_res = $this->applyBYMONTHRules($freq_res);
114 #echo "BYMONTH: ".$freq_res;
115
116 $freq_res = $this->applyBYWEEKNORules($freq_res);
117 #echo "BYWEEKNO: ".$freq_res;
118
119 $freq_res = $this->applyBYYEARDAYRules($freq_res);
120 #echo "BYYEARDAY: ".$freq_res;
121
122 $freq_res = $this->applyBYMONTHDAYRules($freq_res);
123 #echo "BYMONTHDAY: ".$freq_res;
124
125 #$time = microtime(true);
126 $freq_res = $this->applyBYDAYRules($freq_res);
127 #echo "ZEIT: ".(microtime(true) - $time);
128 #echo "BYDAY: ".$freq_res;
129
130 $freq_res = $this->applyBYSETPOSRules($freq_res);
131 #echo "BYSETPOS: ".$freq_res;
132
133 $freq_res = $this->applyLimits($freq_res);
134 #echo $freq_res;
135
137
138 if (ilDateTime::_after($start, $end) || $this->limit_reached) {
139 break;
140 }
141 } while (true);
142
143 $this->applyExclusionDates();
144 $this->applyDurationPeriod($this->valid_dates, $this->period_start, $this->period_end);
145 $this->valid_dates->sort();
146
147 // Restore default timezone
149 return $this->valid_dates;
150 }
applyBYSETPOSRules(ilDateList $list)
Apply BYSETPOST rules.
applyLimits(ilDateList $list)
Apply limits (count or until)
adjustTimeZones(ilDateTime $a_start, ilDateTime $a_end)
Adjust timezone.
applyBYWEEKNORules(ilDateList $list)
Apply BYWEEKNO rules (1 to 53 and -1 to -53).
applyDurationPeriod(ilDateList $list, ilDateTime $start, ilDateTime $end)
Apply duration period.
static _equals(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
Check if two date are equal.
static _restoreDefaultTimeZone()

References $start, $valid_dates, ilDateTime\_after(), ilDateTime\_before(), ilDateTime\_equals(), ilTimeZone\_restoreDefaultTimeZone(), adjustTimeZones(), applyBYDAYRules(), applyBYMONTHDAYRules(), applyBYMONTHRules(), applyBYSETPOSRules(), applyBYWEEKNORules(), applyBYYEARDAYRules(), applyDurationPeriod(), applyExclusionDates(), applyLimits(), ILIAS\Repository\event(), IL_CAL_DAY, incrementByFrequency(), initDateList(), optimizeEndingTime(), optimizeStartingTime(), and validateRecurrence().

+ Here is the call graph for this function:

◆ createDate()

ilCalendarRecurrenceCalculator::createDate (   $a_date,
  $a_format_type = IL_CAL_UNIX 
)
protected

Definition at line 705 of file class.ilCalendarRecurrenceCalculator.php.

705 : ilDateTime
706 {
707 if ($this->event->isFullday()) {
708 return new ilDate($a_date, $a_format_type);
709 } else {
710 // TODO: the timezone for this recurrence must be stored in the db
711 return new ilDateTime($a_date, $a_format_type, $this->timezone);
712 }
713 }
@classDescription Date and time handling
Class for single dates.

References ILIAS\Repository\event().

Referenced by applyBYDAYRules(), applyBYMONTHDAYRules(), applyBYMONTHRules(), applyBYWEEKNORules(), applyBYYEARDAYRules(), and optimizeStartingTime().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getDuration()

ilCalendarRecurrenceCalculator::getDuration ( )
protected

Get duration of event.

Definition at line 55 of file class.ilCalendarRecurrenceCalculator.php.

References $duration.

Referenced by applyDurationPeriod().

+ Here is the caller graph for this function:

◆ getMonthWeekDays()

ilCalendarRecurrenceCalculator::getMonthWeekDays ( int  $year,
int  $month 
)
protected

Definition at line 582 of file class.ilCalendarRecurrenceCalculator.php.

582 : array
583 {
584 static $month_days = array();
585
586 if (isset($month_days[$year][$month])) {
587 return $month_days[$year][$month];
588 }
589
590 $month_str = $month < 10 ? ('0' . $month) : $month;
591 $begin_month = new ilDate($year . '-' . $month_str . '-01', IL_CAL_DATE);
592 $begin_month_info = $begin_month->get(IL_CAL_FKT_GETDATE);
593
594 $days = array(0 => 'SU', 1 => 'MO', 2 => 'TU', 3 => 'WE', 4 => 'TH', 5 => 'FR', 6 => 'SA');
595 for ($i = 0; $i < $begin_month_info['wday']; $i++) {
596 next($days);
597 }
598 for ($i = $begin_month_info['yday']; $i < $begin_month_info['yday'] + ilCalendarUtil::_getMaxDayOfMonth(
599 $year,
600 $month
601 ); $i++) {
602 if (!($current_day = current($days))) {
603 $current_day = reset($days);
604 }
605 $month_days[$year][$month][$current_day][] = $i;
606 next($days);
607 }
608 return $month_days[$year][$month];
609 }
const IL_CAL_DATE

References $i, ilCalendarUtil\_getMaxDayOfMonth(), IL_CAL_DATE, and IL_CAL_FKT_GETDATE.

Referenced by applyBYDAYRules().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getWeekWeekDays()

ilCalendarRecurrenceCalculator::getWeekWeekDays ( array  $seed_info)
protected

get weedays of week

Definition at line 614 of file class.ilCalendarRecurrenceCalculator.php.

614 : array
615 {
616 $days = array(0 => 'SU', 1 => 'MO', 2 => 'TU', 3 => 'WE', 4 => 'TH', 5 => 'FR', 6 => 'SA');
617
618 $start_day = $seed_info['yday'] - $seed_info['wday'];
619 foreach ($days as $num => $day) {
620 $week_days[$day][] = $start_day++;
621 }
622 return $week_days;
623 }

Referenced by applyBYDAYRules().

+ Here is the caller graph for this function:

◆ getYearWeekDays()

ilCalendarRecurrenceCalculator::getYearWeekDays ( ilDateTime  $seed)
protected

get a list of year week days according to the BYMONTH rule

Definition at line 557 of file class.ilCalendarRecurrenceCalculator.php.

557 : array
558 {
559 $time = microtime(true);
560
561 $year_days = array();
562
563 $current_year = $seed->get(IL_CAL_FKT_DATE, 'Y');
564 $start = new ilDate($current_year . '-01-01', IL_CAL_DATE);
565 $offset = $start->get(IL_CAL_FKT_DATE, 'w');
566 $days = array(0 => 'SU', 1 => 'MO', 2 => 'TU', 3 => 'WE', 4 => 'TH', 5 => 'FR', 6 => 'SA');
567 for ($i = 0; $i < $offset; $i++) {
568 next($days);
569 }
570
571 $num_days = ilCalendarUtil::_isLeapYear($current_year) ? 366 : 365;
572 for ($i = 0; $i < $num_days; $i++) {
573 if (!($current_day = current($days))) {
574 $current_day = reset($days);
575 }
576 $year_days[$current_day][] = $i;
577 next($days);
578 }
579 return $year_days;
580 }
static _isLeapYear(int $a_year)
check if a given year is a leap year
get(int $a_format, string $a_format_str='', string $a_tz='')
get formatted date

References $i, $start, ilCalendarUtil\_isLeapYear(), ilDateTime\get(), IL_CAL_DATE, and IL_CAL_FKT_DATE.

Referenced by applyBYDAYRules().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ incrementByFrequency()

ilCalendarRecurrenceCalculator::incrementByFrequency ( ilDateTime  $start)
protected

Definition at line 231 of file class.ilCalendarRecurrenceCalculator.php.

231 : ilDateTime
232 {
233 switch ($this->recurrence->getFrequenceType()) {
235 $start->increment(ilDateTime::YEAR, $this->recurrence->getInterval());
236 break;
237
239 $start->increment(ilDateTime::MONTH, $this->recurrence->getInterval());
240 break;
241
243 $start->increment(ilDateTime::WEEK, $this->recurrence->getInterval());
244 break;
245
247 $start->increment(ilDateTime::DAY, $this->recurrence->getInterval());
248 break;
249
250 default:
251 $this->log->warning('No frequence defined.');
252 break;
253 }
254 return $start;
255 }

References $start, ilDateTime\DAY, ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateTime\increment(), ilDateTime\MONTH, ilDateTime\WEEK, and ilDateTime\YEAR.

Referenced by calculateDateList(), optimizeEndingTime(), and optimizeStartingTime().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initDateList()

ilCalendarRecurrenceCalculator::initDateList ( )
protected

Definition at line 700 of file class.ilCalendarRecurrenceCalculator.php.

700 : ilDateList
701 {
702 return new ilDateList($this->event->isFullday() ? ilDateList::TYPE_DATE : ilDateList::TYPE_DATETIME);
703 }

References ILIAS\Repository\event(), ilDateList\TYPE_DATE, and ilDateList\TYPE_DATETIME.

Referenced by applyBYDAYRules(), applyBYMONTHDAYRules(), applyBYMONTHRules(), applyBYSETPOSRules(), applyBYWEEKNORules(), applyBYYEARDAYRules(), and calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ optimizeEndingTime()

ilCalendarRecurrenceCalculator::optimizeEndingTime ( )
protected

Definition at line 221 of file class.ilCalendarRecurrenceCalculator.php.

221 : ilDateTime
222 {
223 $end = clone $this->period_start;
224 $end = $this->incrementByFrequency($end);
225 if (ilDateTime::_before($this->period_end, $end, ilDateTime::DAY)) {
226 return $end;
227 }
228 return $this->period_end;
229 }

References $period_end, $period_start, ilDateTime\_before(), ilDateTime\DAY, and incrementByFrequency().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ optimizeStartingTime()

ilCalendarRecurrenceCalculator::optimizeStartingTime ( )
protected

Definition at line 205 of file class.ilCalendarRecurrenceCalculator.php.

205 : ilDateTime
206 {
207 // starting time cannot be optimzed if RRULE UNTIL is given.
208 // In that case we have to calculate all dates until "UNTIL" is reached.
209 if ($this->recurrence->getFrequenceUntilCount() > 0) {
210 // Switch the date to the original defined timzone for this recurrence
211 return $this->createDate($this->start->get(IL_CAL_UNIX, '', $this->timezone));
212 }
213 $optimized = $start = $this->createDate($this->start->get(IL_CAL_UNIX, '', $this->timezone));
214 while (ilDateTime::_before($start, $this->period_start)) {
215 $optimized = clone $start;
216 $start = $this->incrementByFrequency($start);
217 }
218 return $optimized;
219 }

References $start, ilDateTime\_before(), createDate(), IL_CAL_UNIX, and incrementByFrequency().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateRecurrence()

ilCalendarRecurrenceCalculator::validateRecurrence ( )
protected

Definition at line 715 of file class.ilCalendarRecurrenceCalculator.php.

715 : bool
716 {
717 return $this->recurrence->validate();
718 }

Referenced by calculateDateList().

+ Here is the caller graph for this function:

Field Documentation

◆ $duration

int ilCalendarRecurrenceCalculator::$duration = 0
protected

Definition at line 40 of file class.ilCalendarRecurrenceCalculator.php.

Referenced by getDuration().

◆ $event

ilDatePeriod ilCalendarRecurrenceCalculator::$event
protected

Definition at line 38 of file class.ilCalendarRecurrenceCalculator.php.

◆ $frequence_context

string ilCalendarRecurrenceCalculator::$frequence_context = ''
protected

Definition at line 41 of file class.ilCalendarRecurrenceCalculator.php.

◆ $limit_reached

bool ilCalendarRecurrenceCalculator::$limit_reached = false
protected

Definition at line 32 of file class.ilCalendarRecurrenceCalculator.php.

◆ $log

ilLogger ilCalendarRecurrenceCalculator::$log
protected

Definition at line 30 of file class.ilCalendarRecurrenceCalculator.php.

◆ $period_end

ilDateTime ilCalendarRecurrenceCalculator::$period_end = null
protected

Definition at line 35 of file class.ilCalendarRecurrenceCalculator.php.

Referenced by optimizeEndingTime().

◆ $period_start

ilDateTime ilCalendarRecurrenceCalculator::$period_start = null
protected

Definition at line 34 of file class.ilCalendarRecurrenceCalculator.php.

Referenced by optimizeEndingTime().

◆ $recurrence

ilCalendarRecurrenceCalculation ilCalendarRecurrenceCalculator::$recurrence
protected

Definition at line 39 of file class.ilCalendarRecurrenceCalculator.php.

◆ $start

ilDateTime ilCalendarRecurrenceCalculator::$start = null
protected

◆ $timezone

string ilCalendarRecurrenceCalculator::$timezone = ilTimeZone::UTC
protected

Definition at line 29 of file class.ilCalendarRecurrenceCalculator.php.

◆ $valid_dates

ilDateList ilCalendarRecurrenceCalculator::$valid_dates = null
protected

Definition at line 33 of file class.ilCalendarRecurrenceCalculator.php.

Referenced by calculateDateList().


The documentation for this class was generated from the following file: