From e00f110ef1b433d140643a1633038627bdea3c85 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 19 May 2019 02:50:14 +0200 Subject: [PATCH 01/13] Move mod/dirfind to src/Module/DirFind --- mod/dirfind.php | 265 ------------------------------- mod/search.php | 14 +- src/App/Router.php | 1 + src/Database/DBA.php | 11 +- src/Model/Search.php | 215 ++++++++++++++++++++++++- src/Module/DirectorySearch.php | 148 +++++++++++++++++ src/Object/Search/Result.php | 146 +++++++++++++++++ src/Object/Search/ResultList.php | 91 +++++++++++ 8 files changed, 615 insertions(+), 276 deletions(-) delete mode 100644 mod/dirfind.php create mode 100644 src/Module/DirectorySearch.php create mode 100644 src/Object/Search/Result.php create mode 100644 src/Object/Search/ResultList.php diff --git a/mod/dirfind.php b/mod/dirfind.php deleted file mode 100644 index a5b77312f3..0000000000 --- a/mod/dirfind.php +++ /dev/null @@ -1,265 +0,0 @@ -page['aside'])) { - $a->page['aside'] = ''; - } - - $a->page['aside'] .= Widget::findPeople(); - - $a->page['aside'] .= Widget::follow(); -} - -function dirfind_content(App $a, $prefix = "") { - - $community = false; - $discover_user = false; - - $local = Config::get('system','poco_local_search'); - - $search = $prefix.Strings::escapeTags(trim(defaults($_REQUEST, 'search', ''))); - - $header = ''; - - if (strpos($search,'@') === 0) { - $search = substr($search,1); - $header = L10n::t('People Search - %s', $search); - if ((filter_var($search, FILTER_VALIDATE_EMAIL) && Network::isEmailDomainValid($search)) || - (substr(Strings::normaliseLink($search), 0, 7) == "http://")) { - $user_data = Probe::uri($search); - $discover_user = (in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])); - } - } - - if (strpos($search,'!') === 0) { - $search = substr($search,1); - $community = true; - $header = L10n::t('Forum Search - %s', $search); - } - - $o = ''; - - if ($search) { - $pager = new Pager($a->query_string); - - if ($discover_user) { - $j = new stdClass(); - $j->total = 1; - $j->items_page = 1; - $j->page = $pager->getPage(); - - $objresult = new stdClass(); - $objresult->cid = 0; - $objresult->name = $user_data["name"]; - $objresult->addr = $user_data["addr"]; - $objresult->url = $user_data["url"]; - $objresult->photo = $user_data["photo"]; - $objresult->tags = ""; - $objresult->network = $user_data["network"]; - - $contact = Model\Contact::getDetailsByURL($user_data["url"], local_user()); - $objresult->cid = $contact["cid"]; - $objresult->pcid = $contact["zid"]; - - $j->results[] = $objresult; - - // Add the contact to the global contacts if it isn't already in our system - if (($contact["cid"] == 0) && ($contact["zid"] == 0) && ($contact["gid"] == 0)) { - Model\GContact::update($user_data); - } - } elseif ($local) { - if ($community) { - $extra_sql = " AND `community`"; - } else { - $extra_sql = ""; - } - - $pager->setItemsPerPage(80); - - if (Config::get('system','diaspora_enabled')) { - $diaspora = Protocol::DIASPORA; - } else { - $diaspora = Protocol::DFRN; - } - - if (!Config::get('system','ostatus_disabled')) { - $ostatus = Protocol::OSTATUS; - } else { - $ostatus = Protocol::DFRN; - } - - $search2 = "%".$search."%"; - - /// @TODO These 2 SELECTs are not checked on validity with DBA::isResult() - $count = q("SELECT count(*) AS `total` FROM `gcontact` - WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s', '%s') AND - ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND - (`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR - `addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql", - DBA::escape(Protocol::ACTIVITYPUB), DBA::escape(Protocol::DFRN), DBA::escape($ostatus), DBA::escape($diaspora), - DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), - DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2))); - - $results = q("SELECT `nurl` - FROM `gcontact` - WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s', '%s') AND - ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND - (`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR - `addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql - GROUP BY `nurl` - ORDER BY `updated` DESC LIMIT %d, %d", - DBA::escape(Protocol::ACTIVITYPUB), DBA::escape(Protocol::DFRN), DBA::escape($ostatus), DBA::escape($diaspora), - DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), - DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), - $pager->getStart(), $pager->getItemsPerPage()); - $j = new stdClass(); - $j->total = $count[0]["total"]; - $j->items_page = $pager->getItemsPerPage(); - $j->page = $pager->getPage(); - foreach ($results AS $result) { - if (PortableContact::alternateOStatusUrl($result["nurl"])) { - continue; - } - - $urlparts = parse_url($result["nurl"]); - - // Ignore results that look strange. - // For historic reasons the gcontact table does contain some garbage. - if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) { - continue; - } - - $result = Model\Contact::getDetailsByURL($result["nurl"], local_user()); - - if ($result["name"] == "") { - $result["name"] = end(explode("/", $urlparts["path"])); - } - - $objresult = new stdClass(); - $objresult->cid = $result["cid"]; - $objresult->pcid = $result["zid"]; - $objresult->name = $result["name"]; - $objresult->addr = $result["addr"]; - $objresult->url = $result["url"]; - $objresult->photo = $result["photo"]; - $objresult->tags = $result["keywords"]; - $objresult->network = $result["network"]; - - $j->results[] = $objresult; - } - - // Add found profiles from the global directory to the local directory - Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search)); - } elseif (strlen(Config::get('system','directory'))) { - $p = (($pager->getPage() != 1) ? '&p=' . $pager->getPage() : ''); - - $x = Network::fetchUrl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search)); - - $j = json_decode($x); - $pager->setItemsPerPage($j->items_page); - } - - if (!empty($j->results)) { - $id = 0; - - $entries = []; - foreach ($j->results as $jj) { - - $alt_text = ""; - - $contact_details = Model\Contact::getDetailsByURL($jj->url, local_user()); - - $itemurl = (($contact_details["addr"] != "") ? $contact_details["addr"] : $jj->url); - - // If We already know this contact then don't show the "connect" button - if ($jj->cid > 0) { - $connlnk = ""; - $conntxt = ""; - $contact = DBA::selectFirst('contact', [], ['id' => $jj->cid]); - if (DBA::isResult($contact)) { - $photo_menu = Model\Contact::photoMenu($contact); - $details = Module\Contact::getContactTemplateVars($contact); - $alt_text = $details['alt_text']; - } else { - $photo_menu = []; - } - } else { - $connlnk = System::baseUrl().'/follow/?url='.(!empty($jj->connect) ? $jj->connect : $jj->url); - $conntxt = L10n::t('Connect'); - - $contact = DBA::selectFirst('contact', [], ['id' => $jj->pcid]); - if (DBA::isResult($contact)) { - $photo_menu = Model\Contact::photoMenu($contact); - } else { - $photo_menu = []; - } - - $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($jj->url)]; - $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk]; - } - - $jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo); - - $entry = [ - 'alt_text' => $alt_text, - 'url' => Model\Contact::magicLink($jj->url), - 'itemurl' => $itemurl, - 'name' => $jj->name, - 'thumb' => ProxyUtils::proxifyUrl($jj->photo, false, ProxyUtils::SIZE_THUMB), - 'img_hover' => $jj->tags, - 'conntxt' => $conntxt, - 'connlnk' => $connlnk, - 'photo_menu' => $photo_menu, - 'details' => $contact_details['location'], - 'tags' => $contact_details['keywords'], - 'about' => $contact_details['about'], - 'account_type' => Model\Contact::getAccountType($contact_details), - 'network' => ContactSelector::networkToName($jj->network, $jj->url), - 'id' => ++$id, - ]; - $entries[] = $entry; - } - - $tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl'); - $o .= Renderer::replaceMacros($tpl,[ - 'title' => $header, - '$contacts' => $entries, - '$paginate' => $pager->renderFull($j->total), - ]); - } else { - info(L10n::t('No matches') . EOL); - } - - } - - return $o; -} diff --git a/mod/search.php b/mod/search.php index 1416f1d89f..21b6918b1c 100644 --- a/mod/search.php +++ b/mod/search.php @@ -12,13 +12,11 @@ use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\Renderer; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Item; +use Friendica\Module\DirectorySearch; use Friendica\Util\Strings; -require_once 'mod/dirfind.php'; - function search_saved_searches() { $o = ''; @@ -150,10 +148,10 @@ function search_content(App $a) { $search = substr($search,1); } if (strpos($search,'@') === 0) { - return dirfind_content($a); + return DirectorySearch::performSearch(); } if (strpos($search,'!') === 0) { - return dirfind_content($a); + return DirectorySearch::performSearch(); } if (!empty($_GET['search-option'])) @@ -164,11 +162,9 @@ function search_content(App $a) { $tag = true; break; case 'contacts': - return dirfind_content($a, "@"); - break; + return DirectorySearch::performSearch('@'); case 'forums': - return dirfind_content($a, "!"); - break; + return DirectorySearch::performSearch('!'); } if (!$search) diff --git a/src/App/Router.php b/src/App/Router.php index 373bb1c32e..4a8807fa70 100644 --- a/src/App/Router.php +++ b/src/App/Router.php @@ -113,6 +113,7 @@ class Router $collector->addRoute(['GET'], '/ignored', Module\Contact::class); }); $this->routeCollector->addRoute(['GET'], '/credits', Module\Credits::class); + $this->routeCollector->addRoute(['GET'], '/dirfind', Module\DirectorySearch::class); $this->routeCollector->addRoute(['GET'], '/directory', Module\Directory::class); $this->routeCollector->addGroup('/feed', function (RouteCollector $collector) { $collector->addRoute(['GET'], '/{nickname}', Module\Feed::class); diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 85bdbbb628..9367e2681f 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -1507,6 +1507,15 @@ class DBA */ public static function buildParameter(array $params = []) { + $groupby_string = ''; + if (isset($params['group_by'])) { + $groupby_string = " GROUP BY "; + foreach ($params['group_by'] as $fields) { + $groupby_string .= "`" . $fields . "`, "; + } + $groupby_string = substr($groupby_string, 0, -2); + } + $order_string = ''; if (isset($params['order'])) { $order_string = " ORDER BY "; @@ -1531,7 +1540,7 @@ class DBA $limit_string = " LIMIT " . intval($params['limit'][0]) . ", " . intval($params['limit'][1]); } - return $order_string.$limit_string; + return $groupby_string.$order_string.$limit_string; } /** diff --git a/src/Model/Search.php b/src/Model/Search.php index 5829ff91d0..815f2dc633 100644 --- a/src/Model/Search.php +++ b/src/Model/Search.php @@ -3,13 +3,23 @@ namespace Friendica\Model; use Friendica\BaseObject; +use Friendica\Core\Protocol; +use Friendica\Core\Worker; use Friendica\Database\DBA; +use Friendica\Network\Probe; +use Friendica\Object\Search\Result; +use Friendica\Object\Search\ResultList; +use Friendica\Protocol\PortableContact; +use Friendica\Util\Network; +use Friendica\Util\Strings; /** - * Model for DB specific logic for the search entity + * Model for searches */ class Search extends BaseObject { + const DEFAULT_DIRECTORY = 'https://dir.friendica.social'; + /** * Returns the list of user defined tags (e.g. #Friendica) * @@ -29,4 +39,207 @@ class Search extends BaseObject return $tags; } + + /** + * Search a user based on his/her profile address + * pattern: @username@domain.tld + * + * @param string $user The user to search for + * + * @return ResultList|null + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function searchUser($user) + { + if ((filter_var($user, FILTER_VALIDATE_EMAIL) && Network::isEmailDomainValid($user)) || + (substr(Strings::normaliseLink($user), 0, 7) == "http://")) { + + $user_data = Probe::uri($user); + if (empty($user_data)) { + return null; + } + + if (!(in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]))) { + return null; + } + + $contactDetails = Contact::getDetailsByURL(defaults($user_data, 'url', ''), local_user()); + $itemurl = (($contactDetails["addr"] != "") ? $contactDetails["addr"] : defaults($user_data, 'url', '')); + + $result = new Result( + defaults($user_data, 'name', ''), + defaults($user_data, 'addr', ''), + $itemurl, + defaults($user_data, 'url', ''), + defaults($user_data, 'photo', ''), + defaults($user_data, 'network', ''), + defaults($contactDetails, 'cid', 0), + 0, + defaults($user_data, 'tags', '') + ); + + return new ResultList(1, 1, 1, [$result]); + + } else { + return null; + } + } + + /** + * Search in the global directory for occurrences of the search string + * This is mainly based on the JSON results of https://dir.friendica.social + * + * @param string $search + * @param int $page + * + * @return ResultList|null + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public static function searchDirectory($search, $page = 1) + { + $config = self::getApp()->getConfig(); + $server = $config->get('system', 'directory', self::DEFAULT_DIRECTORY); + + $searchUrl = $server . '/search?q=' . urlencode($search); + + if ($page > 1) { + $searchUrl .= '&page=' . $page; + } + + $red = 0; + $resultJson = Network::fetchUrl($searchUrl, false,$red, 0, 'application/json'); + + $results = json_decode($resultJson, true); + + $resultList = new ResultList( + defaults($results, 'page', 1), + defaults($results, 'count', 1), + defaults($results, 'itemsperpage', 1) + ); + + $profiles = defaults($results, 'profiles', []); + + foreach ($profiles as $profile) { + $contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user()); + $itemurl = (!empty($contactDetails['addr']) ? $contactDetails['addr'] : defaults($profile, 'profile_url', '')); + + $result = new Result( + defaults($profile, 'name', ''), + defaults($profile, 'addr', ''), + $itemurl, + defaults($profile, 'profile_url', ''), + defaults($profile, 'photo', ''), + Protocol::DFRN, + defaults($contactDetails, 'cid', 0), + 0, + defaults($profile, 'tags', '')); + + $resultList->addResult($result); + } + + return $resultList; + } + + /** + * Search in the local database for occurrences of the search string + * + * @param string $search + * @param int $start + * @param int $itemPage + * @param bool $community + * + * @return ResultList|null + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public static function searchLocal($search, $start = 0, $itemPage = 80, $community = false) + { + $config = self::getApp()->getConfig(); + + $diaspora = $config->get('system', 'diaspora_enabled') ? Protocol::DIASPORA : Protocol::DFRN; + $ostatus = !$config->get('system', 'ostatus_disabled') ? Protocol::OSTATUS : Protocol::DFRN; + + $wildcard = Strings::escapeHtml('%' . $search . '%'); + + $count = DBA::count('gcontact', [ + 'NOT `hide` + AND `network` IN (?, ?, ?, ?) + AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) + AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ? + OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?) + AND `community` = ?', + Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, + $wildcard, $wildcard, $wildcard, + $wildcard, $wildcard, $wildcard, + $community, + ]); + + if (empty($count)) { + return null; + } + + $data = DBA::select('gcontact', ['nurl'], [ + 'NOT `hide` + AND `network` IN (?, ?, ?, ?) + AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) + AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ? + OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?) + AND `community` = ?', + Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, + $wildcard, $wildcard, $wildcard, + $wildcard, $wildcard, $wildcard, + $community, + ], [ + 'group_by' => ['nurl', 'updated'], + 'limit' => [$start, $itemPage], + 'order' => ['updated' => 'DESC'] + ]); + + if (!DBA::isResult($data)) { + return null; + } + + $resultList = new ResultList($start, $itemPage, $count); + + while ($row = DBA::fetch($data)) { + if (PortableContact::alternateOStatusUrl($row["nurl"])) { + continue; + } + + $urlparts = parse_url($row["nurl"]); + + // Ignore results that look strange. + // For historic reasons the gcontact table does contain some garbage. + if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) { + continue; + } + + $contact = Contact::getDetailsByURL($row["nurl"], local_user()); + + if ($contact["name"] == "") { + $contact["name"] = end(explode("/", $urlparts["path"])); + } + + $result = new Result( + $contact["name"], + $contact["addr"], + $contact["addr"], + $contact["url"], + $contact["photo"], + $contact["network"], + $contact["cid"], + $contact["zid"], + $contact["keywords"] + ); + + $resultList->addResult($result); + } + + DBA::close($data); + + // Add found profiles from the global directory to the local directory + Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search)); + + return $resultList; + } } diff --git a/src/Module/DirectorySearch.php b/src/Module/DirectorySearch.php new file mode 100644 index 0000000000..1bacacc57e --- /dev/null +++ b/src/Module/DirectorySearch.php @@ -0,0 +1,148 @@ +page['aside'])) { + $a->page['aside'] = ''; + } + + $a->page['aside'] .= Widget::findPeople(); + $a->page['aside'] .= Widget::follow(); + + return self::performSearch(); + } + + public static function performSearch($prefix = '') + { + $a = self::getApp(); + $config = $a->getConfig(); + + $community = false; + + $localSearch = $config->get('system', 'poco_local_search'); + + $search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', ''))); + + if (!$search) { + return ''; + } + + $header = ''; + + if (strpos($search, '@') === 0) { + $search = substr($search, 1); + $header = L10n::t('People Search - %s', $search); + $results = Model\Search::searchUser($search); + } + + if (strpos($search, '!') === 0) { + $search = substr($search, 1); + $community = true; + $header = L10n::t('Forum Search - %s', $search); + } + + $pager = new Pager($a->query_string); + + if ($localSearch && empty($results)) { + $pager->setItemsPerPage(80); + $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); + + } elseif (strlen(Config::get('system', 'directory')) && empty($results)) { + $results = Model\Search::searchDirectory($search, $pager->getPage()); + $pager->setItemsPerPage($results->getItemsPage()); + } + + if (empty($results) || empty($results->getResults())) { + info(L10n::t('No matches') . EOL); + return ''; + } + $id = 0; + + $entries = []; + foreach ($results->getResults() as $result) { + + $alt_text = ''; + $location = ''; + $about = ''; + $accountType = ''; + $photo_menu = []; + + // If We already know this contact then don't show the "connect" button + if ($result->getCid() > 0 || $result->getPcid() > 0) { + $connlnk = ""; + $conntxt = ""; + $contact = DBA::selectFirst('contact', [], [ + 'id' => ($result->getCid() > 0) ? $result->getCid() : $result->getPcid() + ]); + + if (DBA::isResult($contact)) { + $photo_menu = Model\Contact::photoMenu($contact); + $details = Contact::getContactTemplateVars($contact); + $alt_text = $details['alt_text']; + $location = $contact['location']; + $about = $contact['about']; + $accountType = Model\Contact::getAccountType($contact); + } else { + $photo_menu = []; + } + } else { + $connlnk = $a->getBaseURL() . '/follow/?url=' . $result->getUrl(); + $conntxt = L10n::t('Connect'); + + $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($result->getUrl())]; + $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk]; + } + + $photo = str_replace("http:///photo/", get_server() . "/photo/", $result->getPhoto()); + + $entry = [ + 'alt_text' => $alt_text, + 'url' => Model\Contact::magicLink($result->getUrl()), + 'itemurl' => $result->getItem(), + 'name' => $result->getName(), + 'thumb' => ProxyUtils::proxifyUrl($photo, false, ProxyUtils::SIZE_THUMB), + 'img_hover' => $result->getTags(), + 'conntxt' => $conntxt, + 'connlnk' => $connlnk, + 'photo_menu' => $photo_menu, + 'details' => $location, + 'tags' => $result->getTags(), + 'about' => $about, + 'account_type' => $accountType, + 'network' => ContactSelector::networkToName($result->getNetwork(), $result->getUrl()), + 'id' => ++$id, + ]; + $entries[] = $entry; + } + + $tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl'); + return Renderer::replaceMacros($tpl, [ + 'title' => $header, + '$contacts' => $entries, + '$paginate' => $pager->renderFull($results->getTotal()), + ]); + } +} diff --git a/src/Object/Search/Result.php b/src/Object/Search/Result.php new file mode 100644 index 0000000000..10d6b0aa03 --- /dev/null +++ b/src/Object/Search/Result.php @@ -0,0 +1,146 @@ +cid; + } + + /** + * @return int + */ + public function getPcid() + { + return $this->pcid; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getAddr() + { + return $this->addr; + } + + /** + * @return string + */ + public function getItem() + { + return $this->item; + } + + /** + * @return string + */ + public function getUrl() + { + return $this->url; + } + + /** + * @return string + */ + public function getPhoto() + { + return $this->photo; + } + + /** + * @return string + */ + public function getTags() + { + return $this->tags; + } + + /** + * @return string + */ + public function getNetwork() + { + return $this->network; + } + + /** + * @param string $name + * @param string $addr + * @param string $url + * @param string $photo + * @param string $network + * @param int $cid + * @param int $pcid + * @param string $tags + */ + public function __construct($name, $addr, $item, $url, $photo, $network, $cid = 0, $pcid = 0, $tags = '') + { + $this->name = $name; + $this->addr = $addr; + $this->item = $item; + $this->url = $url; + $this->photo = $photo; + $this->network = $network; + + $this->cid = $cid; + $this->pcid = $pcid; + $this->tags = $tags; + } +} diff --git a/src/Object/Search/ResultList.php b/src/Object/Search/ResultList.php new file mode 100644 index 0000000000..88caaa7e56 --- /dev/null +++ b/src/Object/Search/ResultList.php @@ -0,0 +1,91 @@ +page; + } + + /** + * @return int + */ + public function getTotal() + { + return $this->total; + } + + /** + * @return int + */ + public function getItemsPage() + { + return $this->itemsPage; + } + + /** + * @return Result[] + */ + public function getResults() + { + return $this->results; + } + + /** + * @param int $page + * @param int $total + * @param int $itemsPage + * @param Result[] $results + */ + public function __construct($page = 0, $total = 0, $itemsPage = 0, array $results = []) + { + $this->page = $page; + $this->total = $total; + $this->itemsPage = $itemsPage; + + $this->results = $results; + } + + /** + * Adds a result to the result list + * + * @param Result $result + */ + public function addResult(Result $result) + { + $this->results[] = $result; + } +} From 34a1e923ddccc42bf0a567c82d16cbb9444eeaa2 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 19 May 2019 04:38:35 +0200 Subject: [PATCH 02/13] dependency lowering --- src/Module/DirectorySearch.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Module/DirectorySearch.php b/src/Module/DirectorySearch.php index 1bacacc57e..f071438fa0 100644 --- a/src/Module/DirectorySearch.php +++ b/src/Module/DirectorySearch.php @@ -6,10 +6,8 @@ use Friendica\BaseModule; use Friendica\Content\ContactSelector; use Friendica\Content\Pager; use Friendica\Content\Widget; -use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\Renderer; -use Friendica\Database\DBA; use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Strings; use Friendica\Model; @@ -70,7 +68,7 @@ class DirectorySearch extends BaseModule $pager->setItemsPerPage(80); $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); - } elseif (strlen(Config::get('system', 'directory')) && empty($results)) { + } elseif (strlen($config->get('system', 'directory')) && empty($results)) { $results = Model\Search::searchDirectory($search, $pager->getPage()); $pager->setItemsPerPage($results->getItemsPage()); } @@ -94,11 +92,11 @@ class DirectorySearch extends BaseModule if ($result->getCid() > 0 || $result->getPcid() > 0) { $connlnk = ""; $conntxt = ""; - $contact = DBA::selectFirst('contact', [], [ - 'id' => ($result->getCid() > 0) ? $result->getCid() : $result->getPcid() - ]); + $contact = Model\Contact::getById( + ($result->getCid() > 0) ? $result->getCid() : $result->getPcid() + ); - if (DBA::isResult($contact)) { + if (!empty($contact)) { $photo_menu = Model\Contact::photoMenu($contact); $details = Contact::getContactTemplateVars($contact); $alt_text = $details['alt_text']; From 2520286b1f13592689f3b22cbf1ccf3cf45c3113 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 19 May 2019 04:43:09 +0200 Subject: [PATCH 03/13] some small improvements --- src/Module/DirectorySearch.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Module/DirectorySearch.php b/src/Module/DirectorySearch.php index f071438fa0..7e3e3c2c5f 100644 --- a/src/Module/DirectorySearch.php +++ b/src/Module/DirectorySearch.php @@ -12,6 +12,9 @@ use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Strings; use Friendica\Model; +/** + * Multi search module, which is needed for further search operations + */ class DirectorySearch extends BaseModule { public static function content() @@ -21,7 +24,7 @@ class DirectorySearch extends BaseModule return Login::form(); } - $a = self::getApp(); + $a = self::getApp(); if (empty($a->page['aside'])) { $a->page['aside'] = ''; @@ -86,12 +89,12 @@ class DirectorySearch extends BaseModule $location = ''; $about = ''; $accountType = ''; - $photo_menu = []; + $photo_menu = []; // If We already know this contact then don't show the "connect" button if ($result->getCid() > 0 || $result->getPcid() > 0) { - $connlnk = ""; - $conntxt = ""; + $connLink = ""; + $connTxt = ""; $contact = Model\Contact::getById( ($result->getCid() > 0) ? $result->getCid() : $result->getPcid() ); @@ -107,11 +110,11 @@ class DirectorySearch extends BaseModule $photo_menu = []; } } else { - $connlnk = $a->getBaseURL() . '/follow/?url=' . $result->getUrl(); - $conntxt = L10n::t('Connect'); + $connLink = $a->getBaseURL() . '/follow/?url=' . $result->getUrl(); + $connTxt = L10n::t('Connect'); $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($result->getUrl())]; - $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk]; + $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connLink]; } $photo = str_replace("http:///photo/", get_server() . "/photo/", $result->getPhoto()); @@ -123,8 +126,8 @@ class DirectorySearch extends BaseModule 'name' => $result->getName(), 'thumb' => ProxyUtils::proxifyUrl($photo, false, ProxyUtils::SIZE_THUMB), 'img_hover' => $result->getTags(), - 'conntxt' => $conntxt, - 'connlnk' => $connlnk, + 'conntxt' => $connTxt, + 'connlnk' => $connLink, 'photo_menu' => $photo_menu, 'details' => $location, 'tags' => $result->getTags(), From 5b44fdc2021e09a8e29081d46e5707d25a25a189 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 19 May 2019 05:01:46 +0200 Subject: [PATCH 04/13] Split Directory Search as a base for further changes --- mod/search.php | 10 +-- src/App/Router.php | 2 +- ...rectorySearch.php => BaseSearchModule.php} | 81 ++++-------------- src/Module/Search/Directory.php | 82 +++++++++++++++++++ 4 files changed, 106 insertions(+), 69 deletions(-) rename src/Module/{DirectorySearch.php => BaseSearchModule.php} (62%) create mode 100644 src/Module/Search/Directory.php diff --git a/mod/search.php b/mod/search.php index 21b6918b1c..816ebf18a9 100644 --- a/mod/search.php +++ b/mod/search.php @@ -14,7 +14,7 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\Model\Item; -use Friendica\Module\DirectorySearch; +use Friendica\Module\Directory; use Friendica\Util\Strings; function search_saved_searches() { @@ -148,10 +148,10 @@ function search_content(App $a) { $search = substr($search,1); } if (strpos($search,'@') === 0) { - return DirectorySearch::performSearch(); + return Directory::performSearch(); } if (strpos($search,'!') === 0) { - return DirectorySearch::performSearch(); + return Directory::performSearch(); } if (!empty($_GET['search-option'])) @@ -162,9 +162,9 @@ function search_content(App $a) { $tag = true; break; case 'contacts': - return DirectorySearch::performSearch('@'); + return Directory::performSearch('@'); case 'forums': - return DirectorySearch::performSearch('!'); + return Directory::performSearch('!'); } if (!$search) diff --git a/src/App/Router.php b/src/App/Router.php index 4a8807fa70..02072594cd 100644 --- a/src/App/Router.php +++ b/src/App/Router.php @@ -113,7 +113,7 @@ class Router $collector->addRoute(['GET'], '/ignored', Module\Contact::class); }); $this->routeCollector->addRoute(['GET'], '/credits', Module\Credits::class); - $this->routeCollector->addRoute(['GET'], '/dirfind', Module\DirectorySearch::class); + $this->routeCollector->addRoute(['GET'], '/dirfind', Module\Search\Directory::class); $this->routeCollector->addRoute(['GET'], '/directory', Module\Directory::class); $this->routeCollector->addGroup('/feed', function (RouteCollector $collector) { $collector->addRoute(['GET'], '/{nickname}', Module\Feed::class); diff --git a/src/Module/DirectorySearch.php b/src/Module/BaseSearchModule.php similarity index 62% rename from src/Module/DirectorySearch.php rename to src/Module/BaseSearchModule.php index 7e3e3c2c5f..d11f7e9860 100644 --- a/src/Module/DirectorySearch.php +++ b/src/Module/BaseSearchModule.php @@ -5,83 +5,38 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\Content\ContactSelector; use Friendica\Content\Pager; -use Friendica\Content\Widget; use Friendica\Core\L10n; use Friendica\Core\Renderer; +use Friendica\Object\Search\ResultList; use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Util\Strings; use Friendica\Model; /** - * Multi search module, which is needed for further search operations + * Base class for search modules */ -class DirectorySearch extends BaseModule +abstract class BaseSearchModule extends BaseModule { - public static function content() + /** + * Prints a human readable search result + * + * @param ResultList $results + * @param Pager $pager + * @param string $header + * + * @return string The result + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + protected static function printResult(ResultList $results, Pager $pager, $header = '') { - if (!local_user()) { - notice(L10n::t('Permission denied.')); - return Login::form(); - } - - $a = self::getApp(); - - if (empty($a->page['aside'])) { - $a->page['aside'] = ''; - } - - $a->page['aside'] .= Widget::findPeople(); - $a->page['aside'] .= Widget::follow(); - - return self::performSearch(); - } - - public static function performSearch($prefix = '') - { - $a = self::getApp(); - $config = $a->getConfig(); - - $community = false; - - $localSearch = $config->get('system', 'poco_local_search'); - - $search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', ''))); - - if (!$search) { - return ''; - } - - $header = ''; - - if (strpos($search, '@') === 0) { - $search = substr($search, 1); - $header = L10n::t('People Search - %s', $search); - $results = Model\Search::searchUser($search); - } - - if (strpos($search, '!') === 0) { - $search = substr($search, 1); - $community = true; - $header = L10n::t('Forum Search - %s', $search); - } - - $pager = new Pager($a->query_string); - - if ($localSearch && empty($results)) { - $pager->setItemsPerPage(80); - $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); - - } elseif (strlen($config->get('system', 'directory')) && empty($results)) { - $results = Model\Search::searchDirectory($search, $pager->getPage()); - $pager->setItemsPerPage($results->getItemsPage()); - } - if (empty($results) || empty($results->getResults())) { info(L10n::t('No matches') . EOL); return ''; } - $id = 0; + $a = self::getApp(); + + $id = 0; $entries = []; foreach ($results->getResults() as $result) { diff --git a/src/Module/Search/Directory.php b/src/Module/Search/Directory.php new file mode 100644 index 0000000000..900bf818bc --- /dev/null +++ b/src/Module/Search/Directory.php @@ -0,0 +1,82 @@ +page['aside'])) { + $a->page['aside'] = ''; + } + + $a->page['aside'] .= Widget::findPeople(); + $a->page['aside'] .= Widget::follow(); + + return self::performSearch(); + } + + public static function performSearch($prefix = '') + { + $a = self::getApp(); + $config = $a->getConfig(); + + $community = false; + + $localSearch = $config->get('system', 'poco_local_search'); + + $search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', ''))); + + if (!$search) { + return ''; + } + + $header = ''; + + if (strpos($search, '@') === 0) { + $search = substr($search, 1); + $header = L10n::t('People Search - %s', $search); + $results = Model\Search::searchUser($search); + } + + if (strpos($search, '!') === 0) { + $search = substr($search, 1); + $community = true; + $header = L10n::t('Forum Search - %s', $search); + } + + $pager = new Pager($a->query_string); + + if ($localSearch && empty($results)) { + $pager->setItemsPerPage(80); + $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); + + } elseif (strlen($config->get('system', 'directory')) && empty($results)) { + $results = Model\Search::searchDirectory($search, $pager->getPage()); + $pager->setItemsPerPage($results->getItemsPage()); + } + + return self::printResult($results, $pager, $header); + } +} From a7aae9603acd3787ebb1fb937b6fdf55ea428e0d Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 19 May 2019 05:06:02 +0200 Subject: [PATCH 05/13] Split Directory Search as a base for further changes --- mod/search.php | 10 +++--- src/Module/BaseSearchModule.php | 55 ++++++++++++++++++++++++++++++++- src/Module/Search/Directory.php | 52 +------------------------------ 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/mod/search.php b/mod/search.php index 816ebf18a9..4144e2608f 100644 --- a/mod/search.php +++ b/mod/search.php @@ -14,7 +14,7 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\Model\Item; -use Friendica\Module\Directory; +use Friendica\Module\BaseSearchModule; use Friendica\Util\Strings; function search_saved_searches() { @@ -148,10 +148,10 @@ function search_content(App $a) { $search = substr($search,1); } if (strpos($search,'@') === 0) { - return Directory::performSearch(); + return BaseSearchModule::performSearch(); } if (strpos($search,'!') === 0) { - return Directory::performSearch(); + return BaseSearchModule::performSearch(); } if (!empty($_GET['search-option'])) @@ -162,9 +162,9 @@ function search_content(App $a) { $tag = true; break; case 'contacts': - return Directory::performSearch('@'); + return BaseSearchModule::performSearch('@'); case 'forums': - return Directory::performSearch('!'); + return BaseSearchModule::performSearch('!'); } if (!$search) diff --git a/src/Module/BaseSearchModule.php b/src/Module/BaseSearchModule.php index d11f7e9860..7028208286 100644 --- a/src/Module/BaseSearchModule.php +++ b/src/Module/BaseSearchModule.php @@ -10,12 +10,65 @@ use Friendica\Core\Renderer; use Friendica\Object\Search\ResultList; use Friendica\Util\Proxy as ProxyUtils; use Friendica\Model; +use Friendica\Util\Strings; /** * Base class for search modules */ -abstract class BaseSearchModule extends BaseModule +class BaseSearchModule extends BaseModule { + /** + * Performs a search with an optional prefix + * + * @param string $prefix A optional prefix (e.g. @ or !) for searching + * + * @return string + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function performSearch($prefix = '') + { + $a = self::getApp(); + $config = $a->getConfig(); + + $community = false; + + $localSearch = $config->get('system', 'poco_local_search'); + + $search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', ''))); + + if (!$search) { + return ''; + } + + $header = ''; + + if (strpos($search, '@') === 0) { + $search = substr($search, 1); + $header = L10n::t('People Search - %s', $search); + $results = Model\Search::searchUser($search); + } + + if (strpos($search, '!') === 0) { + $search = substr($search, 1); + $community = true; + $header = L10n::t('Forum Search - %s', $search); + } + + $pager = new Pager($a->query_string); + + if ($localSearch && empty($results)) { + $pager->setItemsPerPage(80); + $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); + + } elseif (strlen($config->get('system', 'directory')) && empty($results)) { + $results = Model\Search::searchDirectory($search, $pager->getPage()); + $pager->setItemsPerPage($results->getItemsPage()); + } + + return self::printResult($results, $pager, $header); + } + /** * Prints a human readable search result * diff --git a/src/Module/Search/Directory.php b/src/Module/Search/Directory.php index 900bf818bc..76ada50d59 100644 --- a/src/Module/Search/Directory.php +++ b/src/Module/Search/Directory.php @@ -2,19 +2,12 @@ namespace Friendica\Module\Search; -use Friendica\BaseModule; -use Friendica\Content\ContactSelector; -use Friendica\Content\Pager; use Friendica\Content\Widget; use Friendica\Core\L10n; -use Friendica\Core\Renderer; use Friendica\Module\BaseSearchModule; -use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Util\Strings; -use Friendica\Model; /** - * Multi search module, which is needed for further search operations + * Directory search module */ class Directory extends BaseSearchModule { @@ -36,47 +29,4 @@ class Directory extends BaseSearchModule return self::performSearch(); } - - public static function performSearch($prefix = '') - { - $a = self::getApp(); - $config = $a->getConfig(); - - $community = false; - - $localSearch = $config->get('system', 'poco_local_search'); - - $search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', ''))); - - if (!$search) { - return ''; - } - - $header = ''; - - if (strpos($search, '@') === 0) { - $search = substr($search, 1); - $header = L10n::t('People Search - %s', $search); - $results = Model\Search::searchUser($search); - } - - if (strpos($search, '!') === 0) { - $search = substr($search, 1); - $community = true; - $header = L10n::t('Forum Search - %s', $search); - } - - $pager = new Pager($a->query_string); - - if ($localSearch && empty($results)) { - $pager->setItemsPerPage(80); - $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); - - } elseif (strlen($config->get('system', 'directory')) && empty($results)) { - $results = Model\Search::searchDirectory($search, $pager->getPage()); - $pager->setItemsPerPage($results->getItemsPage()); - } - - return self::printResult($results, $pager, $header); - } } From 419cc81ef145015d087ffb4f54eb985bc49d2e05 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 19 May 2019 05:13:06 +0200 Subject: [PATCH 06/13] renaming --- src/Database/DBA.php | 2 +- src/Model/Search.php | 22 +++++++++---------- src/Module/BaseSearchModule.php | 14 ++++++------ .../Search/{Result.php => ContactResult.php} | 14 ++++++------ .../{ResultList.php => ContactResultList.php} | 21 +++++++++--------- 5 files changed, 37 insertions(+), 36 deletions(-) rename src/Object/Search/{Result.php => ContactResult.php} (90%) rename src/Object/Search/{ResultList.php => ContactResultList.php} (73%) diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 9367e2681f..2327e4a7f6 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -1540,7 +1540,7 @@ class DBA $limit_string = " LIMIT " . intval($params['limit'][0]) . ", " . intval($params['limit'][1]); } - return $groupby_string.$order_string.$limit_string; + return $groupby_string . $order_string . $limit_string; } /** diff --git a/src/Model/Search.php b/src/Model/Search.php index 815f2dc633..80d5e6698d 100644 --- a/src/Model/Search.php +++ b/src/Model/Search.php @@ -7,8 +7,8 @@ use Friendica\Core\Protocol; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Network\Probe; -use Friendica\Object\Search\Result; -use Friendica\Object\Search\ResultList; +use Friendica\Object\Search\ContactResult; +use Friendica\Object\Search\ContactResultList; use Friendica\Protocol\PortableContact; use Friendica\Util\Network; use Friendica\Util\Strings; @@ -46,7 +46,7 @@ class Search extends BaseObject * * @param string $user The user to search for * - * @return ResultList|null + * @return ContactResultList|null * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ @@ -67,7 +67,7 @@ class Search extends BaseObject $contactDetails = Contact::getDetailsByURL(defaults($user_data, 'url', ''), local_user()); $itemurl = (($contactDetails["addr"] != "") ? $contactDetails["addr"] : defaults($user_data, 'url', '')); - $result = new Result( + $result = new ContactResult( defaults($user_data, 'name', ''), defaults($user_data, 'addr', ''), $itemurl, @@ -79,7 +79,7 @@ class Search extends BaseObject defaults($user_data, 'tags', '') ); - return new ResultList(1, 1, 1, [$result]); + return new ContactResultList(1, 1, 1, [$result]); } else { return null; @@ -93,7 +93,7 @@ class Search extends BaseObject * @param string $search * @param int $page * - * @return ResultList|null + * @return ContactResultList|null * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function searchDirectory($search, $page = 1) @@ -112,7 +112,7 @@ class Search extends BaseObject $results = json_decode($resultJson, true); - $resultList = new ResultList( + $resultList = new ContactResultList( defaults($results, 'page', 1), defaults($results, 'count', 1), defaults($results, 'itemsperpage', 1) @@ -124,7 +124,7 @@ class Search extends BaseObject $contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user()); $itemurl = (!empty($contactDetails['addr']) ? $contactDetails['addr'] : defaults($profile, 'profile_url', '')); - $result = new Result( + $result = new ContactResult( defaults($profile, 'name', ''), defaults($profile, 'addr', ''), $itemurl, @@ -149,7 +149,7 @@ class Search extends BaseObject * @param int $itemPage * @param bool $community * - * @return ResultList|null + * @return ContactResultList|null * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function searchLocal($search, $start = 0, $itemPage = 80, $community = false) @@ -199,7 +199,7 @@ class Search extends BaseObject return null; } - $resultList = new ResultList($start, $itemPage, $count); + $resultList = new ContactResultList($start, $itemPage, $count); while ($row = DBA::fetch($data)) { if (PortableContact::alternateOStatusUrl($row["nurl"])) { @@ -220,7 +220,7 @@ class Search extends BaseObject $contact["name"] = end(explode("/", $urlparts["path"])); } - $result = new Result( + $result = new ContactResult( $contact["name"], $contact["addr"], $contact["addr"], diff --git a/src/Module/BaseSearchModule.php b/src/Module/BaseSearchModule.php index 7028208286..9430ec1b91 100644 --- a/src/Module/BaseSearchModule.php +++ b/src/Module/BaseSearchModule.php @@ -7,7 +7,7 @@ use Friendica\Content\ContactSelector; use Friendica\Content\Pager; use Friendica\Core\L10n; use Friendica\Core\Renderer; -use Friendica\Object\Search\ResultList; +use Friendica\Object\Search\ContactResultList; use Friendica\Util\Proxy as ProxyUtils; use Friendica\Model; use Friendica\Util\Strings; @@ -72,15 +72,15 @@ class BaseSearchModule extends BaseModule /** * Prints a human readable search result * - * @param ResultList $results - * @param Pager $pager - * @param string $header + * @param ContactResultList $results + * @param Pager $pager + * @param string $header * * @return string The result * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - protected static function printResult(ResultList $results, Pager $pager, $header = '') + protected static function printResult(ContactResultList $results, Pager $pager, $header = '') { if (empty($results) || empty($results->getResults())) { info(L10n::t('No matches') . EOL); @@ -100,11 +100,11 @@ class BaseSearchModule extends BaseModule $photo_menu = []; // If We already know this contact then don't show the "connect" button - if ($result->getCid() > 0 || $result->getPcid() > 0) { + if ($result->getCid() > 0 || $result->getPCid() > 0) { $connLink = ""; $connTxt = ""; $contact = Model\Contact::getById( - ($result->getCid() > 0) ? $result->getCid() : $result->getPcid() + ($result->getCid() > 0) ? $result->getCid() : $result->getPCid() ); if (!empty($contact)) { diff --git a/src/Object/Search/Result.php b/src/Object/Search/ContactResult.php similarity index 90% rename from src/Object/Search/Result.php rename to src/Object/Search/ContactResult.php index 10d6b0aa03..699afa862d 100644 --- a/src/Object/Search/Result.php +++ b/src/Object/Search/ContactResult.php @@ -5,11 +5,11 @@ namespace Friendica\Object\Search; use Friendica\Model\Search; /** - * A search result + * A search result for contact searching * - * @see Search for defails + * @see Search for details */ -class Result +class ContactResult { /** * @var int @@ -18,7 +18,7 @@ class Result /** * @var int */ - private $pcid; + private $pCid; /** * @var string */ @@ -59,9 +59,9 @@ class Result /** * @return int */ - public function getPcid() + public function getPCid() { - return $this->pcid; + return $this->pCid; } /** @@ -140,7 +140,7 @@ class Result $this->network = $network; $this->cid = $cid; - $this->pcid = $pcid; + $this->pCid = $pcid; $this->tags = $tags; } } diff --git a/src/Object/Search/ResultList.php b/src/Object/Search/ContactResultList.php similarity index 73% rename from src/Object/Search/ResultList.php rename to src/Object/Search/ContactResultList.php index 88caaa7e56..f3014d3841 100644 --- a/src/Object/Search/ResultList.php +++ b/src/Object/Search/ContactResultList.php @@ -5,11 +5,11 @@ namespace Friendica\Object\Search; use Friendica\Model\Search; /** - * A list of search results with details + * A list of search results for contacts with metadata * * @see Search for details */ -class ResultList +class ContactResultList { /** * Page of the result list @@ -28,7 +28,8 @@ class ResultList private $itemsPage; /** * Array of results - * @var Result[] + * + * @var ContactResult[] */ private $results; @@ -57,7 +58,7 @@ class ResultList } /** - * @return Result[] + * @return ContactResult[] */ public function getResults() { @@ -65,10 +66,10 @@ class ResultList } /** - * @param int $page - * @param int $total - * @param int $itemsPage - * @param Result[] $results + * @param int $page + * @param int $total + * @param int $itemsPage + * @param ContactResult[] $results */ public function __construct($page = 0, $total = 0, $itemsPage = 0, array $results = []) { @@ -82,9 +83,9 @@ class ResultList /** * Adds a result to the result list * - * @param Result $result + * @param ContactResult $result */ - public function addResult(Result $result) + public function addResult(ContactResult $result) { $this->results[] = $result; } From 1e36c68e48b0e88ceacac1a730bd7b7f6c14748c Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 20 May 2019 18:42:27 +0200 Subject: [PATCH 07/13] Moving Search to Core, Refactor Objects --- src/Core/Search.php | 222 ++++++++++++++++++ src/Model/Search.php | 215 +---------------- src/Module/BaseSearchModule.php | 115 ++++----- src/Object/Search/ContactResult.php | 9 +- src/Object/Search/IResult.php | 10 + .../{ContactResultList.php => ResultList.php} | 14 +- 6 files changed, 306 insertions(+), 279 deletions(-) create mode 100644 src/Core/Search.php create mode 100644 src/Object/Search/IResult.php rename src/Object/Search/{ContactResultList.php => ResultList.php} (81%) diff --git a/src/Core/Search.php b/src/Core/Search.php new file mode 100644 index 0000000000..c08d4ebcc9 --- /dev/null +++ b/src/Core/Search.php @@ -0,0 +1,222 @@ +getConfig(); + $server = $config->get('system', 'directory', self::DEFAULT_DIRECTORY); + + $searchUrl = $server . '/search?q=' . urlencode($search); + + if ($page > 1) { + $searchUrl .= '&page=' . $page; + } + + $red = 0; + $resultJson = Network::fetchUrl($searchUrl, false,$red, 0, 'application/json'); + + $results = json_decode($resultJson, true); + + $resultList = new ResultList( + defaults($results, 'page', 1), + defaults($results, 'count', 1), + defaults($results, 'itemsperpage', 1) + ); + + $profiles = defaults($results, 'profiles', []); + + foreach ($profiles as $profile) { + $contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user()); + $itemUrl = (!empty($contactDetails['addr']) ? $contactDetails['addr'] : defaults($profile, 'profile_url', '')); + + $result = new ContactResult( + defaults($profile, 'name', ''), + defaults($profile, 'addr', ''), + $itemUrl, + defaults($profile, 'profile_url', ''), + defaults($profile, 'photo', ''), + Protocol::DFRN, + defaults($contactDetails, 'cid', 0), + 0, + defaults($profile, 'tags', '')); + + $resultList->addResult($result); + } + + return $resultList; + } + + /** + * Search in the local database for occurrences of the search string + * + * @param string $search + * @param int $start + * @param int $itemPage + * @param bool $community + * + * @return ResultList|null + * @throws HTTPException\InternalServerErrorException + */ + public static function getContactsFromLocalDirectory($search, $start = 0, $itemPage = 80, $community = false) + { + $config = self::getApp()->getConfig(); + + $diaspora = $config->get('system', 'diaspora_enabled') ? Protocol::DIASPORA : Protocol::DFRN; + $ostatus = !$config->get('system', 'ostatus_disabled') ? Protocol::OSTATUS : Protocol::DFRN; + + $wildcard = Strings::escapeHtml('%' . $search . '%'); + + $count = DBA::count('gcontact', [ + 'NOT `hide` + AND `network` IN (?, ?, ?, ?) + AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) + AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ? + OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?) + AND `community` = ?', + Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, + $wildcard, $wildcard, $wildcard, + $wildcard, $wildcard, $wildcard, + $community, + ]); + + if (empty($count)) { + return null; + } + + $data = DBA::select('gcontact', ['nurl'], [ + 'NOT `hide` + AND `network` IN (?, ?, ?, ?) + AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) + AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ? + OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?) + AND `community` = ?', + Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, + $wildcard, $wildcard, $wildcard, + $wildcard, $wildcard, $wildcard, + $community, + ], [ + 'group_by' => ['nurl', 'updated'], + 'limit' => [$start, $itemPage], + 'order' => ['updated' => 'DESC'] + ]); + + if (!DBA::isResult($data)) { + return null; + } + + $resultList = new ResultList($start, $itemPage, $count); + + while ($row = DBA::fetch($data)) { + if (PortableContact::alternateOStatusUrl($row["nurl"])) { + continue; + } + + $urlParts = parse_url($row["nurl"]); + + // Ignore results that look strange. + // For historic reasons the gcontact table does contain some garbage. + if (!empty($urlParts['query']) || !empty($urlParts['fragment'])) { + continue; + } + + $contact = Contact::getDetailsByURL($row["nurl"], local_user()); + + if ($contact["name"] == "") { + $contact["name"] = end(explode("/", $urlParts["path"])); + } + + $result = new ContactResult( + $contact["name"], + $contact["addr"], + $contact["addr"], + $contact["url"], + $contact["photo"], + $contact["network"], + $contact["cid"], + $contact["zid"], + $contact["keywords"] + ); + + $resultList->addResult($result); + } + + DBA::close($data); + + // Add found profiles from the global directory to the local directory + Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search)); + + return $resultList; + } +} diff --git a/src/Model/Search.php b/src/Model/Search.php index 80d5e6698d..5829ff91d0 100644 --- a/src/Model/Search.php +++ b/src/Model/Search.php @@ -3,23 +3,13 @@ namespace Friendica\Model; use Friendica\BaseObject; -use Friendica\Core\Protocol; -use Friendica\Core\Worker; use Friendica\Database\DBA; -use Friendica\Network\Probe; -use Friendica\Object\Search\ContactResult; -use Friendica\Object\Search\ContactResultList; -use Friendica\Protocol\PortableContact; -use Friendica\Util\Network; -use Friendica\Util\Strings; /** - * Model for searches + * Model for DB specific logic for the search entity */ class Search extends BaseObject { - const DEFAULT_DIRECTORY = 'https://dir.friendica.social'; - /** * Returns the list of user defined tags (e.g. #Friendica) * @@ -39,207 +29,4 @@ class Search extends BaseObject return $tags; } - - /** - * Search a user based on his/her profile address - * pattern: @username@domain.tld - * - * @param string $user The user to search for - * - * @return ContactResultList|null - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - * @throws \ImagickException - */ - public static function searchUser($user) - { - if ((filter_var($user, FILTER_VALIDATE_EMAIL) && Network::isEmailDomainValid($user)) || - (substr(Strings::normaliseLink($user), 0, 7) == "http://")) { - - $user_data = Probe::uri($user); - if (empty($user_data)) { - return null; - } - - if (!(in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]))) { - return null; - } - - $contactDetails = Contact::getDetailsByURL(defaults($user_data, 'url', ''), local_user()); - $itemurl = (($contactDetails["addr"] != "") ? $contactDetails["addr"] : defaults($user_data, 'url', '')); - - $result = new ContactResult( - defaults($user_data, 'name', ''), - defaults($user_data, 'addr', ''), - $itemurl, - defaults($user_data, 'url', ''), - defaults($user_data, 'photo', ''), - defaults($user_data, 'network', ''), - defaults($contactDetails, 'cid', 0), - 0, - defaults($user_data, 'tags', '') - ); - - return new ContactResultList(1, 1, 1, [$result]); - - } else { - return null; - } - } - - /** - * Search in the global directory for occurrences of the search string - * This is mainly based on the JSON results of https://dir.friendica.social - * - * @param string $search - * @param int $page - * - * @return ContactResultList|null - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ - public static function searchDirectory($search, $page = 1) - { - $config = self::getApp()->getConfig(); - $server = $config->get('system', 'directory', self::DEFAULT_DIRECTORY); - - $searchUrl = $server . '/search?q=' . urlencode($search); - - if ($page > 1) { - $searchUrl .= '&page=' . $page; - } - - $red = 0; - $resultJson = Network::fetchUrl($searchUrl, false,$red, 0, 'application/json'); - - $results = json_decode($resultJson, true); - - $resultList = new ContactResultList( - defaults($results, 'page', 1), - defaults($results, 'count', 1), - defaults($results, 'itemsperpage', 1) - ); - - $profiles = defaults($results, 'profiles', []); - - foreach ($profiles as $profile) { - $contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user()); - $itemurl = (!empty($contactDetails['addr']) ? $contactDetails['addr'] : defaults($profile, 'profile_url', '')); - - $result = new ContactResult( - defaults($profile, 'name', ''), - defaults($profile, 'addr', ''), - $itemurl, - defaults($profile, 'profile_url', ''), - defaults($profile, 'photo', ''), - Protocol::DFRN, - defaults($contactDetails, 'cid', 0), - 0, - defaults($profile, 'tags', '')); - - $resultList->addResult($result); - } - - return $resultList; - } - - /** - * Search in the local database for occurrences of the search string - * - * @param string $search - * @param int $start - * @param int $itemPage - * @param bool $community - * - * @return ContactResultList|null - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ - public static function searchLocal($search, $start = 0, $itemPage = 80, $community = false) - { - $config = self::getApp()->getConfig(); - - $diaspora = $config->get('system', 'diaspora_enabled') ? Protocol::DIASPORA : Protocol::DFRN; - $ostatus = !$config->get('system', 'ostatus_disabled') ? Protocol::OSTATUS : Protocol::DFRN; - - $wildcard = Strings::escapeHtml('%' . $search . '%'); - - $count = DBA::count('gcontact', [ - 'NOT `hide` - AND `network` IN (?, ?, ?, ?) - AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) - AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ? - OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?) - AND `community` = ?', - Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, - $wildcard, $wildcard, $wildcard, - $wildcard, $wildcard, $wildcard, - $community, - ]); - - if (empty($count)) { - return null; - } - - $data = DBA::select('gcontact', ['nurl'], [ - 'NOT `hide` - AND `network` IN (?, ?, ?, ?) - AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) - AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ? - OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?) - AND `community` = ?', - Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, - $wildcard, $wildcard, $wildcard, - $wildcard, $wildcard, $wildcard, - $community, - ], [ - 'group_by' => ['nurl', 'updated'], - 'limit' => [$start, $itemPage], - 'order' => ['updated' => 'DESC'] - ]); - - if (!DBA::isResult($data)) { - return null; - } - - $resultList = new ContactResultList($start, $itemPage, $count); - - while ($row = DBA::fetch($data)) { - if (PortableContact::alternateOStatusUrl($row["nurl"])) { - continue; - } - - $urlparts = parse_url($row["nurl"]); - - // Ignore results that look strange. - // For historic reasons the gcontact table does contain some garbage. - if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) { - continue; - } - - $contact = Contact::getDetailsByURL($row["nurl"], local_user()); - - if ($contact["name"] == "") { - $contact["name"] = end(explode("/", $urlparts["path"])); - } - - $result = new ContactResult( - $contact["name"], - $contact["addr"], - $contact["addr"], - $contact["url"], - $contact["photo"], - $contact["network"], - $contact["cid"], - $contact["zid"], - $contact["keywords"] - ); - - $resultList->addResult($result); - } - - DBA::close($data); - - // Add found profiles from the global directory to the local directory - Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search)); - - return $resultList; - } } diff --git a/src/Module/BaseSearchModule.php b/src/Module/BaseSearchModule.php index 9430ec1b91..7e13a590ed 100644 --- a/src/Module/BaseSearchModule.php +++ b/src/Module/BaseSearchModule.php @@ -7,9 +7,12 @@ use Friendica\Content\ContactSelector; use Friendica\Content\Pager; use Friendica\Core\L10n; use Friendica\Core\Renderer; -use Friendica\Object\Search\ContactResultList; +use Friendica\Core\Search; +use Friendica\Object\Search\ContactResult; +use Friendica\Object\Search\ResultList; use Friendica\Util\Proxy as ProxyUtils; use Friendica\Model; +use Friendica\Network\HTTPException; use Friendica\Util\Strings; /** @@ -23,7 +26,7 @@ class BaseSearchModule extends BaseModule * @param string $prefix A optional prefix (e.g. @ or !) for searching * * @return string - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ public static function performSearch($prefix = '') @@ -46,7 +49,7 @@ class BaseSearchModule extends BaseModule if (strpos($search, '@') === 0) { $search = substr($search, 1); $header = L10n::t('People Search - %s', $search); - $results = Model\Search::searchUser($search); + $results = Search::getContactsFromProbe($search); } if (strpos($search, '!') === 0) { @@ -59,10 +62,10 @@ class BaseSearchModule extends BaseModule if ($localSearch && empty($results)) { $pager->setItemsPerPage(80); - $results = Model\Search::searchLocal($search, $pager->getStart(), $pager->getItemsPerPage(), $community); + $results = Search::getContactsFromLocalDirectory($search, $pager->getStart(), $pager->getItemsPerPage(), $community); } elseif (strlen($config->get('system', 'directory')) && empty($results)) { - $results = Model\Search::searchDirectory($search, $pager->getPage()); + $results = Search::getContactsFromGlobalDirectory($search, $pager->getPage()); $pager->setItemsPerPage($results->getItemsPage()); } @@ -72,15 +75,15 @@ class BaseSearchModule extends BaseModule /** * Prints a human readable search result * - * @param ContactResultList $results + * @param ResultList $results * @param Pager $pager * @param string $header * * @return string The result - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ - protected static function printResult(ContactResultList $results, Pager $pager, $header = '') + protected static function printResult(ResultList $results, Pager $pager, $header = '') { if (empty($results) || empty($results->getResults())) { info(L10n::t('No matches') . EOL); @@ -93,58 +96,62 @@ class BaseSearchModule extends BaseModule $entries = []; foreach ($results->getResults() as $result) { - $alt_text = ''; - $location = ''; - $about = ''; - $accountType = ''; - $photo_menu = []; + // in case the result is a contact result, add a contact-specific entry + if ($result instanceof ContactResult) { - // If We already know this contact then don't show the "connect" button - if ($result->getCid() > 0 || $result->getPCid() > 0) { - $connLink = ""; - $connTxt = ""; - $contact = Model\Contact::getById( - ($result->getCid() > 0) ? $result->getCid() : $result->getPCid() - ); + $alt_text = ''; + $location = ''; + $about = ''; + $accountType = ''; + $photo_menu = []; - if (!empty($contact)) { - $photo_menu = Model\Contact::photoMenu($contact); - $details = Contact::getContactTemplateVars($contact); - $alt_text = $details['alt_text']; - $location = $contact['location']; - $about = $contact['about']; - $accountType = Model\Contact::getAccountType($contact); + // If We already know this contact then don't show the "connect" button + if ($result->getCid() > 0 || $result->getPCid() > 0) { + $connLink = ""; + $connTxt = ""; + $contact = Model\Contact::getById( + ($result->getCid() > 0) ? $result->getCid() : $result->getPCid() + ); + + if (!empty($contact)) { + $photo_menu = Model\Contact::photoMenu($contact); + $details = Contact::getContactTemplateVars($contact); + $alt_text = $details['alt_text']; + $location = $contact['location']; + $about = $contact['about']; + $accountType = Model\Contact::getAccountType($contact); + } else { + $photo_menu = []; + } } else { - $photo_menu = []; + $connLink = $a->getBaseURL() . '/follow/?url=' . $result->getUrl(); + $connTxt = L10n::t('Connect'); + + $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($result->getUrl())]; + $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connLink]; } - } else { - $connLink = $a->getBaseURL() . '/follow/?url=' . $result->getUrl(); - $connTxt = L10n::t('Connect'); - $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($result->getUrl())]; - $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connLink]; + $photo = str_replace("http:///photo/", get_server() . "/photo/", $result->getPhoto()); + + $entry = [ + 'alt_text' => $alt_text, + 'url' => Model\Contact::magicLink($result->getUrl()), + 'itemurl' => $result->getItem(), + 'name' => $result->getName(), + 'thumb' => ProxyUtils::proxifyUrl($photo, false, ProxyUtils::SIZE_THUMB), + 'img_hover' => $result->getTags(), + 'conntxt' => $connTxt, + 'connlnk' => $connLink, + 'photo_menu' => $photo_menu, + 'details' => $location, + 'tags' => $result->getTags(), + 'about' => $about, + 'account_type' => $accountType, + 'network' => ContactSelector::networkToName($result->getNetwork(), $result->getUrl()), + 'id' => ++$id, + ]; + $entries[] = $entry; } - - $photo = str_replace("http:///photo/", get_server() . "/photo/", $result->getPhoto()); - - $entry = [ - 'alt_text' => $alt_text, - 'url' => Model\Contact::magicLink($result->getUrl()), - 'itemurl' => $result->getItem(), - 'name' => $result->getName(), - 'thumb' => ProxyUtils::proxifyUrl($photo, false, ProxyUtils::SIZE_THUMB), - 'img_hover' => $result->getTags(), - 'conntxt' => $connTxt, - 'connlnk' => $connLink, - 'photo_menu' => $photo_menu, - 'details' => $location, - 'tags' => $result->getTags(), - 'about' => $about, - 'account_type' => $accountType, - 'network' => ContactSelector::networkToName($result->getNetwork(), $result->getUrl()), - 'id' => ++$id, - ]; - $entries[] = $entry; } $tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl'); diff --git a/src/Object/Search/ContactResult.php b/src/Object/Search/ContactResult.php index 699afa862d..ccfb5f4cfd 100644 --- a/src/Object/Search/ContactResult.php +++ b/src/Object/Search/ContactResult.php @@ -9,7 +9,7 @@ use Friendica\Model\Search; * * @see Search for details */ -class ContactResult +class ContactResult implements IResult { /** * @var int @@ -123,14 +123,15 @@ class ContactResult /** * @param string $name * @param string $addr + * @param string $item * @param string $url * @param string $photo * @param string $network * @param int $cid - * @param int $pcid + * @param int $pCid * @param string $tags */ - public function __construct($name, $addr, $item, $url, $photo, $network, $cid = 0, $pcid = 0, $tags = '') + public function __construct($name, $addr, $item, $url, $photo, $network, $cid = 0, $pCid = 0, $tags = '') { $this->name = $name; $this->addr = $addr; @@ -140,7 +141,7 @@ class ContactResult $this->network = $network; $this->cid = $cid; - $this->pCid = $pcid; + $this->pCid = $pCid; $this->tags = $tags; } } diff --git a/src/Object/Search/IResult.php b/src/Object/Search/IResult.php new file mode 100644 index 0000000000..bf5dfc9146 --- /dev/null +++ b/src/Object/Search/IResult.php @@ -0,0 +1,10 @@ +results[] = $result; } From 83fd03b1245f662f9087c1bd91d0583663a10299 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 20 May 2019 18:44:44 +0200 Subject: [PATCH 08/13] Add PhpDoc --- src/Core/Search.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Core/Search.php b/src/Core/Search.php index c08d4ebcc9..dcc297780c 100644 --- a/src/Core/Search.php +++ b/src/Core/Search.php @@ -5,14 +5,20 @@ namespace Friendica\Core; use Friendica\BaseObject; use Friendica\Database\DBA; use Friendica\Model\Contact; -use Friendica\Network\Probe; use Friendica\Network\HTTPException; +use Friendica\Network\Probe; use Friendica\Object\Search\ContactResult; use Friendica\Object\Search\ResultList; use Friendica\Protocol\PortableContact; use Friendica\Util\Network; use Friendica\Util\Strings; +/** + * Specific class to perform searches for different systems. Currently: + * - Probe for contacts + * - Search in the local directory + * - Search in the global directory + */ class Search extends BaseObject { const DEFAULT_DIRECTORY = 'https://dir.friendica.social'; From 58c8959da0ece9a23966b315310a3962542bc7f4 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 20 May 2019 19:13:37 +0200 Subject: [PATCH 09/13] Add search types --- src/Core/Search.php | 29 ++++++++++++++++++++++------- src/Module/BaseSearchModule.php | 13 +++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Core/Search.php b/src/Core/Search.php index dcc297780c..d000f8283c 100644 --- a/src/Core/Search.php +++ b/src/Core/Search.php @@ -23,6 +23,10 @@ class Search extends BaseObject { const DEFAULT_DIRECTORY = 'https://dir.friendica.social'; + const TYPE_PEOPLE = 0; + const TYPE_FORUM = 1; + const TYPE_ALL = 2; + /** * Search a user based on his/her profile address * pattern: @username@domain.tld @@ -71,20 +75,31 @@ class Search extends BaseObject /** * Search in the global directory for occurrences of the search string - * This is mainly based on the JSON results of https://dir.friendica.social + * @see https://github.com/friendica/friendica-directory/blob/master/docs/Protocol.md#search * * @param string $search + * @param int $type specific type of searching * @param int $page * * @return ResultList|null * @throws HTTPException\InternalServerErrorException */ - public static function getContactsFromGlobalDirectory($search, $page = 1) + public static function getContactsFromGlobalDirectory($search, $type = self::TYPE_ALL, $page = 1) { $config = self::getApp()->getConfig(); $server = $config->get('system', 'directory', self::DEFAULT_DIRECTORY); - $searchUrl = $server . '/search?q=' . urlencode($search); + $searchUrl = $server . '/search'; + + switch ($type) { + case self::TYPE_FORUM: + $searchUrl .= '/forum'; + break; + case self::TYPE_PEOPLE: + $searchUrl .= '/people'; + break; + } + $searchUrl .= '?q=' . urlencode($search); if ($page > 1) { $searchUrl .= '&page=' . $page; @@ -130,12 +145,12 @@ class Search extends BaseObject * @param string $search * @param int $start * @param int $itemPage - * @param bool $community + * @param int $type * * @return ResultList|null * @throws HTTPException\InternalServerErrorException */ - public static function getContactsFromLocalDirectory($search, $start = 0, $itemPage = 80, $community = false) + public static function getContactsFromLocalDirectory($search, $start = 0, $itemPage = 80, $type = self::TYPE_ALL) { $config = self::getApp()->getConfig(); @@ -154,7 +169,7 @@ class Search extends BaseObject Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, $wildcard, $wildcard, $wildcard, $wildcard, $wildcard, $wildcard, - $community, + ($type === self::TYPE_FORUM), ]); if (empty($count)) { @@ -171,7 +186,7 @@ class Search extends BaseObject Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora, $wildcard, $wildcard, $wildcard, $wildcard, $wildcard, $wildcard, - $community, + ($type === self::TYPE_FORUM), ], [ 'group_by' => ['nurl', 'updated'], 'limit' => [$start, $itemPage], diff --git a/src/Module/BaseSearchModule.php b/src/Module/BaseSearchModule.php index 7e13a590ed..3c02b6f490 100644 --- a/src/Module/BaseSearchModule.php +++ b/src/Module/BaseSearchModule.php @@ -8,11 +8,11 @@ use Friendica\Content\Pager; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Search; +use Friendica\Model; +use Friendica\Network\HTTPException; use Friendica\Object\Search\ContactResult; use Friendica\Object\Search\ResultList; use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Model; -use Friendica\Network\HTTPException; use Friendica\Util\Strings; /** @@ -34,7 +34,7 @@ class BaseSearchModule extends BaseModule $a = self::getApp(); $config = $a->getConfig(); - $community = false; + $type = Search::TYPE_ALL; $localSearch = $config->get('system', 'poco_local_search'); @@ -48,13 +48,14 @@ class BaseSearchModule extends BaseModule if (strpos($search, '@') === 0) { $search = substr($search, 1); + $type = Search::TYPE_PEOPLE; $header = L10n::t('People Search - %s', $search); $results = Search::getContactsFromProbe($search); } if (strpos($search, '!') === 0) { $search = substr($search, 1); - $community = true; + $type = Search::TYPE_FORUM; $header = L10n::t('Forum Search - %s', $search); } @@ -62,10 +63,10 @@ class BaseSearchModule extends BaseModule if ($localSearch && empty($results)) { $pager->setItemsPerPage(80); - $results = Search::getContactsFromLocalDirectory($search, $pager->getStart(), $pager->getItemsPerPage(), $community); + $results = Search::getContactsFromLocalDirectory($search, $pager->getStart(), $pager->getItemsPerPage(), $type); } elseif (strlen($config->get('system', 'directory')) && empty($results)) { - $results = Search::getContactsFromGlobalDirectory($search, $pager->getPage()); + $results = Search::getContactsFromGlobalDirectory($search, $pager->getPage(), $type); $pager->setItemsPerPage($results->getItemsPage()); } From 059b813090eb4f7fdad258c010b14820ce419ad5 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 20 May 2019 19:14:39 +0200 Subject: [PATCH 10/13] Add PhpDoc / Code Standards --- src/Object/Search/IResult.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Object/Search/IResult.php b/src/Object/Search/IResult.php index bf5dfc9146..64fb71c858 100644 --- a/src/Object/Search/IResult.php +++ b/src/Object/Search/IResult.php @@ -1,10 +1,11 @@ Date: Mon, 20 May 2019 19:15:47 +0200 Subject: [PATCH 11/13] refactor method signature --- src/Core/Search.php | 4 ++-- src/Module/BaseSearchModule.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core/Search.php b/src/Core/Search.php index d000f8283c..3a97a700d7 100644 --- a/src/Core/Search.php +++ b/src/Core/Search.php @@ -143,14 +143,14 @@ class Search extends BaseObject * Search in the local database for occurrences of the search string * * @param string $search + * @param int $type * @param int $start * @param int $itemPage - * @param int $type * * @return ResultList|null * @throws HTTPException\InternalServerErrorException */ - public static function getContactsFromLocalDirectory($search, $start = 0, $itemPage = 80, $type = self::TYPE_ALL) + public static function getContactsFromLocalDirectory($search, $type = self::TYPE_ALL, $start = 0, $itemPage = 80) { $config = self::getApp()->getConfig(); diff --git a/src/Module/BaseSearchModule.php b/src/Module/BaseSearchModule.php index 3c02b6f490..bba029db54 100644 --- a/src/Module/BaseSearchModule.php +++ b/src/Module/BaseSearchModule.php @@ -63,7 +63,7 @@ class BaseSearchModule extends BaseModule if ($localSearch && empty($results)) { $pager->setItemsPerPage(80); - $results = Search::getContactsFromLocalDirectory($search, $pager->getStart(), $pager->getItemsPerPage(), $type); + $results = Search::getContactsFromLocalDirectory($search, $type, $pager->getStart(), $pager->getItemsPerPage()); } elseif (strlen($config->get('system', 'directory')) && empty($results)) { $results = Search::getContactsFromGlobalDirectory($search, $pager->getPage(), $type); From 5e79d3fc8279316ebccdc06b791e2d30079e386e Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 20 May 2019 19:19:57 +0200 Subject: [PATCH 12/13] Fixing method signature --- src/Core/Search.php | 17 ++++++++++------- src/Module/BaseSearchModule.php | 16 ++++++++-------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/Core/Search.php b/src/Core/Search.php index 3a97a700d7..0a234d748e 100644 --- a/src/Core/Search.php +++ b/src/Core/Search.php @@ -52,7 +52,7 @@ class Search extends BaseObject } $contactDetails = Contact::getDetailsByURL(defaults($user_data, 'url', ''), local_user()); - $itemUrl = (($contactDetails["addr"] != "") ? $contactDetails["addr"] : defaults($user_data, 'url', '')); + $itemUrl = (($contactDetails["addr"] != "") ? $contactDetails["addr"] : defaults($user_data, 'url', '')); $result = new ContactResult( defaults($user_data, 'name', ''), @@ -75,6 +75,7 @@ class Search extends BaseObject /** * Search in the global directory for occurrences of the search string + * * @see https://github.com/friendica/friendica-directory/blob/master/docs/Protocol.md#search * * @param string $search @@ -105,10 +106,10 @@ class Search extends BaseObject $searchUrl .= '&page=' . $page; } - $red = 0; - $resultJson = Network::fetchUrl($searchUrl, false,$red, 0, 'application/json'); + $red = 0; + $resultJson = Network::fetchUrl($searchUrl, false, $red, 0, 'application/json'); - $results = json_decode($resultJson, true); + $results = json_decode($resultJson, true); $resultList = new ResultList( defaults($results, 'page', 1), @@ -120,7 +121,9 @@ class Search extends BaseObject foreach ($profiles as $profile) { $contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user()); - $itemUrl = (!empty($contactDetails['addr']) ? $contactDetails['addr'] : defaults($profile, 'profile_url', '')); + $itemUrl = (!empty($contactDetails['addr']) ? + $contactDetails['addr'] : + defaults($profile, 'profile_url', '')); $result = new ContactResult( defaults($profile, 'name', ''), @@ -189,8 +192,8 @@ class Search extends BaseObject ($type === self::TYPE_FORUM), ], [ 'group_by' => ['nurl', 'updated'], - 'limit' => [$start, $itemPage], - 'order' => ['updated' => 'DESC'] + 'limit' => [$start, $itemPage], + 'order' => ['updated' => 'DESC'] ]); if (!DBA::isResult($data)) { diff --git a/src/Module/BaseSearchModule.php b/src/Module/BaseSearchModule.php index bba029db54..226a4da4d5 100644 --- a/src/Module/BaseSearchModule.php +++ b/src/Module/BaseSearchModule.php @@ -48,15 +48,15 @@ class BaseSearchModule extends BaseModule if (strpos($search, '@') === 0) { $search = substr($search, 1); - $type = Search::TYPE_PEOPLE; + $type = Search::TYPE_PEOPLE; $header = L10n::t('People Search - %s', $search); $results = Search::getContactsFromProbe($search); } if (strpos($search, '!') === 0) { - $search = substr($search, 1); - $type = Search::TYPE_FORUM; - $header = L10n::t('Forum Search - %s', $search); + $search = substr($search, 1); + $type = Search::TYPE_FORUM; + $header = L10n::t('Forum Search - %s', $search); } $pager = new Pager($a->query_string); @@ -66,7 +66,7 @@ class BaseSearchModule extends BaseModule $results = Search::getContactsFromLocalDirectory($search, $type, $pager->getStart(), $pager->getItemsPerPage()); } elseif (strlen($config->get('system', 'directory')) && empty($results)) { - $results = Search::getContactsFromGlobalDirectory($search, $pager->getPage(), $type); + $results = Search::getContactsFromGlobalDirectory($search, $type, $pager->getPage()); $pager->setItemsPerPage($results->getItemsPage()); } @@ -77,8 +77,8 @@ class BaseSearchModule extends BaseModule * Prints a human readable search result * * @param ResultList $results - * @param Pager $pager - * @param string $header + * @param Pager $pager + * @param string $header * * @return string The result * @throws HTTPException\InternalServerErrorException @@ -93,7 +93,7 @@ class BaseSearchModule extends BaseModule $a = self::getApp(); - $id = 0; + $id = 0; $entries = []; foreach ($results->getResults() as $result) { From 3d67987cbce975b60932b01c7b61131a01e5913a Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 20 May 2019 19:27:53 +0200 Subject: [PATCH 13/13] simplification --- src/Core/Search.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Core/Search.php b/src/Core/Search.php index 0a234d748e..bd4a81a5f4 100644 --- a/src/Core/Search.php +++ b/src/Core/Search.php @@ -52,7 +52,7 @@ class Search extends BaseObject } $contactDetails = Contact::getDetailsByURL(defaults($user_data, 'url', ''), local_user()); - $itemUrl = (($contactDetails["addr"] != "") ? $contactDetails["addr"] : defaults($user_data, 'url', '')); + $itemUrl = defaults($contactDetails, 'addr', defaults($user_data, 'url', '')); $result = new ContactResult( defaults($user_data, 'name', ''), @@ -121,9 +121,7 @@ class Search extends BaseObject foreach ($profiles as $profile) { $contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user()); - $itemUrl = (!empty($contactDetails['addr']) ? - $contactDetails['addr'] : - defaults($profile, 'profile_url', '')); + $itemUrl = defaults($contactDetails, 'addr', defaults($profile, 'profile_url', '')); $result = new ContactResult( defaults($profile, 'name', ''),