summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2020-10-14 09:16:59 -0100
committerGitHub <noreply@github.com>2020-10-14 09:16:59 -0100
commit25cb4f5b8fd14b2acee2ac005c68e2cd41972614 (patch)
treedd5ec49640a5a99e6763ae76f4c69dfe88d899b8
parente156bcdadafb3877ad3797b739df103dc2eb40f8 (diff)
parentde67f15f6d38ac25fea690eb28e4f4c27fac36a8 (diff)
Merge pull request #1072 from nextcloud/search-nc20
Search for nc20
-rw-r--r--lib/AppInfo/Application.php5
-rw-r--r--lib/Db/HashtagsRequestBuilder.php2
-rw-r--r--lib/Model/ActivityPub/ACore.php6
-rw-r--r--lib/Search/UnifiedSearchProvider.php258
-rw-r--r--lib/Search/UnifiedSearchResult.php178
-rw-r--r--lib/Service/CheckService.php3
-rw-r--r--lib/Service/SearchService.php43
7 files changed, 450 insertions, 45 deletions
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/Model/ActivityPub/ACore.php b/lib/Model/ActivityPub/ACore.php
index 6609000d..ee8bfcb7 100644
--- a/lib/Model/ActivityPub/ACore.php
+++ b/lib/Model/ActivityPub/ACore.php
@@ -210,11 +210,7 @@ class ACore extends Item implements JsonSerializable {
* @return bool
*/
public function hasIcon(): bool {
- if ($this->icon === null) {
- return false;
- }
-
- return true;
+ return ($this->icon !== null);
}
/**
diff --git a/lib/Search/UnifiedSearchProvider.php b/lib/Search/UnifiedSearchProvider.php
new file mode 100644
index 00000000..9ef522cc
--- /dev/null
+++ b/lib/Search/UnifiedSearchProvider.php
@@ -0,0 +1,258 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Social Support
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2020, Maxence Lange <maxence@artificial-owl.com>
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+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) {
+ $icon = ($account->hasIcon()) ? $account->getIcon()->getUrl() : '';
+ $result[] = new UnifiedSearchResult(
+ $icon,
+ $account->getPreferredUsername(),
+ '@' . $account->getAccount(),
+ $account->getUrl(),
+ $icon
+ );
+ }
+
+ 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 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Social Support
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2020, Maxence Lange <maxence@artificial-owl.com>
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+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..9dacaa34 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);
}
@@ -180,11 +153,9 @@ class SearchService {
switch ($char) {
case '@':
return self::SEARCH_ACCOUNTS;
- break;
case '#':
return self::SEARCH_HASHTAGS;
- break;
default:
return self::SEARCH_ALL;