3 * @file mod/dirfind.php
7 use Friendica\Content\ContactSelector;
8 use Friendica\Content\Pager;
9 use Friendica\Content\Widget;
10 use Friendica\Core\Config;
11 use Friendica\Core\L10n;
12 use Friendica\Core\Protocol;
13 use Friendica\Core\Renderer;
14 use Friendica\Core\System;
15 use Friendica\Core\Worker;
16 use Friendica\Database\DBA;
19 use Friendica\Network\Probe;
20 use Friendica\Protocol\PortableContact;
21 use Friendica\Util\Network;
22 use Friendica\Util\Proxy as ProxyUtils;
23 use Friendica\Util\Strings;
26 function dirfind_init(App $a) {
29 notice(L10n::t('Permission denied.') . EOL );
33 if (empty($a->page['aside'])) {
34 $a->page['aside'] = '';
37 $a->page['aside'] .= Widget::findPeople();
39 $a->page['aside'] .= Widget::follow();
42 function dirfind_content(App $a, $prefix = "") {
45 $discover_user = false;
47 $local = Config::get('system','poco_local_search');
49 $search = $prefix.Strings::escapeTags(trim(defaults($_REQUEST, 'search', '')));
53 if (strpos($search,'@') === 0) {
54 $search = substr($search,1);
55 $header = L10n::t('People Search - %s', $search);
56 if ((filter_var($search, FILTER_VALIDATE_EMAIL) && Network::isEmailDomainValid($search)) ||
57 (substr(Strings::normaliseLink($search), 0, 7) == "http://")) {
58 $user_data = Probe::uri($search);
59 $discover_user = (in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]));
63 if (strpos($search,'!') === 0) {
64 $search = substr($search,1);
66 $header = L10n::t('Forum Search - %s', $search);
72 $pager = new Pager($a->query_string);
78 $j->page = $pager->getPage();
80 $objresult = new stdClass();
82 $objresult->name = $user_data["name"];
83 $objresult->addr = $user_data["addr"];
84 $objresult->url = $user_data["url"];
85 $objresult->photo = $user_data["photo"];
86 $objresult->tags = "";
87 $objresult->network = $user_data["network"];
89 $contact = Model\Contact::getDetailsByURL($user_data["url"], local_user());
90 $objresult->cid = $contact["cid"];
91 $objresult->pcid = $contact["zid"];
93 $j->results[] = $objresult;
95 // Add the contact to the global contacts if it isn't already in our system
96 if (($contact["cid"] == 0) && ($contact["zid"] == 0) && ($contact["gid"] == 0)) {
97 Model\GContact::update($user_data);
101 $extra_sql = " AND `community`";
106 $pager->setItemsPerPage(80);
108 if (Config::get('system','diaspora_enabled')) {
109 $diaspora = Protocol::DIASPORA;
111 $diaspora = Protocol::DFRN;
114 if (!Config::get('system','ostatus_disabled')) {
115 $ostatus = Protocol::OSTATUS;
117 $ostatus = Protocol::DFRN;
120 $search2 = "%".$search."%";
122 /// @TODO These 2 SELECTs are not checked on validity with DBA::isResult()
123 $count = q("SELECT count(*) AS `total` FROM `gcontact`
124 WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s', '%s') AND
125 ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
126 (`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR
127 `addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql",
128 DBA::escape(Protocol::ACTIVITYPUB), DBA::escape(Protocol::DFRN), DBA::escape($ostatus), DBA::escape($diaspora),
129 DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)),
130 DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)));
132 $results = q("SELECT `nurl`
134 WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s', '%s') AND
135 ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
136 (`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR
137 `addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql
139 ORDER BY `updated` DESC LIMIT %d, %d",
140 DBA::escape(Protocol::ACTIVITYPUB), DBA::escape(Protocol::DFRN), DBA::escape($ostatus), DBA::escape($diaspora),
141 DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)),
142 DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)),
143 $pager->getStart(), $pager->getItemsPerPage());
145 $j->total = $count[0]["total"];
146 $j->items_page = $pager->getItemsPerPage();
147 $j->page = $pager->getPage();
148 foreach ($results AS $result) {
149 if (PortableContact::alternateOStatusUrl($result["nurl"])) {
153 $urlparts = parse_url($result["nurl"]);
155 // Ignore results that look strange.
156 // For historic reasons the gcontact table does contain some garbage.
157 if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) {
161 $result = Model\Contact::getDetailsByURL($result["nurl"], local_user());
163 if ($result["name"] == "") {
164 $result["name"] = end(explode("/", $urlparts["path"]));
167 $objresult = new stdClass();
168 $objresult->cid = $result["cid"];
169 $objresult->pcid = $result["zid"];
170 $objresult->name = $result["name"];
171 $objresult->addr = $result["addr"];
172 $objresult->url = $result["url"];
173 $objresult->photo = $result["photo"];
174 $objresult->tags = $result["keywords"];
175 $objresult->network = $result["network"];
177 $j->results[] = $objresult;
180 // Add found profiles from the global directory to the local directory
181 Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search));
183 $p = (($pager->getPage() != 1) ? '&p=' . $pager->getPage() : '');
185 if (strlen(Config::get('system','directory'))) {
186 $x = Network::fetchUrl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
189 $j = json_decode($x);
191 $pager->setItemsPerPage($j->items_page);
194 if (!empty($j->results)) {
197 foreach ($j->results as $jj) {
201 $contact_details = Model\Contact::getDetailsByURL($jj->url, local_user());
203 $itemurl = (($contact_details["addr"] != "") ? $contact_details["addr"] : $jj->url);
205 // If We already know this contact then don't show the "connect" button
209 $contact = DBA::selectFirst('contact', [], ['id' => $jj->cid]);
210 if (DBA::isResult($contact)) {
211 $photo_menu = Model\Contact::photoMenu($contact);
212 $details = Module\Contact::getContactTemplateVars($contact);
213 $alt_text = $details['alt_text'];
218 $connlnk = System::baseUrl().'/follow/?url='.(!empty($jj->connect) ? $jj->connect : $jj->url);
219 $conntxt = L10n::t('Connect');
221 $contact = DBA::selectFirst('contact', [], ['id' => $jj->pcid]);
222 if (DBA::isResult($contact)) {
223 $photo_menu = Model\Contact::photoMenu($contact);
228 $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($jj->url)];
229 $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk];
232 $jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
235 'alt_text' => $alt_text,
236 'url' => Model\Contact::magicLink($jj->url),
237 'itemurl' => $itemurl,
239 'thumb' => ProxyUtils::proxifyUrl($jj->photo, false, ProxyUtils::SIZE_THUMB),
240 'img_hover' => $jj->tags,
241 'conntxt' => $conntxt,
242 'connlnk' => $connlnk,
243 'photo_menu' => $photo_menu,
244 'details' => $contact_details['location'],
245 'tags' => $contact_details['keywords'],
246 'about' => $contact_details['about'],
247 'account_type' => Model\Contact::getAccountType($contact_details),
248 'network' => ContactSelector::networkToName($jj->network, $jj->url),
254 $tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl');
255 $o .= Renderer::replaceMacros($tpl,[
257 '$contacts' => $entries,
258 '$paginate' => $pager->renderFull($j->total),
261 info(L10n::t('No matches') . EOL);