upgrade icalparser from e6a3a285cf6e239236a40153a66b67b940220b43 to cae1631b9496a7415ef960b0dff1cd0f39fe3135
This commit is contained in:
parent
fe29295a0e
commit
e3db4803e0
31 changed files with 1329 additions and 877 deletions
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Roman Ozana <ozana@omdesign.cz>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
Environment::setup();
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/blank_description.ics');
|
||||
|
||||
Assert::same('', $results['VEVENT'][0]['DESCRIPTION']);
|
||||
Assert::same('America/Los_Angeles', $cal->timezone->getName());
|
||||
|
||||
Assert::same($results['DAYLIGHT'][0]['RRULE']['FREQ'], 'YEARLY');
|
21
include/icalparser/tests/bootstrap.php
Normal file
21
include/icalparser/tests/bootstrap.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace tests;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2004-2022 Roman Ožana (https://ozana.cz)
|
||||
*
|
||||
* @license BSD-3-Clause
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Closure;
|
||||
use Tester\Environment;
|
||||
|
||||
function test($description, Closure $fn) {
|
||||
printf("• %s%s%s", $description, PHP_EOL, $fn());
|
||||
}
|
||||
|
||||
Environment::setup();
|
|
@ -0,0 +1,59 @@
|
|||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:Office Opening Hours
|
||||
X-WR-TIMEZONE:Europe/London
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Europe/London
|
||||
X-LIC-LOCATION:Europe/London
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0000
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:BST
|
||||
DTSTART:19700329T010000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0000
|
||||
TZNAME:GMT
|
||||
DTSTART:19701025T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=Europe/London:20190401T090000
|
||||
DTEND;TZID=Europe/London:20190401T170000
|
||||
RRULE:FREQ=WEEKLY;WKST=SU;BYDAY=MO,TU,WE,TH,FR
|
||||
DTSTAMP:20190402T174536Z
|
||||
UID:1nibcosj8r05bjoia671im7ulg@google.com
|
||||
CREATED:20190401T144832Z
|
||||
DESCRIPTION:
|
||||
LAST-MODIFIED:20190401T145024Z
|
||||
LOCATION:
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Office Opening Hours
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=Europe/London:20190225T090000
|
||||
DTEND;TZID=Europe/London:20190225T170000
|
||||
RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20190329T235959Z;BYDAY=MO,TU,WE,TH,FR
|
||||
DTSTAMP:20190402T174536Z
|
||||
UID:7e581hcu1ub3nm0bb6c4o29suj@google.com
|
||||
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Office
|
||||
Opening Hours;X-NUM-GUESTS=0:mailto:poweredpasture.com_la2jmsbphe5h11351kk
|
||||
scnnqtg@group.calendar.google.com
|
||||
CREATED:20190227T164630Z
|
||||
DESCRIPTION:
|
||||
LAST-MODIFIED:20190401T144725Z
|
||||
LOCATION:
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Office Opening Hours
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
39
include/icalparser/tests/cal/missing_RRULE_notice.ics
Normal file
39
include/icalparser/tests/cal/missing_RRULE_notice.ics
Normal file
|
@ -0,0 +1,39 @@
|
|||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
X-WR-CALNAME:URL
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Europe/Berlin
|
||||
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin
|
||||
X-LIC-LOCATION:Europe/Berlin
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:CEST
|
||||
DTSTART:19700329T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:CET
|
||||
DTSTART:19701025T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
UID:111
|
||||
DTSTAMP:20181123T192651Z
|
||||
CATEGORIES;LANGUAGE=de-DE:Party
|
||||
CONTACT:
|
||||
DESCRIPTION:xxx
|
||||
DTSTART;TZID=Europe/Berlin:20160415T210000
|
||||
DTEND;TZID=Europe/Berlin:20160416T040000
|
||||
LOCATION:xxx
|
||||
RDATE;TZID=Europe/Berlin:20161216T210000
|
||||
RDATE;TZID=Europe/Berlin:20161223T210000
|
||||
RDATE;TZID=Europe/Berlin:20161230T210000
|
||||
SEQUENCE:0
|
||||
SUMMARY:xxx
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
67
include/icalparser/tests/cal/multiple_categories.ics
Executable file
67
include/icalparser/tests/cal/multiple_categories.ics
Executable file
|
@ -0,0 +1,67 @@
|
|||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:Zimbra-Calendar-Provider
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Los_Angeles
|
||||
BEGIN:STANDARD
|
||||
DTSTART:19710101T020000
|
||||
TZOFFSETTO:-0800
|
||||
TZOFFSETFROM:-0700
|
||||
RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU
|
||||
TZNAME:PST
|
||||
END:STANDARD
|
||||
BEGIN:DAYLIGHT
|
||||
DTSTART:19710101T020000
|
||||
TZOFFSETTO:-0700
|
||||
TZOFFSETFROM:-0800
|
||||
RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU
|
||||
TZNAME:PDT
|
||||
END:DAYLIGHT
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
UID:1334F9B7-6136-444E-A58D-472564C6AA73
|
||||
SUMMARY:sahaja <> frashed
|
||||
DESCRIPTION:weekly 1on1
|
||||
CATEGORIES:one, two, three
|
||||
ATTENDEE;CN=James Lal;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS
|
||||
-ACTION;RSVP=TRUE:mailto:jlal@mozilla.com
|
||||
ORGANIZER;CN=Faramarz Rashed:mailto:frashed@mozilla.com
|
||||
DTSTART;TZID=America/Los_Angeles:20120326T110000
|
||||
DTEND;TZID=America/Los_Angeles:20120326T113000
|
||||
STATUS:CONFIRMED
|
||||
CLASS:PUBLIC
|
||||
TRANSP:OPAQUE
|
||||
LAST-MODIFIED:20120326T161522Z
|
||||
DTSTAMP:20120730T165637Z
|
||||
SEQUENCE:9
|
||||
BEGIN:VALARM
|
||||
ACTION:DISPLAY
|
||||
TRIGGER;RELATED=START:-PT5M
|
||||
DESCRIPTION:Reminder
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:14556F9B7-6136-444E-A58D-472564C6AA73
|
||||
SUMMARY:something something
|
||||
DESCRIPTION:weekly 1on1
|
||||
CATEGORIES:one
|
||||
CATEGORIES:two
|
||||
CATEGORIES:three
|
||||
ATTENDEE;CN=James Lal;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS
|
||||
-ACTION;RSVP=TRUE:mailto:jlal@mozilla.com
|
||||
ORGANIZER;CN=Faramarz Rashed:mailto:frashed@mozilla.com
|
||||
DTSTART;TZID=America/Los_Angeles:20120326T110000
|
||||
DTEND;TZID=America/Los_Angeles:20120326T113000
|
||||
STATUS:CONFIRMED
|
||||
CLASS:PUBLIC
|
||||
TRANSP:OPAQUE
|
||||
LAST-MODIFIED:20120326T161522Z
|
||||
DTSTAMP:20120730T165637Z
|
||||
SEQUENCE:9
|
||||
BEGIN:VALARM
|
||||
ACTION:DISPLAY
|
||||
TRIGGER;RELATED=START:-PT5M
|
||||
DESCRIPTION:Reminder
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
32
include/icalparser/tests/cal/url.ics
Normal file
32
include/icalparser/tests/cal/url.ics
Normal file
|
@ -0,0 +1,32 @@
|
|||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
X-WR-CALNAME:URL
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Europe/Berlin
|
||||
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin
|
||||
X-LIC-LOCATION:Europe/Berlin
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:CEST
|
||||
DTSTART:19700329T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:CET
|
||||
DTSTART:19701025T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20191106T093607Z
|
||||
UID:20191106T093607Z-791992399@marudot.com
|
||||
DTSTART;VALUE=DATE:20191101
|
||||
DTEND;VALUE=DATE:20191102
|
||||
SUMMARY:Example event
|
||||
URL:https%3A%2F%2Fgithub.com%2FOzzyCzech%2Ficalparser%2F
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
26
include/icalparser/tests/event.attachements.phpt
Normal file
26
include/icalparser/tests/event.attachements.phpt
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* @author PC Drew <pc@soprisapps.com>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
test('Event with multiple ATTACHMENTS', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/multiple_attachments.ics');
|
||||
$first = $cal->getEvents()->getIterator()->current();
|
||||
|
||||
// Backwards compatibility, there is only ever one key displayed
|
||||
Assert::hasKey('ATTACH', $first);
|
||||
Assert::type('string', $first['ATTACH']);
|
||||
|
||||
// The new key 'ATTACHMENTS' is an array with 1 or more attachments
|
||||
Assert::type('array', $first['ATTACHMENTS']);
|
||||
Assert::count(2, $first['ATTACHMENTS']);
|
||||
});
|
25
include/icalparser/tests/event.categories.phpt
Normal file
25
include/icalparser/tests/event.categories.phpt
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2004-2022 Roman Ožana (https://ozana.cz)
|
||||
*
|
||||
* @license BSD-3-Clause
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
test('Multiple categories test', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/multiple_categories.ics');
|
||||
$events = $cal->getEvents()->sorted();
|
||||
|
||||
foreach ($events as $event) {
|
||||
Assert::type('array', $event['CATEGORIES']);
|
||||
Assert::same(['one', 'two', 'three'], $event['CATEGORIES']);
|
||||
}
|
||||
});
|
25
include/icalparser/tests/event.dates.phpt
Normal file
25
include/icalparser/tests/event.dates.phpt
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2004-2022 Roman Ožana (https://ozana.cz)
|
||||
*
|
||||
* @license BSD-3-Clause
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
|
||||
test('Events with wrong dates', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/wrong_dates.ics');
|
||||
$events = $cal->getEvents()->sorted();
|
||||
Assert::same('29.9.2014 00:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::same(null, $events[1]['DTEND']);
|
||||
|
||||
Assert::same(null, $events[0]['DTSTART']);
|
||||
Assert::same('30.9.2014 00:00:00', $events[0]['DTEND']->format('j.n.Y H:i:s'));
|
||||
});
|
||||
|
34
include/icalparser/tests/event.description.phpt
Normal file
34
include/icalparser/tests/event.description.phpt
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2004-2022 Roman Ožana (https://ozana.cz)
|
||||
*
|
||||
* @license BSD-3-Clause
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
test('Blank description test', function () {
|
||||
$cal = new IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/blank_description.ics');
|
||||
$first = $cal->getEvents()->getIterator()->current();
|
||||
|
||||
Assert::hasKey('DESCRIPTION', $first);
|
||||
Assert::same('', $first['DESCRIPTION']);
|
||||
});
|
||||
|
||||
test('Multiple lines description', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/multiline_description.ics');
|
||||
$events = $cal->getEvents()->sorted();
|
||||
$first = $events->getIterator()->current();
|
||||
|
||||
Assert::same('30.6.2012 06:00:00', $first['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::same("Here is a description that spans multiple lines!\n\nThis should be on a new line as well because the description contains newline characters.", $first['DESCRIPTION']);
|
||||
});
|
||||
|
39
include/icalparser/tests/event.timezones.phpt
Normal file
39
include/icalparser/tests/event.timezones.phpt
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Marc Vachette <marc.vachette@gmail.com>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
|
||||
test('Normal time zone', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/blank_description.ics');
|
||||
Assert::same('America/Los_Angeles', $cal->timezone->getName());
|
||||
});
|
||||
|
||||
test('Negative zero UTC timezone', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/utc_negative_zero.ics');
|
||||
Assert::same('Etc/GMT', $cal->timezone->getName());
|
||||
});
|
||||
|
||||
/**
|
||||
* Time zone with custom prefixes (Mozilla files tken from here: https://www.mozilla.org/en-US/projects/calendar/holidays/)
|
||||
*/
|
||||
test('Time zone with custom prefixes', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/FrenchHolidays.ics');
|
||||
Assert::same('Europe/Paris', $cal->timezone->getName());
|
||||
});
|
||||
|
||||
test('Weird windows timezones', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/weird_windows_timezones.ics');
|
||||
$cal->getEvents()->sorted();
|
||||
Assert::same('Atlantic/Reykjavik', $cal->timezone->getName());
|
||||
});
|
22
include/icalparser/tests/event.url.phpt
Normal file
22
include/icalparser/tests/event.url.phpt
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2004-2022 Roman Ožana (https://ozana.cz)
|
||||
*
|
||||
* @license BSD-3-Clause
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
|
||||
test('URL parsing check', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/url.ics');
|
||||
$first = $cal->getEvents()->getIterator()->current();
|
||||
|
||||
Assert::hasKey('URL', $first);
|
||||
Assert::same($first['URL'], urlencode('https://github.com/OzzyCzech/icalparser/'));
|
||||
});
|
241
include/icalparser/tests/events.recurring.phpt
Normal file
241
include/icalparser/tests/events.recurring.phpt
Normal file
|
@ -0,0 +1,241 @@
|
|||
<?php
|
||||
/**
|
||||
* @author PC Drew <pc@schoolblocks.com>
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
|
||||
test('Recurring instances finite', function () {
|
||||
$cal = new IcalParser();
|
||||
|
||||
$cal->parseFile(__DIR__ . '/cal/recur_instances_finite.ics');
|
||||
$events = $cal->getEvents()->sorted();
|
||||
|
||||
// DTSTART;TZID=America/Los_Angeles:20121002T100000
|
||||
// DTEND;TZID=America/Los_Angeles:20121002T103000
|
||||
// RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU;UNTIL=20121231T100000
|
||||
// RDATE;TZID=America/Los_Angeles:20121110T100000
|
||||
// RDATE;TZID=America/Los_Angeles:20121105T100000
|
||||
Assert::equal(5, $events->count());
|
||||
Assert::equal('2.10.2012 10:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('5.11.2012 10:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('6.11.2012 10:00:00', $events[2]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('10.11.2012 10:00:00', $events[3]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('4.12.2012 10:00:00', $events[4]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
});
|
||||
|
||||
test('Recurring instance check', function () {
|
||||
$cal = new IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances.ics');
|
||||
$events = $cal->getEvents()->sorted();
|
||||
|
||||
$recurrences = [];
|
||||
foreach ($events as $i => $event) {
|
||||
$recurrences[] = $event['DTSTART'];
|
||||
}
|
||||
|
||||
// DTSTART;TZID=America/Los_Angeles:20121002T100000
|
||||
// DTEND;TZID=America/Los_Angeles:20121002T103000
|
||||
// RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU
|
||||
// RDATE;TZID=America/Los_Angeles:20121105T100000
|
||||
// RDATE;TZID=America/Los_Angeles:20121110T100000,20121130T100000
|
||||
// EXDATE;TZID=America/Los_Angeles:20130402T100000
|
||||
// EXDATE;TZID=America/Los_Angeles:20121204T100000
|
||||
// EXDATE;TZID=America/Los_Angeles:20130205T100000
|
||||
// because there is no "UNTIL", we calculate until 3 years from now of repeating events
|
||||
$now = new DateTime('now');
|
||||
$diff = $now->diff(new DateTime('20121002T100000'));
|
||||
$count = ($diff->y + 3) * 12 + $diff->m;
|
||||
Assert::equal($count, count($recurrences));
|
||||
Assert::equal('02.10.2012 15:00:00', $recurrences[0]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.11.2012 20:00:00', $recurrences[1]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('10.11.2012 10:00:00', $recurrences[2]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('30.11.2012 10:00:00', $recurrences[3]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.01.2013 10:00:00', $recurrences[4]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.03.2013 10:00:00', $recurrences[5]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.05.2013 10:00:00', $recurrences[6]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.06.2013 10:00:00', $recurrences[7]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.07.2013 10:00:00', $recurrences[8]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.08.2013 10:00:00', $recurrences[9]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.09.2013 10:00:00', $recurrences[10]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.10.2013 10:00:00', $recurrences[11]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.11.2013 10:00:00', $recurrences[12]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.12.2013 10:00:00', $recurrences[13]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.01.2014 10:00:00', $recurrences[14]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.02.2014 10:00:00', $recurrences[15]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.03.2014 10:00:00', $recurrences[16]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.04.2014 10:00:00', $recurrences[17]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.05.2014 10:00:00', $recurrences[18]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.06.2014 10:00:00', $recurrences[19]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.07.2014 10:00:00', $recurrences[20]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.08.2014 10:00:00', $recurrences[21]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.09.2014 10:00:00', $recurrences[22]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.10.2014 10:00:00', $recurrences[23]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.11.2014 10:00:00', $recurrences[24]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.12.2014 10:00:00', $recurrences[25]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.01.2015 10:00:00', $recurrences[26]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.02.2015 10:00:00', $recurrences[27]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.03.2015 10:00:00', $recurrences[28]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.04.2015 10:00:00', $recurrences[29]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.05.2015 10:00:00', $recurrences[30]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.06.2015 10:00:00', $recurrences[31]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.07.2015 10:00:00', $recurrences[32]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.08.2015 10:00:00', $recurrences[33]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.09.2015 10:00:00', $recurrences[34]->format('d.m.Y H:i:s'));
|
||||
|
||||
foreach ($events->getIterator()->current()['EXDATES'] as $exDate) {
|
||||
Assert::notContains($exDate, $recurrences);
|
||||
}
|
||||
});
|
||||
|
||||
test('Recurrent event with modifications at single date', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/recur_instances_with_modifications.ics');
|
||||
$events = $cal->getEvents()->sorted();
|
||||
|
||||
// There should be 36 total events because of the modified event + 35 recurrences
|
||||
Assert::count(36, $events); // 36 events
|
||||
|
||||
// There should be 35 total recurrences because the modified event should've removed 1 recurrence
|
||||
Assert::hasKey('RECURRENCES', $events->offsetGet(1));
|
||||
$recurrences = $events->getIterator()->current()['RECURRENCES'];
|
||||
Assert::count(35, $recurrences);
|
||||
|
||||
// reccurent event don't have RECURRENCES
|
||||
foreach (range(2, 35) as $index) {
|
||||
Assert::hasNotKey('RECURRENCES', $events->offsetGet($index));
|
||||
}
|
||||
|
||||
// the date 8.8.2016 should be modified
|
||||
$modifiedEvent = $events->offsetGet(0);
|
||||
Assert::hasNotKey('RECURRENCES', $modifiedEvent);
|
||||
// the 12th entry is the modified event, related to the remaining recurring events
|
||||
Assert::same('8.8.2016', $modifiedEvent['DTSTART']->format('j.n.Y'));
|
||||
Assert::notContains($modifiedEvent['DTSTART'], $recurrences);
|
||||
});
|
||||
|
||||
test('Recuring instances with modifications and interval', function () {
|
||||
$cal = new IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances_with_modifications_and_interval.ics');
|
||||
|
||||
// Build the cache of RECURRENCE-IDs and EXDATES first, so that we can properly determine the interval
|
||||
$eventCache = [];
|
||||
foreach ($results['VEVENT'] as $event) {
|
||||
$eventSequence = empty($event['SEQUENCE']) ? "0" : $event['SEQUENCE'];
|
||||
$eventRecurrenceID = empty($event['RECURRENCE-ID']) ? "0" : $event['RECURRENCE-ID'];
|
||||
$eventCache[$event['UID']][$eventRecurrenceID][$eventSequence] = $event;
|
||||
}
|
||||
$trueEvents = [];
|
||||
foreach ($results['VEVENT'] as $event) {
|
||||
if (empty($event['RECURRENCES'])) {
|
||||
$trueEvents[] = $event;
|
||||
} else {
|
||||
$eventUID = $event['UID'];
|
||||
foreach ($event['RECURRENCES'] as $recurrence) {
|
||||
$eventRecurrenceID = $recurrence->format("Ymd");
|
||||
if (empty($eventCache[$eventUID][$eventRecurrenceID])) {
|
||||
$trueEvents[$eventRecurrenceID] = ['DTSTART' => $recurrence];
|
||||
} else {
|
||||
krsort($eventCache[$eventUID][$eventRecurrenceID]);
|
||||
$keys = array_keys($eventCache[$eventUID][$eventRecurrenceID]);
|
||||
$trueEvents[$eventRecurrenceID] = $eventCache[$eventUID][$eventRecurrenceID][$keys[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usort(
|
||||
$trueEvents,
|
||||
static function ($a, $b): int {
|
||||
return ($a['DTSTART'] > $b['DTSTART']) ? 1 : -1;
|
||||
}
|
||||
);
|
||||
|
||||
$events = $cal->getEvents()->sorted()->getArrayCopy();
|
||||
|
||||
Assert::false(empty($events[0]['RECURRENCES']));
|
||||
Assert::equal(count($trueEvents), count($events));
|
||||
foreach ($trueEvents as $index => $trueEvent) {
|
||||
Assert::equal($trueEvent['DTSTART']->format("Ymd"), $events[$index]['DTSTART']->format("Ymd"));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
test('', function () {
|
||||
$cal = new IcalParser();
|
||||
// There is still an issue that needs to be resolved when modifications are made to the initial event that is the
|
||||
// base of the recurrences. The below ICS file has a great edge case example: one event, no recurrences in the
|
||||
// recurring ruleset, and a modification to the initial event.
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances_with_modifications_to_first_day.ics');
|
||||
$events = $cal->getEvents()->sorted()->getArrayCopy();
|
||||
Assert::true(empty($events[0]['RECURRENCES'])); // edited event
|
||||
Assert::true(empty($events[1]['RECURRENCES'])); // recurring event base with no recurrences
|
||||
Assert::equal(1, count($events));
|
||||
});
|
||||
|
||||
test('', function () {
|
||||
$cal = new IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/daily_recur.ics');
|
||||
$events = $cal->getEvents()->sorted()->getArrayCopy();
|
||||
$period = new DatePeriod(new DateTime('20120801T050000'), new DateInterval('P1D'), new DateTime('20150801T050000'));
|
||||
foreach ($period as $i => $day) {
|
||||
Assert::equal($day->format('j.n.Y H:i:s'), $events[$i]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
}
|
||||
});
|
||||
|
||||
test('', function () {
|
||||
$cal = new IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/daily_recur2.ics');
|
||||
$events = $cal->getEvents()->sorted()->getArrayCopy();
|
||||
|
||||
Assert::equal(4, count($events));
|
||||
Assert::equal('21.8.2017 00:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('28.8.2017 00:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('4.9.2017 00:00:00', $events[2]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('11.9.2017 00:00:00', $events[3]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
});
|
||||
|
||||
test('', function () {
|
||||
//https://github.com/OzzyCzech/icalparser/issues/38
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/38_weekly_recurring_event_missing_day.ics');
|
||||
$events = $cal->getEvents()->sorted()->getArrayCopy();
|
||||
|
||||
//first monday
|
||||
Assert::equal('25.2.2019 09:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
//rest of week
|
||||
Assert::equal('26.2.2019 09:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('27.2.2019 09:00:00', $events[2]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('28.2.2019 09:00:00', $events[3]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('1.3.2019 09:00:00', $events[4]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
//now check the next 4 mondays to make sure they exist as well
|
||||
Assert::equal('4.3.2019 09:00:00', $events[5]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('11.3.2019 09:00:00', $events[10]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('18.3.2019 09:00:00', $events[15]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('25.3.2019 09:00:00', $events[20]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
|
||||
//Last week that works correctly
|
||||
Assert::equal('1.4.2019 09:00:00', $events[25]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('2.4.2019 09:00:00', $events[26]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('3.4.2019 09:00:00', $events[27]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('4.4.2019 09:00:00', $events[28]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('5.4.2019 09:00:00', $events[29]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
|
||||
//This week starts failing
|
||||
Assert::equal('8.4.2019 09:00:00', $events[30]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('9.4.2019 09:00:00', $events[31]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('10.4.2019 09:00:00', $events[32]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('11.4.2019 09:00:00', $events[33]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('12.4.2019 09:00:00', $events[34]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
|
||||
Assert::equal('15.4.2019 09:00:00', $events[35]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('16.4.2019 09:00:00', $events[36]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('17.4.2019 09:00:00', $events[37]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('18.4.2019 09:00:00', $events[38]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('19.4.2019 09:00:00', $events[39]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
});
|
36
include/icalparser/tests/events.sorting.phpt
Normal file
36
include/icalparser/tests/events.sorting.phpt
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2004-2022 Roman Ožana (https://ozana.cz)
|
||||
*
|
||||
* @license BSD-3-Clause
|
||||
* @author Roman Ožana <roman@ozana.cz>
|
||||
*/
|
||||
|
||||
use om\IcalParser;
|
||||
use Tester\Assert;
|
||||
use function tests\test;
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
test('Natural sort order by date', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/basic.ics');
|
||||
$first = $cal->getEvents()->sorted()->getIterator()->current();
|
||||
Assert::same('1.1.2013 00:00:00', $first['DTSTART']->format('j.n.Y H:i:s'));
|
||||
});
|
||||
|
||||
test('Reverse events sort (parseFile)', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseFile(__DIR__ . '/cal/basic.ics');
|
||||
$first = $cal->getEvents()->reversed()->getIterator()->current();
|
||||
Assert::same('26.12.2015 00:00:00', $first['DTSTART']->format('j.n.Y H:i:s'));
|
||||
});
|
||||
|
||||
test('Reverse events sort (parseString)', function () {
|
||||
$cal = new IcalParser();
|
||||
$cal->parseString(file_get_contents(__DIR__ . '/cal/basic.ics'));
|
||||
$first = $cal->getEvents()->reversed()->getIterator()->current();
|
||||
Assert::same('26.12.2015 00:00:00', $first['DTSTART']->format('j.n.Y H:i:s'));
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Aaron Parecki <aaron@parecki.com>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
Environment::setup();
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
// sort by date
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/multiline_description.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
Assert::same('30.6.2012 06:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::same("Here is a description that spans multiple lines!\n\nThis should be on a new line as well because the description contains newline characters.", $events[0]['DESCRIPTION']);
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author PC Drew <pc@soprisapps.com>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
\Tester\Environment::setup();
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/multiple_attachments.ics');
|
||||
|
||||
// Backwards compatibility, there is only ever one key displayed
|
||||
Assert::type('string', $results['VEVENT'][0]['ATTACH']);
|
||||
|
||||
// The new key 'ATTACHMENTS' is an array with 1 or more attachments
|
||||
Assert::type('array', $results['VEVENT'][0]['ATTACHMENTS']);
|
||||
Assert::count(2, $results['VEVENT'][0]['ATTACHMENTS']);
|
|
@ -1,170 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author PC Drew <pc@schoolblocks.com>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
Environment::setup();
|
||||
|
||||
$cal = new \om\IcalParser();
|
||||
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances_finite.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
|
||||
// DTSTART;TZID=America/Los_Angeles:20121002T100000
|
||||
// DTEND;TZID=America/Los_Angeles:20121002T103000
|
||||
// RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU;UNTIL=20121231T100000
|
||||
// RDATE;TZID=America/Los_Angeles:20121110T100000
|
||||
// RDATE;TZID=America/Los_Angeles:20121105T100000
|
||||
Assert::equal(5, sizeof($events));
|
||||
Assert::equal('2.10.2012 10:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('5.11.2012 10:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('6.11.2012 10:00:00', $events[2]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('10.11.2012 10:00:00', $events[3]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('4.12.2012 10:00:00', $events[4]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
|
||||
$recurrences = [];
|
||||
foreach($events as $i => $event) {
|
||||
$recurrences[] = $event['DTSTART'];
|
||||
}
|
||||
|
||||
// DTSTART;TZID=America/Los_Angeles:20121002T100000
|
||||
// DTEND;TZID=America/Los_Angeles:20121002T103000
|
||||
// RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU
|
||||
// RDATE;TZID=America/Los_Angeles:20121105T100000
|
||||
// RDATE;TZID=America/Los_Angeles:20121110T100000,20121130T100000
|
||||
// EXDATE;TZID=America/Los_Angeles:20130402T100000
|
||||
// EXDATE;TZID=America/Los_Angeles:20121204T100000
|
||||
// EXDATE;TZID=America/Los_Angeles:20130205T100000
|
||||
// total = 36 events - 3 exclusions + 3 additions
|
||||
// because there is no "UNTIL", we only calculate the next 3 years of repeating events
|
||||
Assert::equal(35, sizeof($recurrences));
|
||||
Assert::equal('02.10.2012 15:00:00', $recurrences[0]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.11.2012 20:00:00', $recurrences[1]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('10.11.2012 10:00:00', $recurrences[2]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('30.11.2012 10:00:00', $recurrences[3]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.01.2013 10:00:00', $recurrences[4]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.03.2013 10:00:00', $recurrences[5]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.05.2013 10:00:00', $recurrences[6]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.06.2013 10:00:00', $recurrences[7]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.07.2013 10:00:00', $recurrences[8]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.08.2013 10:00:00', $recurrences[9]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.09.2013 10:00:00', $recurrences[10]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.10.2013 10:00:00', $recurrences[11]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.11.2013 10:00:00', $recurrences[12]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.12.2013 10:00:00', $recurrences[13]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.01.2014 10:00:00', $recurrences[14]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.02.2014 10:00:00', $recurrences[15]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.03.2014 10:00:00', $recurrences[16]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.04.2014 10:00:00', $recurrences[17]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.05.2014 10:00:00', $recurrences[18]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.06.2014 10:00:00', $recurrences[19]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.07.2014 10:00:00', $recurrences[20]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.08.2014 10:00:00', $recurrences[21]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.09.2014 10:00:00', $recurrences[22]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.10.2014 10:00:00', $recurrences[23]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.11.2014 10:00:00', $recurrences[24]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.12.2014 10:00:00', $recurrences[25]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('06.01.2015 10:00:00', $recurrences[26]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.02.2015 10:00:00', $recurrences[27]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('03.03.2015 10:00:00', $recurrences[28]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.04.2015 10:00:00', $recurrences[29]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('05.05.2015 10:00:00', $recurrences[30]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('02.06.2015 10:00:00', $recurrences[31]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('07.07.2015 10:00:00', $recurrences[32]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('04.08.2015 10:00:00', $recurrences[33]->format('d.m.Y H:i:s'));
|
||||
Assert::equal('01.09.2015 10:00:00', $recurrences[34]->format('d.m.Y H:i:s'));
|
||||
|
||||
foreach ($events[0]['EXDATES'] as $exDate) {
|
||||
Assert::notContains($exDate, $recurrences);
|
||||
}
|
||||
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances_with_modifications.ics');
|
||||
$events = $cal->getSortedEvents(true);
|
||||
|
||||
Assert::false(empty($events[0]['RECURRENCES']));
|
||||
// the 12th entry is the modified event, related to the remaining recurring events
|
||||
Assert::true(empty($events[12]['RECURRENCES']));
|
||||
|
||||
$recurrences = $events[0]['RECURRENCES'];
|
||||
$modifiedEvent = $events[12];
|
||||
|
||||
// There should be 35 total recurrences because the modified event should've removed 1 recurrence
|
||||
Assert::equal(35, sizeof($recurrences));
|
||||
// There should be 36 total events because of the modified event + 35 recurrences
|
||||
Assert::equal(36, sizeof($events));
|
||||
Assert::notContains($modifiedEvent['DTSTART'], $recurrences);
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances_with_modifications_and_interval.ics');
|
||||
|
||||
// Build the cache of RECURRENCE-IDs and EXDATES first, so that we can properly determine the interval
|
||||
$eventCache = array();
|
||||
foreach($results['VEVENT'] as $event) {
|
||||
$eventSequence = empty($event['SEQUENCE']) ? "0" : $event['SEQUENCE'];
|
||||
$eventRecurrenceID = empty($event['RECURRENCE-ID']) ? "0" : $event['RECURRENCE-ID'];
|
||||
|
||||
$eventCache[$event['UID']][$eventRecurrenceID][$eventSequence] = $event;
|
||||
}
|
||||
$trueEvents = array();
|
||||
foreach($results['VEVENT'] as $event) {
|
||||
if(empty($event['RECURRENCES'])) {
|
||||
$trueEvents[] = $event;
|
||||
} else {
|
||||
$eventUID = $event['UID'];
|
||||
foreach($event['RECURRENCES'] as $recurrence) {
|
||||
$eventRecurrenceID = $recurrence->format("Ymd");
|
||||
if(empty($eventCache[$eventUID][$eventRecurrenceID])) {
|
||||
$trueEvents[$eventRecurrenceID] = array('DTSTART' => $recurrence);
|
||||
} else {
|
||||
krsort($eventCache[$eventUID][$eventRecurrenceID]);
|
||||
$keys = array_keys($eventCache[$eventUID][$eventRecurrenceID]);
|
||||
$trueEvents[$eventRecurrenceID] = $eventCache[$eventUID][$eventRecurrenceID][$keys[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usort($trueEvents, function ($a, $b) {
|
||||
return $a['DTSTART'] > $b['DTSTART'];
|
||||
});
|
||||
|
||||
$events = $cal->getSortedEvents(true);
|
||||
Assert::false(empty($events[0]['RECURRENCES']));
|
||||
Assert::equal(count($trueEvents), count($events));
|
||||
foreach($trueEvents as $index => $trueEvent) {
|
||||
Assert::equal($trueEvent['DTSTART']->format("Ymd"), $events[$index]['DTSTART']->format("Ymd"));
|
||||
}
|
||||
|
||||
|
||||
// There is still an issue that needs to be resolved when modifications are made to the initial event that is the
|
||||
// base of the recurrences. The below ICS file has a great edge case example: one event, no recurrences in the
|
||||
// recurring ruleset, and a modification to the initial event.
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/recur_instances_with_modifications_to_first_day.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
Assert::true(empty($events[0]['RECURRENCES'])); // edited event
|
||||
Assert::true(empty($events[1]['RECURRENCES'])); // recurring event base with no recurrences
|
||||
Assert::equal(1, count($events));
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/daily_recur.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
$period = new DatePeriod(new DateTime('20120801T050000'), new DateInterval('P1D'), 365 * 3);
|
||||
foreach($period as $i => $day) {
|
||||
Assert::equal($day->format('j.n.Y H:i:s'), $events[$i]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
}
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/daily_recur2.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
|
||||
Assert::equal(4, sizeof($events));
|
||||
Assert::equal('21.8.2017 00:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('28.8.2017 00:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('4.9.2017 00:00:00', $events[2]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::equal('11.9.2017 00:00:00', $events[3]['DTSTART']->format('j.n.Y H:i:s'));
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Roman Ozana <ozana@omdesign.cz>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
Environment::setup();
|
||||
date_default_timezone_set('Europe/Prague');
|
||||
|
||||
// sort by date
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/basic.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
Assert::same('1.1.2013 00:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
|
||||
// reverse sort (parseFile)
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/basic.ics');
|
||||
$events = $cal->getReverseSortedEvents();
|
||||
Assert::same('26.12.2015 00:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
|
||||
// reverse sort (parseString)
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseString(file_get_contents(__DIR__ . '/cal/basic.ics'));
|
||||
$events = $cal->getReverseSortedEvents();
|
||||
Assert::same('26.12.2015 00:00:00', $events[0]['DTSTART']->format('j.n.Y H:i:s'));
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Marc Vachette <marc.vachette@gmail.com>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
Environment::setup();
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
|
||||
//some clean timezone
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/blank_description.ics');
|
||||
Assert::same('America/Los_Angeles', $cal->timezone->getName());
|
||||
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/utc_negative_zero.ics');
|
||||
Assert::same('Etc/GMT', $cal->timezone->getName());
|
||||
|
||||
//time zone with custom prefixes (Mozilla files tken from here: https://www.mozilla.org/en-US/projects/calendar/holidays/)
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/FrenchHolidays.ics');
|
||||
Assert::same('Europe/Paris', $cal->timezone->getName());
|
||||
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/weird_windows_timezones.ics');
|
||||
$events = $cal->getSortedEvents();
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Roman Ozana <ozana@omdesign.cz>
|
||||
*/
|
||||
|
||||
use Tester\Assert;
|
||||
use Tester\Environment;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
Environment::setup();
|
||||
|
||||
$cal = new \om\IcalParser();
|
||||
$results = $cal->parseFile(__DIR__ . '/cal/wrong_dates.ics');
|
||||
$events = $cal->getSortedEvents();
|
||||
Assert::same('29.9.2014 00:00:00', $events[1]['DTSTART']->format('j.n.Y H:i:s'));
|
||||
Assert::same(null, $events[1]['DTEND']);
|
||||
|
||||
Assert::same(null, $events[0]['DTSTART']);
|
||||
Assert::same('30.9.2014 00:00:00', $events[0]['DTEND']->format('j.n.Y H:i:s'));
|
Loading…
Add table
Add a link
Reference in a new issue