instead of the main VEVENT of a repeating event Fixes part of https://github.com/nextcloud/calendar/issues/3919 Signed-off-by: Anna Larch <anna@nextcloud.com>pull/35743/head
parent
db30974348
commit
38e9cb6a05
@ -0,0 +1,123 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright 2022 Anna Larch <anna.larch@gmx.net> |
||||
* |
||||
* @author 2022 Anna Larch <anna.larch@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\DAV\CalDAV; |
||||
|
||||
use OCA\DAV\AppInfo\Application; |
||||
use OCA\DAV\CalDAV\Schedule\IMipService; |
||||
use OCP\AppFramework\Utility\ITimeFactory; |
||||
use OCP\IConfig; |
||||
use Sabre\VObject\Component\VCalendar; |
||||
use Sabre\VObject\Component\VEvent; |
||||
use Sabre\VObject\Component\VTimeZone; |
||||
use Sabre\VObject\Component\VTodo; |
||||
use function max; |
||||
|
||||
class EventComparisonService { |
||||
|
||||
/** @var string[] */ |
||||
private const EVENT_DIFF = [ |
||||
'RECURRENCE-ID', |
||||
'RRULE', |
||||
'SEQUENCE', |
||||
'LAST-MODIFIED' |
||||
]; |
||||
|
||||
|
||||
/** |
||||
* If found, remove the event from $eventsToFilter that |
||||
* is identical to the passed $filterEvent |
||||
* and return whether an identical event was found |
||||
* |
||||
* This function takes into account the SEQUENCE, |
||||
* RRULE, RECURRENCE-ID and LAST-MODIFIED parameters |
||||
* |
||||
* @param VEvent $filterEvent |
||||
* @param array $eventsToFilter |
||||
* @return bool true if there was an identical event found and removed, false if there wasn't |
||||
*/ |
||||
private function removeIfUnchanged(VEvent $filterEvent, array &$eventsToFilter): bool { |
||||
$filterEventData = []; |
||||
foreach(self::EVENT_DIFF as $eventDiff) { |
||||
$filterEventData[] = IMipService::readPropertyWithDefault($filterEvent, $eventDiff, ''); |
||||
} |
||||
|
||||
/** @var VEvent $component */ |
||||
foreach ($eventsToFilter as $k => $eventToFilter) { |
||||
$eventToFilterData = []; |
||||
foreach(self::EVENT_DIFF as $eventDiff) { |
||||
$eventToFilterData[] = IMipService::readPropertyWithDefault($eventToFilter, $eventDiff, ''); |
||||
} |
||||
// events are identical and can be removed |
||||
if (empty(array_diff($filterEventData, $eventToFilterData))) { |
||||
unset($eventsToFilter[$k]); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Compare two VCalendars with each other and find all changed elements |
||||
* |
||||
* Returns an array of old and new events |
||||
* |
||||
* Old events are only detected if they are also changed |
||||
* If there is no corresponding old event for a VEvent, it |
||||
* has been newly created |
||||
* |
||||
* @param VCalendar $new |
||||
* @param VCalendar|null $old |
||||
* @return array<string, VEvent[]> |
||||
*/ |
||||
public function findModified(VCalendar $new, ?VCalendar $old): array { |
||||
$newEventComponents = $new->getComponents(); |
||||
|
||||
foreach ($newEventComponents as $k => $event) { |
||||
if(!$event instanceof VEvent) { |
||||
unset($newEventComponents[$k]); |
||||
} |
||||
} |
||||
|
||||
if(empty($old)) { |
||||
return ['old' => null, 'new' => $newEventComponents]; |
||||
} |
||||
|
||||
$oldEventComponents = $old->getComponents(); |
||||
if(is_array($oldEventComponents) && !empty($oldEventComponents)) { |
||||
foreach ($oldEventComponents as $k => $event) { |
||||
if(!$event instanceof VEvent) { |
||||
unset($oldEventComponents[$k]); |
||||
continue; |
||||
} |
||||
if($this->removeIfUnchanged($event, $newEventComponents)) { |
||||
unset($oldEventComponents[$k]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return ['old' => array_values($oldEventComponents), 'new' => array_values($newEventComponents)]; |
||||
} |
||||
} |
||||
@ -0,0 +1,146 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright 2023 Daniel Kesselberg <mail@danielkesselberg.de> |
||||
* |
||||
* @author 2023 Daniel Kesselberg <mail@danielkesselberg.de> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\DAV\Tests\unit\CalDAV; |
||||
|
||||
use OCA\DAV\CalDAV\EventComparisonService; |
||||
use Sabre\VObject\Component\VCalendar; |
||||
use Sabre\VObject\Component\VEvent; |
||||
use Test\TestCase; |
||||
|
||||
class EventComparisonServiceTest extends TestCase |
||||
{ |
||||
/** @var EventComparisonService */ |
||||
private $eventComparisonService; |
||||
|
||||
protected function setUp(): void |
||||
{ |
||||
$this->eventComparisonService = new EventComparisonService(); |
||||
} |
||||
|
||||
public function testNoModifiedEvent(): void |
||||
{ |
||||
$vCalendarOld = new VCalendar(); |
||||
$vCalendarNew = new VCalendar(); |
||||
|
||||
$vEventOld = $vCalendarOld->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RRULE' => 'FREQ=DAILY;INTERVAL=1;UNTIL=20160201T000000Z', |
||||
]); |
||||
$vEventOld->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventOld->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$vEventNew = $vCalendarNew->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RRULE' => 'FREQ=DAILY;INTERVAL=1;UNTIL=20160201T000000Z', |
||||
]); |
||||
$vEventNew->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventNew->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$result = $this->eventComparisonService->findModified($vCalendarNew, $vCalendarOld); |
||||
$this->assertEmpty($result['old']); |
||||
$this->assertEmpty($result['new']); |
||||
} |
||||
|
||||
public function testNewEvent(): void |
||||
{ |
||||
$vCalendarOld = null; |
||||
$vCalendarNew = new VCalendar(); |
||||
|
||||
$vEventNew = $vCalendarNew->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RRULE' => 'FREQ=DAILY;INTERVAL=1;UNTIL=20160201T000000Z', |
||||
]); |
||||
$vEventNew->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventNew->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$result = $this->eventComparisonService->findModified($vCalendarNew, $vCalendarOld); |
||||
$this->assertNull($result['old']); |
||||
$this->assertEquals([$vEventNew], $result['new']); |
||||
} |
||||
|
||||
public function testModifiedUnmodifiedEvent(): void |
||||
{ |
||||
$vCalendarOld = new VCalendar(); |
||||
$vCalendarNew = new VCalendar(); |
||||
|
||||
$vEventOld1 = $vCalendarOld->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
]); |
||||
$vEventOld1->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventOld1->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$vEventOld2 = $vCalendarOld->add('VEVENT', [ |
||||
'UID' => 'uid-1235', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
]); |
||||
$vEventOld2->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventOld2->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$vEventNew1 = $vCalendarNew->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
]); |
||||
$vEventNew1->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventNew1->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$vEventNew2 = $vCalendarNew->add('VEVENT', [ |
||||
'UID' => 'uid-1235', |
||||
'LAST-MODIFIED' => 123457, |
||||
'SEQUENCE' => 3, |
||||
'SUMMARY' => 'Fellowship meeting 2', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
]); |
||||
$vEventNew2->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$vEventNew2->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
|
||||
$result = $this->eventComparisonService->findModified($vCalendarNew, $vCalendarOld); |
||||
$this->assertEquals([$vEventOld2], $result['old']); |
||||
$this->assertEquals([$vEventNew2], $result['new']); |
||||
} |
||||
} |
||||
@ -0,0 +1,284 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2016, ownCloud, Inc. |
||||
* @copyright Copyright (c) 2017, Georg Ehrke |
||||
* |
||||
* @author brad2014 <brad2014@users.noreply.github.com> |
||||
* @author Brad Rubenstein <brad@wbr.tech> |
||||
* @author Christoph Wurst <christoph@winzerhof-wurst.at> |
||||
* @author Georg Ehrke <oc.list@georgehrke.com> |
||||
* @author Joas Schilling <coding@schilljs.com> |
||||
* @author Morris Jobke <hey@morrisjobke.de> |
||||
* @author Thomas Citharel <nextcloud@tcit.fr> |
||||
* @author Thomas Müller <thomas.mueller@tmit.eu> |
||||
* |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\DAV\Tests\unit\CalDAV\Schedule; |
||||
|
||||
use OC\L10N\L10N; |
||||
use OC\L10N\LazyL10N; |
||||
use OC\URLGenerator; |
||||
use OCA\DAV\CalDAV\Schedule\IMipService; |
||||
use OCP\IConfig; |
||||
use OCP\IDBConnection; |
||||
use OCP\L10N\IFactory as L10NFactory; |
||||
use OCP\Security\ISecureRandom; |
||||
use PHPUnit\Framework\MockObject\MockObject; |
||||
use Sabre\VObject\Component\VCalendar; |
||||
use Sabre\VObject\Component\VEvent; |
||||
use Sabre\VObject\Property\ICalendar\DateTime; |
||||
use Test\TestCase; |
||||
|
||||
class IMipServiceTest extends TestCase |
||||
{ |
||||
/** @var URLGenerator|MockObject */ |
||||
private $urlGenerator; |
||||
|
||||
/** @var IConfig|MockObject */ |
||||
private $config; |
||||
|
||||
/** @var IDBConnection|MockObject */ |
||||
private $db; |
||||
|
||||
/** @var ISecureRandom|MockObject */ |
||||
private $random; |
||||
|
||||
/** @var L10NFactory|MockObject */ |
||||
private $l10nFactory; |
||||
|
||||
/** @var L10N|MockObject */ |
||||
private $l10n; |
||||
|
||||
/** @var IMipService */ |
||||
private $service; |
||||
|
||||
protected function setUp(): void |
||||
{ |
||||
$this->urlGenerator = $this->createMock(URLGenerator::class); |
||||
$this->config = $this->createMock(IConfig::class); |
||||
$this->db = $this->createMock(IDBConnection::class); |
||||
$this->random = $this->createMock(ISecureRandom::class); |
||||
$this->l10nFactory = $this->createMock(L10NFactory::class); |
||||
$this->l10n = $this->createMock(LazyL10N::class); |
||||
$this->l10nFactory->expects(self::once()) |
||||
->method('findGenericLanguage') |
||||
->willReturn('en'); |
||||
$this->l10nFactory->expects(self::once()) |
||||
->method('get') |
||||
->with('dav', 'en') |
||||
->willReturn($this->l10n); |
||||
$this->service = new IMipService( |
||||
$this->urlGenerator, |
||||
$this->config, |
||||
$this->db, |
||||
$this->random, |
||||
$this->l10nFactory |
||||
); |
||||
} |
||||
|
||||
public function testGetFrom(): void |
||||
{ |
||||
$senderName = "Detective McQueen"; |
||||
$default = "Twin Lakes Police Department - Darkside Division"; |
||||
$expected = "Detective McQueen via Twin Lakes Police Department - Darkside Division"; |
||||
|
||||
$this->l10n->expects(self::once()) |
||||
->method('t') |
||||
->willReturn($expected); |
||||
|
||||
$actual = $this->service->getFrom($senderName, $default); |
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function testBuildBodyDataCreated(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$oldVevent = null; |
||||
$newVevent = new VEvent($vCalendar, 'two', [ |
||||
'UID' => 'uid-1234', |
||||
'SEQUENCE' => 3, |
||||
'LAST-MODIFIED' => 789456, |
||||
'SUMMARY' => 'Second Breakfast', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00') |
||||
]); |
||||
|
||||
$expected = [ |
||||
'meeting_when' => $this->service->generateWhenString($newVevent), |
||||
'meeting_description' => '', |
||||
'meeting_title' => 'Second Breakfast', |
||||
'meeting_location' => '', |
||||
'meeting_url' => '', |
||||
'meeting_url_html' => '', |
||||
]; |
||||
|
||||
$actual = $this->service->buildBodyData($newVevent, $oldVevent); |
||||
|
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function testBuildBodyDataUpdate(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$oldVevent = new VEvent($vCalendar, 'two', [ |
||||
'UID' => 'uid-1234', |
||||
'SEQUENCE' => 1, |
||||
'LAST-MODIFIED' => 456789, |
||||
'SUMMARY' => 'Elevenses', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00') |
||||
]); |
||||
$oldVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); |
||||
$oldVevent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); |
||||
$newVevent = new VEvent($vCalendar, 'two', [ |
||||
'UID' => 'uid-1234', |
||||
'SEQUENCE' => 3, |
||||
'LAST-MODIFIED' => 789456, |
||||
'SUMMARY' => 'Second Breakfast', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00') |
||||
]); |
||||
|
||||
$expected = [ |
||||
'meeting_when' => $this->service->generateWhenString($newVevent), |
||||
'meeting_description' => '', |
||||
'meeting_title' => 'Second Breakfast', |
||||
'meeting_location' => '', |
||||
'meeting_url' => '', |
||||
'meeting_url_html' => '', |
||||
'meeting_when_html' => $this->service->generateWhenString($newVevent), |
||||
'meeting_title_html' => sprintf("<span style='text-decoration: line-through'>%s</span><br />%s", 'Elevenses', 'Second Breakfast'), |
||||
'meeting_description_html' => '', |
||||
'meeting_location_html' => '' |
||||
]; |
||||
|
||||
$actual = $this->service->buildBodyData($newVevent, $oldVevent); |
||||
|
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function testGenerateWhenStringHourlyEvent(): void { |
||||
$vCalendar = new VCalendar(); |
||||
$vevent = new VEvent($vCalendar, 'two', [ |
||||
'UID' => 'uid-1234', |
||||
'SEQUENCE' => 1, |
||||
'LAST-MODIFIED' => 456789, |
||||
'SUMMARY' => 'Elevenses', |
||||
'TZID' => 'Europe/Vienna', |
||||
'DTSTART' => (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), |
||||
'DTEND' => (new \DateTime('2016-01-01 09:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), |
||||
]); |
||||
|
||||
$this->l10n->expects(self::exactly(3)) |
||||
->method('l') |
||||
->withConsecutive( |
||||
['weekdayName', (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'abbreviated']], |
||||
['datetime', (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'medium|short']], |
||||
['time', (new \DateTime('2016-01-01 09:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'short']] |
||||
)->willReturnOnConsecutiveCalls( |
||||
'Fr.', |
||||
'01.01. 08:00', |
||||
'09:00' |
||||
); |
||||
|
||||
$expected = 'Fr., 01.01. 08:00 - 09:00 (Europe/Vienna)'; |
||||
$actual = $this->service->generateWhenString($vevent); |
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function testGetLastOccurrenceRRULE(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$vCalendar->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'RRULE' => 'FREQ=DAILY;INTERVAL=1;UNTIL=20160201T000000Z', |
||||
]); |
||||
|
||||
$occurrence = $this->service->getLastOccurrence($vCalendar); |
||||
$this->assertEquals(1454284800, $occurrence); |
||||
} |
||||
|
||||
public function testGetLastOccurrenceEndDate(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$vCalendar->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'DTEND' => new \DateTime('2017-01-01 00:00:00'), |
||||
]); |
||||
|
||||
$occurrence = $this->service->getLastOccurrence($vCalendar); |
||||
$this->assertEquals(1483228800, $occurrence); |
||||
} |
||||
|
||||
public function testGetLastOccurrenceDuration(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$vCalendar->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
'DURATION' => 'P12W', |
||||
]); |
||||
|
||||
$occurrence = $this->service->getLastOccurrence($vCalendar); |
||||
$this->assertEquals(1458864000, $occurrence); |
||||
} |
||||
|
||||
public function testGetLastOccurrenceAllDay(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$vEvent = $vCalendar->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
]); |
||||
|
||||
// rewrite from DateTime to Date |
||||
$vEvent->DTSTART['VALUE'] = 'DATE'; |
||||
|
||||
$occurrence = $this->service->getLastOccurrence($vCalendar); |
||||
$this->assertEquals(1451692800, $occurrence); |
||||
} |
||||
|
||||
public function testGetLastOccurrenceFallback(): void |
||||
{ |
||||
$vCalendar = new VCalendar(); |
||||
$vCalendar->add('VEVENT', [ |
||||
'UID' => 'uid-1234', |
||||
'LAST-MODIFIED' => 123456, |
||||
'SEQUENCE' => 2, |
||||
'SUMMARY' => 'Fellowship meeting', |
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00'), |
||||
]); |
||||
|
||||
$occurrence = $this->service->getLastOccurrence($vCalendar); |
||||
$this->assertEquals(1451606400, $occurrence); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue