diff --git a/mod/match.php b/mod/match.php deleted file mode 100644 index ea59d7ee61..0000000000 --- a/mod/match.php +++ /dev/null @@ -1,132 +0,0 @@ -. - * - */ - -use Friendica\App; -use Friendica\Content\Widget; -use Friendica\Core\Renderer; -use Friendica\Core\Search; -use Friendica\Database\DBA; -use Friendica\DI; -use Friendica\Model\Contact; -use Friendica\Model\Profile; -use Friendica\Module\Contact as ModuleContact; - -/** - * Controller for /match. - * - * It takes keywords from your profile and queries the directory server for - * matching keywords from other profiles. - * - * @param App $a App - * - * @return string - * @throws ImagickException - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - * @throws Exception - */ -function match_content(App $a) -{ - if (!DI::userSession()->getLocalUserId()) { - return ''; - } - - DI::page()['aside'] .= Widget::findPeople(); - DI::page()['aside'] .= Widget::follow(); - - $_SESSION['return_path'] = DI::args()->getCommand(); - - $profile = Profile::getByUID(DI::userSession()->getLocalUserId()); - - if (!DBA::isResult($profile)) { - return ''; - } - if (!$profile['pub_keywords'] && (!$profile['prv_keywords'])) { - DI::sysmsg()->addNotice(DI::l10n()->t('No keywords to match. Please add keywords to your profile.')); - return ''; - } - - $params = []; - $tags = trim($profile['pub_keywords'] . ' ' . $profile['prv_keywords']); - - if (DI::mode()->isMobile()) { - $limit = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'itemspage_mobile_network', - DI::config()->get('system', 'itemspage_network_mobile')); - } else { - $limit = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'itemspage_network', - DI::config()->get('system', 'itemspage_network')); - } - - $params['s'] = $tags; - $params['n'] = 100; - - $entries = []; - foreach ([Search::getGlobalDirectory(), DI::baseUrl()] as $server) { - if (empty($server)) { - continue; - } - - $msearch = json_decode(DI::httpClient()->post($server . '/msearch', $params)->getBody()); - if (!empty($msearch)) { - $entries = match_get_contacts($msearch, $entries, $limit); - } - } - - if (empty($entries)) { - DI::sysmsg()->addInfo(DI::l10n()->t('No matches')); - } - - $tpl = Renderer::getMarkupTemplate('contact/list.tpl'); - $o = Renderer::replaceMacros($tpl, [ - '$title' => DI::l10n()->t('Profile Match'), - '$contacts' => array_slice($entries, 0, $limit), - ]); - - return $o; -} - -function match_get_contacts($msearch, $entries, $limit) -{ - if (empty($msearch->results)) { - return $entries; - } - - foreach ($msearch->results as $profile) { - if (!$profile) { - continue; - } - - // Already known contact - $contact = Contact::getByURL($profile->url, null, ['rel'], DI::userSession()->getLocalUserId()); - if (!empty($contact) && in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { - continue; - } - - $contact = Contact::getByURLForUser($profile->url, DI::userSession()->getLocalUserId()); - if (!empty($contact)) { - $entries[$contact['id']] = ModuleContact::getContactTemplateVars($contact); - } - - if (count($entries) == $limit) { - break; - } - } - return $entries; -} \ No newline at end of file diff --git a/mod/msearch.php b/mod/msearch.php deleted file mode 100644 index 00a72ea9f7..0000000000 --- a/mod/msearch.php +++ /dev/null @@ -1,64 +0,0 @@ -. - * - */ - -use Friendica\App; -use Friendica\Core\System; -use Friendica\Database\DBA; -use Friendica\DI; -use Friendica\Model\User; -use Friendica\Util\Proxy; - -function msearch_post(App $a) -{ - $search = $_POST['s'] ?? ''; - $perpage = intval(($_POST['n'] ?? 0) ?: 80); - $page = intval(($_POST['p'] ?? 0) ?: 1); - $startrec = ($page - 1) * $perpage; - - $total = 0; - $results = []; - - if (!strlen($search)) { - $output = ['total' => 0, 'items_page' => $perpage, 'page' => $page, 'results' => $results]; - System::jsonExit($output); - } - - $total = 0; - - $condition = ["`net-publish` AND MATCH(`pub_keywords`) AGAINST (?)", $search]; - $total = DBA::count('owner-view', $condition); - - $search_stmt = DBA::select('owner-view', ['pub_keywords', 'name', 'nickname', 'uid'], $condition, ['limit' => [$startrec, $perpage]]); - while ($search_result = DBA::fetch($search_stmt)) { - $results[] = [ - 'name' => $search_result['name'], - 'url' => DI::baseUrl() . '/profile/' . $search_result['nickname'], - 'photo' => User::getAvatarUrl($search_result, Proxy::SIZE_THUMB), - 'tags' => str_replace([',', ' '], [' ', ' '], $search_result['pub_keywords']) - ]; - } - - DBA::close($search_stmt); - - $output = ['total' => $total, 'items_page' => $perpage, 'page' => $page, 'results' => $results]; - - System::jsonExit($output); -} diff --git a/src/Module/Contact/Match.php b/src/Module/Contact/Match.php new file mode 100644 index 0000000000..c03627e30f --- /dev/null +++ b/src/Module/Contact/Match.php @@ -0,0 +1,169 @@ +session = $session; + $this->database = $database; + $this->systemMessages = $systemMessages; + $this->page = $page; + $this->mode = $mode; + $this->config = $config; + $this->pConfig = $pConfig; + $this->httpClient = $httpClient; + } + + protected function content(array $request = []): string + { + if (!$this->session->getLocalUserId()) { + $this->systemMessages->addNotice($this->t('Permission denied.')); + $this->baseUrl->redirect('login&return_path=match'); + } + + $profile = Profile::getByUID($this->session->getLocalUserId()); + + if (empty($profile)) { + $this->logger->warning('Couldn\'t find Profile for user id in session.', ['uid' => $this->session->getLocalUserId()]); + throw new InternalServerErrorException($this->t('Invalid request.')); + } + + $this->page['aside'] .= Widget::findPeople(); + $this->page['aside'] .= Widget::follow(); + + if (empty($profile['pub_keywords']) && empty($profile['prv_keywords'])) { + $this->systemMessages->addNotice($this->t('No keywords to match. Please add keywords to your profile.')); + return ''; + } + + if ($this->mode->isMobile()) { + $limit = $this->pConfig->get($this->session->getLocalUserId(), 'system', 'itemspage_mobile_network') + ?? $this->config->get('system', 'itemspage_network_mobile'); + } else { + $limit = $this->pConfig->get($this->session->getLocalUserId(), 'system', 'itemspage_network') + ?? $this->config->get('system', 'itemspage_network'); + } + + $searchParameters = [ + 's' => trim($profile['pub_keywords'] . ' ' . $profile['prv_keywords']), + 'n' => self::FETCH_PER_PAGE, + ]; + + $entries = []; + + foreach ([Search::getGlobalDirectory(), $this->baseUrl] as $server) { + if (empty($server)) { + continue; + } + + $result = $this->httpClient->post($server . '/search/user/tags', $searchParameters); + if (!$result->isSuccess()) { + // try legacy endpoint + $result = $this->httpClient->post($server . '/contact/search/tags', $searchParameters); + if (!$result->isSuccess()) { + $this->logger->notice('Search-Endpoint not available for server.', ['server' => $server]); + continue; + } + } + + $entries = $this->parseContacts(json_decode($result->getBody()), $entries, $limit); + } + + if (empty($entries)) { + $this->systemMessages->addNotice($this->t('No matches')); + } + + $tpl = Renderer::getMarkupTemplate('contact/list.tpl'); + return Renderer::replaceMacros($tpl, [ + '$title' => $this->t('Profile Match'), + '$contacts' => array_slice($entries, 0, $limit), + ]); + } + + /** + * parses the JSON result and adds the new entries until the limit is reached + * + * @param $jsonResult + * @param array $entries + * @param int $limit + * + * @return array the new entries array + */ + protected function parseContacts($jsonResult, array $entries, int $limit): array + { + if (empty($jsonResult->results)) { + return $entries; + } + + foreach ($jsonResult->results as $profile) { + if (!$profile) { + continue; + } + + // Already known contact + $contact = Contact::getByURL($profile->url, null, ['rel'], $this->session->getLocalUserId()); + if (!empty($contact) && in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { + continue; + } + + $contact = Contact::getByURLForUser($profile->url, $this->session->getLocalUserId()); + if (!empty($contact)) { + $entries[$contact['id']] = ModuleContact::getContactTemplateVars($contact); + } + + if (count($entries) == $limit) { + break; + } + } + return $entries; + } +} diff --git a/src/Module/Search/Tags.php b/src/Module/Search/Tags.php new file mode 100644 index 0000000000..cc43d85b09 --- /dev/null +++ b/src/Module/Search/Tags.php @@ -0,0 +1,88 @@ +database = $database; + } + + protected function rawContent(array $request = []) + { + $tags = $request['s'] ?? ''; + $perPage = intval($request['n'] ?? self::DEFAULT_ITEMS_PER_PAGE); + $page = intval($request['p'] ?? 1); + $startRec = ($page - 1) * $perPage; + + $results = []; + + if (empty($tags)) { + System::jsonExit([ + 'total' => 0, + 'items_page' => $perPage, + 'page' => $page, + 'results' => $results, + ]); + } + + $condition = [ + "`net-publish` AND MATCH(`pub_keywords`) AGAINST (?)", + $tags + ]; + + $totalCount = $this->database->count('owner-view', $condition); + if ($totalCount === 0) { + System::jsonExit([ + 'total' => 0, + 'items_page' => $perPage, + 'page' => $page, + 'results' => $results, + ]); + } + + $searchStmt = $this->database->select('owner-view', + ['pub_keywords', 'name', 'nickname', 'uid'], + $condition, + ['limit' => [$startRec, $perPage]]); + + while ($searchResult = $this->database->fetch($searchStmt)) { + $results[] = [ + 'name' => $searchResult['name'], + 'url' => $this->baseUrl . '/profile/' . $searchResult['nickname'], + 'photo' => User::getAvatarUrl($searchResult, Proxy::SIZE_THUMB), + ]; + } + + $this->database->close($searchStmt); + + System::jsonExit([ + 'total' => $totalCount, + 'items_page' => $perPage, + 'page' => $page, + 'results' => $results, + ]); + } +} diff --git a/static/routes.config.php b/static/routes.config.php index 01415fb260..ee0b8d6767 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -384,6 +384,7 @@ return [ '/hidden' => [Module\Contact::class, [R::GET]], '/hovercard' => [Module\Contact\Hovercard::class, [R::GET]], '/ignored' => [Module\Contact::class, [R::GET]], + '/match' => [Module\Contact\Match::class, [R::GET]], '/pending' => [Module\Contact::class, [R::GET]], '/redir/{id:\d+}' => [Module\Contact\Redir::class, [R::GET]], '/suggestions' => [Module\Contact\Suggestions::class, [R::GET]], @@ -571,10 +572,11 @@ return [ '/salmon/{nickname}' => [Module\OStatus\Salmon::class, [ R::POST]], '/search' => [ - '[/]' => [Module\Search\Index::class, [R::GET]], + '[/]' => [Module\Search\Index::class, [R::GET ]], '/acl' => [Module\Search\Acl::class, [R::GET, R::POST]], - '/saved/add' => [Module\Search\Saved::class, [R::GET]], - '/saved/remove' => [Module\Search\Saved::class, [R::GET]], + '/saved/add' => [Module\Search\Saved::class, [R::GET ]], + '/saved/remove' => [Module\Search\Saved::class, [R::GET ]], + '/user/tags' => [Module\Search\Tags::class, [ R::POST]], ], '/receive' => [ diff --git a/view/templates/widget/peoplefind.tpl b/view/templates/widget/peoplefind.tpl index 7104dc6f3e..c2794b882b 100644 --- a/view/templates/widget/peoplefind.tpl +++ b/view/templates/widget/peoplefind.tpl @@ -5,8 +5,8 @@
- - + + diff --git a/view/theme/frio/templates/widget/peoplefind.tpl b/view/theme/frio/templates/widget/peoplefind.tpl index 11168eca0b..7cb84c6dfc 100644 --- a/view/theme/frio/templates/widget/peoplefind.tpl +++ b/view/theme/frio/templates/widget/peoplefind.tpl @@ -14,7 +14,7 @@ {{* Additional links *}} - +