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