From f34513d8ad93d8694f255e59158597b15a833ba3 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sat, 21 Mar 2026 15:08:05 +0100 Subject: [PATCH] fix(ICalendar): allow to search for event URI Signed-off-by: Jonas --- apps/dav/lib/CalDAV/CalDavBackend.php | 4 ++ .../tests/unit/CalDAV/CalDavBackendTest.php | 66 +++++++++++++++++++ lib/public/Calendar/ICalendar.php | 2 + 3 files changed, 72 insertions(+) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index cdf542467c173..999ce7bedec9c 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -2062,6 +2062,10 @@ public function search( $outerQuery->andWhere($outerQuery->expr()->eq('uid', $outerQuery->createNamedParameter($options['uid']))); } + if (isset($options['uri'])) { + $outerQuery->andWhere($outerQuery->expr()->eq('uri', $outerQuery->createNamedParameter($options['uri']))); + } + if (!empty($options['types'])) { $or = []; foreach ($options['types'] as $type) { diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index f80369ff7c2c4..09d77ddc61a96 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -1840,6 +1840,72 @@ public function testSearchShouldReturnObjectsInTheSameOrderMissingDate(): void { $this->assertEquals('Missing DTSTART 2', $results[3]['objects'][0]['SUMMARY'][0]); } + public function testSearchByUri(): void { + $calendarId = $this->createTestCalendar(); + $uris = []; + $calData = []; + + $uris[] = static::getUniqueID('calobj'); + $calData[] = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:Nextcloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20260323T093039Z +UID:search-by-uri-test1 +LAST-MODIFIED;VALUE=DATE-TIME:20260323T093039Z +DTSTAMP;VALUE=DATE-TIME:20260323T093039Z +SUMMARY:First Test Event +DTSTART;VALUE=DATE-TIME:20260323T093039Z +DTEND;VALUE=DATE-TIME:20260323T093039Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + + $uris[] = static::getUniqueID('calobj'); + $calData[] = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:Nextcloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20260323T093039Z +UID:search-by-uri-test2 +LAST-MODIFIED;VALUE=DATE-TIME:20260323T093039Z +DTSTAMP;VALUE=DATE-TIME:20260323T093039Z +SUMMARY:Second Test Event +DTSTART;VALUE=DATE-TIME:20260323T093039Z +DTEND;VALUE=DATE-TIME:20260323T093039Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + + foreach ($uris as $i => $uri) { + $this->backend->createCalendarObject($calendarId, $uri, $calData[$i]); + } + + $calendarInfo = [ + 'id' => $calendarId, + 'principaluri' => 'user1', + '{http://owncloud.org/ns}owner-principal' => 'user1', + ]; + + // Searching by first event's URI returns this event + $results = $this->backend->search($calendarInfo, '', [], ['uri' => $uris[0]], null, null); + $this->assertCount(1, $results); + $this->assertEquals($uris[0], $results[0]['uri']); + + // Searching by second event's URI returns this event + $results = $this->backend->search($calendarInfo, '', [], ['uri' => $uris[1]], null, null); + $this->assertCount(1, $results); + $this->assertEquals($uris[1], $results[0]['uri']); + + // Searching by a non-existent URI returns nothing + $result = $this->backend->search($calendarInfo, '', [], ['uri' => 'nonexistant.ical'], null, null); + $this->assertCount(0, $result); + } + public function testUnshare(): void { $principalGroup = 'principal:' . self::UNIT_TEST_GROUP; $principalUser = 'principal:' . self::UNIT_TEST_USER; diff --git a/lib/public/Calendar/ICalendar.php b/lib/public/Calendar/ICalendar.php index 50152d1240ba0..a267ec097bd90 100644 --- a/lib/public/Calendar/ICalendar.php +++ b/lib/public/Calendar/ICalendar.php @@ -18,6 +18,7 @@ * @psalm-type CalendarSearchOptions = array{ * timerange?: array{start?: DateTimeInterface, end?: DateTimeInterface}, * uid?: string, + * uri?: string, * types?: string[], * } */ @@ -60,6 +61,7 @@ public function getDisplayColor(): ?string; * @param array $options Optional parameters for the search: * - 'timerange' element that can have 'start' (DateTimeInterface), 'end' (DateTimeInterface), or both. * - 'uid' element to look for events with a given uid. + * - 'uri' element to look for events with a given uri. * - 'types' element to only return events for a given type (e.g. VEVENT or VTODO) * @psalm-param CalendarSearchOptions $options * @param int|null $limit Limit the number of search results.