diff options
Diffstat (limited to 'vendor/sabre/vobject/tests/Sabre/VObject')
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
|