Skip to content

Commit ace0881

Browse files
committed
fix(dav): expand recurrences when searching
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
1 parent 3b6a9cd commit ace0881

2 files changed

Lines changed: 81 additions & 1 deletion

File tree

apps/dav/lib/CalDAV/CalDavBackend.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* @author Thomas Citharel <nextcloud@tcit.fr>
2121
* @author Thomas Müller <thomas.mueller@tmit.eu>
2222
* @author Vinicius Cubas Brand <vinicius@eita.org.br>
23+
* @author Richard Steinmetz <richard@steinmetz.cloud>
2324
*
2425
* @license AGPL-3.0
2526
*
@@ -1959,8 +1960,18 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
19591960
});
19601961
$result->closeCursor();
19611962

1962-
return array_map(function ($o) {
1963+
return array_map(function ($o) use ($options) {
19631964
$calendarData = Reader::read($o['calendardata']);
1965+
1966+
// Expand recurrences if an explicit time range is requested
1967+
if ($calendarData instanceof VCalendar
1968+
&& isset($options['timerange']['start'], $options['timerange']['end'])) {
1969+
$calendarData = $calendarData->expand(
1970+
$options['timerange']['start'],
1971+
$options['timerange']['end'],
1972+
);
1973+
}
1974+
19641975
$comps = $calendarData->getComponents();
19651976
$objects = [];
19661977
$timezones = [];

apps/dav/tests/unit/CalDAV/CalDavBackendTest.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232

3333
namespace OCA\DAV\Tests\unit\CalDAV;
3434

35+
use DateInterval;
3536
use DateTime;
37+
use DateTimeImmutable;
3638
use DateTimeZone;
3739
use OCA\DAV\CalDAV\CalDavBackend;
3840
use OCA\DAV\CalDAV\Calendar;
@@ -1420,4 +1422,71 @@ public function testPruneOutdatedSyncTokens(): void {
14201422
// Check that no crash occurs when prune is called without current changes
14211423
$deleted = $this->backend->pruneOutdatedSyncTokens(1);
14221424
}
1425+
1426+
public function testSearchAndExpandRecurrences() {
1427+
$calendarId = $this->createTestCalendar();
1428+
$calendarInfo = [
1429+
'id' => $calendarId,
1430+
'principaluri' => 'user1',
1431+
'{http://owncloud.org/ns}owner-principal' => 'user1',
1432+
];
1433+
1434+
$calData = <<<'EOD'
1435+
BEGIN:VCALENDAR
1436+
PRODID:-//IDN nextcloud.com//Calendar app 4.5.0-alpha.2//EN
1437+
CALSCALE:GREGORIAN
1438+
VERSION:2.0
1439+
BEGIN:VEVENT
1440+
CREATED:20230921T133401Z
1441+
DTSTAMP:20230921T133448Z
1442+
LAST-MODIFIED:20230921T133448Z
1443+
SEQUENCE:2
1444+
UID:7b7d5d12-683c-48ce-973a-b3e1cb0bae2a
1445+
DTSTART;VALUE=DATE:20230912
1446+
DTEND;VALUE=DATE:20230913
1447+
STATUS:CONFIRMED
1448+
SUMMARY:Daily Event
1449+
RRULE:FREQ=DAILY
1450+
END:VEVENT
1451+
END:VCALENDAR
1452+
EOD;
1453+
$uri = static::getUniqueID('calobj');
1454+
$this->backend->createCalendarObject($calendarId, $uri, $calData);
1455+
1456+
$start = new DateTimeImmutable('2023-09-20T00:00:00Z');
1457+
$end = $start->add(new DateInterval('P14D'));
1458+
1459+
$results = $this->backend->search(
1460+
$calendarInfo,
1461+
'',
1462+
[],
1463+
[
1464+
'timerange' => [
1465+
'start' => $start,
1466+
'end' => $end,
1467+
]
1468+
],
1469+
null,
1470+
null,
1471+
);
1472+
1473+
$this->assertCount(1, $results);
1474+
$this->assertCount(14, $results[0]['objects']);
1475+
foreach ($results as $result) {
1476+
foreach ($result['objects'] as $object) {
1477+
$this->assertEquals($object['UID'][0], '7b7d5d12-683c-48ce-973a-b3e1cb0bae2a');
1478+
$this->assertEquals($object['SUMMARY'][0], 'Daily Event');
1479+
$this->assertGreaterThanOrEqual(
1480+
$start->getTimestamp(),
1481+
$object['DTSTART'][0]->getTimestamp(),
1482+
'Recurrence starting before requested start',
1483+
);
1484+
$this->assertLessThanOrEqual(
1485+
$end->getTimestamp(),
1486+
$object['DTSTART'][0]->getTimestamp(),
1487+
'Recurrence starting after requested end',
1488+
);
1489+
}
1490+
}
1491+
}
14231492
}

0 commit comments

Comments
 (0)