@@ -2349,6 +2349,10 @@ private function searchCalendarObjects(IQueryBuilder $query, ?DateTimeInterface
23492349 }
23502350
23512351 try {
2352+ // The time-range filter is hardcoded to VEVENT: Sabre only
2353+ // expands VEVENT recurrences (EventIterator is VEVENT-only and
2354+ // VTodo::isInTimeRange ignores RRULE), so other component types
2355+ // would not be filtered correctly here.
23522356 $ isValid = $ this ->validateFilterForObject ($ row , [
23532357 'name ' => 'VCALENDAR ' ,
23542358 'comp-filters ' => [
@@ -2452,13 +2456,24 @@ private function transformSearchProperty(Property $prop) {
24522456 }
24532457
24542458 /**
2459+ * Search calendar objects across a principal's calendars.
2460+ *
2461+ * This returns the stored calendar objects and does not expand recurring
2462+ * events. Callers that need the concrete occurrence for a requested time
2463+ * range must expand recurrences from `calendardata` themselves.
2464+ *
2465+ * Note: when a `timerange` option is given, the precise filtering assumes
2466+ * VEVENT components (see searchCalendarObjects()). Passing other component
2467+ * types together with a `timerange` would drop all results.
2468+ *
24552469 * @param string $principalUri
24562470 * @param string $pattern
24572471 * @param array $componentTypes
24582472 * @param array $searchProperties
24592473 * @param array $searchParameters
24602474 * @param array $options
2461- * @return array
2475+ *
2476+ * @return list<array{uri: string, calendarid: int, calendartype: int, calendardata: string}>
24622477 */
24632478 public function searchPrincipalUri (string $ principalUri ,
24642479 string $ pattern ,
@@ -2474,6 +2489,11 @@ public function searchPrincipalUri(string $principalUri,
24742489 $ calendarOr = [];
24752490 $ searchOr = [];
24762491
2492+ $ start = null ;
2493+ $ end = null ;
2494+
2495+ // Todo: The retries when $hasLimit && $hasTimeRange from https://github.com/nextcloud/server/pull/45222 should also be applied here to the calendarObjectIdQuery
2496+
24772497 // Fetch calendars and subscription
24782498 $ calendars = $ this ->getCalendarsForUser ($ principalUri );
24792499 $ subscriptions = $ this ->getSubscriptionsForUser ($ principalUri );
@@ -2552,19 +2572,21 @@ public function searchPrincipalUri(string $principalUri,
25522572 if (isset ($ options ['offset ' ])) {
25532573 $ calendarObjectIdQuery ->setFirstResult ($ options ['offset ' ]);
25542574 }
2555- if (isset ($ options ['timerange ' ])) {
2556- if (isset ($ options ['timerange ' ]['start ' ]) && $ options ['timerange ' ]['start ' ] instanceof DateTimeInterface) {
2557- $ calendarObjectIdQuery ->andWhere ($ calendarObjectIdQuery ->expr ()->gt (
2558- 'lastoccurence ' ,
2559- $ calendarObjectIdQuery ->createNamedParameter ($ options ['timerange ' ]['start ' ]->getTimeStamp ()),
2560- ));
2561- }
2562- if (isset ($ options ['timerange ' ]['end ' ]) && $ options ['timerange ' ]['end ' ] instanceof DateTimeInterface) {
2563- $ calendarObjectIdQuery ->andWhere ($ calendarObjectIdQuery ->expr ()->lt (
2564- 'firstoccurence ' ,
2565- $ calendarObjectIdQuery ->createNamedParameter ($ options ['timerange ' ]['end ' ]->getTimeStamp ()),
2566- ));
2567- }
2575+ if (isset ($ options ['timerange ' ]['start ' ]) && $ options ['timerange ' ]['start ' ] instanceof DateTimeInterface) {
2576+ /** @var DateTimeInterface $start */
2577+ $ start = $ options ['timerange ' ]['start ' ];
2578+ $ calendarObjectIdQuery ->andWhere ($ calendarObjectIdQuery ->expr ()->gt (
2579+ 'lastoccurence ' ,
2580+ $ calendarObjectIdQuery ->createNamedParameter ($ start ->getTimestamp ()),
2581+ ));
2582+ }
2583+ if (isset ($ options ['timerange ' ]['end ' ]) && $ options ['timerange ' ]['end ' ] instanceof DateTimeInterface) {
2584+ /** @var DateTimeInterface $end */
2585+ $ end = $ options ['timerange ' ]['end ' ];
2586+ $ calendarObjectIdQuery ->andWhere ($ calendarObjectIdQuery ->expr ()->lt (
2587+ 'firstoccurence ' ,
2588+ $ calendarObjectIdQuery ->createNamedParameter ($ end ->getTimestamp ()),
2589+ ));
25682590 }
25692591
25702592 $ result = $ calendarObjectIdQuery ->executeQuery ();
@@ -2579,17 +2601,16 @@ public function searchPrincipalUri(string $principalUri,
25792601 ->from ('calendarobjects ' )
25802602 ->where ($ query ->expr ()->in ('id ' , $ query ->createNamedParameter ($ matches , IQueryBuilder::PARAM_INT_ARRAY )));
25812603
2582- $ result = $ query ->executeQuery ();
2583- $ calendarObjects = [];
2584- while (($ array = $ result ->fetch ()) !== false ) {
2585- $ array ['calendarid ' ] = (int )$ array ['calendarid ' ];
2586- $ array ['calendartype ' ] = (int )$ array ['calendartype ' ];
2587- $ array ['calendardata ' ] = $ this ->readBlob ($ array ['calendardata ' ]);
2604+ $ calendarObjects = $ this ->searchCalendarObjects ($ query , $ start , $ end );
25882605
2589- $ calendarObjects [] = $ array ;
2590- }
2591- $ result ->closeCursor ();
2592- return $ calendarObjects ;
2606+ return array_values (array_map (function ($ event ) {
2607+ return [
2608+ 'uri ' => (string )$ event ['uri ' ],
2609+ 'calendarid ' => (int )$ event ['calendarid ' ],
2610+ 'calendartype ' => (int )$ event ['calendartype ' ],
2611+ 'calendardata ' => (string )$ this ->readBlob ($ event ['calendardata ' ]),
2612+ ];
2613+ }, $ calendarObjects ));
25932614 }, $ this ->db );
25942615 }
25952616
0 commit comments