From d3bd428737596073422b178619644addd27ee549 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Tue, 13 Oct 2020 12:44:07 -0100 Subject: search compat nc20 Signed-off-by: Maxence Lange --- lib/AppInfo/Application.php | 5 +- lib/Db/HashtagsRequestBuilder.php | 2 +- lib/Search/UnifiedSearchProvider.php | 256 +++++++++++++++++++++++++++++++++++ lib/Search/UnifiedSearchResult.php | 178 ++++++++++++++++++++++++ lib/Service/CheckService.php | 3 +- lib/Service/SearchService.php | 41 +----- 6 files changed, 447 insertions(+), 38 deletions(-) create mode 100644 lib/Search/UnifiedSearchProvider.php create mode 100644 lib/Search/UnifiedSearchResult.php (limited to 'lib') diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 0f7eab91..977857d3 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -33,9 +33,8 @@ namespace OCA\Social\AppInfo; use Closure; use OC\DB\SchemaWrapper; -use OC\WellKnown\Event\WellKnownEvent; -use OCA\Social\Listeners\WellKnownListener; use OCA\Social\Notification\Notifier; +use OCA\Social\Search\UnifiedSearchProvider; use OCA\Social\Service\ConfigService; use OCA\Social\Service\UpdateService; use OCP\AppFramework\App; @@ -73,6 +72,8 @@ class Application extends App implements IBootstrap { * @param IRegistrationContext $context */ public function register(IRegistrationContext $context): void { + $context->registerSearchProvider(UnifiedSearchProvider::class); + // TODO: nc21, uncomment // $context->registerEventListener(WellKnownEvent::class, WellKnownListener::class); } diff --git a/lib/Db/HashtagsRequestBuilder.php b/lib/Db/HashtagsRequestBuilder.php index f3ab9d0c..a2972b1f 100644 --- a/lib/Db/HashtagsRequestBuilder.php +++ b/lib/Db/HashtagsRequestBuilder.php @@ -109,7 +109,7 @@ class HashtagsRequestBuilder extends CoreRequestBuilder { * * @return array */ - public function parseHashtagsSelectSql($data): array { + public function parseHashtagsSelectSql(array $data): array { return [ 'hashtag' => $this->get('hashtag', $data, ''), 'trend' => $this->getArray('trend', $data, []) diff --git a/lib/Search/UnifiedSearchProvider.php b/lib/Search/UnifiedSearchProvider.php new file mode 100644 index 00000000..f8f8c5bc --- /dev/null +++ b/lib/Search/UnifiedSearchProvider.php @@ -0,0 +1,256 @@ + + * @copyright 2020, Maxence Lange + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Social\Search; + + +use daita\MySmallPhpTools\Traits\TArrayTools; +use Exception; +use OCA\Social\Exceptions\AccountDoesNotExistException; +use OCA\Social\Model\ActivityPub\Actor\Person; +use OCA\Social\Service\AccountService; +use OCA\Social\Service\CacheActorService; +use OCA\Social\Service\ConfigService; +use OCA\Social\Service\FollowService; +use OCA\Social\Service\MiscService; +use OCA\Social\Service\SearchService; +use OCA\Social\Service\StreamService; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Search\IProvider; +use OCP\Search\ISearchQuery; +use OCP\Search\SearchResult; + + +/** + * Class UnifiedSearchProvider + * + * @package OCA\Social\Search + */ +class UnifiedSearchProvider implements IProvider { + + + const PROVIDER_ID = 'social'; + const ORDER = 12; + + + use TArrayTools; + + + /** @var IL10N */ + private $l10n; + + /** @var IURLGenerator */ + private $urlGenerator; + + /** @var StreamService */ + private $streamService; + + /** @var FollowService */ + private $followService; + + /** @var CacheActorService */ + private $cacheActorService; + + /** @var AccountService */ + private $accountService; + + /** @var SearchService */ + private $searchService; + + /** @var ConfigService */ + private $configService; + + /** @var MiscService */ + private $miscService; + + /** @var Person */ + private $viewer; + + /** + * UnifiedSearchProvider constructor. + * + * @param IL10N $l10n + * @param IURLGenerator $urlGenerator + * @param StreamService $streamService + * @param FollowService $followService + * @param CacheActorService $cacheActorService + * @param AccountService $accountService + * @param SearchService $searchService + * @param ConfigService $configService + * @param MiscService $miscService + */ + public function __construct( + IL10N $l10n, IURLGenerator $urlGenerator, StreamService $streamService, FollowService $followService, + CacheActorService $cacheActorService, AccountService $accountService, SearchService $searchService, + ConfigService $configService, MiscService $miscService + ) { + $this->l10n = $l10n; + $this->urlGenerator = $urlGenerator; + $this->streamService = $streamService; + $this->followService = $followService; + $this->cacheActorService = $cacheActorService; + + $this->accountService = $accountService; + $this->searchService = $searchService; + $this->configService = $configService; + $this->miscService = $miscService; + } + + + /** + * return unique id of the provider + */ + public function getId(): string { + return self::PROVIDER_ID; + } + + + /** + * @return string + */ + public function getName(): string { + return $this->l10n->t('Social'); + } + + + /** + * @param string $route + * @param array $routeParameters + * + * @return int + */ + public function getOrder(string $route, array $routeParameters): int { + return self::ORDER; + } + + + /** + * @param IUser $user + * @param ISearchQuery $query + * + * @return SearchResult + * @throws AccountDoesNotExistException + */ + public function search(IUser $user, ISearchQuery $query): SearchResult { + $this->initViewer(); + $search = trim($query->getTerm()); + + $result = array_merge( + $this->convertAccounts($this->searchService->searchAccounts($search)), + $this->convertHashtags($this->searchService->searchHashtags($search)) + ); + +// $this->searchService->searchStreamContent($search) + + return SearchResult::paginated( + $this->l10n->t('Social'), $result, ($query->getCursor() ?? 0) + $query->getLimit() + ); + } + + + /** + * TODO: switch to SessionService + * + * @param bool $exception + * + * @throws AccountDoesNotExistException + */ + private function initViewer(bool $exception = false) { + if (!isset($this->userId)) { + if ($exception) { + throw new AccountDoesNotExistException('userId not defined'); + } + + return; + } + + try { + $this->viewer = $this->accountService->getActorFromUserId($this->userId, true); + + $this->streamService->setViewer($this->viewer); + $this->followService->setViewer($this->viewer); + $this->cacheActorService->setViewer($this->viewer); + } catch (Exception $e) { + if ($exception) { + throw new AccountDoesNotExistException( + 'unable to initViewer - ' . get_class($e) . ' - ' . $e->getMessage() + ); + } + } + } + + + /** + * @param Person[] $accounts + * + * @return UnifiedSearchResult[] + */ + private function convertAccounts(array $accounts): array { + $result = []; + foreach ($accounts as $account) { + $result[] = new UnifiedSearchResult( + $account->getAvatar(), + $account->getPreferredUsername(), + '@' . $account->getAccount(), + $account->getUrl(), + $account->getAvatar() + ); + } + + return $result; + } + + + /** + * @param array $hashtags + * + * @return UnifiedSearchResult[] + */ + private function convertHashtags(array $hashtags): array { + $result = []; + foreach ($hashtags as $hashtag) { + $tag = $hashtag['hashtag']; + $result[] = new UnifiedSearchResult( + '', + $hashtag['trend']['10d'] . ' posts related to \'' . $tag . '\'', + '#' . $tag, + $this->urlGenerator->linkToRouteAbsolute( + 'social.Navigation.timeline', ['path' => 'tags/' . $tag] + ), + '' + ); + } + + return $result; + } + +} + diff --git a/lib/Search/UnifiedSearchResult.php b/lib/Search/UnifiedSearchResult.php new file mode 100644 index 00000000..cecdb838 --- /dev/null +++ b/lib/Search/UnifiedSearchResult.php @@ -0,0 +1,178 @@ + + * @copyright 2020, Maxence Lange + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\Social\Search; + + +use OCP\Search\SearchResultEntry; + + +/** + * Class SearchResultEntry + * + * @package OCA\Social\Search + */ +class UnifiedSearchResult extends SearchResultEntry { + + + /** + * UnifiedSearchResult constructor. + * + * @param string $thumbnailUrl + * @param string $title + * @param string $subline + * @param string $resourceUrl + * @param string $icon + * @param bool $rounded + */ + public function __construct( + string $thumbnailUrl = '', string $title = '', string $subline = '', string $resourceUrl = '', + string $icon = '', + bool $rounded = false + ) { + parent::__construct($thumbnailUrl, $title, $subline, $resourceUrl, $icon, $rounded); + } + + + /** + * @return string + */ + public function getThumbnailUrl(): string { + return $this->thumbnailUrl; + } + + /** + * @param string $thumbnailUrl + * + * @return UnifiedSearchResult + */ + public function setThumbnailUrl(string $thumbnailUrl): self { + $this->thumbnailUrl = $thumbnailUrl; + + return $this; + } + + + /** + * @return string + */ + public function getTitle(): string { + return $this->title; + } + + /** + * @param string $title + * + * @return UnifiedSearchResult + */ + public function setTitle(string $title): self { + $this->title = $title; + + return $this; + } + + + /** + * @return string + */ + public function getSubline(): string { + return $this->subline; + } + + /** + * @param string $subline + * + * @return UnifiedSearchResult + */ + public function setSubline(string $subline): self { + $this->subline = $subline; + + return $this; + } + + + /** + * @return string + */ + public function getResourceUrl(): string { + return $this->resourceUrl; + } + + /** + * @param string $resourceUrl + * + * @return UnifiedSearchResult + */ + public function setResourceUrl(string $resourceUrl): self { + $this->resourceUrl = $resourceUrl; + + return $this; + } + + + /** + * @return string + */ + public function getIcon(): string { + return $this->icon; + } + + /** + * @param string $icon + * + * @return UnifiedSearchResult + */ + public function setIcon(string $icon): self { + $this->icon = $icon; + + return $this; + } + + + /** + * @return bool + */ + public function isRounded(): bool { + return $this->rounded; + } + + /** + * @param bool $rounded + * + * @return UnifiedSearchResult + */ + public function setRounded(bool $rounded): self { + $this->rounded = $rounded; + + return $this; + } + +} + diff --git a/lib/Service/CheckService.php b/lib/Service/CheckService.php index b4ead888..9d19bb5b 100644 --- a/lib/Service/CheckService.php +++ b/lib/Service/CheckService.php @@ -317,8 +317,9 @@ class CheckService { private function requestWellKnown(string $base) { try { $url = $base . '/.well-known/webfinger'; + $options['nextcloud']['allow_local_address'] = true; $response = $this->clientService->newClient() - ->get($url); + ->get($url, $options); if ($response->getStatusCode() === Http::STATUS_OK) { $this->cache->set(self::CACHE_PREFIX . 'wellknown', 'true', 3600); diff --git a/lib/Service/SearchService.php b/lib/Service/SearchService.php index 28f6f524..2ba81599 100644 --- a/lib/Service/SearchService.php +++ b/lib/Service/SearchService.php @@ -33,6 +33,7 @@ namespace OCA\Social\Service; use daita\MySmallPhpTools\Traits\TArrayTools; use Exception; +use OCA\Social\Model\ActivityPub\Actor\Person; class SearchService { @@ -82,14 +83,10 @@ class SearchService { /** * @param string $search * - * @return array + * @return Person[] */ public function searchAccounts(string $search): array { - $result = [ - 'exact' => null, - 'result' => [] - ]; - + $result = []; $type = $this->getTypeFromSearch($search); if ($search === '' || !$type & self::SEARCH_ACCOUNTS) { return $result; @@ -100,19 +97,11 @@ class SearchService { } try { - $exact = $this->cacheActorService->getFromAccount($search); - $exact->setCompleteDetails(true); - $result['exact'] = $exact; - } catch (Exception $e) { - } - - try { - $accounts = $this->cacheActorService->searchCachedAccounts($search); - $result['result'] = $accounts; + $this->cacheActorService->getFromAccount($search); } catch (Exception $e) { } - return $result; + return $this->cacheActorService->searchCachedAccounts($search); } @@ -122,11 +111,7 @@ class SearchService { * @return array */ public function searchHashtags(string $search): array { - $result = [ - 'exact' => null, - 'result' => [] - ]; - + $result = []; $type = $this->getTypeFromSearch($search); if ($search === '' || !$type & self::SEARCH_HASHTAGS) { return $result; @@ -136,19 +121,7 @@ class SearchService { $search = substr($search, 1); } - try { - $exact = $this->hashtagService->getHashtag($search); - $result['exact'] = $exact; - } catch (Exception $e) { - } - - try { - $hashtags = $this->hashtagService->searchHashtags($search, true); - $result['result'] = $hashtags; - } catch (Exception $e) { - } - - return $result; + return $this->hashtagService->searchHashtags($search, true); } -- cgit v1.2.3