aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/vobject/tests/Sabre/VObject
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sabre/vobject/tests/Sabre/VObject')
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VAlarmTest.php175
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VCalendarTest.php244
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VCardTest.php100
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VEventTest.php74
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VFreeBusyTest.php39
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VJournalTest.php41
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Component/VTodoTest.php67
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/ComponentTest.php413
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/DateTimeParserTest.php153
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/DocumentTest.php26
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/ElementListTest.php32
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/EmClientTest.php55
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/FreeBusyGeneratorTest.php246
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Issue153Test.php14
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Issue154Test.php29
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Issue48Test.php47
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Issue50Test.php128
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/ParameterTest.php44
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Property/CompoundTest.php59
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Property/DateTimeTest.php240
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Property/MultiDateTimeTest.php208
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/PropertyTest.php324
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/ReaderTest.php367
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorFifthTuesdayProblemTest.php44
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorIncorrectExpandTest.php62
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorInfiniteLoopProblemTest.php91
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMinusOneProblemTest.php30
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMissingOverriddenTest.php63
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorTest.php1425
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/SlashRTest.php19
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Splitter/ICalendarTest.php283
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/Splitter/VCardTest.php138
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/StringUtilTest.php59
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/TimeZoneUtilTest.php297
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/VersionTest.php17
-rw-r--r--vendor/sabre/vobject/tests/Sabre/VObject/issue153.vcf352
36 files changed, 6005 insertions, 0 deletions
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VAlarmTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VAlarmTest.php
new file mode 100644
index 000000000..d57be7aa5
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VAlarmTest.php
@@ -0,0 +1,175 @@
+<?php
+
+namespace Sabre\VObject\Component;
+
+use Sabre\VObject\Component;
+use DateTime;
+use Sabre\VObject\Reader;
+
+class VAlarmTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider timeRangeTestData
+ */
+ public function testInTimeRange(VAlarm $valarm,$start,$end,$outcome) {
+
+ $this->assertEquals($outcome, $valarm->isInTimeRange($start, $end));
+
+ }
+
+ public function timeRangeTestData() {
+
+ $tests = array();
+
+ // Hard date and time
+ $valarm1 = Component::create('VALARM');
+ $valarm1->TRIGGER = '20120312T130000Z';
+ $valarm1->TRIGGER['VALUE'] = 'DATE-TIME';
+
+ $tests[] = array($valarm1, new DateTime('2012-03-01 01:00:00'), new DateTime('2012-04-01 01:00:00'), true);
+ $tests[] = array($valarm1, new DateTime('2012-03-01 01:00:00'), new DateTime('2012-03-10 01:00:00'), false);
+
+ // Relation to start time of event
+ $valarm2 = Component::create('VALARM');
+ $valarm2->TRIGGER = '-P1D';
+ $valarm2->TRIGGER['VALUE'] = 'DURATION';
+
+ $vevent2 = Component::create('VEVENT');
+ $vevent2->DTSTART = '20120313T130000Z';
+ $vevent2->add($valarm2);
+
+ $tests[] = array($valarm2, new DateTime('2012-03-01 01:00:00'), new DateTime('2012-04-01 01:00:00'), true);
+ $tests[] = array($valarm2, new DateTime('2012-03-01 01:00:00'), new DateTime('2012-03-10 01:00:00'), false);
+
+ // Relation to end time of event
+ $valarm3 = Component::create('VALARM');
+ $valarm3->TRIGGER = '-P1D';
+ $valarm3->TRIGGER['VALUE'] = 'DURATION';
+ $valarm3->TRIGGER['RELATED']= 'END';
+
+ $vevent3 = Component::create('VEVENT');
+ $vevent3->DTSTART = '20120301T130000Z';
+ $vevent3->DTEND = '20120401T130000Z';
+ $vevent3->add($valarm3);
+
+ $tests[] = array($valarm3, new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'), false);
+ $tests[] = array($valarm3, new DateTime('2012-03-25 01:00:00'), new DateTime('2012-04-05 01:00:00'), true);
+
+ // Relation to end time of todo
+ $valarm4 = Component::create('VALARM');
+ $valarm4->TRIGGER = '-P1D';
+ $valarm4->TRIGGER['VALUE'] = 'DURATION';
+ $valarm4->TRIGGER['RELATED']= 'END';
+
+ $vtodo4 = Component::create('VTODO');
+ $vtodo4->DTSTART = '20120301T130000Z';
+ $vtodo4->DUE = '20120401T130000Z';
+ $vtodo4->add($valarm4);
+
+ $tests[] = array($valarm4, new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'), false);
+ $tests[] = array($valarm4, new DateTime('2012-03-25 01:00:00'), new DateTime('2012-04-05 01:00:00'), true);
+
+ // Relation to start time of event + repeat
+ $valarm5 = Component::create('VALARM');
+ $valarm5->TRIGGER = '-P1D';
+ $valarm5->TRIGGER['VALUE'] = 'DURATION';
+ $valarm5->REPEAT = 10;
+ $valarm5->DURATION = 'P1D';
+
+ $vevent5 = Component::create('VEVENT');
+ $vevent5->DTSTART = '20120301T130000Z';
+ $vevent5->add($valarm5);
+
+ $tests[] = array($valarm5, new DateTime('2012-03-09 01:00:00'), new DateTime('2012-03-10 01:00:00'), true);
+
+ // Relation to start time of event + duration, but no repeat
+ $valarm6 = Component::create('VALARM');
+ $valarm6->TRIGGER = '-P1D';
+ $valarm6->TRIGGER['VALUE'] = 'DURATION';
+ $valarm6->DURATION = 'P1D';
+
+ $vevent6 = Component::create('VEVENT');
+ $vevent6->DTSTART = '20120313T130000Z';
+ $vevent6->add($valarm6);
+
+ $tests[] = array($valarm6, new DateTime('2012-03-01 01:00:00'), new DateTime('2012-04-01 01:00:00'), true);
+ $tests[] = array($valarm6, new DateTime('2012-03-01 01:00:00'), new DateTime('2012-03-10 01:00:00'), false);
+
+
+ // Relation to end time of event (DURATION instead of DTEND)
+ $valarm7 = Component::create('VALARM');
+ $valarm7->TRIGGER = '-P1D';
+ $valarm7->TRIGGER['VALUE'] = 'DURATION';
+ $valarm7->TRIGGER['RELATED']= 'END';
+
+ $vevent7 = Component::create('VEVENT');
+ $vevent7->DTSTART = '20120301T130000Z';
+ $vevent7->DURATION = 'P30D';
+ $vevent7->add($valarm7);
+
+ $tests[] = array($valarm7, new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'), false);
+ $tests[] = array($valarm7, new DateTime('2012-03-25 01:00:00'), new DateTime('2012-04-05 01:00:00'), true);
+
+ // Relation to end time of event (No DTEND or DURATION)
+ $valarm7 = Component::create('VALARM');
+ $valarm7->TRIGGER = '-P1D';
+ $valarm7->TRIGGER['VALUE'] = 'DURATION';
+ $valarm7->TRIGGER['RELATED']= 'END';
+
+ $vevent7 = Component::create('VEVENT');
+ $vevent7->DTSTART = '20120301T130000Z';
+ $vevent7->add($valarm7);
+
+ $tests[] = array($valarm7, new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'), true);
+ $tests[] = array($valarm7, new DateTime('2012-03-25 01:00:00'), new DateTime('2012-04-05 01:00:00'), false);
+
+
+ return $tests;
+ }
+
+ /**
+ * @expectedException LogicException
+ */
+ public function testInTimeRangeInvalidComponent() {
+
+ $valarm = Component::create('VALARM');
+ $valarm->TRIGGER = '-P1D';
+ $valarm->TRIGGER['RELATED'] = 'END';
+
+ $vjournal = Component::create('VJOURNAL');
+ $vjournal->add($valarm);
+
+ $valarm->isInTimeRange(new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'));
+
+ }
+
+ /**
+ * This bug was found and reported on the mailing list.
+ */
+ public function testInTimeRangeBuggy() {
+
+$input = <<<BLA
+BEGIN:VCALENDAR
+BEGIN:VTODO
+DTSTAMP:20121003T064931Z
+UID:b848cb9a7bb16e464a06c222ca1f8102@examle.com
+STATUS:NEEDS-ACTION
+DUE:20121005T000000Z
+SUMMARY:Task 1
+CATEGORIES:AlarmCategory
+BEGIN:VALARM
+TRIGGER:-PT10M
+ACTION:DISPLAY
+DESCRIPTION:Task 1
+END:VALARM
+END:VTODO
+END:VCALENDAR
+BLA;
+
+ $vobj = Reader::read($input);
+
+ $this->assertTrue($vobj->VTODO->VALARM->isInTimeRange(new \DateTime('2012-10-01 00:00:00'), new \DateTime('2012-11-01 00:00:00')));
+
+ }
+}
+
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VCalendarTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VCalendarTest.php
new file mode 100644
index 000000000..1d7e0c603
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VCalendarTest.php
@@ -0,0 +1,244 @@
+<?php
+
+namespace Sabre\VObject\Component;
+
+use Sabre\VObject;
+
+class VCalendarTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider expandData
+ */
+ public function testExpand($input, $output) {
+
+ $vcal = VObject\Reader::read($input);
+ $vcal->expand(
+ new \DateTime('2011-12-01'),
+ new \DateTime('2011-12-31')
+ );
+
+ // This will normalize the output
+ $output = VObject\Reader::read($output)->serialize();
+
+ $this->assertEquals($output, $vcal->serialize());
+
+ }
+
+ public function expandData() {
+
+ $tests = array();
+
+ // No data
+ $input = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+END:VCALENDAR
+';
+
+ $output = $input;
+ $tests[] = array($input,$output);
+
+
+ // Simple events
+ $input = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla
+SUMMARY:InExpand
+DTSTART;VALUE=DATE:20111202
+END:VEVENT
+BEGIN:VEVENT
+UID:bla2
+SUMMARY:NotInExpand
+DTSTART;VALUE=DATE:20120101
+END:VEVENT
+END:VCALENDAR
+';
+
+ $output = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla
+SUMMARY:InExpand
+DTSTART;VALUE=DATE:20111202
+END:VEVENT
+END:VCALENDAR
+';
+
+ $tests[] = array($input, $output);
+
+ // Removing timezone info
+ $input = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Europe/Paris
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:bla4
+SUMMARY:RemoveTZ info
+DTSTART;TZID=Europe/Paris:20111203T130102
+END:VEVENT
+END:VCALENDAR
+';
+
+ $output = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla4
+SUMMARY:RemoveTZ info
+DTSTART;VALUE=DATE-TIME:20111203T120102Z
+END:VEVENT
+END:VCALENDAR
+';
+
+ $tests[] = array($input, $output);
+
+ // Recurrence rule
+ $input = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule
+DTSTART:20111125T120000Z
+DTEND:20111125T130000Z
+RRULE:FREQ=WEEKLY
+END:VEVENT
+END:VCALENDAR
+';
+
+ $output = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule
+DTSTART;VALUE=DATE-TIME:20111202T120000Z
+DTEND;VALUE=DATE-TIME:20111202T130000Z
+RECURRENCE-ID:20111202T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule
+DTSTART;VALUE=DATE-TIME:20111209T120000Z
+DTEND;VALUE=DATE-TIME:20111209T130000Z
+RECURRENCE-ID:20111209T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule
+DTSTART;VALUE=DATE-TIME:20111216T120000Z
+DTEND;VALUE=DATE-TIME:20111216T130000Z
+RECURRENCE-ID:20111216T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule
+DTSTART;VALUE=DATE-TIME:20111223T120000Z
+DTEND;VALUE=DATE-TIME:20111223T130000Z
+RECURRENCE-ID:20111223T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule
+DTSTART;VALUE=DATE-TIME:20111230T120000Z
+DTEND;VALUE=DATE-TIME:20111230T130000Z
+RECURRENCE-ID:20111230T120000Z
+END:VEVENT
+END:VCALENDAR
+';
+
+ // Recurrence rule + override
+ $input = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule2
+DTSTART:20111125T120000Z
+DTEND:20111125T130000Z
+RRULE:FREQ=WEEKLY
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+RECURRENCE-ID:20111209T120000Z
+DTSTART:20111209T140000Z
+DTEND:20111209T150000Z
+SUMMARY:Override!
+END:VEVENT
+END:VCALENDAR
+';
+
+ $output = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule2
+DTSTART;VALUE=DATE-TIME:20111202T120000Z
+DTEND;VALUE=DATE-TIME:20111202T130000Z
+RECURRENCE-ID:20111202T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+RECURRENCE-ID:20111209T120000Z
+DTSTART:20111209T140000Z
+DTEND:20111209T150000Z
+SUMMARY:Override!
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule2
+DTSTART;VALUE=DATE-TIME:20111216T120000Z
+DTEND;VALUE=DATE-TIME:20111216T130000Z
+RECURRENCE-ID:20111216T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule2
+DTSTART;VALUE=DATE-TIME:20111223T120000Z
+DTEND;VALUE=DATE-TIME:20111223T130000Z
+RECURRENCE-ID:20111223T120000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:bla6
+SUMMARY:Testing RRule2
+DTSTART;VALUE=DATE-TIME:20111230T120000Z
+DTEND;VALUE=DATE-TIME:20111230T130000Z
+RECURRENCE-ID:20111230T120000Z
+END:VEVENT
+END:VCALENDAR
+';
+
+ $tests[] = array($input, $output);
+ return $tests;
+
+ }
+
+ /**
+ * @expectedException LogicException
+ */
+ public function testBrokenEventExpand() {
+
+ $input = 'BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+BEGIN:VEVENT
+RRULE:FREQ=WEEKLY
+DTSTART;VALUE=DATE:20111202
+END:VEVENT
+END:VCALENDAR
+';
+ $vcal = VObject\Reader::read($input);
+ $vcal->expand(
+ new \DateTime('2011-12-01'),
+ new \DateTime('2011-12-31')
+ );
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VCardTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VCardTest.php
new file mode 100644
index 000000000..584a007d9
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VCardTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Sabre\VObject\Component;
+
+use Sabre\VObject;
+
+class VCardTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider validateData
+ */
+ function testValidate($input, $expectedWarnings, $expectedRepairedOutput) {
+
+ $vcard = VObject\Reader::read($input);
+
+ $warnings = $vcard->validate();
+
+ $warnMsg = array();
+ foreach($warnings as $warning) {
+ $warnMsg[] = $warning['message'];
+ }
+
+ $this->assertEquals($expectedWarnings, $warnMsg);
+
+ $vcard->validate(VObject\Component::REPAIR);
+
+ $this->assertEquals(
+ $expectedRepairedOutput,
+ $vcard->serialize()
+ );
+
+ }
+
+ public function validateData() {
+
+ $tests = array();
+
+ // Correct
+ $tests[] = array(
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ array(),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ );
+
+ // No VERSION
+ $tests[] = array(
+ "BEGIN:VCARD\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ array(
+ 'The VERSION property must appear in the VCARD component exactly 1 time',
+ ),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ );
+
+ // Unknown version
+ $tests[] = array(
+ "BEGIN:VCARD\r\nVERSION:2.2\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ array(
+ 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.',
+ ),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ );
+
+ // No FN
+ $tests[] = array(
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nEND:VCARD\r\n",
+ array(
+ 'The FN property must appear in the VCARD component exactly 1 time',
+ ),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nEND:VCARD\r\n",
+ );
+ // No FN, N fallback
+ $tests[] = array(
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nN:Doe;John;;;;;\r\nEND:VCARD\r\n",
+ array(
+ 'The FN property must appear in the VCARD component exactly 1 time',
+ ),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nN:Doe;John;;;;;\r\nFN:John Doe\r\nEND:VCARD\r\n",
+ );
+ // No FN, N fallback, no first name
+ $tests[] = array(
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nN:Doe;;;;;;\r\nEND:VCARD\r\n",
+ array(
+ 'The FN property must appear in the VCARD component exactly 1 time',
+ ),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nN:Doe;;;;;;\r\nFN:Doe\r\nEND:VCARD\r\n",
+ );
+
+ // No FN, ORG fallback
+ $tests[] = array(
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nORG:Acme Co.\r\nEND:VCARD\r\n",
+ array(
+ 'The FN property must appear in the VCARD component exactly 1 time',
+ ),
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nORG:Acme Co.\r\nFN:Acme Co.\r\nEND:VCARD\r\n",
+ );
+ return $tests;
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VEventTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VEventTest.php
new file mode 100644
index 000000000..616da4ac7
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VEventTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Sabre\VObject\Component;
+
+use Sabre\VObject;
+
+class VEventTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider timeRangeTestData
+ */
+ public function testInTimeRange(VEvent $vevent,$start,$end,$outcome) {
+
+ $this->assertEquals($outcome, $vevent->isInTimeRange($start, $end));
+
+ }
+
+ public function timeRangeTestData() {
+
+ $tests = array();
+
+ $vevent = new VEvent('VEVENT');
+ $vevent->DTSTART = '20111223T120000Z';
+ $tests[] = array($vevent, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vevent, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vevent2 = clone $vevent;
+ $vevent2->DTEND = '20111225T120000Z';
+ $tests[] = array($vevent2, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vevent2, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vevent3 = clone $vevent;
+ $vevent3->DURATION = 'P1D';
+ $tests[] = array($vevent3, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vevent3, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vevent4 = clone $vevent;
+ $vevent4->DTSTART = '20111225';
+ $vevent4->DTSTART['VALUE'] = 'DATE';
+ $tests[] = array($vevent4, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vevent4, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+ // Event with no end date should be treated as lasting the entire day.
+ $tests[] = array($vevent4, new \DateTime('2011-12-25 16:00:00'), new \DateTime('2011-12-25 17:00:00'), true);
+
+
+ $vevent5 = clone $vevent;
+ $vevent5->DURATION = 'P1D';
+ $vevent5->RRULE = 'FREQ=YEARLY';
+ $tests[] = array($vevent5, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vevent5, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+ $tests[] = array($vevent5, new \DateTime('2013-12-01'), new \DateTime('2013-12-31'), true);
+
+ $vevent6 = clone $vevent;
+ $vevent6->DTSTART = '20111225';
+ $vevent6->DTSTART['VALUE'] = 'DATE';
+ $vevent6->DTEND = '20111225';
+ $vevent6->DTEND['VALUE'] = 'DATE';
+
+ $tests[] = array($vevent6, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vevent6, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ // Added this test to ensure that recurrence rules with no DTEND also
+ // get checked for the entire day.
+ $vevent7 = clone $vevent;
+ $vevent7->DTSTART = '20120101';
+ $vevent7->DTSTART['VALUE'] = 'DATE';
+ $vevent7->RRULE = 'FREQ=MONTHLY';
+ $tests[] = array($vevent7, new \DateTime('2012-02-01 15:00:00'), new \DateTime('2012-02-02'), true);
+ return $tests;
+
+ }
+
+}
+
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VFreeBusyTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VFreeBusyTest.php
new file mode 100644
index 000000000..031c3c684
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VFreeBusyTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Sabre\VObject\Component;
+use Sabre\VObject;
+
+class VFreeBusyTest extends \PHPUnit_Framework_TestCase {
+
+ function testIsFree() {
+
+ $input = <<<BLA
+BEGIN:VCALENDAR
+BEGIN:VFREEBUSY
+FREEBUSY;FBTYPE=FREE:20120912T000500Z/PT1H
+FREEBUSY;FBTYPE=BUSY:20120912T010000Z/20120912T020000Z
+FREEBUSY;FBTYPE=BUSY-TENTATIVE:20120912T020000Z/20120912T030000Z
+FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20120912T030000Z/20120912T040000Z
+FREEBUSY;FBTYPE=BUSY:20120912T050000Z/20120912T060000Z,20120912T080000Z/20120912T090000Z
+FREEBUSY;FBTYPE=BUSY:20120912T100000Z/PT1H
+END:VFREEBUSY
+END:VCALENDAR
+BLA;
+
+ $obj = VObject\Reader::read($input);
+ $vfb = $obj->VFREEBUSY;
+
+ $tz = new \DateTimeZone('UTC');
+
+ $this->assertFalse($vfb->isFree(new \DateTime('2012-09-12 01:15:00', $tz), new \DateTime('2012-09-12 01:45:00', $tz)));
+ $this->assertFalse($vfb->isFree(new \DateTime('2012-09-12 08:05:00', $tz), new \DateTime('2012-09-12 08:10:00', $tz)));
+ $this->assertFalse($vfb->isFree(new \DateTime('2012-09-12 10:15:00', $tz), new \DateTime('2012-09-12 10:45:00', $tz)));
+
+ // Checking whether the end time is treated as non-inclusive
+ $this->assertTrue($vfb->isFree(new \DateTime('2012-09-12 09:00:00', $tz), new \DateTime('2012-09-12 09:15:00', $tz)));
+ $this->assertTrue($vfb->isFree(new \DateTime('2012-09-12 09:45:00', $tz), new \DateTime('2012-09-12 10:00:00', $tz)));
+ $this->assertTrue($vfb->isFree(new \DateTime('2012-09-12 11:00:00', $tz), new \DateTime('2012-09-12 12:00:00', $tz)));
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VJournalTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VJournalTest.php
new file mode 100644
index 000000000..46ecb992b
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VJournalTest.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Sabre\VObject\Component;
+
+use Sabre\VObject\Component;
+
+class VJournalTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider timeRangeTestData
+ */
+ public function testInTimeRange(VJournal $vtodo,$start,$end,$outcome) {
+
+ $this->assertEquals($outcome, $vtodo->isInTimeRange($start, $end));
+
+ }
+
+ public function timeRangeTestData() {
+
+ $tests = array();
+
+ $vjournal = Component::create('VJOURNAL');
+ $vjournal->DTSTART = '20111223T120000Z';
+ $tests[] = array($vjournal, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vjournal, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vjournal2 = Component::create('VJOURNAL');
+ $vjournal2->DTSTART = '20111223';
+ $vjournal2->DTSTART['VALUE'] = 'DATE';
+ $tests[] = array($vjournal2, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vjournal2, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vjournal3 = Component::create('VJOURNAL');
+ $tests[] = array($vjournal3, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), false);
+ $tests[] = array($vjournal3, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ return $tests;
+ }
+
+}
+
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Component/VTodoTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VTodoTest.php
new file mode 100644
index 000000000..a84da5cdf
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Component/VTodoTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Sabre\VObject\Component;
+
+use Sabre\VObject\Component;
+
+class VTodoTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider timeRangeTestData
+ */
+ public function testInTimeRange(VTodo $vtodo,$start,$end,$outcome) {
+
+ $this->assertEquals($outcome, $vtodo->isInTimeRange($start, $end));
+
+ }
+
+ public function timeRangeTestData() {
+
+ $tests = array();
+
+ $vtodo = Component::create('VTODO');
+ $vtodo->DTSTART = '20111223T120000Z';
+ $tests[] = array($vtodo, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo2 = clone $vtodo;
+ $vtodo2->DURATION = 'P1D';
+ $tests[] = array($vtodo2, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo2, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo3 = clone $vtodo;
+ $vtodo3->DUE = '20111225';
+ $tests[] = array($vtodo3, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo3, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo4 = Component::create('VTODO');
+ $vtodo4->DUE = '20111225';
+ $tests[] = array($vtodo4, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo4, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo5 = Component::create('VTODO');
+ $vtodo5->COMPLETED = '20111225';
+ $tests[] = array($vtodo5, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo5, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo6 = Component::create('VTODO');
+ $vtodo6->CREATED = '20111225';
+ $tests[] = array($vtodo6, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo6, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo7 = Component::create('VTODO');
+ $vtodo7->CREATED = '20111225';
+ $vtodo7->COMPLETED = '20111226';
+ $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
+
+ $vtodo7 = Component::create('VTODO');
+ $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
+ $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), true);
+
+ return $tests;
+
+ }
+
+}
+
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/ComponentTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/ComponentTest.php
new file mode 100644
index 000000000..07000bda0
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/ComponentTest.php
@@ -0,0 +1,413 @@
+<?php
+
+namespace Sabre\VObject;
+
+class ComponentTest extends \PHPUnit_Framework_TestCase {
+
+ function testIterate() {
+
+ $comp = new Component('VCALENDAR');
+
+ $sub = new Component('VEVENT');
+ $comp->children[] = $sub;
+
+ $sub = new Component('VTODO');
+ $comp->children[] = $sub;
+
+ $count = 0;
+ foreach($comp->children() as $key=>$subcomponent) {
+
+ $count++;
+ $this->assertInstanceOf('Sabre\\VObject\\Component',$subcomponent);
+
+ }
+ $this->assertEquals(2,$count);
+ $this->assertEquals(1,$key);
+
+ }
+
+ function testMagicGet() {
+
+ $comp = new Component('VCALENDAR');
+
+ $sub = new Component('VEVENT');
+ $comp->children[] = $sub;
+
+ $sub = new Component('VTODO');
+ $comp->children[] = $sub;
+
+ $event = $comp->vevent;
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $event);
+ $this->assertEquals('VEVENT', $event->name);
+
+ $this->assertInternalType('null', $comp->vjournal);
+
+ }
+
+ function testMagicGetGroups() {
+
+ $comp = new Component('VCARD');
+
+ $sub = new Property('GROUP1.EMAIL','1@1.com');
+ $comp->children[] = $sub;
+
+ $sub = new Property('GROUP2.EMAIL','2@2.com');
+ $comp->children[] = $sub;
+
+ $sub = new Property('EMAIL','3@3.com');
+ $comp->children[] = $sub;
+
+ $emails = $comp->email;
+ $this->assertEquals(3, count($emails));
+
+ $email1 = $comp->{"group1.email"};
+ $this->assertEquals('EMAIL', $email1[0]->name);
+ $this->assertEquals('GROUP1', $email1[0]->group);
+
+ $email3 = $comp->{".email"};
+ $this->assertEquals('EMAIL', $email3[0]->name);
+ $this->assertEquals(null, $email3[0]->group);
+
+ }
+
+ function testMagicIsset() {
+
+ $comp = new Component('VCALENDAR');
+
+ $sub = new Component('VEVENT');
+ $comp->children[] = $sub;
+
+ $sub = new Component('VTODO');
+ $comp->children[] = $sub;
+
+ $this->assertTrue(isset($comp->vevent));
+ $this->assertTrue(isset($comp->vtodo));
+ $this->assertFalse(isset($comp->vjournal));
+
+ }
+
+ function testMagicSetScalar() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->myProp = 'myValue';
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property',$comp->MYPROP);
+ $this->assertEquals('myValue',$comp->MYPROP->value);
+
+
+ }
+
+ function testMagicSetScalarTwice() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->myProp = 'myValue';
+ $comp->myProp = 'myValue';
+
+ $this->assertEquals(1,count($comp->children));
+ $this->assertInstanceOf('Sabre\\VObject\\Property',$comp->MYPROP);
+ $this->assertEquals('myValue',$comp->MYPROP->value);
+
+ }
+
+ function testMagicSetComponent() {
+
+ $comp = new Component('VCALENDAR');
+
+ // Note that 'myProp' is ignored here.
+ $comp->myProp = new Component('VEVENT');
+
+ $this->assertEquals(1, count($comp->children));
+
+ $this->assertEquals('VEVENT',$comp->VEVENT->name);
+
+ }
+
+ function testMagicSetTwice() {
+
+ $comp = new Component('VCALENDAR');
+
+ $comp->VEVENT = new Component('VEVENT');
+ $comp->VEVENT = new Component('VEVENT');
+
+ $this->assertEquals(1, count($comp->children));
+
+ $this->assertEquals('VEVENT',$comp->VEVENT->name);
+
+ }
+
+ function testArrayAccessGet() {
+
+ $comp = new Component('VCALENDAR');
+
+ $event = new Component('VEVENT');
+ $event->summary = 'Event 1';
+
+ $comp->add($event);
+
+ $event2 = clone $event;
+ $event2->summary = 'Event 2';
+
+ $comp->add($event2);
+
+ $this->assertEquals(2,count($comp->children()));
+ $this->assertTrue($comp->vevent[1] instanceof Component);
+ $this->assertEquals('Event 2', (string)$comp->vevent[1]->summary);
+
+ }
+
+ function testArrayAccessExists() {
+
+ $comp = new Component('VCALENDAR');
+
+ $event = new Component('VEVENT');
+ $event->summary = 'Event 1';
+
+ $comp->add($event);
+
+ $event2 = clone $event;
+ $event2->summary = 'Event 2';
+
+ $comp->add($event2);
+
+ $this->assertTrue(isset($comp->vevent[0]));
+ $this->assertTrue(isset($comp->vevent[1]));
+
+ }
+
+ /**
+ * @expectedException LogicException
+ */
+ function testArrayAccessSet() {
+
+ $comp = new Component('VCALENDAR');
+ $comp['hey'] = 'hi there';
+
+ }
+ /**
+ * @expectedException LogicException
+ */
+ function testArrayAccessUnset() {
+
+ $comp = new Component('VCALENDAR');
+ unset($comp[0]);
+
+ }
+
+ function testAddScalar() {
+
+ $comp = new Component('VCALENDAR');
+
+ $comp->add('myprop','value');
+
+ $this->assertEquals(1, count($comp->children));
+
+ $this->assertTrue($comp->children[0] instanceof Property);
+ $this->assertEquals('MYPROP',$comp->children[0]->name);
+ $this->assertEquals('value',$comp->children[0]->value);
+
+ }
+
+ function testAddScalarParams() {
+
+ $comp = Component::create('VCALENDAR');
+
+ $comp->add('myprop','value',array('param1'=>'value1'));
+
+ $this->assertEquals(1, count($comp->children));
+
+ $this->assertTrue($comp->children[0] instanceof Property);
+ $this->assertEquals('MYPROP',$comp->children[0]->name);
+ $this->assertEquals('value',$comp->children[0]->value);
+
+ $this->assertEquals(1, count($comp->children[0]->parameters));
+
+ $this->assertTrue($comp->children[0]->parameters[0] instanceof Parameter);
+ $this->assertEquals('PARAM1',$comp->children[0]->parameters[0]->name);
+ $this->assertEquals('value1',$comp->children[0]->parameters[0]->value);
+
+ }
+
+
+ function testAddComponent() {
+
+ $comp = new Component('VCALENDAR');
+
+ $comp->add(new Component('VEVENT'));
+
+ $this->assertEquals(1, count($comp->children));
+
+ $this->assertEquals('VEVENT',$comp->VEVENT->name);
+
+ }
+
+ function testAddComponentTwice() {
+
+ $comp = new Component('VCALENDAR');
+
+ $comp->add(new Component('VEVENT'));
+ $comp->add(new Component('VEVENT'));
+
+ $this->assertEquals(2, count($comp->children));
+
+ $this->assertEquals('VEVENT',$comp->VEVENT->name);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testAddArgFail() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->add(new Component('VEVENT'),'hello');
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testAddArgFail2() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->add(array());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testAddArgFail3() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->add('hello',array());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testMagicSetInvalid() {
+
+ $comp = new Component('VCALENDAR');
+
+ // Note that 'myProp' is ignored here.
+ $comp->myProp = new \StdClass();
+
+ $this->assertEquals(1, count($comp->children));
+
+ $this->assertEquals('VEVENT',$comp->VEVENT->name);
+
+ }
+
+ function testMagicUnset() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->add(new Component('VEVENT'));
+
+ unset($comp->vevent);
+
+ $this->assertEquals(array(), $comp->children);
+
+ }
+
+
+ function testCount() {
+
+ $comp = new Component('VCALENDAR');
+ $this->assertEquals(1,$comp->count());
+
+ }
+
+ function testChildren() {
+
+ $comp = new Component('VCALENDAR');
+
+ // Note that 'myProp' is ignored here.
+ $comp->children = array(
+ new Component('VEVENT'),
+ new Component('VTODO')
+ );
+
+ $r = $comp->children();
+ $this->assertTrue($r instanceof ElementList);
+ $this->assertEquals(2,count($r));
+ }
+
+ function testGetComponents() {
+
+ $comp = new Component('VCALENDAR');
+
+ // Note that 'myProp' is ignored here.
+ $comp->children = array(
+ new Property('FOO','BAR'),
+ new Component('VTODO')
+ );
+
+ $r = $comp->getComponents();
+ $this->assertInternalType('array', $r);
+ $this->assertEquals(1, count($r));
+ $this->assertEquals('VTODO', $r[0]->name);
+ }
+
+ function testSerialize() {
+
+ $comp = new Component('VCALENDAR');
+ $this->assertEquals("BEGIN:VCALENDAR\r\nEND:VCALENDAR\r\n", $comp->serialize());
+
+ }
+
+ function testSerializeChildren() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->children = array(
+ new Component('VEVENT'),
+ new Component('VTODO')
+ );
+
+ $str = $comp->serialize();
+
+ $this->assertEquals("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n", $str);
+
+ }
+
+ function testSerializeOrderCompAndProp() {
+
+ $comp = new Component('VCALENDAR');
+ $comp->add(new Component('VEVENT'));
+ $comp->add('PROP1','BLABLA');
+ $comp->add('VERSION','2.0');
+ $comp->add(new Component('VTIMEZONE'));
+
+ $str = $comp->serialize();
+
+ $this->assertEquals("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPROP1:BLABLA\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", $str);
+
+ }
+
+ function testAnotherSerializeOrderProp() {
+
+ $prop4s=array('1', '2', '3', '4', '5', '6', '7', '8', '9', '10');
+
+ $comp = new Component('VCARD');
+ $comp->__set('SOMEPROP','FOO');
+ $comp->__set('ANOTHERPROP','FOO');
+ $comp->__set('THIRDPROP','FOO');
+ foreach ($prop4s as $prop4) {
+ $comp->add('PROP4', 'FOO '.$prop4);
+ }
+ $comp->__set('PROPNUMBERFIVE', 'FOO');
+ $comp->__set('PROPNUMBERSIX', 'FOO');
+ $comp->__set('PROPNUMBERSEVEN', 'FOO');
+ $comp->__set('PROPNUMBEREIGHT', 'FOO');
+ $comp->__set('PROPNUMBERNINE', 'FOO');
+ $comp->__set('PROPNUMBERTEN', 'FOO');
+ $comp->__set('VERSION','2.0');
+ $comp->__set('UID', 'FOO');
+
+ $str = $comp->serialize();
+
+ $this->assertEquals("BEGIN:VCARD\r\nVERSION:2.0\r\nSOMEPROP:FOO\r\nANOTHERPROP:FOO\r\nTHIRDPROP:FOO\r\nPROP4:FOO 1\r\nPROP4:FOO 2\r\nPROP4:FOO 3\r\nPROP4:FOO 4\r\nPROP4:FOO 5\r\nPROP4:FOO 6\r\nPROP4:FOO 7\r\nPROP4:FOO 8\r\nPROP4:FOO 9\r\nPROP4:FOO 10\r\nPROPNUMBERFIVE:FOO\r\nPROPNUMBERSIX:FOO\r\nPROPNUMBERSEVEN:FOO\r\nPROPNUMBEREIGHT:FOO\r\nPROPNUMBERNINE:FOO\r\nPROPNUMBERTEN:FOO\r\nUID:FOO\r\nEND:VCARD\r\n", $str);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/DateTimeParserTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/DateTimeParserTest.php
new file mode 100644
index 000000000..6ea2faed9
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/DateTimeParserTest.php
@@ -0,0 +1,153 @@
+<?php
+
+namespace Sabre\VObject;
+
+use DateTime;
+use DateTimeZone;
+use DateInterval;
+
+class DateTimeParserTest extends \PHPUnit_Framework_TestCase {
+
+ function testParseICalendarDuration() {
+
+ $this->assertEquals('+1 weeks', DateTimeParser::parseDuration('P1W',true));
+ $this->assertEquals('+5 days', DateTimeParser::parseDuration('P5D',true));
+ $this->assertEquals('+5 days 3 hours 50 minutes 12 seconds', DateTimeParser::parseDuration('P5DT3H50M12S',true));
+ $this->assertEquals('-1 weeks 50 minutes', DateTimeParser::parseDuration('-P1WT50M',true));
+ $this->assertEquals('+50 days 3 hours 2 seconds', DateTimeParser::parseDuration('+P50DT3H2S',true));
+ $this->assertEquals(new DateInterval('PT0S'), DateTimeParser::parseDuration('PT0S'));
+
+ }
+
+ function testParseICalendarDurationDateInterval() {
+
+ $expected = new DateInterval('P7D');
+ $this->assertEquals($expected, DateTimeParser::parseDuration('P1W'));
+ $this->assertEquals($expected, DateTimeParser::parse('P1W'));
+
+ $expected = new DateInterval('PT3M');
+ $expected->invert = true;
+ $this->assertEquals($expected, DateTimeParser::parseDuration('-PT3M'));
+
+ }
+
+ /**
+ * @expectedException LogicException
+ */
+ function testParseICalendarDurationFail() {
+
+ DateTimeParser::parseDuration('P1X',true);
+
+ }
+
+ function testParseICalendarDateTime() {
+
+ $dateTime = DateTimeParser::parseDateTime('20100316T141405');
+
+ $compare = new DateTime('2010-03-16 14:14:05',new DateTimeZone('UTC'));
+
+ $this->assertEquals($compare, $dateTime);
+
+ }
+
+ /**
+ * @depends testParseICalendarDateTime
+ * @expectedException LogicException
+ */
+ function testParseICalendarDateTimeBadFormat() {
+
+ $dateTime = DateTimeParser::parseDateTime('20100316T141405 ');
+
+ }
+
+ /**
+ * @depends testParseICalendarDateTime
+ */
+ function testParseICalendarDateTimeUTC() {
+
+ $dateTime = DateTimeParser::parseDateTime('20100316T141405Z');
+
+ $compare = new DateTime('2010-03-16 14:14:05',new DateTimeZone('UTC'));
+ $this->assertEquals($compare, $dateTime);
+
+ }
+
+ /**
+ * @depends testParseICalendarDateTime
+ */
+ function testParseICalendarDateTimeUTC2() {
+
+ $dateTime = DateTimeParser::parseDateTime('20101211T160000Z');
+
+ $compare = new DateTime('2010-12-11 16:00:00',new DateTimeZone('UTC'));
+ $this->assertEquals($compare, $dateTime);
+
+ }
+
+ /**
+ * @depends testParseICalendarDateTime
+ */
+ function testParseICalendarDateTimeCustomTimeZone() {
+
+ $dateTime = DateTimeParser::parseDateTime('20100316T141405', new DateTimeZone('Europe/Amsterdam'));
+
+ $compare = new DateTime('2010-03-16 13:14:05',new DateTimeZone('UTC'));
+ $this->assertEquals($compare, $dateTime);
+
+ }
+
+ function testParseICalendarDate() {
+
+ $dateTime = DateTimeParser::parseDate('20100316');
+
+ $expected = new DateTime('2010-03-16 00:00:00',new DateTimeZone('UTC'));
+
+ $this->assertEquals($expected, $dateTime);
+
+ $dateTime = DateTimeParser::parse('20100316');
+ $this->assertEquals($expected, $dateTime);
+
+ }
+
+ /**
+ * TCheck if a date with year > 4000 will not throw an exception. iOS seems to use 45001231 in yearly recurring events
+ */
+ function testParseICalendarDateGreaterThan4000() {
+
+ $dateTime = DateTimeParser::parseDate('45001231');
+
+ $expected = new DateTime('4500-12-31 00:00:00',new DateTimeZone('UTC'));
+
+ $this->assertEquals($expected, $dateTime);
+
+ $dateTime = DateTimeParser::parse('45001231');
+ $this->assertEquals($expected, $dateTime);
+
+ }
+
+ /**
+ * Check if a datetime with year > 4000 will not throw an exception. iOS seems to use 45001231T235959 in yearly recurring events
+ */
+ function testParseICalendarDateTimeGreaterThan4000() {
+
+ $dateTime = DateTimeParser::parseDateTime('45001231T235959');
+
+ $expected = new DateTime('4500-12-31 23:59:59',new DateTimeZone('UTC'));
+
+ $this->assertEquals($expected, $dateTime);
+
+ $dateTime = DateTimeParser::parse('45001231T235959');
+ $this->assertEquals($expected, $dateTime);
+
+ }
+
+ /**
+ * @depends testParseICalendarDate
+ * @expectedException LogicException
+ */
+ function testParseICalendarDateBadFormat() {
+
+ $dateTime = DateTimeParser::parseDate('20100316T141405');
+
+ }
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/DocumentTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/DocumentTest.php
new file mode 100644
index 000000000..5fd2a2a78
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/DocumentTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Sabre\VObject;
+
+class DocumentTest extends \PHPUnit_Framework_TestCase {
+
+ function testCreateComponent() {
+
+ $vcal = new Component\VCalendar();
+
+ $event = $vcal->createComponent('VEVENT');
+
+ $this->assertInstanceOf('Sabre\VObject\Component\VEvent', $event);
+ $vcal->add($event);
+
+ $prop = $vcal->createProperty('X-PROP','1234256',array('X-PARAM' => '3'));
+ $this->assertInstanceOf('Sabre\VObject\Property', $prop);
+
+ $event->add($prop);
+
+ $out = $vcal->serialize();
+ $this->assertEquals("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nX-PROP;X-PARAM=3:1234256\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", $out);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/ElementListTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/ElementListTest.php
new file mode 100644
index 000000000..84e1bcbe9
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/ElementListTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Sabre\VObject;
+
+class ElementListTest extends \PHPUnit_Framework_TestCase {
+
+ function testIterate() {
+
+ $sub = new Component('VEVENT');
+
+ $elems = array(
+ $sub,
+ clone $sub,
+ clone $sub
+ );
+
+ $elemList = new ElementList($elems);
+
+ $count = 0;
+ foreach($elemList as $key=>$subcomponent) {
+
+ $count++;
+ $this->assertInstanceOf('Sabre\\VObject\\Component',$subcomponent);
+
+ }
+ $this->assertEquals(3,$count);
+ $this->assertEquals(2,$key);
+
+ }
+
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/EmClientTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/EmClientTest.php
new file mode 100644
index 000000000..69d410fe7
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/EmClientTest.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Sabre\VObject;
+
+class EmClientTest extends \PHPUnit_Framework_TestCase {
+
+ function testParseTz() {
+
+ $str = 'BEGIN:VCALENDAR
+X-WR-CALNAME:Blackhawks Schedule 2011-12
+X-APPLE-CALENDAR-COLOR:#E51717
+X-WR-TIMEZONE:America/Chicago
+CALSCALE:GREGORIAN
+PRODID:-//eM Client/4.0.13961.0
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:America/Chicago
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0600
+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
+DTSTART:20070311T020000
+TZNAME:CDT
+TZOFFSETTO:-0500
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0500
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
+DTSTART:20071104T020000
+TZNAME:CST
+TZOFFSETTO:-0600
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20110624T181236Z
+UID:be3bbfff-96e8-4c66-9908-ab791a62231d
+DTEND;TZID="America/Chicago":20111008T223000
+TRANSP:OPAQUE
+SUMMARY:Stars @ Blackhawks (Home Opener)
+DTSTART;TZID="America/Chicago":20111008T193000
+DTSTAMP:20120330T013232Z
+SEQUENCE:2
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+LAST-MODIFIED:20120330T013237Z
+CLASS:PUBLIC
+END:VEVENT
+END:VCALENDAR';
+
+ $vObject = Reader::read($str);
+ $dt = $vObject->VEVENT->DTSTART->getDateTime();
+ $this->assertEquals(new \DateTime('2011-10-08 19:30:00', new \DateTimeZone('America/Chicago')), $dt);
+
+ }
+
+}
+
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/FreeBusyGeneratorTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/FreeBusyGeneratorTest.php
new file mode 100644
index 000000000..1f79e0a47
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/FreeBusyGeneratorTest.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace Sabre\VObject;
+
+class FreeBusyGeneratorTest extends \PHPUnit_Framework_TestCase {
+
+ function getInput() {
+
+ // shows up
+$blob1 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20110101T120000Z
+DTEND:20110101T130000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // opaque, shows up
+$blob2 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+TRANSP:OPAQUE
+DTSTART:20110101T130000Z
+DTEND:20110101T140000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // transparent, hidden
+$blob3 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+TRANSP:TRANSPARENT
+DTSTART:20110101T140000Z
+DTEND:20110101T150000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // cancelled, hidden
+$blob4 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+STATUS:CANCELLED
+DTSTART:20110101T160000Z
+DTEND:20110101T170000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // tentative, shows up
+$blob5 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+STATUS:TENTATIVE
+DTSTART:20110101T180000Z
+DTEND:20110101T190000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // outside of time-range, hidden
+$blob6 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20110101T090000Z
+DTEND:20110101T100000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // outside of time-range, hidden
+$blob7 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20110104T090000Z
+DTEND:20110104T100000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // using duration, shows up
+$blob8 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20110101T190000Z
+DURATION:PT1H
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ // Day-long event, shows up
+$blob9 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART;TYPE=DATE:20110102
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+// No duration, does not show up
+$blob10 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20110101T200000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+// encoded as object, shows up
+$blob11 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20110101T210000Z
+DURATION:PT1H
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+// Freebusy. Some parts show up
+$blob12 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VFREEBUSY
+FREEBUSY:20110103T010000Z/20110103T020000Z
+FREEBUSY;FBTYPE=FREE:20110103T020000Z/20110103T030000Z
+FREEBUSY:20110103T030000Z/20110103T040000Z,20110103T040000Z/20110103T050000Z
+FREEBUSY:20120101T000000Z/20120101T010000Z
+FREEBUSY:20110103T050000Z/PT1H
+END:VFREEBUSY
+END:VCALENDAR
+ICS;
+
+// Yearly recurrence rule, shows up
+$blob13 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20100101T220000Z
+DTEND:20100101T230000Z
+RRULE:FREQ=YEARLY
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+// Yearly recurrence rule + duration, shows up
+$blob14 = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTART:20100101T230000Z
+DURATION:PT1H
+RRULE:FREQ=YEARLY
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+
+ return array(
+ $blob1,
+ $blob2,
+ $blob3,
+ $blob4,
+ $blob5,
+ $blob6,
+ $blob7,
+ $blob8,
+ $blob9,
+ $blob10,
+ Reader::read($blob11),
+ $blob12,
+ $blob13,
+ $blob14,
+ );
+
+ }
+
+ function testGenerator() {
+
+ $gen = new FreeBusyGenerator(
+ new \DateTime('20110101T110000Z', new \DateTimeZone('UTC')),
+ new \DateTime('20110103T110000Z', new \DateTimeZone('UTC')),
+ $this->getInput()
+ );
+
+ $result = $gen->getResult();
+
+ $expected = array(
+ '20110101T120000Z/20110101T130000Z',
+ '20110101T130000Z/20110101T140000Z',
+ '20110101T180000Z/20110101T190000Z',
+ '20110101T190000Z/20110101T200000Z',
+ '20110102T000000Z/20110103T000000Z',
+ '20110101T210000Z/20110101T220000Z',
+
+ '20110103T010000Z/20110103T020000Z',
+ '20110103T030000Z/20110103T040000Z',
+ '20110103T040000Z/20110103T050000Z',
+ '20110103T050000Z/20110103T060000Z',
+
+ '20110101T220000Z/20110101T230000Z',
+ '20110101T230000Z/20110102T000000Z',
+ );
+
+ foreach($result->VFREEBUSY->FREEBUSY as $fb) {
+
+ $this->assertContains((string)$fb, $expected);
+
+ $k = array_search((string)$fb, $expected);
+ unset($expected[$k]);
+
+ }
+ if (count($expected)>0) {
+ $this->fail('There were elements in the expected array that were not found in the output: ' . "\n" . print_r($expected,true) . "\n" . $result->serialize());
+
+ }
+
+ }
+
+ function testGeneratorBaseObject() {
+
+ $obj = new Component('VCALENDAR');
+ $obj->METHOD = 'PUBLISH';
+
+ $gen = new FreeBusyGenerator();
+ $gen->setObjects(array());
+ $gen->setBaseObject($obj);
+
+ $result = $gen->getResult();
+
+ $this->assertEquals('PUBLISH', $result->METHOD->value);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testInvalidArg() {
+
+ $gen = new FreeBusyGenerator(
+ new \DateTime('2012-01-01'),
+ new \DateTime('2012-12-31'),
+ new \StdClass()
+ );
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Issue153Test.php b/vendor/sabre/vobject/tests/Sabre/VObject/Issue153Test.php
new file mode 100644
index 000000000..1cc14c161
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Issue153Test.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Sabre\VObject;
+
+class Issue153Test extends \PHPUnit_Framework_TestCase {
+
+ function testRead() {
+
+ $obj = Reader::read(file_get_contents(dirname(__FILE__) . '/issue153.vcf'));
+ $this->assertEquals('Test Benutzer', (string)$obj->fn);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Issue154Test.php b/vendor/sabre/vobject/tests/Sabre/VObject/Issue154Test.php
new file mode 100644
index 000000000..ed9c7c3f4
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Issue154Test.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Sabre\VObject;
+
+class Issue154Test extends \PHPUnit_Framework_TestCase {
+
+ function testStuff() {
+
+ $vcard = new Component('VCARD');
+ $vcard->VERSION = '3.0';
+ $vcard->PHOTO = base64_encode('random_stuff');
+ $vcard->PHOTO->add('BASE64',null);
+ $vcard->UID = 'foo-bar';
+
+ $result = $vcard->serialize();
+ $expected = array(
+ "BEGIN:VCARD",
+ "VERSION:3.0",
+ "PHOTO;BASE64:" . base64_encode('random_stuff'),
+ "UID:foo-bar",
+ "END:VCARD",
+ "",
+ );
+
+ $this->assertEquals(implode("\r\n", $expected), $result);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Issue48Test.php b/vendor/sabre/vobject/tests/Sabre/VObject/Issue48Test.php
new file mode 100644
index 000000000..980d432b9
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Issue48Test.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Sabre\VObject;
+
+use
+ DateTime,
+ DateTimeZone;
+
+class Issue48Test extends \PHPUnit_Framework_TestCase {
+
+ function testExpand() {
+
+ $input = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+UID:foo
+DTEND;TZID=Europe/Moscow:20130710T120000
+DTSTART;TZID=Europe/Moscow:20130710T110000
+RRULE:FREQ=DAILY;UNTIL=20130712T195959Z
+END:VEVENT
+BEGIN:VEVENT
+UID:foo
+DTEND;TZID=Europe/Moscow:20130713T120000
+DTSTART;TZID=Europe/Moscow:20130713T110000
+RECURRENCE-ID;TZID=Europe/Moscow:20130711T110000
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ $vcal = Reader::read($input);
+ $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
+
+ $it = new RecurrenceIterator($vcal, 'foo');
+
+ $result = iterator_to_array($it);
+
+ $tz = new DateTimeZone('Europe/Moscow');
+
+ $this->assertEquals(array(
+ new DateTime('2013-07-10 11:00:00', $tz),
+ new DateTime('2013-07-12 11:00:00', $tz),
+ new DateTime('2013-07-13 11:00:00', $tz),
+ ), $result);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Issue50Test.php b/vendor/sabre/vobject/tests/Sabre/VObject/Issue50Test.php
new file mode 100644
index 000000000..fdb012ba2
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Issue50Test.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Sabre\VObject;
+
+use
+ DateTime,
+ DateTimeZone;
+
+class Issue50Test extends \PHPUnit_Framework_TestCase {
+
+ function testExpand() {
+
+ $input = <<<ICS
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+BEGIN:VTIMEZONE
+TZID:Europe/Brussels
+X-LIC-LOCATION:Europe/Brussels
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20130705T142510Z
+LAST-MODIFIED:20130715T132556Z
+DTSTAMP:20130715T132556Z
+UID:1aef0b27-3d92-4581-829a-11999dd36724
+SUMMARY:Werken
+RRULE:FREQ=DAILY;COUNT=5
+DTSTART;TZID=Europe/Brussels:20130715T090000
+DTEND;TZID=Europe/Brussels:20130715T170000
+LOCATION:Job
+DESCRIPTION:Vrij
+X-MOZ-GENERATION:9
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20130715T081654Z
+LAST-MODIFIED:20130715T110931Z
+DTSTAMP:20130715T110931Z
+UID:1aef0b27-3d92-4581-829a-11999dd36724
+SUMMARY:Werken
+RECURRENCE-ID;TZID=Europe/Brussels:20130719T090000
+DTSTART;TZID=Europe/Brussels:20130719T070000
+DTEND;TZID=Europe/Brussels:20130719T150000
+SEQUENCE:1
+LOCATION:Job
+DESCRIPTION:Vrij
+X-MOZ-GENERATION:1
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20130715T111654Z
+LAST-MODIFIED:20130715T132556Z
+DTSTAMP:20130715T132556Z
+UID:1aef0b27-3d92-4581-829a-11999dd36724
+SUMMARY:Werken
+RECURRENCE-ID;TZID=Europe/Brussels:20130716T090000
+DTSTART;TZID=Europe/Brussels:20130716T070000
+DTEND;TZID=Europe/Brussels:20130716T150000
+SEQUENCE:1
+LOCATION:Job
+X-MOZ-GENERATION:2
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20130715T125942Z
+LAST-MODIFIED:20130715T130023Z
+DTSTAMP:20130715T130023Z
+UID:1aef0b27-3d92-4581-829a-11999dd36724
+SUMMARY:Werken
+RECURRENCE-ID;TZID=Europe/Brussels:20130717T090000
+DTSTART;TZID=Europe/Brussels:20130717T070000
+DTEND;TZID=Europe/Brussels:20130717T150000
+SEQUENCE:1
+LOCATION:Job
+X-MOZ-GENERATION:3
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20130715T130024Z
+LAST-MODIFIED:20130715T130034Z
+DTSTAMP:20130715T130034Z
+UID:1aef0b27-3d92-4581-829a-11999dd36724
+SUMMARY:Werken
+RECURRENCE-ID;TZID=Europe/Brussels:20130718T090000
+DTSTART;TZID=Europe/Brussels:20130718T090000
+DTEND;TZID=Europe/Brussels:20130718T170000
+LOCATION:Job
+X-MOZ-GENERATION:5
+DESCRIPTION:Vrij
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ $vcal = Reader::read($input);
+ $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
+
+ $it = new RecurrenceIterator($vcal, '1aef0b27-3d92-4581-829a-11999dd36724');
+
+ $result = array();
+ foreach($it as $instance) {
+
+ $result[] = $instance;
+
+ }
+
+ $tz = new DateTimeZone('Europe/Brussels');
+
+ $this->assertEquals(array(
+ new DateTime('2013-07-15 09:00:00', $tz),
+ new DateTime('2013-07-16 07:00:00', $tz),
+ new DateTime('2013-07-17 07:00:00', $tz),
+ new DateTime('2013-07-18 09:00:00', $tz),
+ new DateTime('2013-07-19 07:00:00', $tz),
+ ), $result);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/ParameterTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/ParameterTest.php
new file mode 100644
index 000000000..90eb5d2aa
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/ParameterTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Sabre\VObject;
+
+class ParameterTest extends \PHPUnit_Framework_TestCase {
+
+ function testSetup() {
+
+ $param = new Parameter('name','value');
+ $this->assertEquals('NAME',$param->name);
+ $this->assertEquals('value',$param->value);
+ $this->assertEquals('value',$param->getValue());
+
+ }
+
+ function testCastToString() {
+
+ $param = new Parameter('name','value');
+ $this->assertEquals('value',$param->__toString());
+ $this->assertEquals('value',(string)$param);
+
+ }
+
+ function testSerialize() {
+
+ $param = new Parameter('name','value');
+ $this->assertEquals('NAME=value',$param->serialize());
+
+ }
+
+ function testSerializeEmpty() {
+
+ $param = new Parameter('name',null);
+ $this->assertEquals('NAME',$param->serialize());
+
+ }
+
+ function testSerializeColon() {
+
+ $param = new Parameter('name','va:lue');
+ $this->assertEquals('NAME="va:lue"',$param->serialize());
+
+ }
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Property/CompoundTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Property/CompoundTest.php
new file mode 100644
index 000000000..5d8cdaabb
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Property/CompoundTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Sabre\VObject\Property;
+use Sabre\VObject\Component;
+
+class CompoundTest extends \PHPUnit_Framework_TestCase {
+
+ function testSetParts() {
+
+ $arr = array(
+ 'ABC, Inc.',
+ 'North American Division',
+ 'Marketing;Sales',
+ );
+
+ $elem = new Compound('ORG');
+ $elem->setParts($arr);
+
+ $this->assertEquals('ABC\, Inc.;North American Division;Marketing\;Sales', $elem->value);
+ $this->assertEquals(3, count($elem->getParts()));
+ $parts = $elem->getParts();
+ $this->assertEquals('Marketing;Sales', $parts[2]);
+
+ }
+
+ function testGetParts() {
+
+ $str = 'ABC\, Inc.;North American Division;Marketing\;Sales';
+
+ $elem = new Compound('ORG', $str);
+
+ $this->assertEquals(3, count($elem->getParts()));
+ $parts = $elem->getParts();
+ $this->assertEquals('Marketing;Sales', $parts[2]);
+ }
+
+ function testGetPartsDefaultDelimiter() {
+
+ $str = 'Hi!;Hello!';
+
+ $elem = new Compound('X-FOO', $str);
+
+ $this->assertEquals(array(
+ 'Hi!',
+ 'Hello!',
+ ), $elem->getParts());
+
+ }
+
+ function testGetPartsNull() {
+
+ $str = 'ABC\, Inc.;North American Division;Marketing\;Sales';
+
+ $elem = new Compound('ORG', null);
+
+ $this->assertEquals(0, count($elem->getParts()));
+
+ }
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Property/DateTimeTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Property/DateTimeTest.php
new file mode 100644
index 000000000..b5b522e7d
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Property/DateTimeTest.php
@@ -0,0 +1,240 @@
+<?php
+
+namespace Sabre\VObject\Property;
+use Sabre\VObject\Component;
+
+class DateTimeTest extends \PHPUnit_Framework_TestCase {
+
+ function testSetDateTime() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt);
+
+ $this->assertEquals('19850704T013000', $elem->value);
+ $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+
+ }
+
+ function testSetDateTimeLOCAL() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt, DateTime::LOCAL);
+
+ $this->assertEquals('19850704T013000', $elem->value);
+ $this->assertNull($elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+ }
+
+ function testSetDateTimeUTC() {
+
+ $tz = new \DateTimeZone('GMT');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt, DateTime::UTC);
+
+ $this->assertEquals('19850704T013000Z', $elem->value);
+ $this->assertNull($elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+ }
+
+ function testSetDateTimeLOCALTZ() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt, DateTime::LOCALTZ);
+
+ $this->assertEquals('19850704T013000', $elem->value);
+ $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+ }
+
+ function testSetDateTimeDATE() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt, DateTime::DATE);
+
+ $this->assertEquals('19850704', $elem->value);
+ $this->assertNull($elem['TZID']);
+ $this->assertEquals('DATE', (string)$elem['VALUE']);
+
+ $this->assertFalse($elem->hasTime());
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testSetDateTimeInvalid() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt, 7);
+
+ }
+
+ function testGetDateTimeCached() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new DateTime('DTSTART');
+ $elem->setDateTime($dt);
+
+ $this->assertEquals($elem->getDateTime(), $dt);
+
+ }
+
+ function testGetDateTimeDateNULL() {
+
+ $elem = new DateTime('DTSTART');
+ $dt = $elem->getDateTime();
+
+ $this->assertNull($dt);
+ $this->assertNull($elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateDATE() {
+
+ $elem = new DateTime('DTSTART','19850704');
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 00:00:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals(DateTime::DATE, $elem->getDateType());
+
+ }
+
+
+ function testGetDateTimeDateLOCAL() {
+
+ $elem = new DateTime('DTSTART','19850704T013000');
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals(DateTime::LOCAL, $elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateUTC() {
+
+ $elem = new DateTime('DTSTART','19850704T013000Z');
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals('UTC', $dt->getTimeZone()->getName());
+ $this->assertEquals(DateTime::UTC, $elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateLOCALTZ() {
+
+ $elem = new DateTime('DTSTART','19850704T013000');
+ $elem['TZID'] = 'Europe/Amsterdam';
+
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals('Europe/Amsterdam', $dt->getTimeZone()->getName());
+ $this->assertEquals(DateTime::LOCALTZ, $elem->getDateType());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testGetDateTimeDateInvalid() {
+
+ $elem = new DateTime('DTSTART','bla');
+ $dt = $elem->getDateTime();
+
+ }
+
+ function testGetDateTimeWeirdTZ() {
+
+ $elem = new DateTime('DTSTART','19850704T013000');
+ $elem['TZID'] = '/freeassociation.sourceforge.net/Tzfile/Europe/Amsterdam';
+
+
+ $event = new Component('VEVENT');
+ $event->add($elem);
+
+ $timezone = new Component('VTIMEZONE');
+ $timezone->TZID = '/freeassociation.sourceforge.net/Tzfile/Europe/Amsterdam';
+ $timezone->{'X-LIC-LOCATION'} = 'Europe/Amsterdam';
+
+ $calendar = new Component('VCALENDAR');
+ $calendar->add($event);
+ $calendar->add($timezone);
+
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals('Europe/Amsterdam', $dt->getTimeZone()->getName());
+ $this->assertEquals(DateTime::LOCALTZ, $elem->getDateType());
+
+ }
+
+ function testGetDateTimeBadTimeZone() {
+
+ $default = date_default_timezone_get();
+ date_default_timezone_set('Canada/Eastern');
+
+ $elem = new DateTime('DTSTART','19850704T013000');
+ $elem['TZID'] = 'Moon';
+
+
+ $event = new Component('VEVENT');
+ $event->add($elem);
+
+ $timezone = new Component('VTIMEZONE');
+ $timezone->TZID = 'Moon';
+ $timezone->{'X-LIC-LOCATION'} = 'Moon';
+
+ $calendar = new Component('VCALENDAR');
+ $calendar->add($event);
+ $calendar->add($timezone);
+
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals('Canada/Eastern', $dt->getTimeZone()->getName());
+ $this->assertEquals(DateTime::LOCALTZ, $elem->getDateType());
+ date_default_timezone_set($default);
+
+ }
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Property/MultiDateTimeTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Property/MultiDateTimeTest.php
new file mode 100644
index 000000000..177616652
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Property/MultiDateTimeTest.php
@@ -0,0 +1,208 @@
+<?php
+
+namespace Sabre\VObject\Property;
+
+class MultiDateTimeTest extends \PHPUnit_Framework_TestCase {
+
+ function testSetDateTime() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt2 = new \DateTime('1986-07-04 01:30:00', $tz);
+ $dt1->setTimeZone($tz);
+ $dt2->setTimeZone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt1,$dt2));
+
+ $this->assertEquals('19850704T013000,19860704T013000', $elem->value);
+ $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+
+ }
+
+ function testSetDateTimeLOCAL() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt2 = new \DateTime('1986-07-04 01:30:00', $tz);
+ $dt1->setTimeZone($tz);
+ $dt2->setTimeZone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt1,$dt2), DateTime::LOCAL);
+
+ $this->assertEquals('19850704T013000,19860704T013000', $elem->value);
+ $this->assertNull($elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+ }
+
+ function testSetDateTimeUTC() {
+
+ $tz = new \DateTimeZone('GMT');
+ $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt2 = new \DateTime('1986-07-04 01:30:00', $tz);
+ $dt1->setTimeZone($tz);
+ $dt2->setTimeZone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt1,$dt2), DateTime::UTC);
+
+ $this->assertEquals('19850704T013000Z,19860704T013000Z', $elem->value);
+ $this->assertNull($elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+ }
+
+ function testSetDateTimeLOCALTZ() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt2 = new \DateTime('1986-07-04 01:30:00', $tz);
+ $dt1->setTimeZone($tz);
+ $dt2->setTimeZone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt1,$dt2), DateTime::LOCALTZ);
+
+ $this->assertEquals('19850704T013000,19860704T013000', $elem->value);
+ $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
+ $this->assertEquals('DATE-TIME', (string)$elem['VALUE']);
+
+ $this->assertTrue($elem->hasTime());
+ }
+
+ function testSetDateTimeDATE() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt2 = new \DateTime('1986-07-04 01:30:00', $tz);
+ $dt1->settimezone($tz);
+ $dt2->settimezone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt1,$dt2), DateTime::DATE);
+
+ $this->assertEquals('19850704,19860704', $elem->value);
+ $this->assertNull($elem['TZID']);
+ $this->assertEquals('DATE', (string)$elem['VALUE']);
+
+ $this->assertFalse($elem->hasTime());
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testSetDateTimeInvalid() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt->setTimeZone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt), 7);
+
+ }
+
+ function testGetDateTimeCached() {
+
+ $tz = new \DateTimeZone('Europe/Amsterdam');
+ $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
+ $dt2 = new \DateTime('1986-07-04 01:30:00', $tz);
+ $dt1->settimezone($tz);
+ $dt2->settimezone($tz);
+
+ $elem = new MultiDateTime('DTSTART');
+ $elem->setDateTimes(array($dt1,$dt2));
+
+ $this->assertEquals($elem->getDateTimes(), array($dt1,$dt2));
+
+ }
+
+ function testGetDateTimeDateNULL() {
+
+ $elem = new MultiDateTime('DTSTART');
+ $dt = $elem->getDateTimes();
+
+ $this->assertNull($dt);
+ $this->assertNull($elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateDATE() {
+
+ $elem = new MultiDateTime('DTSTART','19850704,19860704');
+ $dt = $elem->getDateTimes();
+
+ $this->assertEquals('1985-07-04 00:00:00', $dt[0]->format('Y-m-d H:i:s'));
+ $this->assertEquals('1986-07-04 00:00:00', $dt[1]->format('Y-m-d H:i:s'));
+ $this->assertEquals(DateTime::DATE, $elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateDATEReverse() {
+
+ $elem = new MultiDateTime('DTSTART','19850704,19860704');
+
+ $this->assertEquals(DateTime::DATE, $elem->getDateType());
+
+ $dt = $elem->getDateTimes();
+ $this->assertEquals('1985-07-04 00:00:00', $dt[0]->format('Y-m-d H:i:s'));
+ $this->assertEquals('1986-07-04 00:00:00', $dt[1]->format('Y-m-d H:i:s'));
+
+ }
+
+
+ function testGetDateTimeDateLOCAL() {
+
+ $elem = new DateTime('DTSTART','19850704T013000');
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals(DateTime::LOCAL, $elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateUTC() {
+
+ $elem = new DateTime('DTSTART','19850704T013000Z');
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals('UTC', $dt->getTimeZone()->getName());
+ $this->assertEquals(DateTime::UTC, $elem->getDateType());
+
+ }
+
+ function testGetDateTimeDateLOCALTZ() {
+
+ $elem = new DateTime('DTSTART','19850704T013000');
+ $elem['TZID'] = 'Europe/Amsterdam';
+
+ $dt = $elem->getDateTime();
+
+ $this->assertInstanceOf('DateTime', $dt);
+ $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
+ $this->assertEquals('Europe/Amsterdam', $dt->getTimeZone()->getName());
+ $this->assertEquals(DateTime::LOCALTZ, $elem->getDateType());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testGetDateTimeDateInvalid() {
+
+ $elem = new DateTime('DTSTART','bla');
+ $dt = $elem->getDateTime();
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/PropertyTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/PropertyTest.php
new file mode 100644
index 000000000..3bb289567
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/PropertyTest.php
@@ -0,0 +1,324 @@
+<?php
+
+namespace Sabre\VObject;
+
+class PropertyTest extends \PHPUnit_Framework_TestCase {
+
+ public function testToString() {
+
+ $property = new Property('propname','propvalue');
+ $this->assertEquals('PROPNAME', $property->name);
+ $this->assertEquals('propvalue', $property->value);
+ $this->assertEquals('propvalue', $property->__toString());
+ $this->assertEquals('propvalue', (string)$property);
+ $this->assertEquals('propvalue', $property->getValue());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testCreateNonScalar() {
+
+ $property = new Property('propname',array());
+
+ }
+
+ public function testParameterExists() {
+
+ $property = new Property('propname','propvalue');
+ $property->parameters[] = new Parameter('paramname','paramvalue');
+
+ $this->assertTrue(isset($property['PARAMNAME']));
+ $this->assertTrue(isset($property['paramname']));
+ $this->assertFalse(isset($property['foo']));
+
+ }
+
+ public function testParameterGet() {
+
+ $property = new Property('propname','propvalue');
+ $property->parameters[] = new Parameter('paramname','paramvalue');
+
+ $this->assertInstanceOf('Sabre\\VObject\\Parameter',$property['paramname']);
+
+ }
+
+ public function testParameterNotExists() {
+
+ $property = new Property('propname','propvalue');
+ $property->parameters[] = new Parameter('paramname','paramvalue');
+
+ $this->assertInternalType('null',$property['foo']);
+
+ }
+
+ public function testParameterMultiple() {
+
+ $property = new Property('propname','propvalue');
+ $property->parameters[] = new Parameter('paramname','paramvalue');
+ $property->parameters[] = new Parameter('paramname','paramvalue');
+
+ $this->assertInstanceOf('Sabre\\VObject\\Parameter',$property['paramname']);
+ $this->assertEquals(2,count($property['paramname']));
+
+ }
+
+ public function testSetParameterAsString() {
+
+ $property = new Property('propname','propvalue');
+ $property['paramname'] = 'paramvalue';
+
+ $this->assertEquals(1,count($property->parameters));
+ $this->assertInstanceOf('Sabre\\VObject\\Parameter', $property->parameters[0]);
+ $this->assertEquals('PARAMNAME',$property->parameters[0]->name);
+ $this->assertEquals('paramvalue',$property->parameters[0]->value);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testSetParameterAsStringNoKey() {
+
+ $property = new Property('propname','propvalue');
+ $property[] = 'paramvalue';
+
+ }
+
+ public function testSetParameterObject() {
+
+ $property = new Property('propname','propvalue');
+ $param = new Parameter('paramname','paramvalue');
+
+ $property[] = $param;
+
+ $this->assertEquals(1,count($property->parameters));
+ $this->assertEquals($param, $property->parameters[0]);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testSetParameterObjectWithKey() {
+
+ $property = new Property('propname','propvalue');
+ $param = new Parameter('paramname','paramvalue');
+
+ $property['key'] = $param;
+
+ }
+
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testSetParameterObjectRandomObject() {
+
+ $property = new Property('propname','propvalue');
+ $property[] = new \StdClass();
+
+ }
+
+ public function testUnsetParameter() {
+
+ $property = new Property('propname','propvalue');
+ $param = new Parameter('paramname','paramvalue');
+ $property->parameters[] = $param;
+
+ unset($property['PARAMNAME']);
+ $this->assertEquals(0,count($property->parameters));
+
+ }
+
+ public function testParamCount() {
+
+ $property = new Property('propname','propvalue');
+ $param = new Parameter('paramname','paramvalue');
+ $property->parameters[] = $param;
+ $property->parameters[] = clone $param;
+
+ $this->assertEquals(2,count($property->parameters));
+
+ }
+
+ public function testSerialize() {
+
+ $property = new Property('propname','propvalue');
+
+ $this->assertEquals("PROPNAME:propvalue\r\n",$property->serialize());
+
+ }
+
+ public function testSerializeParam() {
+
+ $property = new Property('propname','propvalue');
+ $property->parameters[] = new Parameter('paramname','paramvalue');
+ $property->parameters[] = new Parameter('paramname2','paramvalue2');
+
+ $this->assertEquals("PROPNAME;PARAMNAME=paramvalue;PARAMNAME2=paramvalue2:propvalue\r\n",$property->serialize());
+
+ }
+
+ public function testSerializeNewLine() {
+
+ $property = new Property('propname',"line1\nline2");
+
+ $this->assertEquals("PROPNAME:line1\\nline2\r\n",$property->serialize());
+
+ }
+
+ public function testSerializeLongLine() {
+
+ $value = str_repeat('!',200);
+ $property = new Property('propname',$value);
+
+ $expected = "PROPNAME:" . str_repeat('!',66) . "\r\n " . str_repeat('!',74) . "\r\n " . str_repeat('!',60) . "\r\n";
+
+ $this->assertEquals($expected,$property->serialize());
+
+ }
+
+ public function testSerializeUTF8LineFold() {
+
+ $value = str_repeat('!',65) . "\xc3\xa4bla"; // inserted umlaut-a
+ $property = new Property('propname', $value);
+ $expected = "PROPNAME:" . str_repeat('!',65) . "\r\n \xc3\xa4bla\r\n";
+ $this->assertEquals($expected, $property->serialize());
+
+ }
+
+ public function testGetIterator() {
+
+ $it = new ElementList(array());
+ $property = new Property('propname','propvalue');
+ $property->setIterator($it);
+ $this->assertEquals($it,$property->getIterator());
+
+ }
+
+
+ public function testGetIteratorDefault() {
+
+ $property = new Property('propname','propvalue');
+ $it = $property->getIterator();
+ $this->assertTrue($it instanceof ElementList);
+ $this->assertEquals(1,count($it));
+
+ }
+
+ function testAddScalar() {
+
+ $property = new Property('EMAIL');
+
+ $property->add('myparam','value');
+
+ $this->assertEquals(1, count($property->parameters));
+
+ $this->assertTrue($property->parameters[0] instanceof Parameter);
+ $this->assertEquals('MYPARAM',$property->parameters[0]->name);
+ $this->assertEquals('value',$property->parameters[0]->value);
+
+ }
+
+ function testAddParameter() {
+
+ $prop = new Property('EMAIL');
+
+ $prop->add(new Parameter('MYPARAM','value'));
+
+ $this->assertEquals(1, count($prop->parameters));
+ $this->assertEquals('MYPARAM',$prop['myparam']->name);
+
+ }
+
+ function testAddParameterTwice() {
+
+ $prop = new Property('EMAIL');
+
+ $prop->add(new Parameter('MYPARAM', 'value1'));
+ $prop->add(new Parameter('MYPARAM', 'value2'));
+
+ $this->assertEquals(2, count($prop->parameters));
+
+ $this->assertEquals('MYPARAM',$prop['MYPARAM']->name);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testAddArgFail() {
+
+ $prop = new Property('EMAIL');
+ $prop->add(new Parameter('MPARAM'),'hello');
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testAddArgFail2() {
+
+ $property = new Property('EMAIL','value');
+ $property->add(array());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testAddArgFail3() {
+
+ $property = new Property('EMAIL','value');
+ $property->add('hello',array());
+
+ }
+
+ function testClone() {
+
+ $property = new Property('EMAIL','value');
+ $property['FOO'] = 'BAR';
+
+ $property2 = clone $property;
+
+ $property['FOO'] = 'BAZ';
+ $this->assertEquals('BAR', (string)$property2['FOO']);
+
+ }
+
+ function testCreateParams() {
+
+ $property = Property::create('X-PROP', 'value', array(
+ 'param1' => 'value1',
+ 'param2' => array('value2', 'value3')
+ ));
+
+ $this->assertEquals(1, count($property['PARAM1']));
+ $this->assertEquals(2, count($property['PARAM2']));
+
+ }
+
+ function testValidateNonUTF8() {
+
+ $property = Property::create('X-PROP', "Bla\x00");
+ $result = $property->validate(Property::REPAIR);
+
+ $this->assertEquals('Property is not valid UTF-8!', $result[0]['message']);
+ $this->assertEquals('Bla', $property->value);
+
+ }
+
+
+ function testValidateBadPropertyName() {
+
+ $property = Property::create("X_*&PROP*", "Bla");
+ $result = $property->validate(Property::REPAIR);
+
+ $this->assertEquals($result[0]['message'], 'The propertyname: X_*&PROP* contains invalid characters. Only A-Z, 0-9 and - are allowed');
+ $this->assertEquals('X-PROP', $property->name);
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/ReaderTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/ReaderTest.php
new file mode 100644
index 000000000..0969c6e52
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/ReaderTest.php
@@ -0,0 +1,367 @@
+<?php
+
+namespace Sabre\VObject;
+
+class ReaderTest extends \PHPUnit_Framework_TestCase {
+
+ function testReadComponent() {
+
+ $data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR";
+
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
+ $this->assertEquals('VCALENDAR', $result->name);
+ $this->assertEquals(0, count($result->children));
+
+ }
+
+ function testReadComponentUnixNewLine() {
+
+ $data = "BEGIN:VCALENDAR\nEND:VCALENDAR";
+
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
+ $this->assertEquals('VCALENDAR', $result->name);
+ $this->assertEquals(0, count($result->children));
+
+ }
+
+ function testReadComponentMacNewLine() {
+
+ $data = "BEGIN:VCALENDAR\rEND:VCALENDAR";
+
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
+ $this->assertEquals('VCALENDAR', $result->name);
+ $this->assertEquals(0, count($result->children));
+
+ }
+
+ function testReadComponentLineFold() {
+
+ $data = "BEGIN:\r\n\tVCALENDAR\r\nE\r\n ND:VCALENDAR";
+
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
+ $this->assertEquals('VCALENDAR', $result->name);
+ $this->assertEquals(0, count($result->children));
+
+ }
+
+ /**
+ * @expectedException Sabre\VObject\ParseException
+ */
+ function testReadCorruptComponent() {
+
+ $data = "BEGIN:VCALENDAR\r\nEND:FOO";
+
+ $result = Reader::read($data);
+
+ }
+
+ function testReadProperty() {
+
+ $data = "PROPNAME:propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+
+ }
+
+ function testReadPropertyWithNewLine() {
+
+ $data = 'PROPNAME:Line1\\nLine2\\NLine3\\\\Not the 4th line!';
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals("Line1\nLine2\nLine3\\Not the 4th line!", $result->value);
+
+ }
+
+ function testReadMappedProperty() {
+
+ $data = "DTSTART:20110529";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property\\DateTime', $result);
+ $this->assertEquals('DTSTART', $result->name);
+ $this->assertEquals('20110529', $result->value);
+
+ }
+
+ function testReadMappedPropertyGrouped() {
+
+ $data = "foo.DTSTART:20110529";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property\\DateTime', $result);
+ $this->assertEquals('DTSTART', $result->name);
+ $this->assertEquals('20110529', $result->value);
+
+ }
+
+
+ /**
+ * @expectedException Sabre\VObject\ParseException
+ */
+ function testReadBrokenLine() {
+
+ $data = "PROPNAME;propValue";
+ $result = Reader::read($data);
+
+ }
+
+ function testReadPropertyInComponent() {
+
+ $data = array(
+ "BEGIN:VCALENDAR",
+ "PROPNAME:propValue",
+ "END:VCALENDAR"
+ );
+
+ $result = Reader::read(implode("\r\n",$data));
+
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
+ $this->assertEquals('VCALENDAR', $result->name);
+ $this->assertEquals(1, count($result->children));
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result->children[0]);
+ $this->assertEquals('PROPNAME', $result->children[0]->name);
+ $this->assertEquals('propValue', $result->children[0]->value);
+
+ }
+ function testReadNestedComponent() {
+
+ $data = array(
+ "BEGIN:VCALENDAR",
+ "BEGIN:VTIMEZONE",
+ "BEGIN:DAYLIGHT",
+ "END:DAYLIGHT",
+ "END:VTIMEZONE",
+ "END:VCALENDAR"
+ );
+
+ $result = Reader::read(implode("\r\n",$data));
+
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
+ $this->assertEquals('VCALENDAR', $result->name);
+ $this->assertEquals(1, count($result->children));
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result->children[0]);
+ $this->assertEquals('VTIMEZONE', $result->children[0]->name);
+ $this->assertEquals(1, count($result->children[0]->children));
+ $this->assertInstanceOf('Sabre\\VObject\\Component', $result->children[0]->children[0]);
+ $this->assertEquals('DAYLIGHT', $result->children[0]->children[0]->name);
+
+
+ }
+
+ function testReadPropertyParameter() {
+
+ $data = "PROPNAME;PARAMNAME=paramvalue:propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+ $this->assertEquals(1, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+ $this->assertEquals('paramvalue', $result->parameters[0]->value);
+
+ }
+
+ function testReadPropertyNoValue() {
+
+ $data = "PROPNAME;PARAMNAME:propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+ $this->assertEquals(1, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+
+ $this->assertNull($result->parameters[0]->value);
+
+ }
+
+ function testReadPropertyParameterExtraColon() {
+
+ $data = "PROPNAME;PARAMNAME=paramvalue:propValue:anotherrandomstring";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue:anotherrandomstring', $result->value);
+ $this->assertEquals(1, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+ $this->assertEquals('paramvalue', $result->parameters[0]->value);
+
+ }
+
+ function testReadProperty2Parameters() {
+
+ $data = "PROPNAME;PARAMNAME=paramvalue;PARAMNAME2=paramvalue2:propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+ $this->assertEquals(2, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+ $this->assertEquals('paramvalue', $result->parameters[0]->value);
+ $this->assertEquals('PARAMNAME2', $result->parameters[1]->name);
+ $this->assertEquals('paramvalue2', $result->parameters[1]->value);
+
+ }
+
+ function testReadPropertyParameterQuoted() {
+
+ $data = "PROPNAME;PARAMNAME=\"paramvalue\":propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+ $this->assertEquals(1, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+ $this->assertEquals('paramvalue', $result->parameters[0]->value);
+
+ }
+ function testReadPropertyParameterNewLines() {
+
+ $data = "PROPNAME;PARAMNAME=paramvalue1\\nvalue2\\\\nvalue3:propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+
+ $this->assertEquals(1, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+ $this->assertEquals("paramvalue1\nvalue2\\nvalue3", $result->parameters[0]->value);
+
+ }
+
+ function testReadPropertyParameterQuotedColon() {
+
+ $data = "PROPNAME;PARAMNAME=\"param:value\":propValue";
+ $result = Reader::read($data);
+
+ $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
+ $this->assertEquals('PROPNAME', $result->name);
+ $this->assertEquals('propValue', $result->value);
+ $this->assertEquals(1, count($result->parameters));
+ $this->assertEquals('PARAMNAME', $result->parameters[0]->name);
+ $this->assertEquals('param:value', $result->parameters[0]->value);
+
+ }
+
+ function testReadForgiving() {
+
+ $data = array(
+ "BEGIN:VCALENDAR",
+ "X_PROP:propValue",
+ "END:VCALENDAR"
+ );
+
+ $caught = false;
+ try {
+ $result = Reader::read(implode("\r\n",$data));
+ } catch (ParseException $e) {
+ $caught = true;
+ }
+
+ $this->assertEquals(true, $caught);
+
+ $result = Reader::read(implode("\r\n",$data), Reader::OPTION_FORGIVING);
+
+ $expected = implode("\r\n", array(
+ "BEGIN:VCALENDAR",
+ "X_PROP:propValue",
+ "END:VCALENDAR",
+ ""
+ ));
+
+ $this->assertEquals($expected, $result->serialize());
+
+
+ }
+
+ function testReadWithInvalidLine() {
+
+ $data = array(
+ "BEGIN:VCALENDAR",
+ "DESCRIPTION:propValue",
+ "Yes, we've actually seen a file with non-idented property values on multiple lines",
+ "END:VCALENDAR"
+ );
+
+ $caught = false;
+ try {
+ $result = Reader::read(implode("\r\n",$data));
+ } catch (ParseException $e) {
+ $caught = true;
+ }
+
+ $this->assertEquals(true, $caught);
+
+ $result = Reader::read(implode("\r\n",$data), Reader::OPTION_IGNORE_INVALID_LINES);
+
+ $expected = implode("\r\n", array(
+ "BEGIN:VCALENDAR",
+ "DESCRIPTION:propValue",
+ "END:VCALENDAR",
+ ""
+ ));
+
+ $this->assertEquals($expected, $result->serialize());
+
+
+ }
+
+ /**
+ * Reported as Issue 32.
+ *
+ * @expectedException \Sabre\VObject\ParseException
+ */
+ function testReadIncompleteFile() {
+
+ $input = <<<ICS
+BEGIN:VCALENDAR
+VERSION:1.0
+BEGIN:VEVENT
+X-FUNAMBOL-FOLDER:DEFAULT_FOLDER
+X-FUNAMBOL-ALLDAY:0
+DTSTART:20111017T110000Z
+DTEND:20111017T123000Z
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+CATEGORIES:
+LOCATION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Netviewer Meeting
+PRIORITY:1
+STATUS:3
+X-MICROSOFT-CDO-REPLYTIME:20111017T064200Z
+SUMMARY;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Kopieren: test
+CLASS:PUBLIC
+AALARM:
+RRULE:
+X-FUNAMBOL-BILLINGINFO:
+X-FUNAMBOL-COMPANIES:
+X-FUNAMBOL-MILEAGE:
+X-FUNAMBOL-NOAGING:0
+ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Heino' heino@test.com
+ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Markus' test@test.com
+ATTENDEE;STATUS=NEEDS AC
+ICS;
+
+ Reader::read($input);
+
+ }
+
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorFifthTuesdayProblemTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorFifthTuesdayProblemTest.php
new file mode 100644
index 000000000..069832a0f
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorFifthTuesdayProblemTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Sabre\VObject;
+
+class RecurrenceIteratorFifthTuesdayProblemTest extends \PHPUnit_Framework_TestCase {
+
+ function testGetDTEnd() {
+
+ $ics = <<<ICS
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.4//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+TRANSP:OPAQUE
+DTEND;TZID=America/New_York:20070925T170000
+UID:uuid
+DTSTAMP:19700101T000000Z
+LOCATION:
+DESCRIPTION:
+STATUS:CONFIRMED
+SEQUENCE:18
+SUMMARY:Stuff
+DTSTART;TZID=America/New_York:20070925T160000
+CREATED:20071004T144642Z
+RRULE:FREQ=MONTHLY;INTERVAL=1;UNTIL=20071030T035959Z;BYDAY=5TU
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ $vObject = Reader::read($ics);
+ $it = new RecurrenceIterator($vObject, (string)$vObject->VEVENT->UID);
+
+ while($it->valid()) {
+ $it->next();
+ }
+
+ // If we got here, it means we were successful. The bug that was in the
+ // system before would fail on the 5th tuesday of the month, if the 5th
+ // tuesday did not exist.
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorIncorrectExpandTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorIncorrectExpandTest.php
new file mode 100644
index 000000000..9adc8537f
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorIncorrectExpandTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Sabre\VObject;
+
+use
+ DateTime,
+ DateTimeZone;
+
+/**
+ * This is a unittest for Issue #53.
+ */
+class RecurrenceIteratorIncorrectExpandTest extends \PHPUnit_Framework_TestCase {
+
+ function testExpand() {
+
+ $input = <<<ICS
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+UID:foo
+DTSTART:20130711T050000Z
+DTEND:20130711T053000Z
+RRULE:FREQ=DAILY;INTERVAL=1;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+UID:foo
+DTSTART:20130719T050000Z
+DTEND:20130719T053000Z
+RECURRENCE-ID:20130712T050000Z
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ $vcal = Reader::read($input);
+ $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
+
+ $vcal->expand(new DateTime('2011-01-01'), new DateTime('2014-01-01'));
+
+ $result = $vcal->serialize();
+
+ $output = <<<ICS
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+UID:foo
+DTSTART;VALUE=DATE-TIME:20130711T050000Z
+DTEND;VALUE=DATE-TIME:20130711T053000Z
+END:VEVENT
+BEGIN:VEVENT
+UID:foo
+DTSTART:20130719T050000Z
+DTEND:20130719T053000Z
+RECURRENCE-ID:20130712T050000Z
+END:VEVENT
+END:VCALENDAR
+
+ICS;
+ $this->assertEquals($output, str_replace("\r", "", $result));
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorInfiniteLoopProblemTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorInfiniteLoopProblemTest.php
new file mode 100644
index 000000000..670c39bae
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorInfiniteLoopProblemTest.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Sabre\VObject;
+
+use DateTime;
+use DateTimeZone;
+
+class RecurrenceIteratorInfiniteLoopProblemTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * This bug came from a Fruux customer. This would result in a never-ending
+ * request.
+ */
+ function testFastForwardTooFar() {
+
+ $ev = Component::create('VEVENT');
+ $ev->DTSTART = '20090420T180000Z';
+ $ev->RRULE = 'FREQ=WEEKLY;BYDAY=MO;UNTIL=20090704T205959Z;INTERVAL=1';
+
+ $this->assertFalse($ev->isInTimeRange(new DateTime('2012-01-01 12:00:00'),new DateTime('3000-01-01 00:00:00')));
+
+ }
+
+ /**
+ * Different bug, also likely an infinite loop.
+ */
+ function testYearlyByMonthLoop() {
+
+ $ev = Component::create('VEVENT');
+ $ev->UID = 'uuid';
+ $ev->DTSTART = '20120101T154500';
+ $ev->DTSTART['TZID'] = 'Europe/Berlin';
+ $ev->RRULE = 'FREQ=YEARLY;INTERVAL=1;UNTIL=20120203T225959Z;BYMONTH=2;BYSETPOS=1;BYDAY=SU,MO,TU,WE,TH,FR,SA';
+ $ev->DTEND = '20120101T164500';
+ $ev->DTEND['TZID'] = 'Europe/Berlin';
+
+ // This recurrence rule by itself is a yearly rule that should happen
+ // every february.
+ //
+ // The BYDAY part expands this to every day of the month, but the
+ // BYSETPOS limits this to only the 1st day of the month. Very crazy
+ // way to specify this, and could have certainly been a lot easier.
+ $cal = Component::create('VCALENDAR');
+ $cal->add($ev);
+
+ $it = new RecurrenceIterator($cal,'uuid');
+ $it->fastForward(new DateTime('2012-01-29 23:00:00', new DateTimeZone('UTC')));
+
+ $collect = array();
+
+ while($it->valid()) {
+ $collect[] = $it->getDTSTART();
+ if ($it->getDTSTART() > new DateTime('2013-02-05 22:59:59', new DateTimeZone('UTC'))) {
+ break;
+ }
+ $it->next();
+
+ }
+
+ $this->assertEquals(
+ array(new DateTime('2012-02-01 15:45:00', new DateTimeZone('Europe/Berlin'))),
+ $collect
+ );
+
+ }
+
+ /**
+ * Something, somewhere produced an ics with an interval set to 0. Because
+ * this means we increase the current day (or week, month) by 0, this also
+ * results in an infinite loop.
+ *
+ * @expectedException InvalidArgumentException
+ * @return void
+ */
+ function testZeroInterval() {
+
+ $ev = Component::create('VEVENT');
+ $ev->UID = 'uuid';
+ $ev->DTSTART = '20120824T145700Z';
+ $ev->RRULE = 'FREQ=YEARLY;INTERVAL=0';
+ $cal = Component::create('VCALENDAR');
+ $cal->add($ev);
+
+ $it = new RecurrenceIterator($cal,'uuid');
+ $it->fastForward(new DateTime('2013-01-01 23:00:00', new DateTimeZone('UTC')));
+
+ // if we got this far.. it means we are no longer infinitely looping
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMinusOneProblemTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMinusOneProblemTest.php
new file mode 100644
index 000000000..2c17f9f6b
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMinusOneProblemTest.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Sabre\VObject;
+
+class RecurrenceIteratorMinusOneProblemTest extends \PHPUnit_Framework_TestCase {
+
+ function testMinusOne() {
+
+ $ics = <<<ICS
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+DTSTAMP:20120314T203127Z
+UID:foo
+SUMMARY:foo
+RRULE:FREQ=YEARLY;UNTIL=20120314
+DTSTART;VALUE=DATE:20120315
+DTEND;VALUE=DATE:20120316
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ $vObject = Reader::read($ics);
+ $it = new RecurrenceIterator($vObject, (string)$vObject->VEVENT->UID);
+
+ $this->assertTrue($it->valid());
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMissingOverriddenTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMissingOverriddenTest.php
new file mode 100644
index 000000000..f311329db
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorMissingOverriddenTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Sabre\VObject;
+
+use
+ DateTime,
+ DateTimeZone;
+
+class RecurrenceIteratorMissingOverriddenTest extends \PHPUnit_Framework_TestCase {
+
+ function testExpand() {
+
+ $input = <<<ICS
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+UID:foo
+DTSTART:20130727T120000Z
+DURATION:PT1H
+RRULE:FREQ=DAILY;COUNT=2
+SUMMARY:A
+END:VEVENT
+BEGIN:VEVENT
+RECURRENCE-ID:20130728T120000Z
+UID:foo
+DTSTART:20140101T120000Z
+DURATION:PT1H
+SUMMARY:B
+END:VEVENT
+END:VCALENDAR
+ICS;
+
+ $vcal = Reader::read($input);
+ $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
+
+ $vcal->expand(new DateTime('2011-01-01'), new DateTime('2015-01-01'));
+
+ $result = $vcal->serialize();
+
+ $output = <<<ICS
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+UID:foo
+DTSTART;VALUE=DATE-TIME:20130727T120000Z
+DURATION:PT1H
+SUMMARY:A
+END:VEVENT
+BEGIN:VEVENT
+RECURRENCE-ID:20130728T120000Z
+UID:foo
+DTSTART:20140101T120000Z
+DURATION:PT1H
+SUMMARY:B
+END:VEVENT
+END:VCALENDAR
+
+ICS;
+ $this->assertEquals($output, str_replace("\r","",$result));
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorTest.php
new file mode 100644
index 000000000..1811d8b6f
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/RecurrenceIteratorTest.php
@@ -0,0 +1,1425 @@
+<?php
+
+namespace Sabre\VObject;
+
+use DateTime;
+use DateTimeZone;
+
+class RecurrenceIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ function testValues() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=DAILY;BYHOUR=10;BYMINUTE=5;BYSECOND=16;BYWEEKNO=32;BYYEARDAY=100,200';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07'),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertTrue($it->isInfinite());
+ $this->assertEquals(array(10), $it->byHour);
+ $this->assertEquals(array(5), $it->byMinute);
+ $this->assertEquals(array(16), $it->bySecond);
+ $this->assertEquals(array(32), $it->byWeekNo);
+ $this->assertEquals(array(100,200), $it->byYearDay);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @depends testValues
+ */
+ function testInvalidFreq() {
+
+ $ev = new Component('VEVENT');
+ $ev->RRULE = 'FREQ=SMONTHLY;INTERVAL=3;UNTIL=20111025T000000Z';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07'),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testVCalendarNoUID() {
+
+ $vcal = new Component('VCALENDAR');
+ $it = new RecurrenceIterator($vcal);
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testVCalendarInvalidUID() {
+
+ $vcal = new Component('VCALENDAR');
+ $it = new RecurrenceIterator($vcal,'foo');
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testHourly() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=HOURLY;INTERVAL=3;UNTIL=20111025T000000Z';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07 12:00:00', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,$ev->uid);
+
+ $this->assertEquals('hourly', $it->frequency);
+ $this->assertEquals(3, $it->interval);
+ $this->assertEquals(new DateTime('2011-10-25', new DateTimeZone('UTC')), $it->until);
+
+ // Max is to prevent overflow
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07 12:00:00', $tz),
+ new DateTime('2011-10-07 15:00:00', $tz),
+ new DateTime('2011-10-07 18:00:00', $tz),
+ new DateTime('2011-10-07 21:00:00', $tz),
+ new DateTime('2011-10-08 00:00:00', $tz),
+ new DateTime('2011-10-08 03:00:00', $tz),
+ new DateTime('2011-10-08 06:00:00', $tz),
+ new DateTime('2011-10-08 09:00:00', $tz),
+ new DateTime('2011-10-08 12:00:00', $tz),
+ new DateTime('2011-10-08 15:00:00', $tz),
+ new DateTime('2011-10-08 18:00:00', $tz),
+ new DateTime('2011-10-08 21:00:00', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testDaily() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=DAILY;INTERVAL=3;UNTIL=20111025T000000Z';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,$ev->uid);
+
+ $this->assertEquals('daily', $it->frequency);
+ $this->assertEquals(3, $it->interval);
+ $this->assertEquals(new DateTime('2011-10-25', new DateTimeZone('UTC')), $it->until);
+
+ // Max is to prevent overflow
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07', $tz),
+ new DateTime('2011-10-10', $tz),
+ new DateTime('2011-10-13', $tz),
+ new DateTime('2011-10-16', $tz),
+ new DateTime('2011-10-19', $tz),
+ new DateTime('2011-10-22', $tz),
+ new DateTime('2011-10-25', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testNoRRULE() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,$ev->uid);
+
+ $this->assertEquals('daily', $it->frequency);
+ $this->assertEquals(1, $it->interval);
+
+ // Max is to prevent overflow
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testDailyByDayByHour() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=DAILY;BYDAY=SA,SU;BYHOUR=6,7';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-08 06:00:00', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('daily', $it->frequency);
+ $this->assertEquals(1, $it->interval);
+ $this->assertEquals(array('6','7'), $it->byHour);
+ $this->assertEquals(array('SA','SU'), $it->byDay);
+
+ // Grabbing the next 12 items
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new datetime('2011-10-08 06:00:00', $tz),
+ new datetime('2011-10-08 07:00:00', $tz),
+ new datetime('2011-10-09 06:00:00', $tz),
+ new datetime('2011-10-09 07:00:00', $tz),
+ new datetime('2011-10-15 06:00:00', $tz),
+ new datetime('2011-10-15 07:00:00', $tz),
+ new datetime('2011-10-16 06:00:00', $tz),
+ new datetime('2011-10-16 07:00:00', $tz),
+ new datetime('2011-10-22 06:00:00', $tz),
+ new datetime('2011-10-22 07:00:00', $tz),
+ new datetime('2011-10-23 06:00:00', $tz),
+ new datetime('2011-10-23 07:00:00', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testDailyByHour() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=DAILY;INTERVAL=2;BYHOUR=10,11,12,13,14,15';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2012-10-11 12:00:00', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('daily', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(array('10','11','12','13','14','15'), $it->byHour);
+
+ // Grabbing the next 12 items
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new datetime('2012-10-11 12:00:00', $tz),
+ new datetime('2012-10-11 13:00:00', $tz),
+ new datetime('2012-10-11 14:00:00', $tz),
+ new datetime('2012-10-11 15:00:00', $tz),
+ new datetime('2012-10-13 10:00:00', $tz),
+ new datetime('2012-10-13 11:00:00', $tz),
+ new datetime('2012-10-13 12:00:00', $tz),
+ new datetime('2012-10-13 13:00:00', $tz),
+ new datetime('2012-10-13 14:00:00', $tz),
+ new datetime('2012-10-13 15:00:00', $tz),
+ new datetime('2012-10-15 10:00:00', $tz),
+ new datetime('2012-10-15 11:00:00', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testDailyByDay() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=DAILY;INTERVAL=2;BYDAY=TU,WE,FR';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('daily', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(array('TU','WE','FR'), $it->byDay);
+
+ // Grabbing the next 12 items
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07', $tz),
+ new DateTime('2011-10-11', $tz),
+ new DateTime('2011-10-19', $tz),
+ new DateTime('2011-10-21', $tz),
+ new DateTime('2011-10-25', $tz),
+ new DateTime('2011-11-02', $tz),
+ new DateTime('2011-11-04', $tz),
+ new DateTime('2011-11-08', $tz),
+ new DateTime('2011-11-16', $tz),
+ new DateTime('2011-11-18', $tz),
+ new DateTime('2011-11-22', $tz),
+ new DateTime('2011-11-30', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testWeekly() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;COUNT=10';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('weekly', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(10, $it->count);
+
+ // Max is to prevent overflow
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07', $tz),
+ new DateTime('2011-10-21', $tz),
+ new DateTime('2011-11-04', $tz),
+ new DateTime('2011-11-18', $tz),
+ new DateTime('2011-12-02', $tz),
+ new DateTime('2011-12-16', $tz),
+ new DateTime('2011-12-30', $tz),
+ new DateTime('2012-01-13', $tz),
+ new DateTime('2012-01-27', $tz),
+ new DateTime('2012-02-10', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testWeeklyByDayByHour() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=MO;BYHOUR=8,9,10';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07 08:00:00', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('weekly', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(array('TU','WE','FR'), $it->byDay);
+ $this->assertEquals(array('8','9','10'), $it->byHour);
+ $this->assertEquals('MO', $it->weekStart);
+
+ // Grabbing the next 12 items
+ $max = 15;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07 08:00:00', $tz),
+ new DateTime('2011-10-07 09:00:00', $tz),
+ new DateTime('2011-10-07 10:00:00', $tz),
+ new DateTime('2011-10-18 08:00:00', $tz),
+ new DateTime('2011-10-18 09:00:00', $tz),
+ new DateTime('2011-10-18 10:00:00', $tz),
+ new DateTime('2011-10-19 08:00:00', $tz),
+ new DateTime('2011-10-19 09:00:00', $tz),
+ new DateTime('2011-10-19 10:00:00', $tz),
+ new DateTime('2011-10-21 08:00:00', $tz),
+ new DateTime('2011-10-21 09:00:00', $tz),
+ new DateTime('2011-10-21 10:00:00', $tz),
+ new DateTime('2011-11-01 08:00:00', $tz),
+ new DateTime('2011-11-01 09:00:00', $tz),
+ new DateTime('2011-11-01 10:00:00', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testWeeklyByDaySpecificHour() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=SU';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07 18:00:00', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('weekly', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(array('TU','WE','FR'), $it->byDay);
+ $this->assertEquals('SU', $it->weekStart);
+
+ // Grabbing the next 12 items
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07 18:00:00', $tz),
+ new DateTime('2011-10-18 18:00:00', $tz),
+ new DateTime('2011-10-19 18:00:00', $tz),
+ new DateTime('2011-10-21 18:00:00', $tz),
+ new DateTime('2011-11-01 18:00:00', $tz),
+ new DateTime('2011-11-02 18:00:00', $tz),
+ new DateTime('2011-11-04 18:00:00', $tz),
+ new DateTime('2011-11-15 18:00:00', $tz),
+ new DateTime('2011-11-16 18:00:00', $tz),
+ new DateTime('2011-11-18 18:00:00', $tz),
+ new DateTime('2011-11-29 18:00:00', $tz),
+ new DateTime('2011-11-30 18:00:00', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testWeeklyByDay() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=SU';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-10-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('weekly', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(array('TU','WE','FR'), $it->byDay);
+ $this->assertEquals('SU', $it->weekStart);
+
+ // Grabbing the next 12 items
+ $max = 12;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-10-07', $tz),
+ new DateTime('2011-10-18', $tz),
+ new DateTime('2011-10-19', $tz),
+ new DateTime('2011-10-21', $tz),
+ new DateTime('2011-11-01', $tz),
+ new DateTime('2011-11-02', $tz),
+ new DateTime('2011-11-04', $tz),
+ new DateTime('2011-11-15', $tz),
+ new DateTime('2011-11-16', $tz),
+ new DateTime('2011-11-18', $tz),
+ new DateTime('2011-11-29', $tz),
+ new DateTime('2011-11-30', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testMonthly() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=3;COUNT=5';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-12-05', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('monthly', $it->frequency);
+ $this->assertEquals(3, $it->interval);
+ $this->assertEquals(5, $it->count);
+
+ $max = 14;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-12-05', $tz),
+ new DateTime('2012-03-05', $tz),
+ new DateTime('2012-06-05', $tz),
+ new DateTime('2012-09-05', $tz),
+ new DateTime('2012-12-05', $tz),
+ ),
+ $result
+ );
+
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testMonthlyEndOfMonth() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=2;COUNT=12';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-12-31', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('monthly', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(12, $it->count);
+
+ $max = 14;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-12-31', $tz),
+ new DateTime('2012-08-31', $tz),
+ new DateTime('2012-10-31', $tz),
+ new DateTime('2012-12-31', $tz),
+ new DateTime('2013-08-31', $tz),
+ new DateTime('2013-10-31', $tz),
+ new DateTime('2013-12-31', $tz),
+ new DateTime('2014-08-31', $tz),
+ new DateTime('2014-10-31', $tz),
+ new DateTime('2014-12-31', $tz),
+ new DateTime('2015-08-31', $tz),
+ new DateTime('2015-10-31', $tz),
+ ),
+ $result
+ );
+
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testMonthlyByMonthDay() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=5;COUNT=9;BYMONTHDAY=1,31,-7';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-01-01', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('monthly', $it->frequency);
+ $this->assertEquals(5, $it->interval);
+ $this->assertEquals(9, $it->count);
+ $this->assertEquals(array(1, 31, -7), $it->byMonthDay);
+
+ $max = 14;
+ $result = array();
+ foreach($it as $item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-01-01', $tz),
+ new DateTime('2011-01-25', $tz),
+ new DateTime('2011-01-31', $tz),
+ new DateTime('2011-06-01', $tz),
+ new DateTime('2011-06-24', $tz),
+ new DateTime('2011-11-01', $tz),
+ new DateTime('2011-11-24', $tz),
+ new DateTime('2012-04-01', $tz),
+ new DateTime('2012-04-24', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testMonthlyByDay() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=2;COUNT=16;BYDAY=MO,-2TU,+1WE,3TH';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-01-03', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('monthly', $it->frequency);
+ $this->assertEquals(2, $it->interval);
+ $this->assertEquals(16, $it->count);
+ $this->assertEquals(array('MO','-2TU','+1WE','3TH'), $it->byDay);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-01-03', $tz),
+ new DateTime('2011-01-05', $tz),
+ new DateTime('2011-01-10', $tz),
+ new DateTime('2011-01-17', $tz),
+ new DateTime('2011-01-18', $tz),
+ new DateTime('2011-01-20', $tz),
+ new DateTime('2011-01-24', $tz),
+ new DateTime('2011-01-31', $tz),
+ new DateTime('2011-03-02', $tz),
+ new DateTime('2011-03-07', $tz),
+ new DateTime('2011-03-14', $tz),
+ new DateTime('2011-03-17', $tz),
+ new DateTime('2011-03-21', $tz),
+ new DateTime('2011-03-22', $tz),
+ new DateTime('2011-03-28', $tz),
+ new DateTime('2011-05-02', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testMonthlyByDayByMonthDay() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=MONTHLY;COUNT=10;BYDAY=MO;BYMONTHDAY=1';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-08-01', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('monthly', $it->frequency);
+ $this->assertEquals(1, $it->interval);
+ $this->assertEquals(10, $it->count);
+ $this->assertEquals(array('MO'), $it->byDay);
+ $this->assertEquals(array(1), $it->byMonthDay);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-08-01', $tz),
+ new DateTime('2012-10-01', $tz),
+ new DateTime('2013-04-01', $tz),
+ new DateTime('2013-07-01', $tz),
+ new DateTime('2014-09-01', $tz),
+ new DateTime('2014-12-01', $tz),
+ new DateTime('2015-06-01', $tz),
+ new DateTime('2016-02-01', $tz),
+ new DateTime('2016-08-01', $tz),
+ new DateTime('2017-05-01', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testMonthlyByDayBySetPos() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=MONTHLY;COUNT=10;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1,-1';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-01-03', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('monthly', $it->frequency);
+ $this->assertEquals(1, $it->interval);
+ $this->assertEquals(10, $it->count);
+ $this->assertEquals(array('MO','TU','WE','TH','FR'), $it->byDay);
+ $this->assertEquals(array(1,-1), $it->bySetPos);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-01-03', $tz),
+ new DateTime('2011-01-31', $tz),
+ new DateTime('2011-02-01', $tz),
+ new DateTime('2011-02-28', $tz),
+ new DateTime('2011-03-01', $tz),
+ new DateTime('2011-03-31', $tz),
+ new DateTime('2011-04-01', $tz),
+ new DateTime('2011-04-29', $tz),
+ new DateTime('2011-05-02', $tz),
+ new DateTime('2011-05-31', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testYearly() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=YEARLY;COUNT=10;INTERVAL=3';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-01-01', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('yearly', $it->frequency);
+ $this->assertEquals(3, $it->interval);
+ $this->assertEquals(10, $it->count);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-01-01', $tz),
+ new DateTime('2014-01-01', $tz),
+ new DateTime('2017-01-01', $tz),
+ new DateTime('2020-01-01', $tz),
+ new DateTime('2023-01-01', $tz),
+ new DateTime('2026-01-01', $tz),
+ new DateTime('2029-01-01', $tz),
+ new DateTime('2032-01-01', $tz),
+ new DateTime('2035-01-01', $tz),
+ new DateTime('2038-01-01', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testYearlyLeapYear() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=YEARLY;COUNT=3';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2012-02-29', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('yearly', $it->frequency);
+ $this->assertEquals(3, $it->count);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2012-02-29', $tz),
+ new DateTime('2016-02-29', $tz),
+ new DateTime('2020-02-29', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testYearlyByMonth() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=4;BYMONTH=4,10';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-04-07', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('yearly', $it->frequency);
+ $this->assertEquals(4, $it->interval);
+ $this->assertEquals(8, $it->count);
+ $this->assertEquals(array(4,10), $it->byMonth);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-04-07', $tz),
+ new DateTime('2011-10-07', $tz),
+ new DateTime('2015-04-07', $tz),
+ new DateTime('2015-10-07', $tz),
+ new DateTime('2019-04-07', $tz),
+ new DateTime('2019-10-07', $tz),
+ new DateTime('2023-04-07', $tz),
+ new DateTime('2023-10-07', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testYearlyByMonthByDay() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=5;BYMONTH=4,10;BYDAY=1MO,-1SU';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-04-04', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('yearly', $it->frequency);
+ $this->assertEquals(5, $it->interval);
+ $this->assertEquals(8, $it->count);
+ $this->assertEquals(array(4,10), $it->byMonth);
+ $this->assertEquals(array('1MO','-1SU'), $it->byDay);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-04-04', $tz),
+ new DateTime('2011-04-24', $tz),
+ new DateTime('2011-10-03', $tz),
+ new DateTime('2011-10-30', $tz),
+ new DateTime('2016-04-04', $tz),
+ new DateTime('2016-04-24', $tz),
+ new DateTime('2016-10-03', $tz),
+ new DateTime('2016-10-30', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testFastForward() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=5;BYMONTH=4,10;BYDAY=1MO,-1SU';
+ $dtStart = new Property\DateTime('DTSTART');
+ $dtStart->setDateTime(new DateTime('2011-04-04', new DateTimeZone('UTC')),Property\DateTime::UTC);
+
+ $ev->add($dtStart);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ // The idea is that we're fast-forwarding too far in the future, so
+ // there will be no results left.
+ $it->fastForward(new DateTime('2020-05-05', new DateTimeZone('UTC')));
+
+ $max = 20;
+ $result = array();
+ while($item = $it->current()) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+ $it->next();
+
+ }
+
+ $tz = new DateTimeZone('UTC');
+ $this->assertEquals(array(), $result);
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testComplexExclusions() {
+
+ $ev = new Component('VEVENT');
+ $ev->UID = 'bla';
+ $ev->RRULE = 'FREQ=YEARLY;COUNT=10';
+ $dtStart = new Property\DateTime('DTSTART');
+
+ $tz = new DateTimeZone('Canada/Eastern');
+ $dtStart->setDateTime(new DateTime('2011-01-01 13:50:20', $tz),Property\DateTime::LOCALTZ);
+
+ $exDate1 = new Property\MultiDateTime('EXDATE');
+ $exDate1->setDateTimes(array(new DateTime('2012-01-01 13:50:20', $tz), new DateTime('2014-01-01 13:50:20', $tz)), Property\DateTime::LOCALTZ);
+ $exDate2 = new Property\MultiDateTime('EXDATE');
+ $exDate2->setDateTimes(array(new DateTime('2016-01-01 13:50:20', $tz)), Property\DateTime::LOCALTZ);
+
+ $ev->add($dtStart);
+ $ev->add($exDate1);
+ $ev->add($exDate2);
+
+ $vcal = Component::create('VCALENDAR');
+ $vcal->add($ev);
+
+ $it = new RecurrenceIterator($vcal,(string)$ev->uid);
+
+ $this->assertEquals('yearly', $it->frequency);
+ $this->assertEquals(1, $it->interval);
+ $this->assertEquals(10, $it->count);
+
+ $max = 20;
+ $result = array();
+ foreach($it as $k=>$item) {
+
+ $result[] = $item;
+ $max--;
+
+ if (!$max) break;
+
+ }
+
+ $this->assertEquals(
+ array(
+ new DateTime('2011-01-01 13:50:20', $tz),
+ new DateTime('2013-01-01 13:50:20', $tz),
+ new DateTime('2015-01-01 13:50:20', $tz),
+ new DateTime('2017-01-01 13:50:20', $tz),
+ new DateTime('2018-01-01 13:50:20', $tz),
+ new DateTime('2019-01-01 13:50:20', $tz),
+ new DateTime('2020-01-01 13:50:20', $tz),
+ ),
+ $result
+ );
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testOverridenEvent() {
+
+ $vcal = Component::create('VCALENDAR');
+
+ $ev1 = Component::create('VEVENT');
+ $ev1->UID = 'overridden';
+ $ev1->RRULE = 'FREQ=DAILY;COUNT=10';
+ $ev1->DTSTART = '20120107T120000Z';
+ $ev1->SUMMARY = 'baseEvent';
+
+ $vcal->add($ev1);
+
+ // ev2 overrides an event, and puts it on 2pm instead.
+ $ev2 = Component::create('VEVENT');
+ $ev2->UID = 'overridden';
+ $ev2->{'RECURRENCE-ID'} = '20120110T120000Z';
+ $ev2->DTSTART = '20120110T140000Z';
+ $ev2->SUMMARY = 'Event 2';
+
+ $vcal->add($ev2);
+
+ // ev3 overrides an event, and puts it 2 days and 2 hours later
+ $ev3 = Component::create('VEVENT');
+ $ev3->UID = 'overridden';
+ $ev3->{'RECURRENCE-ID'} = '20120113T120000Z';
+ $ev3->DTSTART = '20120115T140000Z';
+ $ev3->SUMMARY = 'Event 3';
+
+ $vcal->add($ev3);
+
+ $it = new RecurrenceIterator($vcal,'overridden');
+
+ $dates = array();
+ $summaries = array();
+ while($it->valid()) {
+
+ $dates[] = $it->getDTStart();
+ $summaries[] = (string)$it->getEventObject()->SUMMARY;
+ $it->next();
+
+ }
+
+ $tz = new DateTimeZone('GMT');
+ $this->assertEquals(array(
+ new DateTime('2012-01-07 12:00:00',$tz),
+ new DateTime('2012-01-08 12:00:00',$tz),
+ new DateTime('2012-01-09 12:00:00',$tz),
+ new DateTime('2012-01-10 14:00:00',$tz),
+ new DateTime('2012-01-11 12:00:00',$tz),
+ new DateTime('2012-01-12 12:00:00',$tz),
+ new DateTime('2012-01-14 12:00:00',$tz),
+ new DateTime('2012-01-15 12:00:00',$tz),
+ new DateTime('2012-01-15 14:00:00',$tz),
+ new DateTime('2012-01-16 12:00:00',$tz),
+ ), $dates);
+
+ $this->assertEquals(array(
+ 'baseEvent',
+ 'baseEvent',
+ 'baseEvent',
+ 'Event 2',
+ 'baseEvent',
+ 'baseEvent',
+ 'baseEvent',
+ 'baseEvent',
+ 'Event 3',
+ 'baseEvent',
+ ), $summaries);
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testOverridenEvent2() {
+
+ $vcal = Component::create('VCALENDAR');
+
+ $ev1 = Component::create('VEVENT');
+ $ev1->UID = 'overridden';
+ $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3';
+ $ev1->DTSTART = '20120112T120000Z';
+ $ev1->SUMMARY = 'baseEvent';
+
+ $vcal->add($ev1);
+
+ // ev2 overrides an event, and puts it 6 days earlier instead.
+ $ev2 = Component::create('VEVENT');
+ $ev2->UID = 'overridden';
+ $ev2->{'RECURRENCE-ID'} = '20120119T120000Z';
+ $ev2->DTSTART = '20120113T120000Z';
+ $ev2->SUMMARY = 'Override!';
+
+ $vcal->add($ev2);
+
+ $it = new RecurrenceIterator($vcal,'overridden');
+
+ $dates = array();
+ $summaries = array();
+ while($it->valid()) {
+
+ $dates[] = $it->getDTStart();
+ $summaries[] = (string)$it->getEventObject()->SUMMARY;
+ $it->next();
+
+ }
+
+ $tz = new DateTimeZone('GMT');
+ $this->assertEquals(array(
+ new DateTime('2012-01-12 12:00:00',$tz),
+ new DateTime('2012-01-13 12:00:00',$tz),
+ new DateTime('2012-01-26 12:00:00',$tz),
+
+ ), $dates);
+
+ $this->assertEquals(array(
+ 'baseEvent',
+ 'Override!',
+ 'baseEvent',
+ ), $summaries);
+
+ }
+
+ /**
+ * @depends testValues
+ */
+ function testOverridenEventNoValuesExpected() {
+
+ $vcal = Component::create('VCALENDAR');
+
+ $ev1 = Component::create('VEVENT');
+ $ev1->UID = 'overridden';
+ $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3';
+ $ev1->DTSTART = '20120124T120000Z';
+ $ev1->SUMMARY = 'baseEvent';
+
+ $vcal->add($ev1);
+
+ // ev2 overrides an event, and puts it 6 days earlier instead.
+ $ev2 = Component::create('VEVENT');
+ $ev2->UID = 'overridden';
+ $ev2->{'RECURRENCE-ID'} = '20120131T120000Z';
+ $ev2->DTSTART = '20120125T120000Z';
+ $ev2->SUMMARY = 'Override!';
+
+ $vcal->add($ev2);
+
+ $it = new RecurrenceIterator($vcal,'overridden');
+
+ $dates = array();
+ $summaries = array();
+
+ // The reported problem was specifically related to the VCALENDAR
+ // expansion. In this parcitular case, we had to forward to the 28th of
+ // january.
+ $it->fastForward(new DateTime('2012-01-28 23:00:00'));
+
+ // We stop the loop when it hits the 6th of februari. Normally this
+ // iterator would hit 24, 25 (overriden from 31) and 7 feb but because
+ // we 'filter' from the 28th till the 6th, we should get 0 results.
+ while($it->valid() && $it->getDTSTart() < new DateTime('2012-02-06 23:00:00')) {
+
+ $dates[] = $it->getDTStart();
+ $summaries[] = (string)$it->getEventObject()->SUMMARY;
+ $it->next();
+
+ }
+
+ $this->assertEquals(array(), $dates);
+ $this->assertEquals(array(), $summaries);
+
+ }
+}
+
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/SlashRTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/SlashRTest.php
new file mode 100644
index 000000000..ebbfb04a7
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/SlashRTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Sabre\VObject;
+
+/**
+ * This issue was pointed out in Issue 55. \r should be stripped completely
+ * when encoding property values.
+ */
+class SlashRTest extends \PHPUnit_Framework_TestCase {
+
+ function testEncode() {
+
+ $prop = new \Sabre\VObject\Property('test', "abc\r\ndef");
+ $this->assertEquals("TEST:abc\\ndef\r\n", $prop->serialize());
+
+ }
+
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Splitter/ICalendarTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Splitter/ICalendarTest.php
new file mode 100644
index 000000000..43613350f
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Splitter/ICalendarTest.php
@@ -0,0 +1,283 @@
+<?php
+
+namespace Sabre\VObject\Splitter;
+
+use Sabre\VObject;
+
+class ICalendarSplitterTest extends \PHPUnit_Framework_TestCase {
+
+ protected $version;
+
+ function setup() {
+ $this->version = VObject\Version::VERSION;
+ }
+
+ function createStream($data) {
+
+ $stream = fopen('php://memory','r+');
+ fwrite($stream, $data);
+ rewind($stream);
+ return $stream;
+
+ }
+
+ function testICalendarImportValidEvent() {
+
+ $data = <<<EOT
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+UID:foo
+END:VEVENT
+END:VCALENDAR
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+ $this->assertEquals(array(), VObject\Reader::read($return)->validate());
+ }
+
+ function testICalendarImportEndOfData() {
+ $data = <<<EOT
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+UID:foo
+END:VEVENT
+END:VCALENDAR
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+ $this->assertNull($object=$objects->getNext());
+ }
+
+ /**
+ * @expectedException Sabre\VObject\ParseException
+ */
+ function testICalendarImportInvalidEvent() {
+ $data = <<<EOT
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+ }
+
+ function testICalendarImportMultipleValidEvents() {
+
+ $event[] = <<<EOT
+BEGIN:VEVENT
+UID:foo1
+END:VEVENT
+EOT;
+
+$event[] = <<<EOT
+BEGIN:VEVENT
+UID:foo2
+END:VEVENT
+EOT;
+
+ $data = <<<EOT
+BEGIN:VCALENDAR
+$event[0]
+$event[1]
+END:VCALENDAR
+
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+
+ $return = "";
+ $i = 0;
+ while($object=$objects->getNext()) {
+
+ $expected = <<<EOT
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Sabre//Sabre VObject $this->version//EN
+CALSCALE:GREGORIAN
+$event[$i]
+END:VCALENDAR
+
+EOT;
+
+ $return .= $object->serialize();
+ $expected = str_replace("\n", "\r\n", $expected);
+ $this->assertEquals($expected, $object->serialize());
+ $i++;
+ }
+ $this->assertEquals(array(), VObject\Reader::read($return)->validate());
+ }
+
+ function testICalendarImportEventWithoutUID() {
+
+ $data = <<<EOT
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Sabre//Sabre VObject $this->version//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+END:VEVENT
+END:VCALENDAR
+
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $expected = str_replace("\n", "\r\n", $data);
+ $this->assertEquals($expected, $object->serialize());
+ $return .= $object->serialize();
+ }
+
+ $this->assertEquals(array(), VObject\Reader::read($return)->validate());
+ }
+
+ function testICalendarImportMultipleVTIMEZONESAndMultipleValidEvents() {
+
+ $timezones = <<<EOT
+BEGIN:VTIMEZONE
+TZID:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+DTSTART:19810329T020000
+TZNAME:MESZ
+TZOFFSETTO:+0200
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+DTSTART:19961027T030000
+TZNAME:MEZ
+TZOFFSETTO:+0100
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VTIMEZONE
+TZID:Europe/London
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+DTSTART:19810329T010000
+TZNAME:GMT+01:00
+TZOFFSETTO:+0100
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0100
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+DTSTART:19961027T020000
+TZNAME:GMT
+TZOFFSETTO:+0000
+END:STANDARD
+END:VTIMEZONE
+EOT;
+
+ $event[] = <<<EOT
+BEGIN:VEVENT
+UID:foo1
+END:VEVENT
+EOT;
+
+ $event[] = <<<EOT
+BEGIN:VEVENT
+UID:foo2
+END:VEVENT
+EOT;
+
+ $event[] = <<<EOT
+BEGIN:VEVENT
+UID:foo3
+END:VEVENT
+EOT;
+
+ $data = <<<EOT
+BEGIN:VCALENDAR
+$timezones
+$event[0]
+$event[1]
+$event[2]
+END:VCALENDAR
+
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+
+ $return = "";
+ $i = 0;
+ while($object=$objects->getNext()) {
+
+ $expected = <<<EOT
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Sabre//Sabre VObject $this->version//EN
+CALSCALE:GREGORIAN
+$timezones
+$event[$i]
+END:VCALENDAR
+
+EOT;
+ $expected = str_replace("\n", "\r\n", $expected);
+
+ $this->assertEquals($expected, $object->serialize());
+ $return .= $object->serialize();
+ $i++;
+
+ }
+
+ $this->assertEquals(array(), VObject\Reader::read($return)->validate());
+ $this->assertEquals(array(), VObject\Reader::read($return)->validate());
+ }
+
+ function testICalendarImportWithOutVTIMEZONES() {
+
+ $data = <<<EOT
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//Mac OS X 10.8//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20120605T072109Z
+UID:D6716295-C10F-4B20-82F9-E1A3026C7DCF
+DTEND;VALUE=DATE:20120717
+TRANSP:TRANSPARENT
+SUMMARY:Start Vorbereitung
+DTSTART;VALUE=DATE:20120716
+DTSTAMP:20120605T072115Z
+SEQUENCE:2
+BEGIN:VALARM
+X-WR-ALARMUID:A99EDA6A-35EB-4446-B8BC-CDA3C60C627D
+UID:A99EDA6A-35EB-4446-B8BC-CDA3C60C627D
+TRIGGER:-PT15H
+X-APPLE-DEFAULT-ALARM:TRUE
+ATTACH;VALUE=URI:Basso
+ACTION:AUDIO
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new ICalendar($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+
+ $this->assertEquals(array(), VObject\Reader::read($return)->validate());
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/Splitter/VCardTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/Splitter/VCardTest.php
new file mode 100644
index 000000000..b6b41925f
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/Splitter/VCardTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace Sabre\VObject\Splitter;
+
+use Sabre\VObject;
+
+class VCardSplitterTest extends \PHPUnit_Framework_TestCase {
+
+ function createStream($data) {
+
+ $stream = fopen('php://memory','r+');
+ fwrite($stream, $data);
+ rewind($stream);
+ return $stream;
+
+ }
+
+ function testVCardImportValidVCard() {
+ $data = <<<EOT
+BEGIN:VCARD
+UID:foo
+END:VCARD
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new VCard($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+
+ VObject\Reader::read($return);
+ }
+
+ function testVCardImportValidVCardsWithCategories() {
+ $data = <<<EOT
+BEGIN:VCARD
+UID:card-in-foo1-and-foo2
+CATEGORIES:foo1\,foo2
+END:VCARD
+BEGIN:VCARD
+UID:card-in-foo1
+CATEGORIES:foo1
+END:VCARD
+BEGIN:VCARD
+UID:card-in-foo3
+CATEGORIES:foo3
+END:VCARD
+BEGIN:VCARD
+UID:card-in-foo1-and-foo3
+CATEGORIES:foo1\,foo3
+END:VCARD
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new VCard($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+
+ VObject\Reader::read($return);
+ }
+
+ function testVCardImportEndOfData() {
+ $data = <<<EOT
+BEGIN:VCARD
+UID:foo
+END:VCARD
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new VCard($tempFile);
+ $object=$objects->getNext();
+
+ $this->assertFalse($object=$objects->getNext());
+
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testVCardImportCheckInvalidArgumentException() {
+ $data = <<<EOT
+BEGIN:FOO
+END:FOO
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new VCard($tempFile);
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+
+ }
+
+ function testVCardImportMultipleValidVCards() {
+ $data = <<<EOT
+BEGIN:VCARD
+UID:foo
+END:VCARD
+BEGIN:VCARD
+UID:foo
+END:VCARD
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new VCard($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+
+ VObject\Reader::read($return);
+ }
+
+ function testVCardImportVCardWithoutUID() {
+ $data = <<<EOT
+BEGIN:VCARD
+END:VCARD
+EOT;
+ $tempFile = $this->createStream($data);
+
+ $objects = new VCard($tempFile);
+
+ $return = "";
+ while($object=$objects->getNext()) {
+ $return .= $object->serialize();
+ }
+
+ VObject\Reader::read($return);
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/StringUtilTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/StringUtilTest.php
new file mode 100644
index 000000000..59a83d294
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/StringUtilTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Sabre\VObject;
+
+class StringUtilTest extends \PHPUnit_Framework_TestCase {
+
+ function testNonUTF8() {
+
+ $string = StringUtil::isUTF8(chr('0xbf'));
+
+ $this->assertEquals(false, $string);
+
+ }
+
+ function testIsUTF8() {
+
+ $string = StringUtil::isUTF8('I 💚 SabreDAV');
+
+ $this->assertEquals(true, $string);
+
+ }
+
+ function testUTF8ControlChar() {
+
+ $string = StringUtil::isUTF8(chr('0x00'));
+
+ $this->assertEquals(false, $string);
+
+ }
+
+ function testConvertToUTF8nonUTF8() {
+
+ $string = StringUtil::convertToUTF8(chr('0xbf'));
+
+ $this->assertEquals(utf8_encode(chr('0xbf')), $string);
+
+ }
+
+ function testConvertToUTF8IsUTF8() {
+
+ $string = StringUtil::convertToUTF8('I 💚 SabreDAV');
+
+ $this->assertEquals('I 💚 SabreDAV', $string);
+
+ }
+
+ function testConvertToUTF8ControlChar() {
+
+ $string = StringUtil::convertToUTF8(chr(0x00));
+
+ $this->assertEquals('', $string);
+
+ }
+
+
+
+
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/TimeZoneUtilTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/TimeZoneUtilTest.php
new file mode 100644
index 000000000..7f76353d2
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/TimeZoneUtilTest.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace Sabre\VObject;
+
+class TimezoneUtilTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider getMapping
+ */
+ function testCorrectTZ($timezoneName) {
+
+ $tz = new \DateTimeZone($timezoneName);
+
+ }
+
+ function getMapping() {
+
+ // PHPUNit requires an array of arrays
+ return array_map(
+ function($value) {
+ return array($value);
+ },
+ TimeZoneUtil::$map
+ );
+
+ }
+
+ function testExchangeMap() {
+
+ $vobj = <<<HI
+BEGIN:VCALENDAR
+METHOD:REQUEST
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:foo
+X-MICROSOFT-CDO-TZID:2
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20120416T092149Z
+DTSTART;TZID="foo":20120418T1
+ 00000
+SUMMARY:Begin Unterhaltsreinigung
+UID:040000008200E00074C5B7101A82E0080000000010DA091DC31BCD01000000000000000
+ 0100000008FECD2E607780649BE5A4C9EE6418CBC
+ 000
+END:VEVENT
+END:VCALENDAR
+HI;
+
+ $tz = TimeZoneUtil::getTimeZone('foo', Reader::read($vobj));
+ $ex = new \DateTimeZone('Europe/Lisbon');
+
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ function testWetherMicrosoftIsStillInsane() {
+
+ $vobj = <<<HI
+BEGIN:VCALENDAR
+METHOD:REQUEST
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:(GMT+01.00) Sarajevo/Warsaw/Zagreb
+X-MICROSOFT-CDO-TZID:2
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+END:VTIMEZONE
+END:VCALENDAR
+HI;
+
+ $tz = TimeZoneUtil::getTimeZone('(GMT+01.00) Sarajevo/Warsaw/Zagreb', Reader::read($vobj));
+ $ex = new \DateTimeZone('Europe/Sarajevo');
+
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ function testUnknownExchangeId() {
+
+ $vobj = <<<HI
+BEGIN:VCALENDAR
+METHOD:REQUEST
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:foo
+X-MICROSOFT-CDO-TZID:2000
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20120416T092149Z
+DTSTART;TZID="foo":20120418T1
+ 00000
+SUMMARY:Begin Unterhaltsreinigung
+UID:040000008200E00074C5B7101A82E0080000000010DA091DC31BCD01000000000000000
+ 0100000008FECD2E607780649BE5A4C9EE6418CBC
+DTEND;TZID="Sarajevo, Skopje, Sofija, Vilnius, Warsaw, Zagreb":20120418T103
+ 000
+END:VEVENT
+END:VCALENDAR
+HI;
+
+ $tz = TimeZoneUtil::getTimeZone('foo', Reader::read($vobj));
+ $ex = new \DateTimeZone(date_default_timezone_get());
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ function testWindowsTimeZone() {
+
+ $tz = TimeZoneUtil::getTimeZone('Eastern Standard Time');
+ $ex = new \DateTimeZone('America/New_York');
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ function testTimezoneOffset() {
+
+ $tz = TimeZoneUtil::getTimeZone('GMT-0400', null, true);
+ $ex = new \DateTimeZone('Etc/GMT-4');
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testTimezoneFail() {
+
+ $tz = TimeZoneUtil::getTimeZone('FooBar',null,true);
+
+ }
+
+ function testFallBack() {
+
+ $vobj = <<<HI
+BEGIN:VCALENDAR
+METHOD:REQUEST
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:foo
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20120416T092149Z
+DTSTART;TZID="foo":20120418T1
+ 00000
+SUMMARY:Begin Unterhaltsreinigung
+UID:040000008200E00074C5B7101A82E0080000000010DA091DC31BCD01000000000000000
+ 0100000008FECD2E607780649BE5A4C9EE6418CBC
+ 000
+END:VEVENT
+END:VCALENDAR
+HI;
+
+ $tz = TimeZoneUtil::getTimeZone('foo', Reader::read($vobj));
+ $ex = new \DateTimeZone(date_default_timezone_get());
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ function testLjubljanaBug() {
+
+ $vobj = <<<HI
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Ximian//NONSGML Evolution Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/freeassociation.sourceforge.net/Tzfile/Europe/Ljubljana
+X-LIC-LOCATION:Europe/Ljubljana
+BEGIN:STANDARD
+TZNAME:CET
+DTSTART:19701028T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+END:STANDARD
+BEGIN:DAYLIGHT
+TZNAME:CEST
+DTSTART:19700325T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:foo
+DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Ljubljana:
+ 20121003T080000
+DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Ljubljana:
+ 20121003T083000
+TRANSP:OPAQUE
+SEQUENCE:2
+SUMMARY:testing
+CREATED:20121002T172613Z
+LAST-MODIFIED:20121002T172613Z
+END:VEVENT
+END:VCALENDAR
+
+HI;
+
+
+ $tz = TimeZoneUtil::getTimeZone('/freeassociation.sourceforge.net/Tzfile/Europe/Ljubljana', Reader::read($vobj));
+ $ex = new \DateTimeZone('Europe/Ljubljana');
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+ function testWeirdSystemVLICs() {
+
+$vobj = <<<HI
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Ximian//NONSGML Evolution Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/freeassociation.sourceforge.net/Tzfile/SystemV/EST5EDT
+X-LIC-LOCATION:SystemV/EST5EDT
+BEGIN:STANDARD
+TZNAME:EST
+DTSTART:19701104T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+TZNAME:EDT
+DTSTART:19700311T020000
+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:20121026T021107Z-6301-1000-1-0@chAir
+DTSTAMP:20120905T172126Z
+DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/SystemV/EST5EDT:
+ 20121026T153000
+DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/SystemV/EST5EDT:
+ 20121026T160000
+TRANSP:OPAQUE
+SEQUENCE:5
+SUMMARY:pick up Ibby
+CLASS:PUBLIC
+CREATED:20121026T021108Z
+LAST-MODIFIED:20121026T021118Z
+X-EVOLUTION-MOVE-CALENDAR:1
+END:VEVENT
+END:VCALENDAR
+HI;
+
+ $tz = TimeZoneUtil::getTimeZone('/freeassociation.sourceforge.net/Tzfile/SystemV/EST5EDT', Reader::read($vobj), true);
+ $ex = new \DateTimeZone('EST5EDT');
+ $this->assertEquals($ex->getName(), $tz->getName());
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/VersionTest.php b/vendor/sabre/vobject/tests/Sabre/VObject/VersionTest.php
new file mode 100644
index 000000000..ae6855e85
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/VersionTest.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Sabre\VObject;
+
+class VersionTest extends \PHPUnit_Framework_TestCase {
+
+ function testString() {
+
+ $v = Version::VERSION;
+ $this->assertEquals(-1, version_compare('0.9.0',$v));
+
+ $s = Version::STABILITY;
+ $this->assertTrue($s == 'alpha' || $s == 'beta' || $s =='stable');
+
+ }
+
+}
diff --git a/vendor/sabre/vobject/tests/Sabre/VObject/issue153.vcf b/vendor/sabre/vobject/tests/Sabre/VObject/issue153.vcf
new file mode 100644
index 000000000..5fb0fa297
--- /dev/null
+++ b/vendor/sabre/vobject/tests/Sabre/VObject/issue153.vcf
@@ -0,0 +1,352 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Benutzer;Test;;;
+FN:Test Benutzer
+PHOTO;BASE64:
+ /9j/4AAQSkZJRgABAQAAAQABAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQA
+ AAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABQKADAAQAAAABAAABQAAAAAD/2wBD
+ AAIBAQIBAQICAQICAgICAwUDAwMDAwYEBAMFBwYHBwcGBgYHCAsJBwgKCAYGCQ0JCgsLDAwMBwkN
+ Dg0MDgsMDAv/2wBDAQICAgMCAwUDAwULCAYICwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsL
+ CwsLCwsLCwsLCwsLCwsLCwsLCwv/wAARCAFAAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAA
+ AAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKB
+ kaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZn
+ aGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT
+ 1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcI
+ CQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
+ YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6
+ goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk
+ 5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD8J7JbO8tYo1tIFCDLOVG5qfdaVZRwmSOFWzyA
+ F4H1rLt5WViMhdp6HgmtKK8O3B+4Rhx6fSgBI9FtjaNN5aErwRjilSys7lFAt41xyTtqc2yJCVlY
+ 7eqgGqv2jyLcebjZnGPWncdzT0+w0u5eQXtrGiBcIyoPmNMXwpb/AGMTSRRbH6YAyPwqK21GKdfL
+ BAVfu+1SQX4jnjKFsp03dPypCKN9oEaKSkC7R0bGKpnSlSPdHErZOORXV3Ouy337sCLB6kpx+FY0
+ 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
+ zbVbk4/OrNpefLsnyyg5UUAf/9k=
+END:VCARD