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 function __construct($rrule, DateTimeInterface $start) { 31 32 $this->startDate = $start; 33 $this->parseRDate($rrule); 34 $this->currentDate = clone $this->startDate; 35 36 } 37 38 /* Implementation of the Iterator interface {{{ */ 39 40 function current() { 41 42 if (!$this->valid()) return; 43 return clone $this->currentDate; 44 45 } 46 47 /** 48 * Returns the current item number. 49 * 50 * @return int 51 */ 52 function key() { 53 54 return $this->counter; 55 56 } 57 58 /** 59 * Returns whether the current item is a valid item for the recurrence 60 * iterator. 61 * 62 * @return bool 63 */ 64 function valid() { 65 66 return ($this->counter <= count($this->dates)); 67 68 } 69 70 /** 71 * Resets the iterator. 72 * 73 * @return void 74 */ 75 function rewind() { 76 77 $this->currentDate = clone $this->startDate; 78 $this->counter = 0; 79 80 } 81 82 /** 83 * Goes on to the next iteration. 84 * 85 * @return void 86 */ 87 function next() { 88 89 $this->counter++; 90 if (!$this->valid()) return; 91 92 $this->currentDate = 93 DateTimeParser::parse( 94 $this->dates[$this->counter - 1], 95 $this->startDate->getTimezone() 96 ); 97 98 } 99 100 /* End of Iterator implementation }}} */ 101 102 /** 103 * Returns true if this recurring event never ends. 104 * 105 * @return bool 106 */ 107 function isInfinite() { 108 109 return false; 110 111 } 112 113 /** 114 * This method allows you to quickly go to the next occurrence after the 115 * specified date. 116 * 117 * @param DateTimeInterface $dt 118 * 119 * @return void 120 */ 121 function fastForward(DateTimeInterface $dt) { 122 123 while ($this->valid() && $this->currentDate < $dt) { 124 $this->next(); 125 } 126 127 } 128 129 /** 130 * The reference start date/time for the rrule. 131 * 132 * All calculations are based on this initial date. 133 * 134 * @var DateTimeInterface 135 */ 136 protected $startDate; 137 138 /** 139 * The date of the current iteration. You can get this by calling 140 * ->current(). 141 * 142 * @var DateTimeInterface 143 */ 144 protected $currentDate; 145 146 /** 147 * The current item in the list. 148 * 149 * You can get this number with the key() method. 150 * 151 * @var int 152 */ 153 protected $counter = 0; 154 155 /* }}} */ 156 157 /** 158 * This method receives a string from an RRULE property, and populates this 159 * class with all the values. 160 * 161 * @param string|array $rrule 162 * 163 * @return void 164 */ 165 protected function parseRDate($rdate) { 166 167 if (is_string($rdate)) { 168 $rdate = explode(',', $rdate); 169 } 170 171 $this->dates = $rdate; 172 173 } 174 175 /** 176 * Array with the RRULE dates 177 * 178 * @var array 179 */ 180 protected $dates = []; 181 182} 183