ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ilCalendarRecurrenceCalculator Class Reference

Calculates an ilDateList for a given calendar entry and recurrence rule. 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

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 }
const IL_CAL_UNIX
getEnd()
Get end of period.
getStart()
Get start of date period.
$GLOBALS["DIC"]
Definition: wac.php:54

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 }
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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 foreach ($this->recurrence->getBYDAYList() as $byday) {
521 $year_day = array();
522 $day = strtoupper(substr($byday, -2));
523 $num_by_day = (int) $byday;
524
525 if ($num_by_day) {
526 if ($num_by_day > 0) {
527 if (isset($day_array[$day][$num_by_day - 1])) {
528 $year_day = array($day_array[$day][$num_by_day - 1]);
529 }
530 } elseif (isset($day_array[$day][count($day_array[$day]) + $num_by_day])) {
531 $year_day = array($day_array[$day][count($day_array[$day]) + $num_by_day]);
532 }
533 } elseif (isset($day_array[$day])) {
534 $year_day = $day_array[$day];
535 }
536 foreach ($year_day as $day) {
537 switch ($this->frequence_context) {
542 $tmp_date = clone $start;
543 $tmp_date->increment(IL_CAL_DAY, $day);
544 $days_list->add($tmp_date);
545 break;
546 }
547 }
548 }
549 }
550 return $days_list;
551 }
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

References 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 627 of file class.ilCalendarRecurrenceCalculator.php.

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

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)
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 689 of file class.ilCalendarRecurrenceCalculator.php.

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

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 651 of file class.ilCalendarRecurrenceCalculator.php.

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

References $counter, $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 704 of file class.ilCalendarRecurrenceCalculator.php.

704 : ilDateTime
705 {
706 if ($this->event->isFullday()) {
707 return new ilDate($a_date, $a_format_type);
708 } else {
709 // TODO: the timezone for this recurrence must be stored in the db
710 return new ilDateTime($a_date, $a_format_type, $this->timezone);
711 }
712 }
@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 581 of file class.ilCalendarRecurrenceCalculator.php.

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

References ilCalendarUtil\_getMaxDayOfMonth(), IL_CAL_DATE, IL_CAL_FKT_GETDATE, and ILIAS\User\Profile\ChangeMail\next.

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 613 of file class.ilCalendarRecurrenceCalculator.php.

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

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 556 of file class.ilCalendarRecurrenceCalculator.php.

556 : array
557 {
558 $time = microtime(true);
559
560 $year_days = array();
561
562 $current_year = $seed->get(IL_CAL_FKT_DATE, 'Y');
563 $start = new ilDate($current_year . '-01-01', IL_CAL_DATE);
564 $offset = $start->get(IL_CAL_FKT_DATE, 'w');
565 $days = array(0 => 'SU', 1 => 'MO', 2 => 'TU', 3 => 'WE', 4 => 'TH', 5 => 'FR', 6 => 'SA');
566 for ($i = 0; $i < $offset; $i++) {
567 next($days);
568 }
569
570 $num_days = ilCalendarUtil::_isLeapYear($current_year) ? 366 : 365;
571 for ($i = 0; $i < $num_days; $i++) {
572 if (!($current_day = current($days))) {
573 $current_day = reset($days);
574 }
575 $year_days[$current_day][] = $i;
576 next($days);
577 }
578 return $year_days;
579 }
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 $start, ilCalendarUtil\_isLeapYear(), ilDateTime\get(), IL_CAL_DATE, IL_CAL_FKT_DATE, and ILIAS\User\Profile\ChangeMail\next.

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 699 of file class.ilCalendarRecurrenceCalculator.php.

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

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 714 of file class.ilCalendarRecurrenceCalculator.php.

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

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: