diff --git a/include/acl_selectors.php b/include/acl_selectors.php deleted file mode 100644 index e69ac36f68..0000000000 --- a/include/acl_selectors.php +++ /dev/null @@ -1,747 +0,0 @@ -\r\n"; - - $r = q("SELECT `id`, `name` FROM `group` WHERE NOT `deleted` AND `uid` = %d ORDER BY `name` ASC", - intval(local_user()) - ); - - - $arr = ['group' => $r, 'entry' => $o]; - - // e.g. 'network_pre_group_deny', 'profile_pre_group_allow' - - Addon::callHooks($a->module . '_pre_' . $selname, $arr); - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - if ((is_array($preselected)) && in_array($rr['id'], $preselected)) { - $selected = " selected=\"selected\" "; - } else { - $selected = ''; - } - - $trimmed = mb_substr($rr['name'],0,12); - - $o .= "\r\n"; - } - - } - $o .= "\r\n"; - - Addon::callHooks($a->module . '_post_' . $selname, $o); - - - return $o; -} - -/// @TODO find proper type-hints -function contact_selector($selname, $selclass, $options, $preselected = false) -{ - $a = get_app(); - - $mutual = false; - $networks = null; - $single = false; - $exclude = false; - $size = 4; - - if (is_array($options)) { - if (x($options, 'size')) - $size = $options['size']; - - if (x($options, 'mutual_friends')) { - $mutual = true; - } - if (x($options, 'single')) { - $single = true; - } - if (x($options, 'multiple')) { - $single = false; - } - if (x($options, 'exclude')) { - $exclude = $options['exclude']; - } - - if (x($options, 'networks')) { - switch ($options['networks']) { - case 'DFRN_ONLY': - $networks = [NETWORK_DFRN]; - break; - case 'PRIVATE': - if (is_array($a->user) && $a->user['prvnets']) { - $networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA]; - } else { - $networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA]; - } - break; - case 'TWO_WAY': - if (is_array($a->user) && $a->user['prvnets']) { - $networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA]; - } else { - $networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA, NETWORK_OSTATUS]; - } - break; - default: /// @TODO Maybe log this call? - break; - } - } - } - - $x = ['options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks]; - - Addon::callHooks('contact_select_options', $x); - - $o = ''; - - $sql_extra = ''; - - if (x($x, 'mutual')) { - $sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND)); - } - - if (x($x, 'exclude')) { - $sql_extra .= sprintf(" AND `id` != %d ", intval($x['exclude'])); - } - - if (is_array($x['networks']) && count($x['networks'])) { - /// @TODO rewrite to foreach() - for ($y = 0; $y < count($x['networks']) ; $y ++) { - $x['networks'][$y] = "'" . dbesc($x['networks'][$y]) . "'"; - } - $str_nets = implode(',', $x['networks']); - $sql_extra .= " AND `network` IN ( $str_nets ) "; - } - - $tabindex = (x($options, 'tabindex') ? "tabindex=\"" . $options["tabindex"] . "\"" : ""); - - if ($x['single']) { - $o .= "\r\n"; - } - - $r = q("SELECT `id`, `name`, `url`, `network` FROM `contact` - WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' - $sql_extra - ORDER BY `name` ASC ", - intval(local_user()) - ); - - - $arr = ['contact' => $r, 'entry' => $o]; - - // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow' - - Addon::callHooks($a->module . '_pre_' . $selname, $arr); - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - if ((is_array($preselected)) && in_array($rr['id'], $preselected)) { - $selected = " selected=\"selected\" "; - } else { - $selected = ''; - } - - $trimmed = mb_substr($rr['name'],0,20); - - $o .= "\r\n"; - } - - } - - $o .= "\r\n"; - - Addon::callHooks($a->module . '_post_' . $selname, $o); - - return $o; -} - - - -function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false, $privatenet = false, $tabindex = null) { - $a = get_app(); - - $o = ''; - - // When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector - // to one recipient. By default our selector allows multiple selects amongst all contacts. - - $sql_extra = ''; - - if ($privmail || $celeb) { - $sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND)); - } - - if ($privmail) { - $sql_extra .= sprintf(" AND `network` IN ('%s' , '%s') ", - NETWORK_DFRN, NETWORK_DIASPORA); - } elseif ($privatenet) { - $sql_extra .= sprintf(" AND `network` IN ('%s' , '%s', '%s', '%s') ", - NETWORK_DFRN, NETWORK_MAIL, NETWORK_FACEBOOK, NETWORK_DIASPORA); - } - - $tabindex = ($tabindex > 0 ? "tabindex=\"$tabindex\"" : ""); - - if ($privmail && $preselected) { - $sql_extra .= " AND `id` IN (".implode(",", $preselected).")"; - $hidepreselected = ' style="display: none;"'; - } else { - $hidepreselected = ""; - } - - if ($privmail) { - $o .= "\r\n"; - } - - $r = q("SELECT `id`, `name`, `url`, `network` FROM `contact` - WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' - $sql_extra - ORDER BY `name` ASC ", - intval(local_user()) - ); - - - $arr = ['contact' => $r, 'entry' => $o]; - - // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow' - - Addon::callHooks($a->module . '_pre_' . $selname, $arr); - - $receiverlist = []; - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - if ((is_array($preselected)) && in_array($rr['id'], $preselected)) { - $selected = " selected=\"selected\" "; - } else { - $selected = ''; - } - - if ($privmail) { - $trimmed = Protocol::formatMention($rr['url'], $rr['name']); - } else { - $trimmed = mb_substr($rr['name'],0,20); - } - - $receiverlist[] = $trimmed; - - $o .= "\r\n"; - } - - } - - $o .= "\r\n"; - - if ($privmail && $preselected) { - $o .= implode(", ", $receiverlist); - } - - Addon::callHooks($a->module . '_post_' . $selname, $o); - - return $o; -} - - -function fixacl(&$item) { - $item = intval(str_replace(['<', '>'], ['', ''], $item)); -} - -function prune_deadguys($arr) { - - if (! $arr) { - return $arr; - } - - $str = dbesc(implode(',', $arr)); - - $r = q("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 "); - - if (DBM::is_result($r)) { - $ret = []; - foreach ($r as $rr) { - $ret[] = intval($rr['id']); - } - return $ret; - } - - return []; -} - - -function get_acl_permissions($user = null) { - $allow_cid = $allow_gid = $deny_cid = $deny_gid = false; - - if (is_array($user)) { - $allow_cid = ((strlen($user['allow_cid'])) - ? explode('><', $user['allow_cid']) : [] ); - $allow_gid = ((strlen($user['allow_gid'])) - ? explode('><', $user['allow_gid']) : [] ); - $deny_cid = ((strlen($user['deny_cid'])) - ? explode('><', $user['deny_cid']) : [] ); - $deny_gid = ((strlen($user['deny_gid'])) - ? explode('><', $user['deny_gid']) : [] ); - array_walk($allow_cid,'fixacl'); - array_walk($allow_gid,'fixacl'); - array_walk($deny_cid,'fixacl'); - array_walk($deny_gid,'fixacl'); - } - - $allow_cid = prune_deadguys($allow_cid); - - return [ - 'allow_cid' => $allow_cid, - 'allow_gid' => $allow_gid, - 'deny_cid' => $deny_cid, - 'deny_gid' => $deny_gid, - ]; -} - - -function populate_acl($user = null, $show_jotnets = false) { - - $perms = get_acl_permissions($user); - - $jotnets = ''; - if ($show_jotnets) { - $mail_disabled = ((function_exists('imap_open') && (! Config::get('system','imap_disabled'))) ? 0 : 1); - - $mail_enabled = false; - $pubmail_enabled = false; - - if (! $mail_disabled) { - $r = q("SELECT `pubmail` FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", - intval(local_user()) - ); - if (DBM::is_result($r)) { - $mail_enabled = true; - if (intval($r[0]['pubmail'])) { - $pubmail_enabled = true; - } - } - } - - if (!$user['hidewall']) { - if ($mail_enabled) { - $selected = (($pubmail_enabled) ? ' checked="checked" ' : ''); - $jotnets .= '
' . L10n::t("Post to Email") . '
'; - } - - Addon::callHooks('jot_networks', $jotnets); - } else { - $jotnets .= L10n::t('Connectors disabled, since "%s" is enabled.', L10n::t('Hide your profile details from unknown viewers?')); - } - } - - $tpl = get_markup_template("acl_selector.tpl"); - $o = replace_macros($tpl, [ - '$showall'=> L10n::t("Visible to everybody"), - '$show' => L10n::t("show"), - '$hide' => L10n::t("don't show"), - '$allowcid' => json_encode($perms['allow_cid']), - '$allowgid' => json_encode($perms['allow_gid']), - '$denycid' => json_encode($perms['deny_cid']), - '$denygid' => json_encode($perms['deny_gid']), - '$networks' => $show_jotnets, - '$emailcc' => L10n::t('CC: email addresses'), - '$emtitle' => L10n::t('Example: bob@example.com, mary@example.com'), - '$jotnets' => $jotnets, - '$aclModalTitle' => L10n::t('Permissions'), - '$aclModalDismiss' => L10n::t('Close'), - '$features' => [ - 'aclautomention' => (Feature::isEnabled($user['uid'], "aclautomention") ? "true" : "false") - ], - ]); - - - return $o; - -} - -function acl_lookup(App $a, $out_type = 'json') -{ - if (!local_user()) { - return ''; - } - - $start = defaults($_REQUEST, 'start' , 0); - $count = defaults($_REQUEST, 'count' , 100); - $search = defaults($_REQUEST, 'search' , ''); - $type = defaults($_REQUEST, 'type' , ''); - $conv_id = defaults($_REQUEST, 'conversation', null); - - // For use with jquery.textcomplete for private mail completion - if (x($_REQUEST, 'query')) { - if (! $type) { - $type = 'm'; - } - $search = $_REQUEST['query']; - } - - logger("Searching for ".$search." - type ".$type, LOGGER_DEBUG); - - if ($search != '') { - $sql_extra = "AND `name` LIKE '%%".dbesc($search)."%%'"; - $sql_extra2 = "AND (`attag` LIKE '%%".dbesc($search)."%%' OR `name` LIKE '%%".dbesc($search)."%%' OR `nick` LIKE '%%".dbesc($search)."%%')"; - } else { - /// @TODO Avoid these needless else blocks by putting variable-initialization atop of if() - $sql_extra = $sql_extra2 = ""; - } - - // count groups and contacts - if ($type == '' || $type == 'g') { - $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra", - intval(local_user()) - ); - $group_count = (int)$r[0]['g']; - } else { - $group_count = 0; - } - - $sql_extra2 .= " ".Widget::unavailableNetworks(); - - if ($type == '' || $type == 'c') { - // autocomplete for editor mentions - $r = q("SELECT COUNT(*) AS c FROM `contact` - WHERE `uid` = %d AND NOT `self` - AND NOT `blocked` AND NOT `pending` AND NOT `archive` - AND `success_update` >= `failure_update` - 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 `blocked` AND NOT `pending` AND NOT `archive` - AND (`forum` OR `prv`) - AND `success_update` >= `failure_update` - 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 `blocked` AND NOT `pending` AND NOT `archive` - AND `success_update` >= `failure_update` - AND `network` IN ('%s', '%s') $sql_extra2" , - intval(local_user()), - dbesc(NETWORK_DFRN), - dbesc(NETWORK_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` $sql_extra2" , - intval(local_user()) - ); - $contact_count = (int)$r[0]['c']; - } else { - $contact_count = 0; - } - - $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" => htmlentities($g['name']), - "id" => intval($g['id']), - "uids" => array_map("intval", explode(",",$g['uids'])), - "link" => '', - "forum" => '0' - ]; - } - if ((count($groups) > 0) && ($search == "")) { - $groups[] = ["separator" => true]; - } - } - - 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 `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' - AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s')) - $sql_extra2 - ORDER BY `name` ASC ", - intval(local_user()), - dbesc(NETWORK_OSTATUS), dbesc(NETWORK_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 `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' - AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s')) - $sql_extra2 - ORDER BY `name` ASC ", - intval(local_user()), - dbesc(NETWORK_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 `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' - AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s')) - AND (`forum` OR `prv`) - $sql_extra2 - ORDER BY `name` ASC ", - intval(local_user()), - dbesc(NETWORK_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 `blocked` AND NOT `pending` AND NOT `archive` - AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s') - $sql_extra2 - ORDER BY `name` ASC ", - intval(local_user()), - dbesc(NETWORK_DFRN), - dbesc(NETWORK_DIASPORA) - ); - } elseif ($type == 'a') { - $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact` - WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update` - $sql_extra2 - ORDER BY `name` ASC ", - intval(local_user()) - ); - } elseif ($type == 'x') { - // autocomplete for global contact search (e.g. navbar search) - $r = navbar_complete($a); - $contacts = []; - if ($r) { - foreach ($r as $g) { - $contacts[] = [ - 'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO), - 'name' => $g['name'], - 'nick' => (x($g['addr']) ? $g['addr'] : $g['url']), - 'network' => $g['network'], - 'link' => $g['url'], - 'forum' => (x($g['community']) ? 1 : 0), - ]; - } - } - $o = [ - 'start' => $start, - 'count' => $count, - 'items' => $contacts, - ]; - echo json_encode($o); - killme(); - } else { - $r = []; - } - - if (DBM::is_result($r)) { - $forums = []; - foreach ($r as $g) { - $entry = [ - 'type' => 'c', - 'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO), - 'name' => htmlentities($g['name']), - 'id' => intval($g['id']), - 'network' => $g['network'], - 'link' => $g['url'], - 'nick' => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']), - 'addr' => htmlentities(($g['addr']) ? $g['addr'] : $g['url']), - 'forum' => ((x($g, 'forum') || x($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) { - /* - * 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 dbesc($i['link']); - } - , $contacts); - - $unknown_contacts = []; - $r = q("SELECT `author-link` - FROM `item` WHERE `parent` = %d - AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%') - AND `author-link` NOT IN ('%s') - GROUP BY `author-link`, `author-avatar`, `author-name` - ORDER BY `author-name` ASC - ", - intval($conv_id), - dbesc($search), - dbesc($search), - implode("', '", $known_contacts) - ); - if (DBM::is_result($r)) { - foreach ($r as $row) { - $contact = Contact::getDetailsByURL($row['author-link']); - - if (count($contact) > 0) { - $unknown_contacts[] = [ - 'type' => 'c', - 'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO), - 'name' => htmlentities($contact['name']), - 'id' => intval($contact['cid']), - 'network' => $contact['network'], - 'link' => $contact['url'], - 'nick' => htmlentities($contact['nick'] ? : $contact['addr']), - 'addr' => htmlentities(($contact['addr']) ? $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, - ]; - - Addon::callHooks('acl_lookup_end', $results); - - if ($out_type === 'html') { - $o = [ - 'tot' => $results['tot'], - 'start' => $results['start'], - 'count' => $results['count'], - 'groups' => $results['groups'], - 'contacts' => $results['contacts'], - ]; - return $o; - } - - $o = [ - 'tot' => $results['tot'], - 'start' => $results['start'], - 'count' => $results['count'], - 'items' => $results['items'], - ]; - - echo json_encode($o); - - killme(); -} -/** - * @brief Searching for global contacts for autocompletion - * - * @param App $a - * @return array with the search results - */ -function navbar_complete(App $a) { - -// logger('navbar_complete'); - - if ((Config::get('system','block_public')) && (! local_user()) && (! remote_user())) { - return; - } - - // check if searching in the local global contact table is enabled - $localsearch = Config::get('system','poco_local_search'); - - $search = notags(trim($_REQUEST['search'])); - $mode = $_REQUEST['smode']; - - // 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); - } - - if ($localsearch) { - $x = GContact::searchByName($search, $mode); - return $x; - } - - if (! $localsearch) { - $p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : ''); - - $x = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search)); - if ($x['success']) { - $j = json_decode($x['body'],true); - if ($j && isset($j['results'])) { - return $j['results']; - } - } - } - - /// @TODO Not needed here? - return; -} diff --git a/include/conversation.php b/include/conversation.php index c7a2379d53..ba7b7315b0 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -21,8 +21,6 @@ use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; use Friendica\Util\XML; -require_once "include/acl_selectors.php"; - function item_extract_images($body) { $saved_image = []; diff --git a/mod/acl.php b/mod/acl.php index e04a3fbc7e..11d9e5683a 100644 --- a/mod/acl.php +++ b/mod/acl.php @@ -1,12 +1,309 @@ = `failure_update` + 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 `blocked` AND NOT `pending` AND NOT `archive` + AND (`forum` OR `prv`) + AND `success_update` >= `failure_update` + 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 `blocked` AND NOT `pending` AND NOT `archive` + AND `success_update` >= `failure_update` + AND `network` IN ('%s', '%s') $sql_extra2", + intval(local_user()), + dbesc(NETWORK_DFRN), + dbesc(NETWORK_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` $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' => htmlentities($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 `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' + AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s')) + $sql_extra2 + ORDER BY `name` ASC ", + intval(local_user()), + dbesc(NETWORK_OSTATUS), + dbesc(NETWORK_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 `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' + AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s')) + $sql_extra2 + ORDER BY `name` ASC ", + intval(local_user()), + dbesc(NETWORK_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 `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' + AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s')) + AND (`forum` OR `prv`) + $sql_extra2 + ORDER BY `name` ASC ", + intval(local_user()), + dbesc(NETWORK_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 `blocked` AND NOT `pending` AND NOT `archive` + AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s') + $sql_extra2 + ORDER BY `name` ASC ", + intval(local_user()), + dbesc(NETWORK_DFRN), + dbesc(NETWORK_DIASPORA) + ); + } elseif ($type == 'a') { + $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact` + WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update` + $sql_extra2 + ORDER BY `name` ASC ", + intval(local_user()) + ); + } elseif ($type == 'x') { + // autocomplete for global contact search (e.g. navbar search) + $search = notags(trim($_REQUEST['search'])); + $mode = $_REQUEST['smode']; + + $r = ACL::contactAutocomplete($search, $mode); + + $contacts = []; + foreach ($r as $g) { + $contacts[] = [ + 'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO), + 'name' => $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 (DBM::is_result($r)) { + $forums = []; + foreach ($r as $g) { + $entry = [ + 'type' => 'c', + 'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO), + 'name' => htmlentities($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) { + /* + * 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 dbesc($i['link']); + }, $contacts); + + $unknown_contacts = []; + $r = q("SELECT `author-link` + FROM `item` WHERE `parent` = %d + AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%') + AND `author-link` NOT IN ('%s') + GROUP BY `author-link`, `author-avatar`, `author-name` + ORDER BY `author-name` ASC + ", + intval($conv_id), + dbesc($search), + dbesc($search), + implode("', '", $known_contacts) + ); + if (DBM::is_result($r)) { + foreach ($r as $row) { + $contact = Contact::getDetailsByURL($row['author-link']); + + if (count($contact) > 0) { + $unknown_contacts[] = [ + 'type' => 'c', + 'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO), + 'name' => htmlentities($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, + ]; + + Addon::callHooks('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/mod/bookmarklet.php b/mod/bookmarklet.php index 7a6a3ee21c..9ae3e28f08 100644 --- a/mod/bookmarklet.php +++ b/mod/bookmarklet.php @@ -2,7 +2,9 @@ /** * @file mod/bookmarklet.php */ + use Friendica\App; +use Friendica\Core\ACL; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Module\Login; @@ -35,8 +37,8 @@ function bookmarklet_content(App $a) 'default_location' => $a->user['default-location'], 'nickname' => $a->user['nickname'], 'lockstate' => ((is_array($a->user) && ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid'])))) ? 'lock' : 'unlock'), - 'default_perms' => get_acl_permissions($a->user), - 'acl' => populate_acl($a->user, true), + 'default_perms' => ACL::getDefaultUserPermissions($a->user), + 'acl' => ACL::getFullSelectorHTML($a->user, true), 'bang' => '', 'visitor' => 'block', 'profile_uid' => local_user(), diff --git a/mod/community.php b/mod/community.php index 88fc6168bb..40ebdbb6e0 100644 --- a/mod/community.php +++ b/mod/community.php @@ -2,8 +2,10 @@ /** * @file mod/community.php */ + use Friendica\App; use Friendica\Content\Nav; +use Friendica\Core\ACL; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\PConfig; @@ -104,7 +106,7 @@ function community_content(App $a, $update = 0) 'default_location' => $a->user['default-location'], 'nickname' => $a->user['nickname'], 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), - 'acl' => populate_acl($a->user, true), + 'acl' => ACL::getFullSelectorHTML($a->user, true), 'bang' => '', 'visitor' => 'block', 'profile_uid' => local_user(), diff --git a/mod/display.php b/mod/display.php index 42aad736cc..ab27b283b7 100644 --- a/mod/display.php +++ b/mod/display.php @@ -5,6 +5,7 @@ use Friendica\App; use Friendica\Content\Text\BBCode; +use Friendica\Core\ACL; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\Protocol; @@ -204,7 +205,6 @@ function display_content(App $a, $update = false, $update_uid = 0) { require_once 'include/security.php'; require_once 'include/conversation.php'; - require_once 'include/acl_selectors.php'; $o = ''; @@ -317,7 +317,7 @@ function display_content(App $a, $update = false, $update_uid = 0) { 'default_location' => $a->user['default-location'], 'nickname' => $a->user['nickname'], 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), - 'acl' => populate_acl($a->user, true), + 'acl' => ACL::getFullSelectorHTML($a->user, true), 'bang' => '', 'visitor' => 'block', 'profile_uid' => local_user(), diff --git a/mod/editpost.php b/mod/editpost.php index 3081b67293..aa2c296845 100644 --- a/mod/editpost.php +++ b/mod/editpost.php @@ -10,8 +10,6 @@ use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBM; -require_once 'include/acl_selectors.php'; - function editpost_content(App $a) { $o = ''; diff --git a/mod/events.php b/mod/events.php index 695dbb290f..8dab59b038 100644 --- a/mod/events.php +++ b/mod/events.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Content\Nav; +use Friendica\Core\ACL; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Core\Worker; @@ -478,12 +479,10 @@ function events_content(App $a) { $fhour = ((x($orig_event)) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'H') : '00'); $fminute = ((x($orig_event)) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'i') : '00'); - require_once 'include/acl_selectors.php' ; - - $perms = get_acl_permissions($orig_event); + $perms = ACL::getDefaultUserPermissions($orig_event); if ($mode === 'new' || $mode === 'copy') { - $acl = (($cid) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $a->user))); + $acl = (($cid) ? '' : ACL::getFullSelectorHTML(((x($orig_event)) ? $orig_event : $a->user))); } // If we copy an old event, we need to remove the ID and URI diff --git a/mod/fsuggest.php b/mod/fsuggest.php index 86878a5295..4f432d840a 100644 --- a/mod/fsuggest.php +++ b/mod/fsuggest.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\Core\ACL; use Friendica\Core\L10n; use Friendica\Core\Worker; use Friendica\Database\DBM; @@ -75,8 +76,6 @@ function fsuggest_post(App $a) function fsuggest_content(App $a) { - require_once 'include/acl_selectors.php'; - if (! local_user()) { notice(L10n::t('Permission denied.') . EOL); return; @@ -105,11 +104,10 @@ function fsuggest_content(App $a) $o .= '
'; - $o .= contact_selector( + $o .= ACL::getSuggestContactSelectHTML( 'suggest', 'suggest-select', - ['size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true], - false + ['size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true] ); diff --git a/mod/group.php b/mod/group.php index 0473e2af9f..870025074c 100644 --- a/mod/group.php +++ b/mod/group.php @@ -146,7 +146,6 @@ function group_content(App $a) { } if (($a->argc > 1) && (intval($a->argv[1]))) { - require_once 'include/acl_selectors.php'; require_once 'mod/contacts.php'; $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", diff --git a/mod/message.php b/mod/message.php index 40f1dd08c0..e9bfc076bb 100644 --- a/mod/message.php +++ b/mod/message.php @@ -7,6 +7,7 @@ use Friendica\App; use Friendica\Content\Nav; use Friendica\Content\Smilies; use Friendica\Content\Text\BBCode; +use Friendica\Core\ACL; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBM; @@ -15,7 +16,6 @@ use Friendica\Model\Mail; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; -require_once 'include/acl_selectors.php'; require_once 'include/conversation.php'; function message_init(App $a) @@ -207,7 +207,7 @@ function message_content(App $a) '$linkurl' => L10n::t('Please enter a link URL:') ]); - $preselect = isset($a->argv[2]) ? [$a->argv[2]] : false; + $preselect = isset($a->argv[2]) ? [$a->argv[2]] : []; $prename = $preurl = $preid = ''; @@ -236,14 +236,14 @@ function message_content(App $a) $preid = $r[0]['id']; $preselect = [$preid]; } else { - $preselect = false; + $preselect = []; } } $prefill = $preselect ? $prename : ''; // the ugly select box - $select = contact_select('messageto', 'message-to-select', $preselect, 4, true, false, false, 10); + $select = ACL::getMessageContactSelectHTML('messageto', 'message-to-select', $preselect, 4, 10); $tpl = get_markup_template('prv_message.tpl'); $o .= replace_macros($tpl, [ diff --git a/mod/network.php b/mod/network.php index c2cb8e03fc..4ab773bd32 100644 --- a/mod/network.php +++ b/mod/network.php @@ -9,6 +9,7 @@ use Friendica\Content\Feature; use Friendica\Content\ForumManager; use Friendica\Content\Nav; use Friendica\Content\Widget; +use Friendica\Core\ACL; use Friendica\Core\Addon; use Friendica\Core\Config; use Friendica\Core\L10n; @@ -24,7 +25,6 @@ use Friendica\Util\DateTimeFormat; require_once 'include/conversation.php'; require_once 'include/items.php'; -require_once 'include/acl_selectors.php'; function network_init(App $a) { @@ -427,8 +427,8 @@ function networkFlatView(App $a, $update = 0) 'lockstate' => (((is_array($a->user) && ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))))) ? 'lock' : 'unlock'), - 'default_perms' => get_acl_permissions($a->user), - 'acl' => populate_acl($a->user, true), + 'default_perms' => ACL::getDefaultUserPermissions($a->user), + 'acl' => ACL::getFullSelectorHTML($a->user, true), 'bang' => '', 'visitor' => 'block', 'profile_uid' => local_user(), @@ -576,8 +576,8 @@ function networkThreadedView(App $a, $update, $parent) 'lockstate' => ((($gid) || ($cid) || ($nets) || (is_array($a->user) && ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))))) ? 'lock' : 'unlock'), - 'default_perms' => get_acl_permissions($a->user), - 'acl' => populate_acl((($gid || $cid || $nets) ? $def_acl : $a->user), true), + 'default_perms' => ACL::getDefaultUserPermissions($a->user), + 'acl' => ACL::getFullSelectorHTML((($gid || $cid || $nets) ? $def_acl : $a->user), true), 'bang' => (($gid || $cid || $nets) ? '!' : ''), 'visitor' => 'block', 'profile_uid' => local_user(), diff --git a/mod/notes.php b/mod/notes.php index 3b46df07da..aa239fb0e0 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -33,7 +33,6 @@ function notes_content(App $a, $update = false) require_once 'include/security.php'; require_once 'include/conversation.php'; - require_once 'include/acl_selectors.php'; $groups = []; diff --git a/mod/photos.php b/mod/photos.php index 3cd8b75286..c8dad750d1 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -7,6 +7,7 @@ use Friendica\App; use Friendica\Content\Feature; use Friendica\Content\Nav; use Friendica\Content\Text\BBCode; +use Friendica\Core\ACL; use Friendica\Core\Addon; use Friendica\Core\Config; use Friendica\Core\L10n; @@ -26,7 +27,6 @@ use Friendica\Util\Map; use Friendica\Util\Temporal; require_once 'include/items.php'; -require_once 'include/acl_selectors.php'; require_once 'include/security.php'; function photos_init(App $a) { @@ -1084,7 +1084,7 @@ function photos_content(App $a) $tpl = get_markup_template('photos_upload.tpl'); - $aclselect_e = ($visitor ? '' : populate_acl($a->user)); + $aclselect_e = ($visitor ? '' : ACL::getFullSelectorHTML($a->user)); $o .= replace_macros($tpl,[ '$pagename' => L10n::t('Upload Photos'), @@ -1425,7 +1425,7 @@ function photos_content(App $a) $album_e = $ph[0]['album']; $caption_e = $ph[0]['desc']; - $aclselect_e = populate_acl($ph[0]); + $aclselect_e = ACL::getFullSelectorHTML($ph[0]); $edit = replace_macros($edit_tpl, [ '$id' => $ph[0]['id'], diff --git a/mod/profile.php b/mod/profile.php index 5e5988994c..ab11b4d5fe 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Content\Nav; use Friendica\Content\Widget; +use Friendica\Core\ACL; use Friendica\Core\Addon; use Friendica\Core\Config; use Friendica\Core\L10n; @@ -118,7 +119,6 @@ function profile_content(App $a, $update = 0) require_once 'include/security.php'; require_once 'include/conversation.php'; - require_once 'include/acl_selectors.php'; require_once 'include/items.php'; $groups = []; @@ -213,7 +213,7 @@ function profile_content(App $a, $update = 0) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid']) ) ? 'lock' : 'unlock', - 'acl' => $is_owner ? populate_acl($a->user, true) : '', + 'acl' => $is_owner ? ACL::getFullSelectorHTML($a->user, true) : '', 'bang' => '', 'visitor' => $is_owner || $commvisitor ? 'block' : 'none', 'profile_uid' => $a->profile['profile_uid'], diff --git a/mod/settings.php b/mod/settings.php index 6fcbe4d116..46c3d2ec96 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Content\Feature; use Friendica\Content\Nav; +use Friendica\Core\ACL; use Friendica\Core\Addon; use Friendica\Core\Config; use Friendica\Core\L10n; @@ -999,8 +1000,6 @@ function settings_content(App $a) * ACCOUNT SETTINGS */ - require_once('include/acl_selectors.php'); - $profile = dba::selectFirst('profile', [], ['is-default' => true, 'uid' => local_user()]); if (!DBM::is_result($profile)) { notice(L10n::t('Unable to find your profile. Please contact your admin.') . EOL); @@ -1224,7 +1223,7 @@ function settings_content(App $a) '$permissions' => L10n::t('Default Post Permissions'), '$permdesc' => L10n::t("\x28click to open/close\x29"), '$visibility' => $profile['net-publish'], - '$aclselect' => populate_acl($a->user), + '$aclselect' => ACL::getFullSelectorHTML($a->user), '$suggestme' => $suggestme, '$blockwall'=> $blockwall, // array('blockwall', L10n::t('Allow friends to post to your profile page:'), !$blockwall, ''), '$blocktags'=> $blocktags, // array('blocktags', L10n::t('Allow friends to tag your posts:'), !$blocktags, ''), diff --git a/mod/videos.php b/mod/videos.php index 75a4d031f3..f4b8c46b1b 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -19,7 +19,6 @@ use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; require_once 'include/items.php'; -require_once 'include/acl_selectors.php'; require_once 'include/security.php'; function videos_init(App $a) { diff --git a/src/Core/ACL.php b/src/Core/ACL.php new file mode 100644 index 0000000000..ae05fd1360 --- /dev/null +++ b/src/Core/ACL.php @@ -0,0 +1,358 @@ + + */ +class ACL extends BaseObject +{ + /** + * Returns a select input tag with all the contact of the local user + * + * @param string $selname Name attribute of the select input tag + * @param string $selclass Class attribute of the select input tag + * @param array $options Available options: + * - size: length of the select box + * - mutual_friends: Only used for the hook + * - single: Only used for the hook + * - exclude: Only used for the hook + * @param array $preselected Contact ID that should be already selected + * @return string + */ + public static function getSuggestContactSelectHTML($selname, $selclass, array $options = [], array $preselected = []) + { + $a = self::getApp(); + + $networks = null; + + $size = defaults($options, 'size', 4); + $mutual = !empty($options['mutual_friends']); + $single = !empty($options['single']) && empty($options['multiple']); + $exclude = defaults($options, 'exclude', false); + + switch (defaults($options, 'networks', Protocol::PHANTOM)) { + case 'DFRN_ONLY': + $networks = [NETWORK_DFRN]; + break; + case 'PRIVATE': + if (!empty($a->user['prvnets'])) { + $networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA]; + } else { + $networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA]; + } + break; + case 'TWO_WAY': + if (!empty($a->user['prvnets'])) { + $networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA]; + } else { + $networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA, NETWORK_OSTATUS]; + } + break; + default: /// @TODO Maybe log this call? + break; + } + + $x = ['options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks]; + + Addon::callHooks('contact_select_options', $x); + + $o = ''; + + $sql_extra = ''; + + if (!empty($x['mutual'])) { + $sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND)); + } + + if (!empty($x['exclude'])) { + $sql_extra .= sprintf(" AND `id` != %d ", intval($x['exclude'])); + } + + if (!empty($x['networks'])) { + /// @TODO rewrite to foreach() + array_walk($x['networks'], function (&$value) { + $value = "'" . dbesc($value) . "'"; + }); + $str_nets = implode(',', $x['networks']); + $sql_extra .= " AND `network` IN ( $str_nets ) "; + } + + $tabindex = (!empty($options['tabindex']) ? 'tabindex="' . $options["tabindex"] . '"' : ''); + + if (!empty($x['single'])) { + $o .= "\r\n"; + } + + $stmt = dba::p("SELECT `id`, `name`, `url`, `network` FROM `contact` + WHERE `uid` = ? AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' + $sql_extra + ORDER BY `name` ASC ", intval(local_user()) + ); + + $contacts = dba::inArray($stmt); + + $arr = ['contact' => $contacts, 'entry' => $o]; + + // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow' + Addon::callHooks($a->module . '_pre_' . $selname, $arr); + + if (DBM::is_result($contacts)) { + foreach ($contacts as $contact) { + if (in_array($contact['id'], $preselected)) { + $selected = ' selected="selected" '; + } else { + $selected = ''; + } + + $trimmed = mb_substr($contact['name'], 0, 20); + + $o .= "\r\n"; + } + } + + $o .= '' . PHP_EOL; + + Addon::callHooks($a->module . '_post_' . $selname, $o); + + return $o; + } + + /** + * Returns a select input tag with all the contact of the local user + * + * @param string $selname Name attribute of the select input tag + * @param string $selclass Class attribute of the select input tag + * @param array $preselected Contact IDs that should be already selected + * @param int $size Length of the select box + * @param int $tabindex Select input tag tabindex attribute + * @return string + */ + public static function getMessageContactSelectHTML($selname, $selclass, array $preselected = [], $size = 4, $tabindex = null) + { + $a = self::getApp(); + + $o = ''; + + // When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector + // to one recipient. By default our selector allows multiple selects amongst all contacts. + $sql_extra = sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND)); + $sql_extra .= sprintf(" AND `network` IN ('%s' , '%s') ", NETWORK_DFRN, NETWORK_DIASPORA); + + $tabindex_attr = !empty($tabindex) ? ' tabindex="' . intval($tabindex) . '"' : ''; + + $hidepreselected = ''; + if ($preselected) { + $sql_extra .= " AND `id` IN (" . implode(",", $preselected) . ")"; + $hidepreselected = ' style="display: none;"'; + } + + $o .= "' . PHP_EOL; + + if ($preselected) { + $o .= implode(', ', $receiverlist); + } + + Addon::callHooks($a->module . '_post_' . $selname, $o); + + return $o; + } + + /** + * Return the default permission of the provided user array + * + * @param array $user + * @return array Hash of contact id lists + */ + public static function getDefaultUserPermissions(array $user = null) + { + $matches = []; + + $acl_regex = '/<([0-9]+)>/i'; + + preg_match_all($acl_regex, defaults($user, 'allow_cid', ''), $matches); + $allow_cid = $matches[1]; + preg_match_all($acl_regex, defaults($user, 'allow_gid', ''), $matches); + $allow_gid = $matches[1]; + preg_match_all($acl_regex, defaults($user, 'deny_cid', ''), $matches); + $deny_cid = $matches[1]; + preg_match_all($acl_regex, defaults($user, 'deny_gid', ''), $matches); + $deny_gid = $matches[1]; + + Contact::pruneUnavailable($allow_cid); + + return [ + 'allow_cid' => $allow_cid, + 'allow_gid' => $allow_gid, + 'deny_cid' => $deny_cid, + 'deny_gid' => $deny_gid, + ]; + } + + /** + * Return the full jot ACL selector HTML + * + * @param array $user + * @param bool $show_jotnets + * @return string + */ + public static function getFullSelectorHTML(array $user = null, $show_jotnets = false) + { + $perms = self::getDefaultUserPermissions($user); + + $jotnets = ''; + if ($show_jotnets) { + $imap_disabled = !function_exists('imap_open') || Config::get('system', 'imap_disabled'); + + $mail_enabled = false; + $pubmail_enabled = false; + + if (!$imap_disabled) { + $mailacct = dba::selectFirst('mailacct', ['pubmail'], ['`uid` = ? AND `server` != ""', local_user()]); + if (DBM::is_result($mailacct)) { + $mail_enabled = true; + $pubmail_enabled = !empty($mailacct['pubmail']); + } + } + + if (empty($user['hidewall'])) { + if ($mail_enabled) { + $selected = $pubmail_enabled ? ' checked="checked"' : ''; + $jotnets .= '
' . L10n::t("Post to Email") . '
'; + } + + Addon::callHooks('jot_networks', $jotnets); + } else { + $jotnets .= L10n::t('Connectors disabled, since "%s" is enabled.', + L10n::t('Hide your profile details from unknown viewers?')); + } + } + + $tpl = get_markup_template('acl_selector.tpl'); + $o = replace_macros($tpl, [ + '$showall' => L10n::t('Visible to everybody'), + '$show' => L10n::t('show'), + '$hide' => L10n::t('don\'t show'), + '$allowcid' => json_encode($perms['allow_cid']), + '$allowgid' => json_encode($perms['allow_gid']), + '$denycid' => json_encode($perms['deny_cid']), + '$denygid' => json_encode($perms['deny_gid']), + '$networks' => $show_jotnets, + '$emailcc' => L10n::t('CC: email addresses'), + '$emtitle' => L10n::t('Example: bob@example.com, mary@example.com'), + '$jotnets' => $jotnets, + '$aclModalTitle' => L10n::t('Permissions'), + '$aclModalDismiss' => L10n::t('Close'), + '$features' => [ + 'aclautomention' => Feature::isEnabled($user['uid'], 'aclautomention') ? 'true' : 'false' + ], + ]); + + 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") + * @return array with the search results + */ + public static function contactAutocomplete($search, $mode) + { + if ((Config::get('system', 'block_public')) && (!local_user()) && (!remote_user())) { + 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 { + $a = self::getApp(); + $p = $a->pager['page'] != 1 ? '&p=' . $a->pager['page'] : ''; + + $response = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search)); + if ($response['success']) { + $lsearch = json_decode($response['body'], true); + if (!empty($lsearch['results'])) { + $return = $lsearch['results']; + } + } + } + + return defaults($return, []); + } +} diff --git a/src/Model/Contact.php b/src/Model/Contact.php index fc27b0c410..b4d20586ad 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1517,4 +1517,29 @@ class Contact extends BaseObject } } } + + /** + * Remove the unavailable contact ids from the provided list + * + * @param array $contact_ids Contact id list + */ + public static function pruneUnavailable(array &$contact_ids) + { + if (empty($contact_ids)) { + return; + } + + $str = dbesc(implode(',', $contact_ids)); + + $stmt = dba::p("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0"); + + $return = []; + while($contact = dba::fetch($stmt)) { + $return[] = $contact['id']; + } + + dba::close($stmt); + + $contact_ids = $return; + } } diff --git a/src/Model/Group.php b/src/Model/Group.php index 9e472a7ade..f48dd50431 100644 --- a/src/Model/Group.php +++ b/src/Model/Group.php @@ -4,8 +4,8 @@ */ namespace Friendica\Model; -use Friendica\Core\L10n; use Friendica\BaseObject; +use Friendica\Core\L10n; use Friendica\Database\DBM; use dba; @@ -289,8 +289,7 @@ class Group extends BaseObject } if ($check_dead && !$use_gcontact) { - require_once 'include/acl_selectors.php'; - $return = prune_deadguys($return); + Contact::pruneUnavailable($return); } return $return; }