mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
feat(search): Seach for persons as event attendees and organizers
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
parent
78d5ec463b
commit
9b8cb5c819
2 changed files with 86 additions and 18 deletions
|
|
@ -29,19 +29,24 @@ namespace OCA\DAV\Search;
|
|||
|
||||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCP\IUser;
|
||||
use OCP\Search\IFilteringProvider;
|
||||
use OCP\Search\ISearchQuery;
|
||||
use OCP\Search\SearchResult;
|
||||
use OCP\Search\SearchResultEntry;
|
||||
use Sabre\VObject\Component;
|
||||
use Sabre\VObject\DateTimeParser;
|
||||
use Sabre\VObject\Property;
|
||||
use function array_combine;
|
||||
use function array_fill;
|
||||
use function array_key_exists;
|
||||
use function array_map;
|
||||
|
||||
/**
|
||||
* Class EventsSearchProvider
|
||||
*
|
||||
* @package OCA\DAV\Search
|
||||
*/
|
||||
class EventsSearchProvider extends ACalendarSearchProvider {
|
||||
class EventsSearchProvider extends ACalendarSearchProvider implements IFilteringProvider {
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
|
|
@ -106,22 +111,60 @@ class EventsSearchProvider extends ACalendarSearchProvider {
|
|||
$calendarsById = $this->getSortedCalendars($principalUri);
|
||||
$subscriptionsById = $this->getSortedSubscriptions($principalUri);
|
||||
|
||||
$searchResults = $this->backend->searchPrincipalUri(
|
||||
$principalUri,
|
||||
$query->getFilter('term')?->get() ?? '',
|
||||
[self::$componentType],
|
||||
self::$searchProperties,
|
||||
self::$searchParameters,
|
||||
[
|
||||
'limit' => $query->getLimit(),
|
||||
'offset' => $query->getCursor(),
|
||||
'timerange' => [
|
||||
'start' => $query->getFilter('since')?->get(),
|
||||
'end' => $query->getFilter('until')?->get(),
|
||||
/** @var string|null $term */
|
||||
$term = $query->getFilter('term')?->get();
|
||||
if ($term === null) {
|
||||
$searchResults = [];
|
||||
} else {
|
||||
$searchResults = $this->backend->searchPrincipalUri(
|
||||
$principalUri,
|
||||
$term,
|
||||
[self::$componentType],
|
||||
self::$searchProperties,
|
||||
self::$searchParameters,
|
||||
[
|
||||
'limit' => $query->getLimit(),
|
||||
'offset' => $query->getCursor(),
|
||||
'timerange' => [
|
||||
'start' => $query->getFilter('since')?->get(),
|
||||
'end' => $query->getFilter('until')?->get(),
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
/** @var IUser|null $person */
|
||||
$person = $query->getFilter('person')?->get();
|
||||
$personDisplayName = $person?->getDisplayName();
|
||||
if ($personDisplayName !== null) {
|
||||
$attendeeSearchResults = $this->backend->searchPrincipalUri(
|
||||
$principalUri,
|
||||
$personDisplayName,
|
||||
[self::$componentType],
|
||||
['ATTENDEE'],
|
||||
self::$searchParameters,
|
||||
[
|
||||
'limit' => $query->getLimit(),
|
||||
'offset' => $query->getCursor(),
|
||||
'timerange' => [
|
||||
'start' => $query->getFilter('since')?->get(),
|
||||
'end' => $query->getFilter('until')?->get(),
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
$formattedResults = \array_map(function (array $eventRow) use ($calendarsById, $subscriptionsById):SearchResultEntry {
|
||||
);
|
||||
|
||||
$searchResultIndex = array_combine(
|
||||
array_map(fn($event) => $event['calendarid'] . '-' . $event['uri'], $searchResults),
|
||||
array_fill(0, count($searchResults), null),
|
||||
);
|
||||
foreach ($attendeeSearchResults as $attendeeResult) {
|
||||
if (array_key_exists($attendeeResult['calendarid'] . '-' . $attendeeResult['uri'], $searchResultIndex)) {
|
||||
// Duplicate
|
||||
continue;
|
||||
}
|
||||
$searchResults[] = $attendeeResult;
|
||||
}
|
||||
}
|
||||
$formattedResults = \array_map(function (array $eventRow) use ($calendarsById, $subscriptionsById): SearchResultEntry {
|
||||
$component = $this->getPrimaryComponent($eventRow['calendardata'], self::$componentType);
|
||||
$title = (string)($component->SUMMARY ?? $this->l10n->t('Untitled event'));
|
||||
$subline = $this->generateSubline($component);
|
||||
|
|
@ -228,4 +271,21 @@ class EventsSearchProvider extends ACalendarSearchProvider {
|
|||
): bool {
|
||||
return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d');
|
||||
}
|
||||
|
||||
public function getSupportedFilters(): array {
|
||||
return [
|
||||
'term',
|
||||
'person',
|
||||
'since',
|
||||
'until',
|
||||
];
|
||||
}
|
||||
|
||||
public function getAlternateIds(): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getCustomFilters(): array {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ use OCP\App\IAppManager;
|
|||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Search\IFilter;
|
||||
use OCP\Search\ISearchQuery;
|
||||
use OCP\Search\SearchResult;
|
||||
use OCP\Search\SearchResultEntry;
|
||||
|
|
@ -293,7 +294,14 @@ class EventsSearchProviderTest extends TestCase {
|
|||
$user = $this->createMock(IUser::class);
|
||||
$user->method('getUID')->willReturn('john.doe');
|
||||
$query = $this->createMock(ISearchQuery::class);
|
||||
$query->method('getTerm')->willReturn('search term');
|
||||
$seachTermFilter = $this->createMock(IFilter::class);
|
||||
$query->method('getFilter')->willReturnCallback(function($name) use ($seachTermFilter) {
|
||||
return match ($name) {
|
||||
'term' => $seachTermFilter,
|
||||
default => null,
|
||||
};
|
||||
});
|
||||
$seachTermFilter->method('get')->willReturn('search term');
|
||||
$query->method('getLimit')->willReturn(5);
|
||||
$query->method('getCursor')->willReturn(20);
|
||||
$this->appManager->expects($this->once())
|
||||
|
|
@ -328,7 +336,7 @@ class EventsSearchProviderTest extends TestCase {
|
|||
]);
|
||||
$this->backend->expects($this->once())
|
||||
->method('searchPrincipalUri')
|
||||
->with('principals/users/john.doe', '', ['VEVENT'],
|
||||
->with('principals/users/john.doe', 'search term', ['VEVENT'],
|
||||
['SUMMARY', 'LOCATION', 'DESCRIPTION', 'ATTENDEE', 'ORGANIZER', 'CATEGORIES'],
|
||||
['ATTENDEE' => ['CN'], 'ORGANIZER' => ['CN']],
|
||||
['limit' => 5, 'offset' => 20, 'timerange' => ['start' => null, 'end' => null]])
|
||||
|
|
|
|||
Loading…
Reference in a new issue