Skip to content

Commit afa6104

Browse files
kesselbbackportbot[bot]
authored andcommitted
feat(caldav): order the calendar objects by start date for search
Sorting the events by the start date leads to more predictable results for the search API consumers. Signed-off-by: Daniel Kesselberg <[email protected]> [skip ci]
1 parent 1edbc8e commit afa6104

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

apps/dav/lib/CalDAV/CalDavBackend.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
namespace OCA\DAV\CalDAV;
4141

4242
use DateTime;
43+
use DateTimeImmutable;
4344
use DateTimeInterface;
4445
use OCA\DAV\AppInfo\Application;
4546
use OCA\DAV\Connector\Sabre\Principal;
@@ -1958,6 +1959,10 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
19581959

19591960
$outerQuery->andWhere($outerQuery->expr()->in('c.id', $outerQuery->createFunction($innerQuery->getSQL())));
19601961

1962+
// Without explicit order by its undefined in which order the SQL server returns the events.
1963+
// For the pagination with hasLimit and hasTimeRange, a stable ordering is helpful.
1964+
$outerQuery->addOrderBy('id');
1965+
19611966
$offset = (int)$offset;
19621967
$outerQuery->setFirstResult($offset);
19631968

@@ -1993,7 +1998,7 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
19931998
$calendarObjects = $this->searchCalendarObjects($outerQuery, $start, $end);
19941999
}
19952000

1996-
return array_map(function ($o) use ($options) {
2001+
$calendarObjects = array_map(function ($o) use ($options) {
19972002
$calendarData = Reader::read($o['calendardata']);
19982003

19992004
// Expand recurrences if an explicit time range is requested
@@ -2029,6 +2034,17 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
20292034
}, $timezones),
20302035
];
20312036
}, $calendarObjects);
2037+
2038+
usort($calendarObjects, function (array $a, array $b) {
2039+
/** @var DateTimeImmutable $startA */
2040+
$startA = $a['objects'][0]['DTSTART'][0] ?? new DateTimeImmutable(self::MAX_DATE);
2041+
/** @var DateTimeImmutable $startB */
2042+
$startB = $b['objects'][0]['DTSTART'][0] ?? new DateTimeImmutable(self::MAX_DATE);
2043+
2044+
return $startA->getTimestamp() <=> $startB->getTimestamp();
2045+
});
2046+
2047+
return $calendarObjects;
20322048
}
20332049

20342050
private function searchCalendarObjects(IQueryBuilder $query, DateTimeInterface|null $start, DateTimeInterface|null $end): array {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
BEGIN:VCALENDAR
2+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
3+
VERSION:2.0
4+
BEGIN:VEVENT
5+
CREATED:20240507T122246Z
6+
LAST-MODIFIED:20240507T175258Z
7+
DTSTAMP:20240507T175258Z
8+
UID:39e1b04f-d1cc-4622-bf97-11c38e070f43
9+
SUMMARY:Missing DTSTART 1
10+
DTEND;TZID=Europe/Berlin:20240514T133000
11+
TRANSP:OPAQUE
12+
X-MOZ-GENERATION:2
13+
END:VEVENT
14+
END:VCALENDAR
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
BEGIN:VCALENDAR
2+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
3+
VERSION:2.0
4+
BEGIN:VEVENT
5+
CREATED:20240507T122246Z
6+
LAST-MODIFIED:20240507T175258Z
7+
DTSTAMP:20240507T175258Z
8+
UID:12413feb-4b8c-4e95-ae7f-9ec4f42f3348
9+
SUMMARY:Missing DTSTART 2
10+
DTEND;TZID=Europe/Berlin:20240514T133000
11+
TRANSP:OPAQUE
12+
X-MOZ-GENERATION:2
13+
END:VEVENT
14+
END:VCALENDAR

lib/public/Calendar/ICalendar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function getDisplayColor(): ?string;
6565
* ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]]
6666
* @param int|null $limit - limit number of search results
6767
* @param int|null $offset - offset for paging of search results
68-
* @return array an array of events/journals/todos which are arrays of key-value-pairs
68+
* @return array an array of events/journals/todos which are arrays of key-value-pairs. the events are sorted by start date (closest first, furthest last)
6969
* @since 13.0.0
7070
*/
7171
public function search(string $pattern, array $searchProperties = [], array $options = [], ?int $limit = null, ?int $offset = null): array;

0 commit comments

Comments
 (0)