ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Sabre\VObject\Recur\RRuleIterator Class Reference

RRuleParser. More...

+ Inheritance diagram for Sabre\VObject\Recur\RRuleIterator:
+ Collaboration diagram for Sabre\VObject\Recur\RRuleIterator:

Public Member Functions

 __construct ($rrule, DateTimeInterface $start)
 Creates the Iterator. More...
 
 current ()
 
 key ()
 Returns the current item number. More...
 
 valid ()
 Returns whether the current item is a valid item for the recurrence iterator. More...
 
 rewind ()
 Resets the iterator. More...
 
 next ()
 Goes on to the next iteration. More...
 
 isInfinite ()
 Returns true if this recurring event never ends. More...
 
 fastForward (DateTimeInterface $dt)
 This method allows you to quickly go to the next occurrence after the specified date. More...
 

Protected Member Functions

 nextHourly ()
 Does the processing for advancing the iterator for hourly frequency. More...
 
 nextDaily ()
 Does the processing for advancing the iterator for daily frequency. More...
 
 nextWeekly ()
 Does the processing for advancing the iterator for weekly frequency. More...
 
 nextMonthly ()
 Does the processing for advancing the iterator for monthly frequency. More...
 
 nextYearly ()
 Does the processing for advancing the iterator for yearly frequency. More...
 
 parseRRule ($rrule)
 This method receives a string from an RRULE property, and populates this class with all the values. More...
 
 getMonthlyOccurrences ()
 Returns all the occurrences for a monthly frequency with a 'byDay' or 'byMonthDay' expansion for the current month. More...
 
 getHours ()
 
 getDays ()
 
 getMonths ()
 

Protected Attributes

 $startDate
 
 $currentDate
 
 $frequency
 
 $count
 
 $interval = 1
 
 $until
 
 $bySecond
 
 $byMinute
 
 $byHour
 
 $counter = 0
 
 $byDay
 
 $byMonthDay
 
 $byYearDay
 
 $byWeekNo
 
 $byMonth
 
 $bySetPos
 
 $weekStart = 'MO'
 
 $dayNames
 
 $dayMap
 

Detailed Description

RRuleParser.

This class receives an RRULE string, and allows you to iterate to get a list of dates in that recurrence.

For instance, passing: FREQ=DAILY;LIMIT=5 will cause the iterator to contain 5 items, one for each day.

Author
Evert Pot (http://evertpot.com/) @license http://sabre.io/license/ Modified BSD License

Definition at line 25 of file RRuleIterator.php.

Constructor & Destructor Documentation

◆ __construct()

Sabre\VObject\Recur\RRuleIterator::__construct (   $rrule,
DateTimeInterface  $start 
)

Creates the Iterator.

Parameters
string | array$rrule
DateTimeInterface$start

Definition at line 33 of file RRuleIterator.php.

33 {
34
35 $this->startDate = $start;
36 $this->parseRRule($rrule);
37 $this->currentDate = clone $this->startDate;
38
39 }
parseRRule($rrule)
This method receives a string from an RRULE property, and populates this class with all the values.
$start
Definition: bench.php:8

References $start, Sabre\VObject\Recur\RRuleIterator\$startDate, and Sabre\VObject\Recur\RRuleIterator\parseRRule().

+ Here is the call graph for this function:

Member Function Documentation

◆ current()

Sabre\VObject\Recur\RRuleIterator::current ( )

Definition at line 43 of file RRuleIterator.php.

43 {
44
45 if (!$this->valid()) return;
46 return clone $this->currentDate;
47
48 }
valid()
Returns whether the current item is a valid item for the recurrence iterator.

References Sabre\VObject\Recur\RRuleIterator\$currentDate, and Sabre\VObject\Recur\RRuleIterator\valid().

+ Here is the call graph for this function:

◆ fastForward()

Sabre\VObject\Recur\RRuleIterator::fastForward ( DateTimeInterface  $dt)

This method allows you to quickly go to the next occurrence after the specified date.

Parameters
DateTimeInterface$dt
Returns
void

Definition at line 146 of file RRuleIterator.php.

146 {
147
148 while ($this->valid() && $this->currentDate < $dt) {
149 $this->next();
150 }
151
152 }
next()
Goes on to the next iteration.

References Sabre\VObject\Recur\RRuleIterator\next(), and Sabre\VObject\Recur\RRuleIterator\valid().

+ Here is the call graph for this function:

◆ getDays()

Sabre\VObject\Recur\RRuleIterator::getDays ( )
protected

Definition at line 989 of file RRuleIterator.php.

989 {
990
991 $recurrenceDays = [];
992 foreach ($this->byDay as $byDay) {
993
994 // The day may be preceeded with a positive (+n) or
995 // negative (-n) integer. However, this does not make
996 // sense in 'weekly' so we ignore it here.
997 $recurrenceDays[] = $this->dayMap[substr($byDay, -2)];
998
999 }
1000
1001 return $recurrenceDays;
1002 }

References Sabre\VObject\Recur\RRuleIterator\$byDay.

Referenced by Sabre\VObject\Recur\RRuleIterator\nextDaily(), and Sabre\VObject\Recur\RRuleIterator\nextWeekly().

+ Here is the caller graph for this function:

◆ getHours()

Sabre\VObject\Recur\RRuleIterator::getHours ( )
protected

Definition at line 979 of file RRuleIterator.php.

979 {
980
981 $recurrenceHours = [];
982 foreach ($this->byHour as $byHour) {
983 $recurrenceHours[] = $byHour;
984 }
985
986 return $recurrenceHours;
987 }

References Sabre\VObject\Recur\RRuleIterator\$byHour.

Referenced by Sabre\VObject\Recur\RRuleIterator\nextDaily(), and Sabre\VObject\Recur\RRuleIterator\nextWeekly().

+ Here is the caller graph for this function:

◆ getMonthlyOccurrences()

Sabre\VObject\Recur\RRuleIterator::getMonthlyOccurrences ( )
protected

Returns all the occurrences for a monthly frequency with a 'byDay' or 'byMonthDay' expansion for the current month.

The returned list is an array of integers with the day of month (1-31).

Returns
array

Definition at line 855 of file RRuleIterator.php.

855 {
856
858
859 $byDayResults = [];
860
861 // Our strategy is to simply go through the byDays, advance the date to
862 // that point and add it to the results.
863 if ($this->byDay) foreach ($this->byDay as $day) {
864
865 $dayName = $this->dayNames[$this->dayMap[substr($day, -2)]];
866
867
868 // Dayname will be something like 'wednesday'. Now we need to find
869 // all wednesdays in this month.
870 $dayHits = [];
871
872 // workaround for missing 'first day of the month' support in hhvm
873 $checkDate = new \DateTime($startDate->format('Y-m-1'));
874 // workaround modify always advancing the date even if the current day is a $dayName in hhvm
875 if ($checkDate->format('l') !== $dayName) {
876 $checkDate = $checkDate->modify($dayName);
877 }
878
879 do {
880 $dayHits[] = $checkDate->format('j');
881 $checkDate = $checkDate->modify('next ' . $dayName);
882 } while ($checkDate->format('n') === $startDate->format('n'));
883
884 // So now we have 'all wednesdays' for month. It is however
885 // possible that the user only really wanted the 1st, 2nd or last
886 // wednesday.
887 if (strlen($day) > 2) {
888 $offset = (int)substr($day, 0, -2);
889
890 if ($offset > 0) {
891 // It is possible that the day does not exist, such as a
892 // 5th or 6th wednesday of the month.
893 if (isset($dayHits[$offset - 1])) {
894 $byDayResults[] = $dayHits[$offset - 1];
895 }
896 } else {
897
898 // if it was negative we count from the end of the array
899 // might not exist, fx. -5th tuesday
900 if (isset($dayHits[count($dayHits) + $offset])) {
901 $byDayResults[] = $dayHits[count($dayHits) + $offset];
902 }
903 }
904 } else {
905 // There was no counter (first, second, last wednesdays), so we
906 // just need to add the all to the list).
907 $byDayResults = array_merge($byDayResults, $dayHits);
908
909 }
910
911 }
912
913 $byMonthDayResults = [];
914 if ($this->byMonthDay) foreach ($this->byMonthDay as $monthDay) {
915
916 // Removing values that are out of range for this month
917 if ($monthDay > $startDate->format('t') ||
918 $monthDay < 0 - $startDate->format('t')) {
919 continue;
920 }
921 if ($monthDay > 0) {
922 $byMonthDayResults[] = $monthDay;
923 } else {
924 // Negative values
925 $byMonthDayResults[] = $startDate->format('t') + 1 + $monthDay;
926 }
927 }
928
929 // If there was just byDay or just byMonthDay, they just specify our
930 // (almost) final list. If both were provided, then byDay limits the
931 // list.
932 if ($this->byMonthDay && $this->byDay) {
933 $result = array_intersect($byMonthDayResults, $byDayResults);
934 } elseif ($this->byMonthDay) {
935 $result = $byMonthDayResults;
936 } else {
937 $result = $byDayResults;
938 }
939 $result = array_unique($result);
940 sort($result, SORT_NUMERIC);
941
942 // The last thing that needs checking is the BYSETPOS. If it's set, it
943 // means only certain items in the set survive the filter.
944 if (!$this->bySetPos) {
945 return $result;
946 }
947
948 $filteredResult = [];
949 foreach ($this->bySetPos as $setPos) {
950
951 if ($setPos < 0) {
952 $setPos = count($result) + ($setPos + 1);
953 }
954 if (isset($result[$setPos - 1])) {
955 $filteredResult[] = $result[$setPos - 1];
956 }
957 }
958
959 sort($filteredResult, SORT_NUMERIC);
960 return $filteredResult;
961
962 }
$result

References Sabre\VObject\Recur\RRuleIterator\$currentDate, $result, and Sabre\VObject\Recur\RRuleIterator\$startDate.

Referenced by Sabre\VObject\Recur\RRuleIterator\nextMonthly(), and Sabre\VObject\Recur\RRuleIterator\nextYearly().

+ Here is the caller graph for this function:

◆ getMonths()

Sabre\VObject\Recur\RRuleIterator::getMonths ( )
protected

Definition at line 1004 of file RRuleIterator.php.

1004 {
1005
1006 $recurrenceMonths = [];
1007 foreach ($this->byMonth as $byMonth) {
1008 $recurrenceMonths[] = $byMonth;
1009 }
1010
1011 return $recurrenceMonths;
1012 }

References Sabre\VObject\Recur\RRuleIterator\$byMonth.

Referenced by Sabre\VObject\Recur\RRuleIterator\nextDaily().

+ Here is the caller graph for this function:

◆ isInfinite()

Sabre\VObject\Recur\RRuleIterator::isInfinite ( )

Returns true if this recurring event never ends.

Returns
bool

Definition at line 132 of file RRuleIterator.php.

132 {
133
134 return !$this->count && !$this->until;
135
136 }

References Sabre\VObject\Recur\RRuleIterator\$until.

◆ key()

Sabre\VObject\Recur\RRuleIterator::key ( )

Returns the current item number.

Returns
int

Definition at line 55 of file RRuleIterator.php.

References Sabre\VObject\Recur\RRuleIterator\$counter.

◆ next()

Sabre\VObject\Recur\RRuleIterator::next ( )

Goes on to the next iteration.

Returns
void

Definition at line 94 of file RRuleIterator.php.

94 {
95
96 // Otherwise, we find the next event in the normal RRULE
97 // sequence.
98 switch ($this->frequency) {
99
100 case 'hourly' :
101 $this->nextHourly();
102 break;
103
104 case 'daily' :
105 $this->nextDaily();
106 break;
107
108 case 'weekly' :
109 $this->nextWeekly();
110 break;
111
112 case 'monthly' :
113 $this->nextMonthly();
114 break;
115
116 case 'yearly' :
117 $this->nextYearly();
118 break;
119
120 }
121 $this->counter++;
122
123 }
nextDaily()
Does the processing for advancing the iterator for daily frequency.
nextMonthly()
Does the processing for advancing the iterator for monthly frequency.
nextHourly()
Does the processing for advancing the iterator for hourly frequency.
nextWeekly()
Does the processing for advancing the iterator for weekly frequency.
nextYearly()
Does the processing for advancing the iterator for yearly frequency.

References Sabre\VObject\Recur\RRuleIterator\nextDaily(), Sabre\VObject\Recur\RRuleIterator\nextHourly(), Sabre\VObject\Recur\RRuleIterator\nextMonthly(), Sabre\VObject\Recur\RRuleIterator\nextWeekly(), and Sabre\VObject\Recur\RRuleIterator\nextYearly().

Referenced by Sabre\VObject\Recur\RRuleIterator\fastForward().

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

◆ nextDaily()

Sabre\VObject\Recur\RRuleIterator::nextDaily ( )
protected

Does the processing for advancing the iterator for daily frequency.

Returns
void

Definition at line 334 of file RRuleIterator.php.

334 {
335
336 if (!$this->byHour && !$this->byDay) {
337 $this->currentDate = $this->currentDate->modify('+' . $this->interval . ' days');
338 return;
339 }
340
341 if (!empty($this->byHour)) {
342 $recurrenceHours = $this->getHours();
343 }
344
345 if (!empty($this->byDay)) {
346 $recurrenceDays = $this->getDays();
347 }
348
349 if (!empty($this->byMonth)) {
350 $recurrenceMonths = $this->getMonths();
351 }
352
353 do {
354 if ($this->byHour) {
355 if ($this->currentDate->format('G') == '23') {
356 // to obey the interval rule
357 $this->currentDate = $this->currentDate->modify('+' . $this->interval - 1 . ' days');
358 }
359
360 $this->currentDate = $this->currentDate->modify('+1 hours');
361
362 } else {
363 $this->currentDate = $this->currentDate->modify('+' . $this->interval . ' days');
364
365 }
366
367 // Current month of the year
368 $currentMonth = $this->currentDate->format('n');
369
370 // Current day of the week
371 $currentDay = $this->currentDate->format('w');
372
373 // Current hour of the day
374 $currentHour = $this->currentDate->format('G');
375
376 } while (
377 ($this->byDay && !in_array($currentDay, $recurrenceDays)) ||
378 ($this->byHour && !in_array($currentHour, $recurrenceHours)) ||
379 ($this->byMonth && !in_array($currentMonth, $recurrenceMonths))
380 );
381
382 }

References Sabre\VObject\Recur\RRuleIterator\getDays(), Sabre\VObject\Recur\RRuleIterator\getHours(), and Sabre\VObject\Recur\RRuleIterator\getMonths().

Referenced by Sabre\VObject\Recur\RRuleIterator\next().

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

◆ nextHourly()

Sabre\VObject\Recur\RRuleIterator::nextHourly ( )
protected

Does the processing for advancing the iterator for hourly frequency.

Returns
void

Definition at line 323 of file RRuleIterator.php.

323 {
324
325 $this->currentDate = $this->currentDate->modify('+' . $this->interval . ' hours');
326
327 }

Referenced by Sabre\VObject\Recur\RRuleIterator\next().

+ Here is the caller graph for this function:

◆ nextMonthly()

Sabre\VObject\Recur\RRuleIterator::nextMonthly ( )
protected

Does the processing for advancing the iterator for monthly frequency.

Returns
void

Definition at line 441 of file RRuleIterator.php.

441 {
442
443 $currentDayOfMonth = $this->currentDate->format('j');
444 if (!$this->byMonthDay && !$this->byDay) {
445
446 // If the current day is higher than the 28th, rollover can
447 // occur to the next month. We Must skip these invalid
448 // entries.
449 if ($currentDayOfMonth < 29) {
450 $this->currentDate = $this->currentDate->modify('+' . $this->interval . ' months');
451 } else {
452 $increase = 0;
453 do {
454 $increase++;
455 $tempDate = clone $this->currentDate;
456 $tempDate = $tempDate->modify('+ ' . ($this->interval * $increase) . ' months');
457 } while ($tempDate->format('j') != $currentDayOfMonth);
458 $this->currentDate = $tempDate;
459 }
460 return;
461 }
462
463 while (true) {
464
465 $occurrences = $this->getMonthlyOccurrences();
466
467 foreach ($occurrences as $occurrence) {
468
469 // The first occurrence thats higher than the current
470 // day of the month wins.
471 if ($occurrence > $currentDayOfMonth) {
472 break 2;
473 }
474
475 }
476
477 // If we made it all the way here, it means there were no
478 // valid occurrences, and we need to advance to the next
479 // month.
480 //
481 // This line does not currently work in hhvm. Temporary workaround
482 // follows:
483 // $this->currentDate->modify('first day of this month');
484 $this->currentDate = new DateTimeImmutable($this->currentDate->format('Y-m-1 H:i:s'), $this->currentDate->getTimezone());
485 // end of workaround
486 $this->currentDate = $this->currentDate->modify('+ ' . $this->interval . ' months');
487
488 // This goes to 0 because we need to start counting at the
489 // beginning.
490 $currentDayOfMonth = 0;
491
492 }
493
494 $this->currentDate = $this->currentDate->setDate(
495 (int)$this->currentDate->format('Y'),
496 (int)$this->currentDate->format('n'),
497 (int)$occurrence
498 );
499
500 }
getMonthlyOccurrences()
Returns all the occurrences for a monthly frequency with a 'byDay' or 'byMonthDay' expansion for the ...

References Sabre\VObject\Recur\RRuleIterator\$currentDate, and Sabre\VObject\Recur\RRuleIterator\getMonthlyOccurrences().

Referenced by Sabre\VObject\Recur\RRuleIterator\next().

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

◆ nextWeekly()

Sabre\VObject\Recur\RRuleIterator::nextWeekly ( )
protected

Does the processing for advancing the iterator for weekly frequency.

Returns
void

Definition at line 389 of file RRuleIterator.php.

389 {
390
391 if (!$this->byHour && !$this->byDay) {
392 $this->currentDate = $this->currentDate->modify('+' . $this->interval . ' weeks');
393 return;
394 }
395
396 if ($this->byHour) {
397 $recurrenceHours = $this->getHours();
398 }
399
400 if ($this->byDay) {
401 $recurrenceDays = $this->getDays();
402 }
403
404 // First day of the week:
405 $firstDay = $this->dayMap[$this->weekStart];
406
407 do {
408
409 if ($this->byHour) {
410 $this->currentDate = $this->currentDate->modify('+1 hours');
411 } else {
412 $this->currentDate = $this->currentDate->modify('+1 days');
413 }
414
415 // Current day of the week
416 $currentDay = (int)$this->currentDate->format('w');
417
418 // Current hour of the day
419 $currentHour = (int)$this->currentDate->format('G');
420
421 // We need to roll over to the next week
422 if ($currentDay === $firstDay && (!$this->byHour || $currentHour == '0')) {
423 $this->currentDate = $this->currentDate->modify('+' . $this->interval - 1 . ' weeks');
424
425 // We need to go to the first day of this week, but only if we
426 // are not already on this first day of this week.
427 if ($this->currentDate->format('w') != $firstDay) {
428 $this->currentDate = $this->currentDate->modify('last ' . $this->dayNames[$this->dayMap[$this->weekStart]]);
429 }
430 }
431
432 // We have a match
433 } while (($this->byDay && !in_array($currentDay, $recurrenceDays)) || ($this->byHour && !in_array($currentHour, $recurrenceHours)));
434 }

References Sabre\VObject\Recur\RRuleIterator\$weekStart, Sabre\VObject\Recur\RRuleIterator\getDays(), and Sabre\VObject\Recur\RRuleIterator\getHours().

Referenced by Sabre\VObject\Recur\RRuleIterator\next().

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

◆ nextYearly()

Sabre\VObject\Recur\RRuleIterator::nextYearly ( )
protected

Does the processing for advancing the iterator for yearly frequency.

Returns
void

Definition at line 507 of file RRuleIterator.php.

507 {
508
509 $currentMonth = $this->currentDate->format('n');
510 $currentYear = $this->currentDate->format('Y');
511 $currentDayOfMonth = $this->currentDate->format('j');
512
513 // No sub-rules, so we just advance by year
514 if (empty($this->byMonth)) {
515
516 // Unless it was a leap day!
517 if ($currentMonth == 2 && $currentDayOfMonth == 29) {
518
519 $counter = 0;
520 do {
521 $counter++;
522 // Here we increase the year count by the interval, until
523 // we hit a date that's also in a leap year.
524 //
525 // We could just find the next interval that's dividable by
526 // 4, but that would ignore the rule that there's no leap
527 // year every year that's dividable by a 100, but not by
528 // 400. (1800, 1900, 2100). So we just rely on the datetime
529 // functions instead.
530 $nextDate = clone $this->currentDate;
531 $nextDate = $nextDate->modify('+ ' . ($this->interval * $counter) . ' years');
532 } while ($nextDate->format('n') != 2);
533
534 $this->currentDate = $nextDate;
535
536 return;
537
538 }
539
540 if ($this->byWeekNo !== null) { // byWeekNo is an array with values from -53 to -1, or 1 to 53
541 $dayOffsets = [];
542 if ($this->byDay) {
543 foreach ($this->byDay as $byDay) {
544 $dayOffsets[] = $this->dayMap[$byDay];
545 }
546 } else { // default is Monday
547 $dayOffsets[] = 1;
548 }
549
550 $currentYear = $this->currentDate->format('Y');
551
552 while (true) {
553 $checkDates = [];
554
555 // loop through all WeekNo and Days to check all the combinations
556 foreach ($this->byWeekNo as $byWeekNo) {
557 foreach ($dayOffsets as $dayOffset) {
558 $date = clone $this->currentDate;
559 $date->setISODate($currentYear, $byWeekNo, $dayOffset);
560
561 if ($date > $this->currentDate) {
562 $checkDates[] = $date;
563 }
564 }
565 }
566
567 if (count($checkDates) > 0) {
568 $this->currentDate = min($checkDates);
569 return;
570 }
571
572 // if there is no date found, check the next year
573 $currentYear += $this->interval;
574 }
575 }
576
577 if ($this->byYearDay !== null) { // byYearDay is an array with values from -366 to -1, or 1 to 366
578 $dayOffsets = [];
579 if ($this->byDay) {
580 foreach ($this->byDay as $byDay) {
581 $dayOffsets[] = $this->dayMap[$byDay];
582 }
583 } else { // default is Monday-Sunday
584 $dayOffsets = [1,2,3,4,5,6,7];
585 }
586
587 $currentYear = $this->currentDate->format('Y');
588
589 while (true) {
590 $checkDates = [];
591
592 // loop through all YearDay and Days to check all the combinations
593 foreach ($this->byYearDay as $byYearDay) {
594 $date = clone $this->currentDate;
595 $date = $date->setDate($currentYear, 1, 1);
596 if ($byYearDay > 0) {
597 $date = $date->add(new \DateInterval('P' . $byYearDay . 'D'));
598 } else {
599 $date = $date->sub(new \DateInterval('P' . abs($byYearDay) . 'D'));
600 }
601
602 if ($date > $this->currentDate && in_array($date->format('N'), $dayOffsets)) {
603 $checkDates[] = $date;
604 }
605 }
606
607 if (count($checkDates) > 0) {
608 $this->currentDate = min($checkDates);
609 return;
610 }
611
612 // if there is no date found, check the next year
613 $currentYear += $this->interval;
614 }
615 }
616
617 // The easiest form
618 $this->currentDate = $this->currentDate->modify('+' . $this->interval . ' years');
619 return;
620
621 }
622
623 $currentMonth = $this->currentDate->format('n');
624 $currentYear = $this->currentDate->format('Y');
625 $currentDayOfMonth = $this->currentDate->format('j');
626
627 $advancedToNewMonth = false;
628
629 // If we got a byDay or getMonthDay filter, we must first expand
630 // further.
631 if ($this->byDay || $this->byMonthDay) {
632
633 while (true) {
634
635 $occurrences = $this->getMonthlyOccurrences();
636
637 foreach ($occurrences as $occurrence) {
638
639 // The first occurrence that's higher than the current
640 // day of the month wins.
641 // If we advanced to the next month or year, the first
642 // occurrence is always correct.
643 if ($occurrence > $currentDayOfMonth || $advancedToNewMonth) {
644 break 2;
645 }
646
647 }
648
649 // If we made it here, it means we need to advance to
650 // the next month or year.
651 $currentDayOfMonth = 1;
652 $advancedToNewMonth = true;
653 do {
654
655 $currentMonth++;
656 if ($currentMonth > 12) {
657 $currentYear += $this->interval;
658 $currentMonth = 1;
659 }
660 } while (!in_array($currentMonth, $this->byMonth));
661
662 $this->currentDate = $this->currentDate->setDate(
663 (int)$currentYear,
664 (int)$currentMonth,
665 (int)$currentDayOfMonth
666 );
667
668 }
669
670 // If we made it here, it means we got a valid occurrence
671 $this->currentDate = $this->currentDate->setDate(
672 (int)$currentYear,
673 (int)$currentMonth,
674 (int)$occurrence
675 );
676 return;
677
678 } else {
679
680 // These are the 'byMonth' rules, if there are no byDay or
681 // byMonthDay sub-rules.
682 do {
683
684 $currentMonth++;
685 if ($currentMonth > 12) {
686 $currentYear += $this->interval;
687 $currentMonth = 1;
688 }
689 } while (!in_array($currentMonth, $this->byMonth));
690 $this->currentDate = $this->currentDate->setDate(
691 (int)$currentYear,
692 (int)$currentMonth,
693 (int)$currentDayOfMonth
694 );
695
696 return;
697
698 }
699
700 }

References Sabre\VObject\Recur\RRuleIterator\$byDay, Sabre\VObject\Recur\RRuleIterator\$byWeekNo, Sabre\VObject\Recur\RRuleIterator\$byYearDay, Sabre\VObject\Recur\RRuleIterator\$counter, Sabre\VObject\Recur\RRuleIterator\$currentDate, Sabre\VObject\Recur\RRuleIterator\$interval, and Sabre\VObject\Recur\RRuleIterator\getMonthlyOccurrences().

Referenced by Sabre\VObject\Recur\RRuleIterator\next().

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

◆ parseRRule()

Sabre\VObject\Recur\RRuleIterator::parseRRule (   $rrule)
protected

This method receives a string from an RRULE property, and populates this class with all the values.

Parameters
string | array$rrule
Returns
void

Definition at line 712 of file RRuleIterator.php.

712 {
713
714 if (is_string($rrule)) {
716 }
717
718 foreach ($rrule as $key => $value) {
719
720 $key = strtoupper($key);
721 switch ($key) {
722
723 case 'FREQ' :
724 $value = strtolower($value);
725 if (!in_array(
726 $value,
727 ['secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly']
728 )) {
729 throw new InvalidDataException('Unknown value for FREQ=' . strtoupper($value));
730 }
731 $this->frequency = $value;
732 break;
733
734 case 'UNTIL' :
735 $this->until = DateTimeParser::parse($value, $this->startDate->getTimezone());
736
737 // In some cases events are generated with an UNTIL=
738 // parameter before the actual start of the event.
739 //
740 // Not sure why this is happening. We assume that the
741 // intention was that the event only recurs once.
742 //
743 // So we are modifying the parameter so our code doesn't
744 // break.
745 if ($this->until < $this->startDate) {
746 $this->until = $this->startDate;
747 }
748 break;
749
750 case 'INTERVAL' :
751 // No break
752
753 case 'COUNT' :
754 $val = (int)$value;
755 if ($val < 1) {
756 throw new InvalidDataException(strtoupper($key) . ' in RRULE must be a positive integer!');
757 }
758 $key = strtolower($key);
759 $this->$key = $val;
760 break;
761
762 case 'BYSECOND' :
763 $this->bySecond = (array)$value;
764 break;
765
766 case 'BYMINUTE' :
767 $this->byMinute = (array)$value;
768 break;
769
770 case 'BYHOUR' :
771 $this->byHour = (array)$value;
772 break;
773
774 case 'BYDAY' :
775 $value = (array)$value;
776 foreach ($value as $part) {
777 if (!preg_match('#^ (-|\+)? ([1-5])? (MO|TU|WE|TH|FR|SA|SU) $# xi', $part)) {
778 throw new InvalidDataException('Invalid part in BYDAY clause: ' . $part);
779 }
780 }
781 $this->byDay = $value;
782 break;
783
784 case 'BYMONTHDAY' :
785 $this->byMonthDay = (array)$value;
786 break;
787
788 case 'BYYEARDAY' :
789 $this->byYearDay = (array)$value;
790 foreach ($this->byYearDay as $byYearDay) {
791 if (!is_numeric($byYearDay) || (int)$byYearDay < -366 || (int)$byYearDay == 0 || (int)$byYearDay > 366) {
792 throw new InvalidDataException('BYYEARDAY in RRULE must have value(s) from 1 to 366, or -366 to -1!');
793 }
794 }
795 break;
796
797 case 'BYWEEKNO' :
798 $this->byWeekNo = (array)$value;
799 foreach ($this->byWeekNo as $byWeekNo) {
800 if (!is_numeric($byWeekNo) || (int)$byWeekNo < -53 || (int)$byWeekNo == 0 || (int)$byWeekNo > 53) {
801 throw new InvalidDataException('BYWEEKNO in RRULE must have value(s) from 1 to 53, or -53 to -1!');
802 }
803 }
804 break;
805
806 case 'BYMONTH' :
807 $this->byMonth = (array)$value;
808 foreach ($this->byMonth as $byMonth) {
809 if (!is_numeric($byMonth) || (int)$byMonth < 1 || (int)$byMonth > 12) {
810 throw new InvalidDataException('BYMONTH in RRULE must have value(s) betweeen 1 and 12!');
811 }
812 }
813 break;
814
815 case 'BYSETPOS' :
816 $this->bySetPos = (array)$value;
817 break;
818
819 case 'WKST' :
820 $this->weekStart = strtoupper($value);
821 break;
822
823 default:
824 throw new InvalidDataException('Not supported: ' . strtoupper($key));
825
826 }
827
828 }
829
830 }
static parse($date, $referenceTz=null)
Parses either a Date or DateTime, or Duration value.
static stringToArray($value)
Parses an RRULE value string, and turns it into a struct-ish array.
Definition: Recur.php:209
$key
Definition: croninfo.php:18

References Sabre\VObject\Recur\RRuleIterator\$byMonth, Sabre\VObject\Recur\RRuleIterator\$byWeekNo, Sabre\VObject\Recur\RRuleIterator\$byYearDay, $key, Sabre\VObject\Recur\RRuleIterator\$startDate, Sabre\VObject\DateTimeParser\parse(), and Sabre\VObject\Property\ICalendar\Recur\stringToArray().

Referenced by Sabre\VObject\Recur\RRuleIterator\__construct().

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

◆ rewind()

Sabre\VObject\Recur\RRuleIterator::rewind ( )

Resets the iterator.

Returns
void

Definition at line 82 of file RRuleIterator.php.

82 {
83
84 $this->currentDate = clone $this->startDate;
85 $this->counter = 0;
86
87 }

References Sabre\VObject\Recur\RRuleIterator\$startDate.

◆ valid()

Sabre\VObject\Recur\RRuleIterator::valid ( )

Returns whether the current item is a valid item for the recurrence iterator.

This will return false if we've gone beyond the UNTIL or COUNT statements.

Returns
bool

Definition at line 68 of file RRuleIterator.php.

68 {
69
70 if (!is_null($this->count)) {
71 return $this->counter < $this->count;
72 }
73 return is_null($this->until) || $this->currentDate <= $this->until;
74
75 }

References Sabre\VObject\Recur\RRuleIterator\$count, and Sabre\VObject\Recur\RRuleIterator\$until.

Referenced by Sabre\VObject\Recur\RRuleIterator\current(), and Sabre\VObject\Recur\RRuleIterator\fastForward().

+ Here is the caller graph for this function:

Field Documentation

◆ $byDay

Sabre\VObject\Recur\RRuleIterator::$byDay
protected

◆ $byHour

Sabre\VObject\Recur\RRuleIterator::$byHour
protected

Definition at line 228 of file RRuleIterator.php.

Referenced by Sabre\VObject\Recur\RRuleIterator\getHours().

◆ $byMinute

Sabre\VObject\Recur\RRuleIterator::$byMinute
protected

Definition at line 219 of file RRuleIterator.php.

◆ $byMonth

Sabre\VObject\Recur\RRuleIterator::$byMonth
protected

◆ $byMonthDay

Sabre\VObject\Recur\RRuleIterator::$byMonthDay
protected

Definition at line 261 of file RRuleIterator.php.

◆ $bySecond

Sabre\VObject\Recur\RRuleIterator::$bySecond
protected

Definition at line 210 of file RRuleIterator.php.

◆ $bySetPos

Sabre\VObject\Recur\RRuleIterator::$bySetPos
protected

Definition at line 307 of file RRuleIterator.php.

◆ $byWeekNo

Sabre\VObject\Recur\RRuleIterator::$byWeekNo
protected

◆ $byYearDay

Sabre\VObject\Recur\RRuleIterator::$byYearDay
protected

◆ $count

Sabre\VObject\Recur\RRuleIterator::$count
protected

Definition at line 184 of file RRuleIterator.php.

Referenced by Sabre\VObject\Recur\RRuleIterator\valid().

◆ $counter

Sabre\VObject\Recur\RRuleIterator::$counter = 0
protected

◆ $currentDate

◆ $dayMap

Sabre\VObject\Recur\RRuleIterator::$dayMap
protected
Initial value:
= [
'SU' => 0,
'MO' => 1,
'TU' => 2,
'WE' => 3,
'TH' => 4,
'FR' => 5,
'SA' => 6,
]

Definition at line 969 of file RRuleIterator.php.

◆ $dayNames

Sabre\VObject\Recur\RRuleIterator::$dayNames
protected
Initial value:
= [
0 => 'Sunday',
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday',
]

Definition at line 837 of file RRuleIterator.php.

◆ $frequency

Sabre\VObject\Recur\RRuleIterator::$frequency
protected

Definition at line 177 of file RRuleIterator.php.

◆ $interval

Sabre\VObject\Recur\RRuleIterator::$interval = 1
protected

Definition at line 194 of file RRuleIterator.php.

Referenced by Sabre\VObject\Recur\RRuleIterator\nextYearly().

◆ $startDate

◆ $until

Sabre\VObject\Recur\RRuleIterator::$until
protected

◆ $weekStart

Sabre\VObject\Recur\RRuleIterator::$weekStart = 'MO'
protected

Definition at line 314 of file RRuleIterator.php.

Referenced by Sabre\VObject\Recur\RRuleIterator\nextWeekly().


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