]> git.mxchange.org Git - friendica.git/commitdiff
Move mod/dirfind to src/Module/DirFind
authorPhilipp Holzer <admin+github@philipp.info>
Sun, 19 May 2019 00:50:14 +0000 (02:50 +0200)
committerPhilipp Holzer <admin+github@philipp.info>
Sun, 19 May 2019 02:28:16 +0000 (04:28 +0200)
mod/dirfind.php [deleted file]
mod/search.php
src/App/Router.php
src/Database/DBA.php
src/Model/Search.php
src/Module/DirectorySearch.php [new file with mode: 0644]
src/Object/Search/Result.php [new file with mode: 0644]
src/Object/Search/ResultList.php [new file with mode: 0644]

diff --git a/mod/dirfind.php b/mod/dirfind.php
deleted file mode 100644 (file)
index a5b7731..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-<?php
-/**
- * @file mod/dirfind.php
- */
-
-use Friendica\App;
-use Friendica\Content\ContactSelector;
-use Friendica\Content\Pager;
-use Friendica\Content\Widget;
-use Friendica\Core\Config;
-use Friendica\Core\L10n;
-use Friendica\Core\Protocol;
-use Friendica\Core\Renderer;
-use Friendica\Core\System;
-use Friendica\Core\Worker;
-use Friendica\Database\DBA;
-use Friendica\Model;
-use Friendica\Module;
-use Friendica\Network\Probe;
-use Friendica\Protocol\PortableContact;
-use Friendica\Util\Network;
-use Friendica\Util\Proxy as ProxyUtils;
-use Friendica\Util\Strings;
-
-
-function dirfind_init(App $a) {
-
-       if (! local_user()) {
-               notice(L10n::t('Permission denied.') . EOL );
-               return;
-       }
-
-       if (empty($a->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;
-}
index 1416f1d89f52d34edb82e9a94da5af8e91353779..21b6918b1ced35a341d2c688b92b68faf8c94cbb 100644 (file)
@@ -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)
index 373bb1c32e81a3059b15868aca61db72cb352e65..4a8807fa7025ca90fc36edade579b5ffd0da31aa 100644 (file)
@@ -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);
index 85bdbbb628baec62afc021e9d6f23ed14c041831..9367e2681fd57fb0db881cfb9ad7b8c968db82cd 100644 (file)
@@ -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;
        }
 
        /**
index 5829ff91d0c7dc69eb3370f882a2587f593836e2..815f2dc633acf46fe70bb818210e31ef9517d817 100644 (file)
@@ -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 (file)
index 0000000..1bacacc
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+
+namespace Friendica\Module;
+
+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;
+
+class DirectorySearch extends BaseModule
+{
+       public static function content()
+       {
+               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;
+
+               $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 (file)
index 0000000..10d6b0a
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+
+namespace Friendica\Object\Search;
+
+use Friendica\Model\Search;
+
+/**
+ * A search result
+ *
+ * @see Search for defails
+ */
+class Result
+{
+       /**
+        * @var int
+        */
+       private $cid;
+       /**
+        * @var int
+        */
+       private $pcid;
+       /**
+        * @var string
+        */
+       private $name;
+       /**
+        * @var string
+        */
+       private $addr;
+       /**
+        * @var string
+        */
+       private $item;
+       /**
+        * @var string
+        */
+       private $url;
+       /**
+        * @var string
+        */
+       private $photo;
+       /**
+        * @var string
+        */
+       private $tags;
+       /**
+        * @var string
+        */
+       private $network;
+
+       /**
+        * @return int
+        */
+       public function getCid()
+       {
+               return $this->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 (file)
index 0000000..88caaa7
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+
+namespace Friendica\Object\Search;
+
+use Friendica\Model\Search;
+
+/**
+ * A list of search results with details
+ *
+ * @see Search for details
+ */
+class ResultList
+{
+       /**
+        * Page of the result list
+        * @var int
+        */
+       private $page;
+       /**
+        * Total count of results
+        * @var int
+        */
+       private $total;
+       /**
+        * items per page
+        * @var int
+        */
+       private $itemsPage;
+       /**
+        * Array of results
+        * @var Result[]
+        */
+       private $results;
+
+       /**
+        * @return int
+        */
+       public function getPage()
+       {
+               return $this->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;
+       }
+}