Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dav): expand recurrences when searching #40541

Merged
merged 1 commit into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -1959,8 +1960,18 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
});
$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 = [];
Expand Down
69 changes: 69 additions & 0 deletions apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1420,4 +1422,71 @@ public function testPruneOutdatedSyncTokens(): void {
// 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',
);
}
}
}
}
Loading