diff --git a/mod/acl.php b/mod/acl.php
deleted file mode 100644
index 2b3f2a26c0..0000000000
--- a/mod/acl.php
+++ /dev/null
@@ -1,317 +0,0 @@
- 'acl', 'action' => 'content', 'subaction' => 'search', 'search' => $search, 'type' => $type, 'conversation' => $conv_id]);
-
- if ($search != '') {
- $sql_extra = "AND `name` LIKE '%%" . DBA::escape($search) . "%%'";
- $sql_extra2 = "AND (`attag` LIKE '%%" . DBA::escape($search) . "%%' OR `name` LIKE '%%" . DBA::escape($search) . "%%' OR `nick` LIKE '%%" . DBA::escape($search) . "%%')";
- } else {
- /// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
- $sql_extra = $sql_extra2 = '';
- }
-
- // count groups and contacts
- $group_count = 0;
- if ($type == '' || $type == 'g') {
- $r = q("SELECT COUNT(*) AS g FROM `group` WHERE NOT `deleted` AND `uid` = %d $sql_extra",
- intval(local_user())
- );
- $group_count = (int) $r[0]['g'];
- }
-
- $sql_extra2 .= ' ' . Widget::unavailableNetworks();
-
- $contact_count = 0;
- if ($type == '' || $type == 'c') {
- // autocomplete for editor mentions
- $r = q("SELECT COUNT(*) AS c FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted`
- AND NOT `blocked` AND NOT `pending` AND NOT `archive`
- AND `notify` != '' $sql_extra2",
- intval(local_user())
- );
- $contact_count = (int) $r[0]['c'];
- } elseif ($type == 'f') {
- // autocomplete for editor mentions of forums
- $r = q("SELECT COUNT(*) AS c FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted`
- AND NOT `blocked` AND NOT `pending` AND NOT `archive`
- AND (`forum` OR `prv`)
- AND `notify` != '' $sql_extra2",
- intval(local_user())
- );
- $contact_count = (int) $r[0]['c'];
- } elseif ($type == 'm') {
- // autocomplete for Private Messages
- $r = q("SELECT COUNT(*) AS c FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted`
- AND NOT `blocked` AND NOT `pending` AND NOT `archive`
- AND `network` IN ('%s', '%s', '%s') $sql_extra2",
- intval(local_user()),
- DBA::escape(Protocol::ACTIVITYPUB),
- DBA::escape(Protocol::DFRN),
- DBA::escape(Protocol::DIASPORA)
- );
- $contact_count = (int) $r[0]['c'];
- } elseif ($type == 'a') {
- // autocomplete for Contacts
- $r = q("SELECT COUNT(*) AS c FROM `contact`
- WHERE `uid` = %d AND NOT `self`
- AND NOT `pending` AND NOT `deleted` $sql_extra2",
- intval(local_user())
- );
- $contact_count = (int) $r[0]['c'];
- }
-
- $tot = $group_count + $contact_count;
-
- $groups = [];
- $contacts = [];
-
- if ($type == '' || $type == 'g') {
- /// @todo We should cache this query.
- // This can be done when we can delete cache entries via wildcard
- $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
- FROM `group`
- INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
- WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
- $sql_extra
- GROUP BY `group`.`name`, `group`.`id`
- ORDER BY `group`.`name`
- LIMIT %d,%d",
- intval(local_user()),
- intval($start),
- intval($count)
- );
-
- foreach ($r as $g) {
- $groups[] = [
- 'type' => 'g',
- 'photo' => 'images/twopeople.png',
- 'name' => htmlspecialchars($g['name']),
- 'id' => intval($g['id']),
- 'uids' => array_map('intval', explode(',', $g['uids'])),
- 'link' => '',
- 'forum' => '0'
- ];
- }
- if ((count($groups) > 0) && ($search == '')) {
- $groups[] = ['separator' => true];
- }
- }
-
- $r = [];
- if ($type == '') {
- $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
- AND NOT (`network` IN ('%s', '%s'))
- $sql_extra2
- ORDER BY `name` ASC ",
- intval(local_user()),
- DBA::escape(Protocol::OSTATUS),
- DBA::escape(Protocol::STATUSNET)
- );
- } elseif ($type == 'c') {
- $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
- AND NOT (`network` IN ('%s'))
- $sql_extra2
- ORDER BY `name` ASC ",
- intval(local_user()),
- DBA::escape(Protocol::STATUSNET)
- );
- } elseif ($type == 'f') {
- $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
- AND NOT (`network` IN ('%s'))
- AND (`forum` OR `prv`)
- $sql_extra2
- ORDER BY `name` ASC ",
- intval(local_user()),
- DBA::escape(Protocol::STATUSNET)
- );
- } elseif ($type == 'm') {
- $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
- WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
- AND `network` IN ('%s', '%s', '%s')
- $sql_extra2
- ORDER BY `name` ASC ",
- intval(local_user()),
- DBA::escape(Protocol::ACTIVITYPUB),
- DBA::escape(Protocol::DFRN),
- DBA::escape(Protocol::DIASPORA)
- );
- } elseif ($type == 'a') {
- $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
- WHERE `uid` = %d AND NOT `deleted` AND NOT `pending` AND NOT `archive`
- $sql_extra2
- ORDER BY `name` ASC ",
- intval(local_user())
- );
- } elseif ($type == 'x') {
- // autocomplete for global contact search (e.g. navbar search)
- $search = Strings::escapeTags(trim($_REQUEST['search']));
- $mode = $_REQUEST['smode'];
- $page = $_REQUEST['page'] ?? 1;
-
- $r = ACL::contactAutocomplete($search, $mode, $page);
-
- $contacts = [];
- foreach ($r as $g) {
- $contacts[] = [
- 'photo' => ProxyUtils::proxifyUrl($g['photo'], false, ProxyUtils::SIZE_MICRO),
- 'name' => htmlspecialchars($g['name']),
- 'nick' => defaults($g, 'addr', $g['url']),
- 'network' => $g['network'],
- 'link' => $g['url'],
- 'forum' => !empty($g['community']) ? 1 : 0,
- ];
- }
- $o = [
- 'start' => $start,
- 'count' => $count,
- 'items' => $contacts,
- ];
- echo json_encode($o);
- exit;
- }
-
- if (DBA::isResult($r)) {
- $forums = [];
- foreach ($r as $g) {
- $entry = [
- 'type' => 'c',
- 'photo' => ProxyUtils::proxifyUrl($g['micro'], false, ProxyUtils::SIZE_MICRO),
- 'name' => htmlspecialchars($g['name']),
- 'id' => intval($g['id']),
- 'network' => $g['network'],
- 'link' => $g['url'],
- 'nick' => htmlentities(defaults($g, 'attag', $g['nick'])),
- 'addr' => htmlentities(defaults($g, 'addr', $g['url'])),
- 'forum' => !empty($g['forum']) || !empty($g['prv']) ? 1 : 0,
- ];
- if ($entry['forum']) {
- $forums[] = $entry;
- } else {
- $contacts[] = $entry;
- }
- }
- if (count($forums) > 0) {
- if ($search == '') {
- $forums[] = ['separator' => true];
- }
- $contacts = array_merge($forums, $contacts);
- }
- }
-
- $items = array_merge($groups, $contacts);
-
- if ($conv_id) {
- // In multi threaded posts the conv_id is not the parent of the whole thread
- $parent_item = Item::selectFirst(['parent'], ['id' => $conv_id]);
- if (DBA::isResult($parent_item)) {
- $conv_id = $parent_item['parent'];
- }
-
- /*
- * if $conv_id is set, get unknown contacts in thread
- * but first get known contacts url to filter them out
- */
- $known_contacts = array_map(function ($i) {
- return $i['link'];
- }, $contacts);
-
- $unknown_contacts = [];
-
- $condition = ["`parent` = ?", $conv_id];
- $params = ['order' => ['author-name' => true]];
- $authors = Item::selectForUser(local_user(), ['author-link'], $condition, $params);
- $item_authors = [];
- while ($author = Item::fetch($authors)) {
- $item_authors[$author['author-link']] = $author['author-link'];
- }
- DBA::close($authors);
-
- foreach ($item_authors as $author) {
- if (in_array($author, $known_contacts)) {
- continue;
- }
-
- $contact = Contact::getDetailsByURL($author);
-
- if (count($contact) > 0) {
- $unknown_contacts[] = [
- 'type' => 'c',
- 'photo' => ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO),
- 'name' => htmlspecialchars($contact['name']),
- 'id' => intval($contact['cid']),
- 'network' => $contact['network'],
- 'link' => $contact['url'],
- 'nick' => htmlentities(defaults($contact, 'nick', $contact['addr'])),
- 'addr' => htmlentities(defaults($contact, 'addr', $contact['url'])),
- 'forum' => $contact['forum']
- ];
- }
- }
-
- $items = array_merge($items, $unknown_contacts);
- $tot += count($unknown_contacts);
- }
-
- $results = [
- 'tot' => $tot,
- 'start' => $start,
- 'count' => $count,
- 'groups' => $groups,
- 'contacts' => $contacts,
- 'items' => $items,
- 'type' => $type,
- 'search' => $search,
- ];
-
- Hook::callAll('acl_lookup_end', $results);
-
- $o = [
- 'tot' => $results['tot'],
- 'start' => $results['start'],
- 'count' => $results['count'],
- 'items' => $results['items'],
- ];
-
- echo json_encode($o);
- exit;
-}
diff --git a/src/Core/ACL.php b/src/Core/ACL.php
index 55c174d96b..fd9bfc6e22 100644
--- a/src/Core/ACL.php
+++ b/src/Core/ACL.php
@@ -321,47 +321,4 @@ class ACL extends BaseObject
return $o;
}
-
- /**
- * Searching for global contacts for autocompletion
- *
- * @brief Searching for global contacts for autocompletion
- * @param string $search Name or part of a name or nick
- * @param string $mode Search mode (e.g. "community")
- * @param int $page Page number (starts at 1)
- * @return array with the search results
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
- */
- public static function contactAutocomplete($search, $mode, int $page = 1)
- {
- if (Config::get('system', 'block_public') && !Session::isAuthenticated()) {
- return [];
- }
-
- // don't search if search term has less than 2 characters
- if (!$search || mb_strlen($search) < 2) {
- return [];
- }
-
- if (substr($search, 0, 1) === '@') {
- $search = substr($search, 1);
- }
-
- // check if searching in the local global contact table is enabled
- if (Config::get('system', 'poco_local_search')) {
- $return = GContact::searchByName($search, $mode);
- } else {
- $p = $page > 1 ? 'p=' . $page : '';
-
- $curlResult = Network::curl(get_server() . '/lsearch?' . $p . '&search=' . urlencode($search));
- if ($curlResult->isSuccess()) {
- $lsearch = json_decode($curlResult->getBody(), true);
- if (!empty($lsearch['results'])) {
- $return = $lsearch['results'];
- }
- }
- }
-
- return $return ?? [];
- }
}
diff --git a/src/Module/Search/Acl.php b/src/Module/Search/Acl.php
new file mode 100644
index 0000000000..07cc9cdac5
--- /dev/null
+++ b/src/Module/Search/Acl.php
@@ -0,0 +1,374 @@
+ 'acl', 'action' => 'content', 'subaction' => 'search', 'search' => $search, 'type' => $type, 'conversation' => $conv_id]);
+
+ $sql_extra = '';
+ $sql_extra2 = '';
+
+ if ($search != '') {
+ $sql_extra = "AND `name` LIKE '%%" . DBA::escape($search) . "%%'";
+ $sql_extra2 = "AND (`attag` LIKE '%%" . DBA::escape($search) . "%%' OR `name` LIKE '%%" . DBA::escape($search) . "%%' OR `nick` LIKE '%%" . DBA::escape($search) . "%%')";
+ }
+
+ // count groups and contacts
+ $group_count = 0;
+ if ($type == '' || $type == 'g') {
+ $r = q("SELECT COUNT(*) AS g FROM `group` WHERE NOT `deleted` AND `uid` = %d $sql_extra",
+ intval(local_user())
+ );
+ $group_count = (int) $r[0]['g'];
+ }
+
+ $sql_extra2 .= ' ' . Widget::unavailableNetworks();
+
+ $contact_count = 0;
+ if ($type == '' || $type == 'c') {
+ // autocomplete for editor mentions
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted`
+ AND NOT `blocked` AND NOT `pending` AND NOT `archive`
+ AND `notify` != '' $sql_extra2",
+ intval(local_user())
+ );
+ $contact_count = (int) $r[0]['c'];
+ } elseif ($type == 'f') {
+ // autocomplete for editor mentions of forums
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted`
+ AND NOT `blocked` AND NOT `pending` AND NOT `archive`
+ AND (`forum` OR `prv`)
+ AND `notify` != '' $sql_extra2",
+ intval(local_user())
+ );
+ $contact_count = (int) $r[0]['c'];
+ } elseif ($type == 'm') {
+ // autocomplete for Private Messages
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted`
+ AND NOT `blocked` AND NOT `pending` AND NOT `archive`
+ AND `network` IN ('%s', '%s', '%s') $sql_extra2",
+ intval(local_user()),
+ DBA::escape(Protocol::ACTIVITYPUB),
+ DBA::escape(Protocol::DFRN),
+ DBA::escape(Protocol::DIASPORA)
+ );
+ $contact_count = (int) $r[0]['c'];
+ } elseif ($type == 'a') {
+ // autocomplete for Contacts
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND NOT `self`
+ AND NOT `pending` AND NOT `deleted` $sql_extra2",
+ intval(local_user())
+ );
+ $contact_count = (int) $r[0]['c'];
+ }
+
+ $tot = $group_count + $contact_count;
+
+ $groups = [];
+ $contacts = [];
+
+ if ($type == '' || $type == 'g') {
+ /// @todo We should cache this query.
+ // This can be done when we can delete cache entries via wildcard
+ $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
+ FROM `group`
+ INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
+ WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
+ $sql_extra
+ GROUP BY `group`.`name`, `group`.`id`
+ ORDER BY `group`.`name`
+ LIMIT %d, %d",
+ intval(local_user()),
+ intval($start),
+ intval($count)
+ );
+
+ foreach ($r as $g) {
+ $groups[] = [
+ 'type' => 'g',
+ 'photo' => 'images/twopeople.png',
+ 'name' => htmlspecialchars($g['name']),
+ 'id' => intval($g['id']),
+ 'uids' => array_map('intval', explode(',', $g['uids'])),
+ 'link' => '',
+ 'forum' => '0'
+ ];
+ }
+ if ((count($groups) > 0) && ($search == '')) {
+ $groups[] = ['separator' => true];
+ }
+ }
+
+ $r = [];
+ if ($type == '') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
+ AND NOT (`network` IN ('%s', '%s'))
+ $sql_extra2
+ ORDER BY `name`",
+ intval(local_user()),
+ DBA::escape(Protocol::OSTATUS),
+ DBA::escape(Protocol::STATUSNET)
+ );
+ } elseif ($type == 'c') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
+ AND NOT (`network` IN ('%s'))
+ $sql_extra2
+ ORDER BY `name`",
+ intval(local_user()),
+ DBA::escape(Protocol::STATUSNET)
+ );
+ } elseif ($type == 'f') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
+ AND NOT (`network` IN ('%s'))
+ AND (`forum` OR `prv`)
+ $sql_extra2
+ ORDER BY `name`",
+ intval(local_user()),
+ DBA::escape(Protocol::STATUSNET)
+ );
+ } elseif ($type == 'm') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
+ WHERE `uid` = %d AND NOT `self` AND NOT `deleted` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
+ AND `network` IN ('%s', '%s', '%s')
+ $sql_extra2
+ ORDER BY `name`",
+ intval(local_user()),
+ DBA::escape(Protocol::ACTIVITYPUB),
+ DBA::escape(Protocol::DFRN),
+ DBA::escape(Protocol::DIASPORA)
+ );
+ } elseif ($type == 'a') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
+ WHERE `uid` = %d AND NOT `deleted` AND NOT `pending` AND NOT `archive`
+ $sql_extra2
+ ORDER BY `name`",
+ intval(local_user())
+ );
+ } elseif ($type == 'x') {
+ // autocomplete for global contact search (e.g. navbar search)
+ $search = Strings::escapeTags(trim($_REQUEST['search']));
+ $mode = $_REQUEST['smode'];
+ $page = $_REQUEST['page'] ?? 1;
+
+ $r = self::contactAutocomplete($search, $mode, $page);
+
+ $contacts = [];
+ foreach ($r as $g) {
+ $contacts[] = [
+ 'photo' => ProxyUtils::proxifyUrl($g['photo'], false, ProxyUtils::SIZE_MICRO),
+ 'name' => htmlspecialchars($g['name']),
+ 'nick' => $g['addr'] ?: $g['url'],
+ 'network' => $g['network'],
+ 'link' => $g['url'],
+ 'forum' => !empty($g['community']) ? 1 : 0,
+ ];
+ }
+ $o = [
+ 'start' => $start,
+ 'count' => $count,
+ 'items' => $contacts,
+ ];
+ echo json_encode($o);
+ exit;
+ }
+
+ if (DBA::isResult($r)) {
+ $forums = [];
+ foreach ($r as $g) {
+ $entry = [
+ 'type' => 'c',
+ 'photo' => ProxyUtils::proxifyUrl($g['micro'], false, ProxyUtils::SIZE_MICRO),
+ 'name' => htmlspecialchars($g['name']),
+ 'id' => intval($g['id']),
+ 'network' => $g['network'],
+ 'link' => $g['url'],
+ 'nick' => htmlentities(defaults($g, 'attag', $g['nick'])),
+ 'addr' => htmlentities(defaults($g, 'addr', $g['url'])),
+ 'forum' => !empty($g['forum']) || !empty($g['prv']) ? 1 : 0,
+ ];
+ if ($entry['forum']) {
+ $forums[] = $entry;
+ } else {
+ $contacts[] = $entry;
+ }
+ }
+ if (count($forums) > 0) {
+ if ($search == '') {
+ $forums[] = ['separator' => true];
+ }
+ $contacts = array_merge($forums, $contacts);
+ }
+ }
+
+ $items = array_merge($groups, $contacts);
+
+ if ($conv_id) {
+ // In multi threaded posts the conv_id is not the parent of the whole thread
+ $parent_item = Item::selectFirst(['parent'], ['id' => $conv_id]);
+ if (DBA::isResult($parent_item)) {
+ $conv_id = $parent_item['parent'];
+ }
+
+ /*
+ * if $conv_id is set, get unknown contacts in thread
+ * but first get known contacts url to filter them out
+ */
+ $known_contacts = array_map(function ($i) {
+ return $i['link'];
+ }, $contacts);
+
+ $unknown_contacts = [];
+
+ $condition = ["`parent` = ?", $conv_id];
+ $params = ['order' => ['author-name' => true]];
+ $authors = Item::selectForUser(local_user(), ['author-link'], $condition, $params);
+ $item_authors = [];
+ while ($author = Item::fetch($authors)) {
+ $item_authors[$author['author-link']] = $author['author-link'];
+ }
+ DBA::close($authors);
+
+ foreach ($item_authors as $author) {
+ if (in_array($author, $known_contacts)) {
+ continue;
+ }
+
+ $contact = Contact::getDetailsByURL($author);
+
+ if (count($contact) > 0) {
+ $unknown_contacts[] = [
+ 'type' => 'c',
+ 'photo' => ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO),
+ 'name' => htmlspecialchars($contact['name']),
+ 'id' => intval($contact['cid']),
+ 'network' => $contact['network'],
+ 'link' => $contact['url'],
+ 'nick' => htmlentities(defaults($contact, 'nick', $contact['addr'])),
+ 'addr' => htmlentities(defaults($contact, 'addr', $contact['url'])),
+ 'forum' => $contact['forum']
+ ];
+ }
+ }
+
+ $items = array_merge($items, $unknown_contacts);
+ $tot += count($unknown_contacts);
+ }
+
+ $results = [
+ 'tot' => $tot,
+ 'start' => $start,
+ 'count' => $count,
+ 'groups' => $groups,
+ 'contacts' => $contacts,
+ 'items' => $items,
+ 'type' => $type,
+ 'search' => $search,
+ ];
+
+ Hook::callAll('acl_lookup_end', $results);
+
+ $o = [
+ 'tot' => $results['tot'],
+ 'start' => $results['start'],
+ 'count' => $results['count'],
+ 'items' => $results['items'],
+ ];
+
+ echo json_encode($o);
+ exit;
+ }
+
+
+ /**
+ * Searching for global contacts for autocompletion
+ *
+ * @brief Searching for global contacts for autocompletion
+ * @param string $search Name or part of a name or nick
+ * @param string $mode Search mode (e.g. "community")
+ * @param int $page Page number (starts at 1)
+ * @return array with the search results
+ * @throws HTTPException\InternalServerErrorException
+ */
+ private static function contactAutocomplete($search, $mode, int $page = 1)
+ {
+ if (Config::get('system', 'block_public') && !Session::isAuthenticated()) {
+ return [];
+ }
+
+ // don't search if search term has less than 2 characters
+ if (!$search || mb_strlen($search) < 2) {
+ return [];
+ }
+
+ if (substr($search, 0, 1) === '@') {
+ $search = substr($search, 1);
+ }
+
+ // check if searching in the local global contact table is enabled
+ if (Config::get('system', 'poco_local_search')) {
+ $return = GContact::searchByName($search, $mode);
+ } else {
+ $p = $page > 1 ? 'p=' . $page : '';
+
+ $curlResult = Network::curl(get_server() . '/lsearch?' . $p . '&search=' . urlencode($search));
+ if ($curlResult->isSuccess()) {
+ $lsearch = json_decode($curlResult->getBody(), true);
+ if (!empty($lsearch['results'])) {
+ $return = $lsearch['results'];
+ }
+ }
+ }
+
+ return $return ?? [];
+ }
+}
diff --git a/static/routes.config.php b/static/routes.config.php
index c1546a634c..1ba4a40521 100644
--- a/static/routes.config.php
+++ b/static/routes.config.php
@@ -188,6 +188,10 @@ return [
'/{sub1}/{sub2}/{url}' => [Module\Proxy::class, [R::GET]],
],
+ '/search' => [
+ '/acl' => [Module\Search\Acl::class, [R::GET, R::POST]],
+ ],
+
'/settings' => [
'/2fa' => [
'[/]' => [Module\Settings\TwoFactor\Index::class, [R::GET, R::POST]],
diff --git a/view/js/main.js b/view/js/main.js
index 8b1303e7d3..e2cee43d54 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -466,7 +466,7 @@ function updateConvItems(data) {
$('body').css('cursor', 'auto');
}
/* autocomplete @nicknames */
- $(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
+ $(".comment-edit-form textarea").editor_autocomplete(baseurl + '/search/acl');
/* autocomplete bbcode */
$(".comment-edit-form textarea").bbco_autocomplete('bbcode');
}
diff --git a/view/templates/acl_selector.tpl b/view/templates/acl_selector.tpl
index da86a478bf..58a0f483b8 100644
--- a/view/templates/acl_selector.tpl
+++ b/view/templates/acl_selector.tpl
@@ -48,7 +48,7 @@
$(document).ready(function() {
if(typeof acl=="undefined"){
acl = new ACL(
- baseurl+"/acl",
+ baseurl + '/search/acl',
[ {{$allowcid nofilter}},{{$allowgid nofilter}},{{$denycid nofilter}},{{$denygid nofilter}} ],
{{$features.aclautomention}},
{{if $APP->is_mobile}}true{{else}}false{{/if}}
diff --git a/view/templates/contacts-head.tpl b/view/templates/contacts-head.tpl
index ea562233f4..e10491b376 100644
--- a/view/templates/contacts-head.tpl
+++ b/view/templates/contacts-head.tpl
@@ -1,7 +1,7 @@
diff --git a/view/templates/display-head.tpl b/view/templates/display-head.tpl
index b0f0a828e7..aafa0d6988 100644
--- a/view/templates/display-head.tpl
+++ b/view/templates/display-head.tpl
@@ -6,8 +6,8 @@
{{/if}}
diff --git a/view/templates/item/compose-footer.tpl b/view/templates/item/compose-footer.tpl
index 9e950b98d2..7e18d18ff7 100644
--- a/view/templates/item/compose-footer.tpl
+++ b/view/templates/item/compose-footer.tpl
@@ -24,7 +24,7 @@
var textlen = $(this).val().length;
$('#character-counter').text(textlen);
});
- $textarea.editor_autocomplete(baseurl+"/acl");
+ $textarea.editor_autocomplete(baseurl + '/search/acl');
$textarea.bbco_autocomplete('bbcode');
let $acl_allow_input = $('#acl_allow');
diff --git a/view/templates/jot-header.tpl b/view/templates/jot-header.tpl
index f169b09212..0d2ad6f6f6 100644
--- a/view/templates/jot-header.tpl
+++ b/view/templates/jot-header.tpl
@@ -19,7 +19,7 @@ function initEditor(callback) {
$("#profile-jot-text-loading").show();
$("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
- $("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
+ $("#profile-jot-text").editor_autocomplete(baseurl + '/search/acl');
$("#profile-jot-text").bbco_autocomplete('bbcode');
$("a#jot-perms-icon").colorbox(colorbox_options);
$(".jothidden").show();
diff --git a/view/templates/message-head.tpl b/view/templates/message-head.tpl
index 3fabebc0d2..fe71bc425b 100644
--- a/view/templates/message-head.tpl
+++ b/view/templates/message-head.tpl
@@ -1,7 +1,7 @@
diff --git a/view/theme/smoothly/templates/jot-header.tpl b/view/theme/smoothly/templates/jot-header.tpl
index b549f1840d..f30f34a899 100644
--- a/view/theme/smoothly/templates/jot-header.tpl
+++ b/view/theme/smoothly/templates/jot-header.tpl
@@ -10,7 +10,7 @@ function initEditor(callback) {
$("#profile-jot-text-loading").show();
$("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
- $("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
+ $("#profile-jot-text").editor_autocomplete(baseurl + '/search/acl');
$("#profile-jot-text").bbco_autocomplete('bbcode');
$(".jothidden").show();
$("a#jot-perms-icon").colorbox({
diff --git a/view/theme/vier/templates/nav_head.tpl b/view/theme/vier/templates/nav_head.tpl
index ff1b96fae8..b92573f381 100644
--- a/view/theme/vier/templates/nav_head.tpl
+++ b/view/theme/vier/templates/nav_head.tpl
@@ -1,6 +1,6 @@