3 /* ACL selector json backend */
6 use Friendica\Content\Widget;
7 use Friendica\Core\ACL;
8 use Friendica\Core\Addon;
9 use Friendica\Database\DBM;
10 use Friendica\Model\Contact;
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 (!empty($_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
47 if ($type == '' || $type == 'g') {
48 $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
51 $group_count = (int) $r[0]['g'];
54 $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'];
100 $tot = $group_count + $contact_count;
105 if ($type == '' || $type == 'g') {
106 /// @todo We should cache this query.
107 // This can be done when we can delete cache entries via wildcard
108 $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
110 INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
111 WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
113 GROUP BY `group`.`name`, `group`.`id`
114 ORDER BY `group`.`name`
116 intval(local_user()),
124 'photo' => 'images/twopeople.png',
125 'name' => htmlentities($g['name']),
126 'id' => intval($g['id']),
127 'uids' => array_map('intval', explode(',', $g['uids'])),
132 if ((count($groups) > 0) && ($search == '')) {
133 $groups[] = ['separator' => true];
139 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
140 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
141 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s'))
143 ORDER BY `name` ASC ",
144 intval(local_user()),
145 dbesc(NETWORK_OSTATUS),
146 dbesc(NETWORK_STATUSNET)
148 } elseif ($type == 'c') {
149 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
150 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
151 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
153 ORDER BY `name` ASC ",
154 intval(local_user()),
155 dbesc(NETWORK_STATUSNET)
157 } elseif ($type == 'f') {
158 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
159 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
160 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
161 AND (`forum` OR `prv`)
163 ORDER BY `name` ASC ",
164 intval(local_user()),
165 dbesc(NETWORK_STATUSNET)
167 } elseif ($type == 'm') {
168 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
169 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
170 AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s')
172 ORDER BY `name` ASC ",
173 intval(local_user()),
175 dbesc(NETWORK_DIASPORA)
177 } elseif ($type == 'a') {
178 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
179 WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update`
181 ORDER BY `name` ASC ",
184 } elseif ($type == 'x') {
185 // autocomplete for global contact search (e.g. navbar search)
186 $search = notags(trim($_REQUEST['search']));
187 $mode = $_REQUEST['smode'];
189 $r = ACL::contactAutocomplete($search, $mode);
194 'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
195 'name' => $g['name'],
196 'nick' => defaults($g, 'addr', $g['url']),
197 'network' => $g['network'],
199 'forum' => !empty($g['community']) ? 1 : 0,
205 'items' => $contacts,
207 echo json_encode($o);
211 if (DBM::is_result($r)) {
216 'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
217 'name' => htmlentities($g['name']),
218 'id' => intval($g['id']),
219 'network' => $g['network'],
221 'nick' => htmlentities(defaults($g, 'attag', $g['nick'])),
222 'addr' => htmlentities(defaults($g, 'addr', $g['url'])),
223 'forum' => !empty($g['forum']) || !empty($g['prv']) ? 1 : 0,
225 if ($entry['forum']) {
228 $contacts[] = $entry;
231 if (count($forums) > 0) {
233 $forums[] = ['separator' => true];
235 $contacts = array_merge($forums, $contacts);
239 $items = array_merge($groups, $contacts);
243 * if $conv_id is set, get unknown contacts in thread
244 * but first get known contacts url to filter them out
246 $known_contacts = array_map(function ($i) {
247 return dbesc($i['link']);
250 $unknown_contacts = [];
251 $r = q("SELECT `author-link`
252 FROM `item` WHERE `parent` = %d
253 AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
254 AND `author-link` NOT IN ('%s')
255 GROUP BY `author-link`, `author-avatar`, `author-name`
256 ORDER BY `author-name` ASC
261 implode("', '", $known_contacts)
263 if (DBM::is_result($r)) {
264 foreach ($r as $row) {
265 $contact = Contact::getDetailsByURL($row['author-link']);
267 if (count($contact) > 0) {
268 $unknown_contacts[] = [
270 'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
271 'name' => htmlentities($contact['name']),
272 'id' => intval($contact['cid']),
273 'network' => $contact['network'],
274 'link' => $contact['url'],
275 'nick' => htmlentities(defaults($contact, 'nick', $contact['addr'])),
276 'addr' => htmlentities(defaults($contact, 'addr', $contact['url'])),
277 'forum' => $contact['forum']
283 $items = array_merge($items, $unknown_contacts);
284 $tot += count($unknown_contacts);
292 'contacts' => $contacts,
298 Addon::callHooks('acl_lookup_end', $results);
301 'tot' => $results['tot'],
302 'start' => $results['start'],
303 'count' => $results['count'],
304 'items' => $results['items'],
307 echo json_encode($o);