ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
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

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.

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

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
getStart()
Get start of date period.
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
getEnd()
Get end of period.
+ 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.

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

Referenced by calculateDateList().

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  }
static _setDefaultTimeZone(string $a_tz)
switchTimeZone(string $a_timezone_identifier='')
Switch timezone.
+ 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.

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().

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  }
increment(string $a_type, int $a_count=1)
getYearWeekDays(ilDateTime $seed)
get a list of year week days according to the BYMONTH rule
const IL_CAL_DAY
getWeekWeekDays(array $seed_info)
get weedays of week
List of dates.
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
const IL_CAL_FKT_GETDATE
+ 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.

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().

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
const IL_CAL_UNIX
List of dates.
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
$i
Definition: metadata.php:41
+ 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.

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

Referenced by calculateDateList().

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  }
const IL_CAL_UNIX
List of dates.
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
+ 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.

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

Referenced by calculateDateList().

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  }
sort()
Sort list.
getAtPosition(int $a_pos)
get item at specific position
List of dates.
+ 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.

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().

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  }
const IL_CAL_UNIX
List of dates.
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
+ 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.

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().

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  }
const IL_CAL_UNIX
List of dates.
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
+ 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.

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

Referenced by calculateDateList().

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 _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.
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.
+ 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.

Referenced by calculateDateList().

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  }
+ 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.

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

Referenced by calculateDateList().

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  }
remove(ilDateTime $remove)
remove from list
$res
Definition: ltiservices.php:69
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.
sort()
Sort list.
const IL_CAL_DAY
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.
+ 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.

References $period_end, $period_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().

Referenced by ilConsultationHoursGUI\createAppointments(), and ilObjSessionGUI\createRecurringSessions().

67  : ilDateList
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
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 
96  $start = $this->optimizeStartingTime();
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  }
applyDurationPeriod(ilDateList $list, ilDateTime $start, ilDateTime $end)
Apply duration period.
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.
static _restoreDefaultTimeZone()
const IL_CAL_DAY
adjustTimeZones(ilDateTime $a_start, ilDateTime $a_end)
Adjust timezone.
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.
List of dates.
applyBYSETPOSRules(ilDateList $list)
Apply BYSETPOST rules.
applyLimits(ilDateList $list)
Apply limits (count or until)
static _equals(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
Check if two date are equal.
applyBYWEEKNORules(ilDateList $list)
Apply BYWEEKNO rules (1 to 53 and -1 to -53).
+ Here is the call graph for this function:
+ Here is the caller 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.

References ILIAS\Repository\event().

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

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  }
+ 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.

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

Referenced by applyBYDAYRules().

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  }
static _getMaxDayOfMonth(int $a_year, int $a_month)
get max day of month 2008,2 => 29
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
$i
Definition: metadata.php:41
+ 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.

Referenced by applyBYDAYRules().

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  }
+ 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.

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

Referenced by applyBYDAYRules().

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  }
get(int $a_format, string $a_format_str='', string $a_tz='')
get formatted date
static _isLeapYear(int $a_year)
check if a given year is a leap year
const IL_CAL_FKT_DATE
const IL_CAL_DATE
$i
Definition: metadata.php:41
+ 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.

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().

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  }
increment(string $a_type, int $a_count=1)
+ 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.

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

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

700  : ilDateList
701  {
702  return new ilDateList($this->event->isFullday() ? ilDateList::TYPE_DATE : ilDateList::TYPE_DATETIME);
703  }
List of dates.
+ 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.

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

Referenced by calculateDateList().

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  }
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.
+ 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.

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

Referenced by calculateDateList().

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  }
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.
const IL_CAL_UNIX
createDate($a_date, $a_format_type=IL_CAL_UNIX)
+ 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.

Referenced by calculateDateList().

715  : bool
716  {
717  return $this->recurrence->validate();
718  }
+ 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

◆ $period_start

ilDateTime ilCalendarRecurrenceCalculator::$period_start = null
protected

◆ $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: