1<?php 2 3namespace Sabre\VObject\Recur; 4 5use DateTimeInterface; 6use Iterator; 7use Sabre\VObject\DateTimeParser; 8 9/** 10 * RRuleParser. 11 * 12 * This class receives an RRULE string, and allows you to iterate to get a list 13 * of dates in that recurrence. 14 * 15 * For instance, passing: FREQ=DAILY;LIMIT=5 will cause the iterator to contain 16 * 5 items, one for each day. 17 * 18 * @copyright Copyright (C) fruux GmbH (https://fruux.com/) 19 * @author Evert Pot (http://evertpot.com/) 20 * @license http://sabre.io/license/ Modified BSD License 21 */ 22class RDateIterator implements Iterator 23{ 24 /** 25 * Creates the Iterator. 26 * 27 * @param string|array $rrule 28 * @param DateTimeInterface $start 29 */ 30 public function __construct($rrule, DateTimeInterface $start) 31 { 32 $this->startDate = $start; 33 $this->parseRDate($rrule); 34 $this->currentDate = clone $this->startDate; 35 } 36 37 /* Implementation of the Iterator interface {{{ */ 38 39 public function current() 40 { 41 if (!$this->valid()) { 42 return; 43 } 44 45 return clone $this->currentDate; 46 } 47 48 /** 49 * Returns the current item number. 50 * 51 * @return int 52 */ 53 public function key() 54 { 55 return $this->counter; 56 } 57 58 /** 59 * Returns whether the current item is a valid item for the recurrence 60 * iterator. 61 * 62 * @return bool 63 */ 64 public function valid() 65 { 66 return $this->counter <= count($this->dates); 67 } 68 69 /** 70 * Resets the iterator. 71 */ 72 public function rewind() 73 { 74 $this->currentDate = clone $this->startDate; 75 $this->counter = 0; 76 } 77 78 /** 79 * Goes on to the next iteration. 80 */ 81 public function next() 82 { 83 ++$this->counter; 84 if (!$this->valid()) { 85 return; 86 } 87 88 $this->currentDate = 89 DateTimeParser::parse( 90 $this->dates[$this->counter - 1], 91 $this->startDate->getTimezone() 92 ); 93 } 94 95 /* End of Iterator implementation }}} */ 96 97 /** 98 * Returns true if this recurring event never ends. 99 * 100 * @return bool 101 */ 102 public function isInfinite() 103 { 104 return false; 105 } 106 107 /** 108 * This method allows you to quickly go to the next occurrence after the 109 * specified date. 110 * 111 * @param DateTimeInterface $dt 112 */ 113 public function fastForward(DateTimeInterface $dt) 114 { 115 while ($this->valid() && $this->currentDate < $dt) { 116 $this->next(); 117 } 118 } 119 120 /** 121 * The reference start date/time for the rrule. 122 * 123 * All calculations are based on this initial date. 124 * 125 * @var DateTimeInterface 126 */ 127 protected $startDate; 128 129 /** 130 * The date of the current iteration. You can get this by calling 131 * ->current(). 132 * 133 * @var DateTimeInterface 134 */ 135 protected $currentDate; 136 137 /** 138 * The current item in the list. 139 * 140 * You can get this number with the key() method. 141 * 142 * @var int 143 */ 144 protected $counter = 0; 145 146 /* }}} */ 147 148 /** 149 * This method receives a string from an RRULE property, and populates this 150 * class with all the values. 151 * 152 * @param string|array $rrule 153 */ 154 protected function parseRDate($rdate) 155 { 156 if (is_string($rdate)) { 157 $rdate = explode(',', $rdate); 158 } 159 160 $this->dates = $rdate; 161 } 162 163 /** 164 * Array with the RRULE dates. 165 * 166 * @var array 167 */ 168 protected $dates = []; 169} 170