3 /* ACL selector json backend */
6 use Friendica\Content\Widget;
7 use Friendica\Core\ACL;
8 use Friendica\Core\Addon;
9 use Friendica\Core\Protocol;
10 use Friendica\Database\DBA;
11 use Friendica\Model\Contact;
12 use Friendica\Model\Item;
13 use Friendica\Util\Proxy as ProxyUtils;
15 require_once 'include/dba.php';
17 function acl_content(App $a)
23 $start = defaults($_REQUEST, 'start' , 0);
24 $count = defaults($_REQUEST, 'count' , 100);
25 $search = defaults($_REQUEST, 'search' , '');
26 $type = defaults($_REQUEST, 'type' , '');
27 $conv_id = defaults($_REQUEST, 'conversation', null);
29 // For use with jquery.textcomplete for private mail completion
30 if (!empty($_REQUEST['query'])) {
34 $search = $_REQUEST['query'];
37 logger("Searching for ".$search." - type ".$type." conversation ".$conv_id, LOGGER_DEBUG);
40 $sql_extra = "AND `name` LIKE '%%" . DBA::escape($search) . "%%'";
41 $sql_extra2 = "AND (`attag` LIKE '%%" . DBA::escape($search) . "%%' OR `name` LIKE '%%" . DBA::escape($search) . "%%' OR `nick` LIKE '%%" . DBA::escape($search) . "%%')";
43 /// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
44 $sql_extra = $sql_extra2 = '';
47 // count groups and contacts
49 if ($type == '' || $type == 'g') {
50 $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
53 $group_count = (int) $r[0]['g'];
56 $sql_extra2 .= ' ' . Widget::unavailableNetworks();
59 if ($type == '' || $type == 'c') {
60 // autocomplete for editor mentions
61 $r = q("SELECT COUNT(*) AS c FROM `contact`
62 WHERE `uid` = %d AND NOT `self`
63 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
64 AND `success_update` >= `failure_update`
65 AND `notify` != '' $sql_extra2",
68 $contact_count = (int) $r[0]['c'];
69 } elseif ($type == 'f') {
70 // autocomplete for editor mentions of forums
71 $r = q("SELECT COUNT(*) AS c FROM `contact`
72 WHERE `uid` = %d AND NOT `self`
73 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
74 AND (`forum` OR `prv`)
75 AND `success_update` >= `failure_update`
76 AND `notify` != '' $sql_extra2",
79 $contact_count = (int) $r[0]['c'];
80 } elseif ($type == 'm') {
81 // autocomplete for Private Messages
82 $r = q("SELECT COUNT(*) AS c FROM `contact`
83 WHERE `uid` = %d AND NOT `self`
84 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
85 AND `success_update` >= `failure_update`
86 AND `network` IN ('%s', '%s') $sql_extra2",
88 DBA::escape(Protocol::DFRN),
89 DBA::escape(Protocol::DIASPORA)
91 $contact_count = (int) $r[0]['c'];
92 } elseif ($type == 'a') {
93 // autocomplete for Contacts
94 $r = q("SELECT COUNT(*) AS c FROM `contact`
95 WHERE `uid` = %d AND NOT `self`
96 AND NOT `pending` $sql_extra2",
99 $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];
141 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
142 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
143 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s'))
145 ORDER BY `name` ASC ",
146 intval(local_user()),
147 DBA::escape(Protocol::OSTATUS),
148 DBA::escape(Protocol::STATUSNET)
150 } elseif ($type == 'c') {
151 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
152 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
153 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
155 ORDER BY `name` ASC ",
156 intval(local_user()),
157 DBA::escape(Protocol::STATUSNET)
159 } elseif ($type == 'f') {
160 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
161 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
162 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
163 AND (`forum` OR `prv`)
165 ORDER BY `name` ASC ",
166 intval(local_user()),
167 DBA::escape(Protocol::STATUSNET)
169 } elseif ($type == 'm') {
170 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
171 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
172 AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s')
174 ORDER BY `name` ASC ",
175 intval(local_user()),
176 DBA::escape(Protocol::DFRN),
177 DBA::escape(Protocol::DIASPORA)
179 } elseif ($type == 'a') {
180 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
181 WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update`
183 ORDER BY `name` ASC ",
186 } elseif ($type == 'x') {
187 // autocomplete for global contact search (e.g. navbar search)
188 $search = notags(trim($_REQUEST['search']));
189 $mode = $_REQUEST['smode'];
191 $r = ACL::contactAutocomplete($search, $mode);
196 'photo' => ProxyUtils::proxifyUrl($g['photo'], false, ProxyUtils::SIZE_MICRO),
197 'name' => $g['name'],
198 'nick' => defaults($g, 'addr', $g['url']),
199 'network' => $g['network'],
201 'forum' => !empty($g['community']) ? 1 : 0,
207 'items' => $contacts,
209 echo json_encode($o);
213 if (DBA::isResult($r)) {
218 'photo' => ProxyUtils::proxifyUrl($g['micro'], false, ProxyUtils::SIZE_MICRO),
219 'name' => htmlentities($g['name']),
220 'id' => intval($g['id']),
221 'network' => $g['network'],
223 'nick' => htmlentities(defaults($g, 'attag', $g['nick'])),
224 'addr' => htmlentities(defaults($g, 'addr', $g['url'])),
225 'forum' => !empty($g['forum']) || !empty($g['prv']) ? 1 : 0,
227 if ($entry['forum']) {
230 $contacts[] = $entry;
233 if (count($forums) > 0) {
235 $forums[] = ['separator' => true];
237 $contacts = array_merge($forums, $contacts);
241 $items = array_merge($groups, $contacts);
244 // In multi threaded posts the conv_id is not the parent of the whole thread
245 $parent_item = Item::selectFirst(['parent'], ['id' => $conv_id]);
246 if (DBA::isResult($parent_item)) {
247 $conv_id = $parent_item['parent'];
251 * if $conv_id is set, get unknown contacts in thread
252 * but first get known contacts url to filter them out
254 $known_contacts = array_map(function ($i) {
258 $unknown_contacts = [];
260 $condition = ["`parent` = ?", $conv_id];
261 $params = ['order' => ['author-name' => true]];
262 $authors = Item::selectForUser(local_user(), ['author-link'], $condition, $params);
264 while ($author = Item::fetch($authors)) {
265 $item_authors[$author['author-link']] = $author['author-link'];
267 DBA::close($authors);
269 foreach ($item_authors as $author) {
270 if (in_array($author, $known_contacts)) {
274 $contact = Contact::getDetailsByURL($author);
276 if (count($contact) > 0) {
277 $unknown_contacts[] = [
279 'photo' => ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO),
280 'name' => htmlentities($contact['name']),
281 'id' => intval($contact['cid']),
282 'network' => $contact['network'],
283 'link' => $contact['url'],
284 'nick' => htmlentities(defaults($contact, 'nick', $contact['addr'])),
285 'addr' => htmlentities(defaults($contact, 'addr', $contact['url'])),
286 'forum' => $contact['forum']
291 $items = array_merge($items, $unknown_contacts);
292 $tot += count($unknown_contacts);
300 'contacts' => $contacts,
306 Addon::callHooks('acl_lookup_end', $results);
309 'tot' => $results['tot'],
310 'start' => $results['start'],
311 'count' => $results['count'],
312 'items' => $results['items'],
315 echo json_encode($o);