Skip to content

Commit b005846

Browse files
Carefully filter out non matching time ranges for CalDAV search
When we search for CalDAV objects in the DB we take the first and last occurence into account. For recurring events that is when they take place the very first time and the very last time. Searching in a more specific time range will still match this condition, because the recurring event starts before the end of the requested range but ends after the start of the requested range. Sabre has filters for this. If we apply them on all seach objects of a search with a time range, then only the recurring events actually taking place at the time of the requested time range will be returned. Signed-off-by: Christoph Wurst <[email protected]>
1 parent 168a1b0 commit b005846

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

apps/dav/lib/CalDAV/CalDavBackend.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@
100100
use function array_values;
101101
use function explode;
102102
use function is_array;
103+
use function is_resource;
103104
use function pathinfo;
105+
use function rewind;
104106
use function sprintf;
105107
use function str_replace;
106108
use function strtolower;
@@ -1915,7 +1917,39 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
19151917
}
19161918

19171919
$result = $outerQuery->executeQuery();
1918-
$calendarObjects = $result->fetchAll();
1920+
$calendarObjects = array_filter($result->fetchAll(), function (array $row) use ($options) {
1921+
$start = $options['timerange']['start'] ?? null;
1922+
$end = $options['timerange']['end'] ?? null;
1923+
1924+
if ($start === null || !($start instanceof DateTimeInterface) || $end === null || !($end instanceof DateTimeInterface)) {
1925+
// No filter required
1926+
return true;
1927+
}
1928+
1929+
$isValid = $this->validateFilterForObject($row, [
1930+
'name' => 'VCALENDAR',
1931+
'comp-filters' => [
1932+
[
1933+
'name' => 'VEVENT',
1934+
'comp-filters' => [],
1935+
'prop-filters' => [],
1936+
'is-not-defined' => false,
1937+
'time-range' => [
1938+
'start' => $start,
1939+
'end' => $end,
1940+
],
1941+
],
1942+
],
1943+
'prop-filters' => [],
1944+
'is-not-defined' => false,
1945+
'time-range' => null,
1946+
]);
1947+
if (is_resource($row['calendardata'])) {
1948+
// Put the stream back to the beginning so it can be read another time
1949+
rewind($row['calendardata']);
1950+
}
1951+
return $isValid;
1952+
});
19191953
$result->closeCursor();
19201954

19211955
return array_map(function ($o) {

0 commit comments

Comments
 (0)