diff options
author | Richard Steinmetz <richard@steinmetz.cloud> | 2023-09-20 17:45:54 +0200 |
---|---|---|
committer | backportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com> | 2023-09-26 08:04:33 +0000 |
commit | 28f58a8af9b3ec2bd73176ba97982368a557f86e (patch) | |
tree | 93517e658adbf80ca93222441bcffb39875c9b43 | |
parent | 2ebd5bb939a2e57b569bc6713290af67a3d91689 (diff) | |
download | nextcloud-server-28f58a8af9b3ec2bd73176ba97982368a557f86e.tar.gz nextcloud-server-28f58a8af9b3ec2bd73176ba97982368a557f86e.zip |
fix(dav): expand recurrences when searching
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
-rw-r--r-- | apps/dav/lib/CalDAV/CalDavBackend.php | 13 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/CalDavBackendTest.php | 69 |
2 files changed, 81 insertions, 1 deletions
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 4c1acfbfbfe..672543460c3 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -20,6 +20,7 @@ * @author Thomas Citharel <nextcloud@tcit.fr> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vinicius Cubas Brand <vinicius@eita.org.br> + * @author Richard Steinmetz <richard@steinmetz.cloud> * * @license AGPL-3.0 * @@ -1959,8 +1960,18 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription }); $result->closeCursor(); - return array_map(function ($o) { + return array_map(function ($o) use ($options) { $calendarData = Reader::read($o['calendardata']); + + // Expand recurrences if an explicit time range is requested + if ($calendarData instanceof VCalendar + && isset($options['timerange']['start'], $options['timerange']['end'])) { + $calendarData = $calendarData->expand( + $options['timerange']['start'], + $options['timerange']['end'], + ); + } + $comps = $calendarData->getComponents(); $objects = []; $timezones = []; diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index 1be42c22ed7..868205301dd 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -32,7 +32,9 @@ namespace OCA\DAV\Tests\unit\CalDAV; +use DateInterval; use DateTime; +use DateTimeImmutable; use DateTimeZone; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\Calendar; @@ -1420,4 +1422,71 @@ EOD; // Check that no crash occurs when prune is called without current changes $deleted = $this->backend->pruneOutdatedSyncTokens(1); } + + public function testSearchAndExpandRecurrences() { + $calendarId = $this->createTestCalendar(); + $calendarInfo = [ + 'id' => $calendarId, + 'principaluri' => 'user1', + '{http://owncloud.org/ns}owner-principal' => 'user1', + ]; + + $calData = <<<'EOD' +BEGIN:VCALENDAR +PRODID:-//IDN nextcloud.com//Calendar app 4.5.0-alpha.2//EN +CALSCALE:GREGORIAN +VERSION:2.0 +BEGIN:VEVENT +CREATED:20230921T133401Z +DTSTAMP:20230921T133448Z +LAST-MODIFIED:20230921T133448Z +SEQUENCE:2 +UID:7b7d5d12-683c-48ce-973a-b3e1cb0bae2a +DTSTART;VALUE=DATE:20230912 +DTEND;VALUE=DATE:20230913 +STATUS:CONFIRMED +SUMMARY:Daily Event +RRULE:FREQ=DAILY +END:VEVENT +END:VCALENDAR +EOD; + $uri = static::getUniqueID('calobj'); + $this->backend->createCalendarObject($calendarId, $uri, $calData); + + $start = new DateTimeImmutable('2023-09-20T00:00:00Z'); + $end = $start->add(new DateInterval('P14D')); + + $results = $this->backend->search( + $calendarInfo, + '', + [], + [ + 'timerange' => [ + 'start' => $start, + 'end' => $end, + ] + ], + null, + null, + ); + + $this->assertCount(1, $results); + $this->assertCount(14, $results[0]['objects']); + foreach ($results as $result) { + foreach ($result['objects'] as $object) { + $this->assertEquals($object['UID'][0], '7b7d5d12-683c-48ce-973a-b3e1cb0bae2a'); + $this->assertEquals($object['SUMMARY'][0], 'Daily Event'); + $this->assertGreaterThanOrEqual( + $start->getTimestamp(), + $object['DTSTART'][0]->getTimestamp(), + 'Recurrence starting before requested start', + ); + $this->assertLessThanOrEqual( + $end->getTimestamp(), + $object['DTSTART'][0]->getTimestamp(), + 'Recurrence starting after requested end', + ); + } + } + } } |