]> git.mxchange.org Git - friendica-addons.git/blob - dav/sabre-vobject/tests/Sabre/VObject/RecurrenceIteratorTest.php
Second part of refactoring; should be runnable again, yet not thoroughly tested
[friendica-addons.git] / dav / sabre-vobject / tests / Sabre / VObject / RecurrenceIteratorTest.php
1 <?php
2
3 namespace Sabre\VObject;
4
5 use DateTime;
6 use DateTimeZone;
7
8 class RecurrenceIteratorTest extends \PHPUnit_Framework_TestCase {
9
10     function testValues() {
11
12         $ev = new Component('VEVENT');
13         $ev->UID = 'bla';
14         $ev->RRULE = 'FREQ=DAILY;BYHOUR=10;BYMINUTE=5;BYSECOND=16;BYWEEKNO=32;BYYEARDAY=100,200';
15         $dtStart = new Property\DateTime('DTSTART');
16         $dtStart->setDateTime(new DateTime('2011-10-07'),Property\DateTime::UTC);
17
18         $ev->add($dtStart);
19
20         $vcal = Component::create('VCALENDAR');
21         $vcal->add($ev);
22
23         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
24
25         $this->assertEquals(array(10), $it->byHour);
26         $this->assertEquals(array(5), $it->byMinute);
27         $this->assertEquals(array(16), $it->bySecond);
28         $this->assertEquals(array(32), $it->byWeekNo);
29         $this->assertEquals(array(100,200), $it->byYearDay);
30
31     }
32
33     /**
34      * @expectedException InvalidArgumentException
35      * @depends testValues
36      */
37     function testInvalidFreq() {
38
39         $ev = new Component('VEVENT');
40         $ev->RRULE = 'FREQ=SMONTHLY;INTERVAL=3;UNTIL=20111025T000000Z';
41         $dtStart = new Property\DateTime('DTSTART');
42         $dtStart->setDateTime(new DateTime('2011-10-07'),Property\DateTime::UTC);
43
44         $ev->add($dtStart);
45
46         $vcal = Component::create('VCALENDAR');
47         $vcal->add($ev);
48
49         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
50
51     }
52
53     /**
54      * @expectedException InvalidArgumentException
55      */
56     function testVCalendarNoUID() {
57
58         $vcal = new Component('VCALENDAR');
59         $it = new RecurrenceIterator($vcal);
60
61     }
62
63     /**
64      * @expectedException InvalidArgumentException
65      */
66     function testVCalendarInvalidUID() {
67
68         $vcal = new Component('VCALENDAR');
69         $it = new RecurrenceIterator($vcal,'foo');
70
71     }
72
73     /**
74      * @depends testValues
75      */
76     function testDaily() {
77
78         $ev = new Component('VEVENT');
79         $ev->UID = 'bla';
80         $ev->RRULE = 'FREQ=DAILY;INTERVAL=3;UNTIL=20111025T000000Z';
81         $dtStart = new Property\DateTime('DTSTART');
82         $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
83
84         $ev->add($dtStart);
85
86         $vcal = Component::create('VCALENDAR');
87         $vcal->add($ev);
88
89         $it = new RecurrenceIterator($vcal,$ev->uid);
90
91         $this->assertEquals('daily', $it->frequency);
92         $this->assertEquals(3, $it->interval);
93         $this->assertEquals(new DateTime('2011-10-25', new DateTimeZone('UTC')), $it->until);
94
95         // Max is to prevent overflow
96         $max = 12;
97         $result = array();
98         foreach($it as $item) {
99
100             $result[] = $item;
101             $max--;
102
103             if (!$max) break;
104
105         }
106
107         $tz = new DateTimeZone('UTC');
108
109         $this->assertEquals(
110             array(
111                 new DateTime('2011-10-07', $tz),
112                 new DateTime('2011-10-10', $tz),
113                 new DateTime('2011-10-13', $tz),
114                 new DateTime('2011-10-16', $tz),
115                 new DateTime('2011-10-19', $tz),
116                 new DateTime('2011-10-22', $tz),
117                 new DateTime('2011-10-25', $tz),
118             ),
119             $result
120         );
121
122     }
123
124     /**
125      * @depends testValues
126      */
127     function testNoRRULE() {
128
129         $ev = new Component('VEVENT');
130         $ev->UID = 'bla';
131         $dtStart = new Property\DateTime('DTSTART');
132         $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
133
134         $ev->add($dtStart);
135
136         $vcal = Component::create('VCALENDAR');
137         $vcal->add($ev);
138
139         $it = new RecurrenceIterator($vcal,$ev->uid);
140
141         $this->assertEquals('daily', $it->frequency);
142         $this->assertEquals(1, $it->interval);
143
144         // Max is to prevent overflow
145         $max = 12;
146         $result = array();
147         foreach($it as $item) {
148
149             $result[] = $item;
150             $max--;
151
152             if (!$max) break;
153
154         }
155
156         $tz = new DateTimeZone('UTC');
157
158         $this->assertEquals(
159             array(
160                 new DateTime('2011-10-07', $tz),
161             ),
162             $result
163         );
164
165     }
166
167     /**
168      * @depends testValues
169      */
170     function testDailyByDay() {
171
172         $ev = new Component('VEVENT');
173         $ev->UID = 'bla';
174         $ev->RRULE = 'FREQ=DAILY;INTERVAL=2;BYDAY=TU,WE,FR';
175         $dtStart = new Property\DateTime('DTSTART');
176         $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
177
178         $ev->add($dtStart);
179
180         $vcal = Component::create('VCALENDAR');
181         $vcal->add($ev);
182
183         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
184
185         $this->assertEquals('daily', $it->frequency);
186         $this->assertEquals(2, $it->interval);
187         $this->assertEquals(array('TU','WE','FR'), $it->byDay);
188
189         // Grabbing the next 12 items
190         $max = 12;
191         $result = array();
192         foreach($it as $item) {
193
194             $result[] = $item;
195             $max--;
196
197             if (!$max) break;
198
199         }
200
201         $tz = new DateTimeZone('UTC');
202
203         $this->assertEquals(
204             array(
205                 new DateTime('2011-10-07', $tz),
206                 new DateTime('2011-10-11', $tz),
207                 new DateTime('2011-10-19', $tz),
208                 new DateTime('2011-10-21', $tz),
209                 new DateTime('2011-10-25', $tz),
210                 new DateTime('2011-11-02', $tz),
211                 new DateTime('2011-11-04', $tz),
212                 new DateTime('2011-11-08', $tz),
213                 new DateTime('2011-11-16', $tz),
214                 new DateTime('2011-11-18', $tz),
215                 new DateTime('2011-11-22', $tz),
216                 new DateTime('2011-11-30', $tz),
217             ),
218             $result
219         );
220
221     }
222
223     /**
224      * @depends testValues
225      */
226     function testWeekly() {
227
228         $ev = new Component('VEVENT');
229         $ev->UID = 'bla';
230         $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;COUNT=10';
231         $dtStart = new Property\DateTime('DTSTART');
232         $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
233
234         $ev->add($dtStart);
235
236         $vcal = Component::create('VCALENDAR');
237         $vcal->add($ev);
238
239         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
240
241         $this->assertEquals('weekly', $it->frequency);
242         $this->assertEquals(2, $it->interval);
243         $this->assertEquals(10, $it->count);
244
245         // Max is to prevent overflow
246         $max = 12;
247         $result = array();
248         foreach($it as $item) {
249
250             $result[] = $item;
251             $max--;
252
253             if (!$max) break;
254
255         }
256
257         $tz = new DateTimeZone('UTC');
258
259         $this->assertEquals(
260             array(
261                 new DateTime('2011-10-07', $tz),
262                 new DateTime('2011-10-21', $tz),
263                 new DateTime('2011-11-04', $tz),
264                 new DateTime('2011-11-18', $tz),
265                 new DateTime('2011-12-02', $tz),
266                 new DateTime('2011-12-16', $tz),
267                 new DateTime('2011-12-30', $tz),
268                 new DateTime('2012-01-13', $tz),
269                 new DateTime('2012-01-27', $tz),
270                 new DateTime('2012-02-10', $tz),
271             ),
272             $result
273         );
274
275     }
276
277     /**
278      * @depends testValues
279      */
280     function testWeeklyByDay() {
281
282         $ev = new Component('VEVENT');
283         $ev->UID = 'bla';
284         $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=SU';
285         $dtStart = new Property\DateTime('DTSTART');
286         $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
287
288         $ev->add($dtStart);
289
290         $vcal = Component::create('VCALENDAR');
291         $vcal->add($ev);
292
293         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
294
295         $this->assertEquals('weekly', $it->frequency);
296         $this->assertEquals(2, $it->interval);
297         $this->assertEquals(array('TU','WE','FR'), $it->byDay);
298         $this->assertEquals('SU', $it->weekStart);
299
300         // Grabbing the next 12 items
301         $max = 12;
302         $result = array();
303         foreach($it as $item) {
304
305             $result[] = $item;
306             $max--;
307
308             if (!$max) break;
309
310         }
311
312         $tz = new DateTimeZone('UTC');
313
314         $this->assertEquals(
315             array(
316                 new DateTime('2011-10-07', $tz),
317                 new DateTime('2011-10-18', $tz),
318                 new DateTime('2011-10-19', $tz),
319                 new DateTime('2011-10-21', $tz),
320                 new DateTime('2011-11-01', $tz),
321                 new DateTime('2011-11-02', $tz),
322                 new DateTime('2011-11-04', $tz),
323                 new DateTime('2011-11-15', $tz),
324                 new DateTime('2011-11-16', $tz),
325                 new DateTime('2011-11-18', $tz),
326                 new DateTime('2011-11-29', $tz),
327                 new DateTime('2011-11-30', $tz),
328             ),
329             $result
330         );
331
332     }
333
334     /**
335      * @depends testValues
336      */
337     function testMonthly() {
338
339         $ev = new Component('VEVENT');
340         $ev->UID = 'bla';
341         $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=3;COUNT=5';
342         $dtStart = new Property\DateTime('DTSTART');
343         $dtStart->setDateTime(new DateTime('2011-12-05', new DateTimeZone('UTC')),Property\DateTime::UTC);
344
345         $ev->add($dtStart);
346
347         $vcal = Component::create('VCALENDAR');
348         $vcal->add($ev);
349
350         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
351
352         $this->assertEquals('monthly', $it->frequency);
353         $this->assertEquals(3, $it->interval);
354         $this->assertEquals(5, $it->count);
355
356         $max = 14;
357         $result = array();
358         foreach($it as $item) {
359
360             $result[] = $item;
361             $max--;
362
363             if (!$max) break;
364
365         }
366
367         $tz = new DateTimeZone('UTC');
368
369         $this->assertEquals(
370             array(
371                 new DateTime('2011-12-05', $tz),
372                 new DateTime('2012-03-05', $tz),
373                 new DateTime('2012-06-05', $tz),
374                 new DateTime('2012-09-05', $tz),
375                 new DateTime('2012-12-05', $tz),
376             ),
377             $result
378         );
379
380
381     }
382
383     /**
384      * @depends testValues
385      */
386     function testMonthlyEndOfMonth() {
387
388         $ev = new Component('VEVENT');
389         $ev->UID = 'bla';
390         $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=2;COUNT=12';
391         $dtStart = new Property\DateTime('DTSTART');
392         $dtStart->setDateTime(new DateTime('2011-12-31', new DateTimeZone('UTC')),Property\DateTime::UTC);
393
394         $ev->add($dtStart);
395
396         $vcal = Component::create('VCALENDAR');
397         $vcal->add($ev);
398
399         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
400
401         $this->assertEquals('monthly', $it->frequency);
402         $this->assertEquals(2, $it->interval);
403         $this->assertEquals(12, $it->count);
404
405         $max = 14;
406         $result = array();
407         foreach($it as $item) {
408
409             $result[] = $item;
410             $max--;
411
412             if (!$max) break;
413
414         }
415
416         $tz = new DateTimeZone('UTC');
417
418         $this->assertEquals(
419             array(
420                 new DateTime('2011-12-31', $tz),
421                 new DateTime('2012-08-31', $tz),
422                 new DateTime('2012-10-31', $tz),
423                 new DateTime('2012-12-31', $tz),
424                 new DateTime('2013-08-31', $tz),
425                 new DateTime('2013-10-31', $tz),
426                 new DateTime('2013-12-31', $tz),
427                 new DateTime('2014-08-31', $tz),
428                 new DateTime('2014-10-31', $tz),
429                 new DateTime('2014-12-31', $tz),
430                 new DateTime('2015-08-31', $tz),
431                 new DateTime('2015-10-31', $tz),
432             ),
433             $result
434         );
435
436
437     }
438
439     /**
440      * @depends testValues
441      */
442     function testMonthlyByMonthDay() {
443
444         $ev = new Component('VEVENT');
445         $ev->UID = 'bla';
446         $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=5;COUNT=9;BYMONTHDAY=1,31,-7';
447         $dtStart = new Property\DateTime('DTSTART');
448         $dtStart->setDateTime(new DateTime('2011-01-01', new DateTimeZone('UTC')),Property\DateTime::UTC);
449
450         $ev->add($dtStart);
451
452         $vcal = Component::create('VCALENDAR');
453         $vcal->add($ev);
454
455         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
456
457         $this->assertEquals('monthly', $it->frequency);
458         $this->assertEquals(5, $it->interval);
459         $this->assertEquals(9, $it->count);
460         $this->assertEquals(array(1, 31, -7), $it->byMonthDay);
461
462         $max = 14;
463         $result = array();
464         foreach($it as $item) {
465
466             $result[] = $item;
467             $max--;
468
469             if (!$max) break;
470
471         }
472
473         $tz = new DateTimeZone('UTC');
474
475         $this->assertEquals(
476             array(
477                 new DateTime('2011-01-01', $tz),
478                 new DateTime('2011-01-25', $tz),
479                 new DateTime('2011-01-31', $tz),
480                 new DateTime('2011-06-01', $tz),
481                 new DateTime('2011-06-24', $tz),
482                 new DateTime('2011-11-01', $tz),
483                 new DateTime('2011-11-24', $tz),
484                 new DateTime('2012-04-01', $tz),
485                 new DateTime('2012-04-24', $tz),
486             ),
487             $result
488         );
489
490     }
491
492     /**
493      * @depends testValues
494      */
495     function testMonthlyByDay() {
496
497         $ev = new Component('VEVENT');
498         $ev->UID = 'bla';
499         $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=2;COUNT=16;BYDAY=MO,-2TU,+1WE,3TH';
500         $dtStart = new Property\DateTime('DTSTART');
501         $dtStart->setDateTime(new DateTime('2011-01-03', new DateTimeZone('UTC')),Property\DateTime::UTC);
502
503         $ev->add($dtStart);
504
505         $vcal = Component::create('VCALENDAR');
506         $vcal->add($ev);
507
508         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
509
510         $this->assertEquals('monthly', $it->frequency);
511         $this->assertEquals(2, $it->interval);
512         $this->assertEquals(16, $it->count);
513         $this->assertEquals(array('MO','-2TU','+1WE','3TH'), $it->byDay);
514
515         $max = 20;
516         $result = array();
517         foreach($it as $k=>$item) {
518
519             $result[] = $item;
520             $max--;
521
522             if (!$max) break;
523
524         }
525
526         $tz = new DateTimeZone('UTC');
527
528         $this->assertEquals(
529             array(
530                 new DateTime('2011-01-03', $tz),
531                 new DateTime('2011-01-05', $tz),
532                 new DateTime('2011-01-10', $tz),
533                 new DateTime('2011-01-17', $tz),
534                 new DateTime('2011-01-18', $tz),
535                 new DateTime('2011-01-20', $tz),
536                 new DateTime('2011-01-24', $tz),
537                 new DateTime('2011-01-31', $tz),
538                 new DateTime('2011-03-02', $tz),
539                 new DateTime('2011-03-07', $tz),
540                 new DateTime('2011-03-14', $tz),
541                 new DateTime('2011-03-17', $tz),
542                 new DateTime('2011-03-21', $tz),
543                 new DateTime('2011-03-22', $tz),
544                 new DateTime('2011-03-28', $tz),
545                 new DateTime('2011-05-02', $tz),
546             ),
547             $result
548         );
549
550     }
551
552     /**
553      * @depends testValues
554      */
555     function testMonthlyByDayByMonthDay() {
556
557         $ev = new Component('VEVENT');
558         $ev->UID = 'bla';
559         $ev->RRULE = 'FREQ=MONTHLY;COUNT=10;BYDAY=MO;BYMONTHDAY=1';
560         $dtStart = new Property\DateTime('DTSTART');
561         $dtStart->setDateTime(new DateTime('2011-08-01', new DateTimeZone('UTC')),Property\DateTime::UTC);
562
563         $ev->add($dtStart);
564
565         $vcal = Component::create('VCALENDAR');
566         $vcal->add($ev);
567
568         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
569
570         $this->assertEquals('monthly', $it->frequency);
571         $this->assertEquals(1, $it->interval);
572         $this->assertEquals(10, $it->count);
573         $this->assertEquals(array('MO'), $it->byDay);
574         $this->assertEquals(array(1), $it->byMonthDay);
575
576         $max = 20;
577         $result = array();
578         foreach($it as $k=>$item) {
579
580             $result[] = $item;
581             $max--;
582
583             if (!$max) break;
584
585         }
586
587         $tz = new DateTimeZone('UTC');
588
589         $this->assertEquals(
590             array(
591                 new DateTime('2011-08-01', $tz),
592                 new DateTime('2012-10-01', $tz),
593                 new DateTime('2013-04-01', $tz),
594                 new DateTime('2013-07-01', $tz),
595                 new DateTime('2014-09-01', $tz),
596                 new DateTime('2014-12-01', $tz),
597                 new DateTime('2015-06-01', $tz),
598                 new DateTime('2016-02-01', $tz),
599                 new DateTime('2016-08-01', $tz),
600                 new DateTime('2017-05-01', $tz),
601             ),
602             $result
603         );
604
605     }
606
607     /**
608      * @depends testValues
609      */
610     function testMonthlyByDayBySetPos() {
611
612         $ev = new Component('VEVENT');
613         $ev->UID = 'bla';
614         $ev->RRULE = 'FREQ=MONTHLY;COUNT=10;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1,-1';
615         $dtStart = new Property\DateTime('DTSTART');
616         $dtStart->setDateTime(new DateTime('2011-01-03', new DateTimeZone('UTC')),Property\DateTime::UTC);
617
618         $ev->add($dtStart);
619
620         $vcal = Component::create('VCALENDAR');
621         $vcal->add($ev);
622
623         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
624
625         $this->assertEquals('monthly', $it->frequency);
626         $this->assertEquals(1, $it->interval);
627         $this->assertEquals(10, $it->count);
628         $this->assertEquals(array('MO','TU','WE','TH','FR'), $it->byDay);
629         $this->assertEquals(array(1,-1), $it->bySetPos);
630
631         $max = 20;
632         $result = array();
633         foreach($it as $k=>$item) {
634
635             $result[] = $item;
636             $max--;
637
638             if (!$max) break;
639
640         }
641
642         $tz = new DateTimeZone('UTC');
643
644         $this->assertEquals(
645             array(
646                 new DateTime('2011-01-03', $tz),
647                 new DateTime('2011-01-31', $tz),
648                 new DateTime('2011-02-01', $tz),
649                 new DateTime('2011-02-28', $tz),
650                 new DateTime('2011-03-01', $tz),
651                 new DateTime('2011-03-31', $tz),
652                 new DateTime('2011-04-01', $tz),
653                 new DateTime('2011-04-29', $tz),
654                 new DateTime('2011-05-02', $tz),
655                 new DateTime('2011-05-31', $tz),
656             ),
657             $result
658         );
659
660     }
661
662     /**
663      * @depends testValues
664      */
665     function testYearly() {
666
667         $ev = new Component('VEVENT');
668         $ev->UID = 'bla';
669         $ev->RRULE = 'FREQ=YEARLY;COUNT=10;INTERVAL=3';
670         $dtStart = new Property\DateTime('DTSTART');
671         $dtStart->setDateTime(new DateTime('2011-01-01', new DateTimeZone('UTC')),Property\DateTime::UTC);
672
673         $ev->add($dtStart);
674
675         $vcal = Component::create('VCALENDAR');
676         $vcal->add($ev);
677
678         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
679
680         $this->assertEquals('yearly', $it->frequency);
681         $this->assertEquals(3, $it->interval);
682         $this->assertEquals(10, $it->count);
683
684         $max = 20;
685         $result = array();
686         foreach($it as $k=>$item) {
687
688             $result[] = $item;
689             $max--;
690
691             if (!$max) break;
692
693         }
694
695         $tz = new DateTimeZone('UTC');
696
697         $this->assertEquals(
698             array(
699                 new DateTime('2011-01-01', $tz),
700                 new DateTime('2014-01-01', $tz),
701                 new DateTime('2017-01-01', $tz),
702                 new DateTime('2020-01-01', $tz),
703                 new DateTime('2023-01-01', $tz),
704                 new DateTime('2026-01-01', $tz),
705                 new DateTime('2029-01-01', $tz),
706                 new DateTime('2032-01-01', $tz),
707                 new DateTime('2035-01-01', $tz),
708                 new DateTime('2038-01-01', $tz),
709             ),
710             $result
711         );
712
713     }
714
715     /**
716      * @depends testValues
717      */
718     function testYearlyLeapYear() {
719
720         $ev = new Component('VEVENT');
721         $ev->UID = 'bla';
722         $ev->RRULE = 'FREQ=YEARLY;COUNT=3';
723         $dtStart = new Property\DateTime('DTSTART');
724         $dtStart->setDateTime(new DateTime('2012-02-29', new DateTimeZone('UTC')),Property\DateTime::UTC);
725
726         $ev->add($dtStart);
727
728         $vcal = Component::create('VCALENDAR');
729         $vcal->add($ev);
730
731         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
732
733         $this->assertEquals('yearly', $it->frequency);
734         $this->assertEquals(3, $it->count);
735
736         $max = 20;
737         $result = array();
738         foreach($it as $k=>$item) {
739
740             $result[] = $item;
741             $max--;
742
743             if (!$max) break;
744
745         }
746
747         $tz = new DateTimeZone('UTC');
748
749         $this->assertEquals(
750             array(
751                 new DateTime('2012-02-29', $tz),
752                 new DateTime('2016-02-29', $tz),
753                 new DateTime('2020-02-29', $tz),
754             ),
755             $result
756         );
757
758     }
759
760     /**
761      * @depends testValues
762      */
763     function testYearlyByMonth() {
764
765         $ev = new Component('VEVENT');
766         $ev->UID = 'bla';
767         $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=4;BYMONTH=4,10';
768         $dtStart = new Property\DateTime('DTSTART');
769         $dtStart->setDateTime(new DateTime('2011-04-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
770
771         $ev->add($dtStart);
772
773         $vcal = Component::create('VCALENDAR');
774         $vcal->add($ev);
775
776         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
777
778         $this->assertEquals('yearly', $it->frequency);
779         $this->assertEquals(4, $it->interval);
780         $this->assertEquals(8, $it->count);
781         $this->assertEquals(array(4,10), $it->byMonth);
782
783         $max = 20;
784         $result = array();
785         foreach($it as $k=>$item) {
786
787             $result[] = $item;
788             $max--;
789
790             if (!$max) break;
791
792         }
793
794         $tz = new DateTimeZone('UTC');
795
796         $this->assertEquals(
797             array(
798                 new DateTime('2011-04-07', $tz),
799                 new DateTime('2011-10-07', $tz),
800                 new DateTime('2015-04-07', $tz),
801                 new DateTime('2015-10-07', $tz),
802                 new DateTime('2019-04-07', $tz),
803                 new DateTime('2019-10-07', $tz),
804                 new DateTime('2023-04-07', $tz),
805                 new DateTime('2023-10-07', $tz),
806             ),
807             $result
808         );
809
810     }
811
812     /**
813      * @depends testValues
814      */
815     function testYearlyByMonthByDay() {
816
817         $ev = new Component('VEVENT');
818         $ev->UID = 'bla';
819         $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=5;BYMONTH=4,10;BYDAY=1MO,-1SU';
820         $dtStart = new Property\DateTime('DTSTART');
821         $dtStart->setDateTime(new DateTime('2011-04-04', new DateTimeZone('UTC')),Property\DateTime::UTC);
822
823         $ev->add($dtStart);
824
825         $vcal = Component::create('VCALENDAR');
826         $vcal->add($ev);
827
828         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
829
830         $this->assertEquals('yearly', $it->frequency);
831         $this->assertEquals(5, $it->interval);
832         $this->assertEquals(8, $it->count);
833         $this->assertEquals(array(4,10), $it->byMonth);
834         $this->assertEquals(array('1MO','-1SU'), $it->byDay);
835
836         $max = 20;
837         $result = array();
838         foreach($it as $k=>$item) {
839
840             $result[] = $item;
841             $max--;
842
843             if (!$max) break;
844
845         }
846
847         $tz = new DateTimeZone('UTC');
848
849         $this->assertEquals(
850             array(
851                 new DateTime('2011-04-04', $tz),
852                 new DateTime('2011-04-24', $tz),
853                 new DateTime('2011-10-03', $tz),
854                 new DateTime('2011-10-30', $tz),
855                 new DateTime('2016-04-04', $tz),
856                 new DateTime('2016-04-24', $tz),
857                 new DateTime('2016-10-03', $tz),
858                 new DateTime('2016-10-30', $tz),
859             ),
860             $result
861         );
862
863     }
864
865     /**
866      * @depends testValues
867      */
868     function testFastForward() {
869
870         $ev = new Component('VEVENT');
871         $ev->UID = 'bla';
872         $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=5;BYMONTH=4,10;BYDAY=1MO,-1SU';
873         $dtStart = new Property\DateTime('DTSTART');
874         $dtStart->setDateTime(new DateTime('2011-04-04', new DateTimeZone('UTC')),Property\DateTime::UTC);
875
876         $ev->add($dtStart);
877
878         $vcal = Component::create('VCALENDAR');
879         $vcal->add($ev);
880
881         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
882
883         // The idea is that we're fast-forwarding too far in the future, so
884         // there will be no results left.
885         $it->fastForward(new DateTime('2020-05-05', new DateTimeZone('UTC')));
886
887         $max = 20;
888         $result = array();
889         while($item = $it->current()) {
890
891             $result[] = $item;
892             $max--;
893
894             if (!$max) break;
895             $it->next();
896
897         }
898
899         $tz = new DateTimeZone('UTC');
900         $this->assertEquals(array(), $result);
901
902     }
903
904     /**
905      * @depends testValues
906      */
907     function testComplexExclusions() {
908
909         $ev = new Component('VEVENT');
910         $ev->UID = 'bla';
911         $ev->RRULE = 'FREQ=YEARLY;COUNT=10';
912         $dtStart = new Property\DateTime('DTSTART');
913
914         $tz = new DateTimeZone('Canada/Eastern');
915         $dtStart->setDateTime(new DateTime('2011-01-01 13:50:20', $tz),Property\DateTime::LOCALTZ);
916
917         $exDate1 = new Property\MultiDateTime('EXDATE');
918         $exDate1->setDateTimes(array(new DateTime('2012-01-01 13:50:20', $tz), new DateTime('2014-01-01 13:50:20', $tz)), Property\DateTime::LOCALTZ);
919         $exDate2 = new Property\MultiDateTime('EXDATE');
920         $exDate2->setDateTimes(array(new DateTime('2016-01-01 13:50:20', $tz)), Property\DateTime::LOCALTZ);
921
922         $ev->add($dtStart);
923         $ev->add($exDate1);
924         $ev->add($exDate2);
925
926         $vcal = Component::create('VCALENDAR');
927         $vcal->add($ev);
928
929         $it = new RecurrenceIterator($vcal,(string)$ev->uid);
930
931         $this->assertEquals('yearly', $it->frequency);
932         $this->assertEquals(1, $it->interval);
933         $this->assertEquals(10, $it->count);
934
935         $max = 20;
936         $result = array();
937         foreach($it as $k=>$item) {
938
939             $result[] = $item;
940             $max--;
941
942             if (!$max) break;
943
944         }
945
946         $this->assertEquals(
947             array(
948                 new DateTime('2011-01-01 13:50:20', $tz),
949                 new DateTime('2013-01-01 13:50:20', $tz),
950                 new DateTime('2015-01-01 13:50:20', $tz),
951                 new DateTime('2017-01-01 13:50:20', $tz),
952                 new DateTime('2018-01-01 13:50:20', $tz),
953                 new DateTime('2019-01-01 13:50:20', $tz),
954                 new DateTime('2020-01-01 13:50:20', $tz),
955             ),
956             $result
957         );
958
959     }
960
961     /**
962      * @depends testValues
963      */
964     function testOverridenEvent() {
965
966         $vcal = Component::create('VCALENDAR');
967
968         $ev1 = Component::create('VEVENT');
969         $ev1->UID = 'overridden';
970         $ev1->RRULE = 'FREQ=DAILY;COUNT=10';
971         $ev1->DTSTART = '20120107T120000Z';
972         $ev1->SUMMARY = 'baseEvent';
973
974         $vcal->add($ev1);
975
976         // ev2 overrides an event, and puts it on 2pm instead.
977         $ev2 = Component::create('VEVENT');
978         $ev2->UID = 'overridden';
979         $ev2->{'RECURRENCE-ID'} = '20120110T120000Z';
980         $ev2->DTSTART = '20120110T140000Z';
981         $ev2->SUMMARY = 'Event 2';
982
983         $vcal->add($ev2);
984
985         // ev3 overrides an event, and puts it 2 days and 2 hours later 
986         $ev3 = Component::create('VEVENT');
987         $ev3->UID = 'overridden';
988         $ev3->{'RECURRENCE-ID'} = '20120113T120000Z';
989         $ev3->DTSTART = '20120115T140000Z';
990         $ev3->SUMMARY = 'Event 3';
991
992         $vcal->add($ev3);
993
994         $it = new RecurrenceIterator($vcal,'overridden');
995
996         $dates = array();
997         $summaries = array();
998         while($it->valid()) {
999
1000             $dates[] = $it->getDTStart();
1001             $summaries[] = (string)$it->getEventObject()->SUMMARY;
1002             $it->next();
1003
1004         }
1005
1006         $tz = new DateTimeZone('GMT');
1007         $this->assertEquals(array(
1008             new DateTime('2012-01-07 12:00:00',$tz),
1009             new DateTime('2012-01-08 12:00:00',$tz),
1010             new DateTime('2012-01-09 12:00:00',$tz),
1011             new DateTime('2012-01-10 14:00:00',$tz),
1012             new DateTime('2012-01-11 12:00:00',$tz),
1013             new DateTime('2012-01-12 12:00:00',$tz),
1014             new DateTime('2012-01-14 12:00:00',$tz),
1015             new DateTime('2012-01-15 12:00:00',$tz),
1016             new DateTime('2012-01-15 14:00:00',$tz),
1017             new DateTime('2012-01-16 12:00:00',$tz),
1018         ), $dates);
1019
1020         $this->assertEquals(array(
1021             'baseEvent',
1022             'baseEvent',
1023             'baseEvent',
1024             'Event 2',
1025             'baseEvent',
1026             'baseEvent',
1027             'baseEvent',
1028             'baseEvent',
1029             'Event 3',
1030             'baseEvent',
1031         ), $summaries);
1032
1033     }
1034
1035     /**
1036      * @depends testValues
1037      */
1038     function testOverridenEvent2() {
1039
1040         $vcal = Component::create('VCALENDAR');
1041
1042         $ev1 = Component::create('VEVENT');
1043         $ev1->UID = 'overridden';
1044         $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3';
1045         $ev1->DTSTART = '20120112T120000Z';
1046         $ev1->SUMMARY = 'baseEvent';
1047
1048         $vcal->add($ev1);
1049
1050         // ev2 overrides an event, and puts it 6 days earlier instead.
1051         $ev2 = Component::create('VEVENT');
1052         $ev2->UID = 'overridden';
1053         $ev2->{'RECURRENCE-ID'} = '20120119T120000Z';
1054         $ev2->DTSTART = '20120113T120000Z';
1055         $ev2->SUMMARY = 'Override!';
1056
1057         $vcal->add($ev2);
1058
1059         $it = new RecurrenceIterator($vcal,'overridden');
1060
1061         $dates = array();
1062         $summaries = array();
1063         while($it->valid()) {
1064
1065             $dates[] = $it->getDTStart();
1066             $summaries[] = (string)$it->getEventObject()->SUMMARY;
1067             $it->next();
1068
1069         }
1070
1071         $tz = new DateTimeZone('GMT');
1072         $this->assertEquals(array(
1073             new DateTime('2012-01-12 12:00:00',$tz),
1074             new DateTime('2012-01-13 12:00:00',$tz),
1075             new DateTime('2012-01-26 12:00:00',$tz),
1076
1077         ), $dates);
1078
1079         $this->assertEquals(array(
1080             'baseEvent',
1081             'Override!',
1082             'baseEvent',
1083         ), $summaries);
1084
1085     }
1086
1087     /**
1088      * @depends testValues
1089      */
1090     function testOverridenEventNoValuesExpected() {
1091
1092         $vcal = Component::create('VCALENDAR');
1093
1094         $ev1 = Component::create('VEVENT');
1095         $ev1->UID = 'overridden';
1096         $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3';
1097         $ev1->DTSTART = '20120124T120000Z';
1098         $ev1->SUMMARY = 'baseEvent';
1099
1100         $vcal->add($ev1);
1101
1102         // ev2 overrides an event, and puts it 6 days earlier instead.
1103         $ev2 = Component::create('VEVENT');
1104         $ev2->UID = 'overridden';
1105         $ev2->{'RECURRENCE-ID'} = '20120131T120000Z';
1106         $ev2->DTSTART = '20120125T120000Z';
1107         $ev2->SUMMARY = 'Override!';
1108
1109         $vcal->add($ev2);
1110
1111         $it = new RecurrenceIterator($vcal,'overridden');
1112
1113         $dates = array();
1114         $summaries = array();
1115
1116         // The reported problem was specifically related to the VCALENDAR 
1117         // expansion. In this parcitular case, we had to forward to the 28th of 
1118         // january.
1119         $it->fastForward(new DateTime('2012-01-28 23:00:00'));
1120
1121         // We stop the loop when it hits the 6th of februari. Normally this 
1122         // iterator would hit 24, 25 (overriden from 31) and 7 feb but because 
1123         // we 'filter' from the 28th till the 6th, we should get 0 results.
1124         while($it->valid() && $it->getDTSTart() < new DateTime('2012-02-06 23:00:00')) {
1125
1126             $dates[] = $it->getDTStart();
1127             $summaries[] = (string)$it->getEventObject()->SUMMARY;
1128             $it->next();
1129
1130         }
1131
1132         $this->assertEquals(array(), $dates);
1133         $this->assertEquals(array(), $summaries);
1134
1135     }
1136 }
1137