3 /* ACL selector json backend */
6 use Friendica\Content\Widget;
7 use Friendica\Core\Addon;
8 use Friendica\Database\DBM;
9 use Friendica\Model\Contact;
11 require_once 'include/acl_selectors.php';
12 require_once 'include/dba.php';
13 require_once 'mod/proxy.php';
15 function acl_content(App $a)
21 $start = defaults($_REQUEST, 'start', 0);
22 $count = defaults($_REQUEST, 'count', 100);
23 $search = defaults($_REQUEST, 'search', '');
24 $type = defaults($_REQUEST, 'type', '');
25 $conv_id = defaults($_REQUEST, 'conversation', null);
27 // For use with jquery.textcomplete for private mail completion
28 if (x($_REQUEST, 'query')) {
32 $search = $_REQUEST['query'];
35 logger('Searching for ' . $search . ' - type ' . $type, LOGGER_DEBUG);
38 $sql_extra = "AND `name` LIKE '%%" . dbesc($search) . "%%'";
39 $sql_extra2 = "AND (`attag` LIKE '%%" . dbesc($search) . "%%' OR `name` LIKE '%%" . dbesc($search) . "%%' OR `nick` LIKE '%%" . dbesc($search) . "%%')";
41 /// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
42 $sql_extra = $sql_extra2 = '';
45 // count groups and contacts
46 if ($type == '' || $type == 'g') {
47 $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
50 $group_count = (int) $r[0]['g'];
55 $sql_extra2 .= ' ' . Widget::unavailableNetworks();
57 if ($type == '' || $type == 'c') {
58 // autocomplete for editor mentions
59 $r = q("SELECT COUNT(*) AS c FROM `contact`
60 WHERE `uid` = %d AND NOT `self`
61 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
62 AND `success_update` >= `failure_update`
63 AND `notify` != '' $sql_extra2",
66 $contact_count = (int) $r[0]['c'];
67 } elseif ($type == 'f') {
68 // autocomplete for editor mentions of forums
69 $r = q("SELECT COUNT(*) AS c FROM `contact`
70 WHERE `uid` = %d AND NOT `self`
71 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
72 AND (`forum` OR `prv`)
73 AND `success_update` >= `failure_update`
74 AND `notify` != '' $sql_extra2",
77 $contact_count = (int) $r[0]['c'];
78 } elseif ($type == 'm') {
79 // autocomplete for Private Messages
80 $r = q("SELECT COUNT(*) AS c FROM `contact`
81 WHERE `uid` = %d AND NOT `self`
82 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
83 AND `success_update` >= `failure_update`
84 AND `network` IN ('%s', '%s') $sql_extra2",
87 dbesc(NETWORK_DIASPORA)
89 $contact_count = (int) $r[0]['c'];
90 } elseif ($type == 'a') {
91 // autocomplete for Contacts
92 $r = q("SELECT COUNT(*) AS c FROM `contact`
93 WHERE `uid` = %d AND NOT `self`
94 AND NOT `pending` $sql_extra2",
97 $contact_count = (int) $r[0]['c'];
102 $tot = $group_count + $contact_count;
107 if ($type == '' || $type == 'g') {
108 /// @todo We should cache this query.
109 // This can be done when we can delete cache entries via wildcard
110 $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
112 INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
113 WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
115 GROUP BY `group`.`name`, `group`.`id`
116 ORDER BY `group`.`name`
118 intval(local_user()),
126 'photo' => 'images/twopeople.png',
127 'name' => htmlentities($g['name']),
128 'id' => intval($g['id']),
129 'uids' => array_map('intval', explode(',', $g['uids'])),
134 if ((count($groups) > 0) && ($search == '')) {
135 $groups[] = ['separator' => true];
140 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
141 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
142 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s'))
144 ORDER BY `name` ASC ",
145 intval(local_user()),
146 dbesc(NETWORK_OSTATUS),
147 dbesc(NETWORK_STATUSNET)
149 } elseif ($type == 'c') {
150 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
151 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
152 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
154 ORDER BY `name` ASC ",
155 intval(local_user()),
156 dbesc(NETWORK_STATUSNET)
158 } elseif ($type == 'f') {
159 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
160 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
161 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
162 AND (`forum` OR `prv`)
164 ORDER BY `name` ASC ",
165 intval(local_user()),
166 dbesc(NETWORK_STATUSNET)
168 } elseif ($type == 'm') {
169 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
170 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
171 AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s')
173 ORDER BY `name` ASC ",
174 intval(local_user()),
176 dbesc(NETWORK_DIASPORA)
178 } elseif ($type == 'a') {
179 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
180 WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update`
182 ORDER BY `name` ASC ",
185 } elseif ($type == 'x') {
186 // autocomplete for global contact search (e.g. navbar search)
187 $r = navbar_complete($a);
191 'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
192 'name' => $g['name'],
193 'nick' => (x($g['addr']) ? $g['addr'] : $g['url']),
194 'network' => $g['network'],
196 'forum' => (x($g['community']) ? 1 : 0),
202 'items' => $contacts,
204 echo json_encode($o);
210 if (DBM::is_result($r)) {
215 'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
216 'name' => htmlentities($g['name']),
217 'id' => intval($g['id']),
218 'network' => $g['network'],
220 'nick' => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
221 'addr' => htmlentities(($g['addr']) ? $g['addr'] : $g['url']),
222 'forum' => ((x($g, 'forum') || x($g, 'prv')) ? 1 : 0),
224 if ($entry['forum']) {
227 $contacts[] = $entry;
230 if (count($forums) > 0) {
232 $forums[] = ['separator' => true];
234 $contacts = array_merge($forums, $contacts);
238 $items = array_merge($groups, $contacts);
242 * if $conv_id is set, get unknown contacts in thread
243 * but first get known contacts url to filter them out
245 $known_contacts = array_map(function ($i) {
246 return dbesc($i['link']);
249 $unknown_contacts = [];
250 $r = q("SELECT `author-link`
251 FROM `item` WHERE `parent` = %d
252 AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
253 AND `author-link` NOT IN ('%s')
254 GROUP BY `author-link`, `author-avatar`, `author-name`
255 ORDER BY `author-name` ASC
260 implode("', '", $known_contacts)
262 if (DBM::is_result($r)) {
263 foreach ($r as $row) {
264 $contact = Contact::getDetailsByURL($row['author-link']);
266 if (count($contact) > 0) {
267 $unknown_contacts[] = [
269 'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
270 'name' => htmlentities($contact['name']),
271 'id' => intval($contact['cid']),
272 'network' => $contact['network'],
273 'link' => $contact['url'],
274 'nick' => htmlentities($contact['nick'] ?: $contact['addr']),
275 'addr' => htmlentities(($contact['addr']) ? $contact['addr'] : $contact['url']),
276 'forum' => $contact['forum']
282 $items = array_merge($items, $unknown_contacts);
283 $tot += count($unknown_contacts);
291 'contacts' => $contacts,
297 Addon::callHooks('acl_lookup_end', $results);
300 'tot' => $results['tot'],
301 'start' => $results['start'],
302 'count' => $results['count'],
303 'items' => $results['items'],
306 echo json_encode($o);