Skip to content

Commit 9b8cb5c

Browse files
feat(search): Seach for persons as event attendees and organizers
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
1 parent 78d5ec4 commit 9b8cb5c

File tree

2 files changed

+86
-18
lines changed

2 files changed

+86
-18
lines changed

apps/dav/lib/Search/EventsSearchProvider.php

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,24 @@
2929

3030
use OCA\DAV\CalDAV\CalDavBackend;
3131
use OCP\IUser;
32+
use OCP\Search\IFilteringProvider;
3233
use OCP\Search\ISearchQuery;
3334
use OCP\Search\SearchResult;
3435
use OCP\Search\SearchResultEntry;
3536
use Sabre\VObject\Component;
3637
use Sabre\VObject\DateTimeParser;
3738
use Sabre\VObject\Property;
39+
use function array_combine;
40+
use function array_fill;
41+
use function array_key_exists;
42+
use function array_map;
3843

3944
/**
4045
* Class EventsSearchProvider
4146
*
4247
* @package OCA\DAV\Search
4348
*/
44-
class EventsSearchProvider extends ACalendarSearchProvider {
49+
class EventsSearchProvider extends ACalendarSearchProvider implements IFilteringProvider {
4550
/**
4651
* @var string[]
4752
*/
@@ -106,22 +111,60 @@ public function search(
106111
$calendarsById = $this->getSortedCalendars($principalUri);
107112
$subscriptionsById = $this->getSortedSubscriptions($principalUri);
108113

109-
$searchResults = $this->backend->searchPrincipalUri(
110-
$principalUri,
111-
$query->getFilter('term')?->get() ?? '',
112-
[self::$componentType],
113-
self::$searchProperties,
114-
self::$searchParameters,
115-
[
116-
'limit' => $query->getLimit(),
117-
'offset' => $query->getCursor(),
118-
'timerange' => [
119-
'start' => $query->getFilter('since')?->get(),
120-
'end' => $query->getFilter('until')?->get(),
114+
/** @var string|null $term */
115+
$term = $query->getFilter('term')?->get();
116+
if ($term === null) {
117+
$searchResults = [];
118+
} else {
119+
$searchResults = $this->backend->searchPrincipalUri(
120+
$principalUri,
121+
$term,
122+
[self::$componentType],
123+
self::$searchProperties,
124+
self::$searchParameters,
125+
[
126+
'limit' => $query->getLimit(),
127+
'offset' => $query->getCursor(),
128+
'timerange' => [
129+
'start' => $query->getFilter('since')?->get(),
130+
'end' => $query->getFilter('until')?->get(),
131+
],
132+
]
133+
);
134+
}
135+
/** @var IUser|null $person */
136+
$person = $query->getFilter('person')?->get();
137+
$personDisplayName = $person?->getDisplayName();
138+
if ($personDisplayName !== null) {
139+
$attendeeSearchResults = $this->backend->searchPrincipalUri(
140+
$principalUri,
141+
$personDisplayName,
142+
[self::$componentType],
143+
['ATTENDEE'],
144+
self::$searchParameters,
145+
[
146+
'limit' => $query->getLimit(),
147+
'offset' => $query->getCursor(),
148+
'timerange' => [
149+
'start' => $query->getFilter('since')?->get(),
150+
'end' => $query->getFilter('until')?->get(),
151+
],
121152
],
122-
]
123-
);
124-
$formattedResults = \array_map(function (array $eventRow) use ($calendarsById, $subscriptionsById):SearchResultEntry {
153+
);
154+
155+
$searchResultIndex = array_combine(
156+
array_map(fn($event) => $event['calendarid'] . '-' . $event['uri'], $searchResults),
157+
array_fill(0, count($searchResults), null),
158+
);
159+
foreach ($attendeeSearchResults as $attendeeResult) {
160+
if (array_key_exists($attendeeResult['calendarid'] . '-' . $attendeeResult['uri'], $searchResultIndex)) {
161+
// Duplicate
162+
continue;
163+
}
164+
$searchResults[] = $attendeeResult;
165+
}
166+
}
167+
$formattedResults = \array_map(function (array $eventRow) use ($calendarsById, $subscriptionsById): SearchResultEntry {
125168
$component = $this->getPrimaryComponent($eventRow['calendardata'], self::$componentType);
126169
$title = (string)($component->SUMMARY ?? $this->l10n->t('Untitled event'));
127170
$subline = $this->generateSubline($component);
@@ -228,4 +271,21 @@ protected function isDayEqual(
228271
): bool {
229272
return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d');
230273
}
274+
275+
public function getSupportedFilters(): array {
276+
return [
277+
'term',
278+
'person',
279+
'since',
280+
'until',
281+
];
282+
}
283+
284+
public function getAlternateIds(): array {
285+
return [];
286+
}
287+
288+
public function getCustomFilters(): array {
289+
return [];
290+
}
231291
}

apps/dav/tests/unit/Search/EventsSearchProviderTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use OCP\IL10N;
3333
use OCP\IURLGenerator;
3434
use OCP\IUser;
35+
use OCP\Search\IFilter;
3536
use OCP\Search\ISearchQuery;
3637
use OCP\Search\SearchResult;
3738
use OCP\Search\SearchResultEntry;
@@ -293,7 +294,14 @@ public function testSearch(): void {
293294
$user = $this->createMock(IUser::class);
294295
$user->method('getUID')->willReturn('john.doe');
295296
$query = $this->createMock(ISearchQuery::class);
296-
$query->method('getTerm')->willReturn('search term');
297+
$seachTermFilter = $this->createMock(IFilter::class);
298+
$query->method('getFilter')->willReturnCallback(function($name) use ($seachTermFilter) {
299+
return match ($name) {
300+
'term' => $seachTermFilter,
301+
default => null,
302+
};
303+
});
304+
$seachTermFilter->method('get')->willReturn('search term');
297305
$query->method('getLimit')->willReturn(5);
298306
$query->method('getCursor')->willReturn(20);
299307
$this->appManager->expects($this->once())
@@ -328,7 +336,7 @@ public function testSearch(): void {
328336
]);
329337
$this->backend->expects($this->once())
330338
->method('searchPrincipalUri')
331-
->with('principals/users/john.doe', '', ['VEVENT'],
339+
->with('principals/users/john.doe', 'search term', ['VEVENT'],
332340
['SUMMARY', 'LOCATION', 'DESCRIPTION', 'ATTENDEE', 'ORGANIZER', 'CATEGORIES'],
333341
['ATTENDEE' => ['CN'], 'ORGANIZER' => ['CN']],
334342
['limit' => 5, 'offset' => 20, 'timerange' => ['start' => null, 'end' => null]])

0 commit comments

Comments
 (0)