diff options
author | RedMatrix <info@friendica.com> | 2015-01-05 07:30:07 +1100 |
---|---|---|
committer | RedMatrix <info@friendica.com> | 2015-01-05 07:30:07 +1100 |
commit | ebb1a616849e275111cd24a20d08031aff4c4161 (patch) | |
tree | 72a12265027374eef1fb04a12abaa34c284c7337 | |
parent | cb181993a8c63cca8f13c7890a6ab1544f44676f (diff) | |
parent | ac4c17dd4c4df70b31fd7246108fdbc9d6f2a593 (diff) | |
download | volse-hubzilla-ebb1a616849e275111cd24a20d08031aff4c4161.tar.gz volse-hubzilla-ebb1a616849e275111cd24a20d08031aff4c4161.tar.bz2 volse-hubzilla-ebb1a616849e275111cd24a20d08031aff4c4161.zip |
Merge pull request #816 from pafcu/acl
Autocomplete improvements
-rwxr-xr-x | boot.php | 1 | ||||
-rw-r--r-- | mod/acl.php | 147 | ||||
-rw-r--r-- | view/js/autocomplete.js | 16 | ||||
-rwxr-xr-x | view/tpl/head.tpl | 2 | ||||
-rwxr-xr-x | view/tpl/jot-header.tpl | 2 |
5 files changed, 88 insertions, 80 deletions
@@ -1024,6 +1024,7 @@ class App { '$head_js' => head_get_js(), '$js_strings' => js_strings(), '$zid' => get_my_address(), + '$channel_id' => $this->profile['uid'], )) . $this->page['htmlhead']; // always put main.js at the end diff --git a/mod/acl.php b/mod/acl.php index 24f2a35e0..8c6eae0b0 100644 --- a/mod/acl.php +++ b/mod/acl.php @@ -13,6 +13,9 @@ function acl_init(&$a){ $type = (x($_REQUEST,'type')?$_REQUEST['type']:""); $noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false); + // List of channels whose connections to also suggest, e.g. currently viewed channel or channels mentioned in a post + $extra_channels = (x($_REQUEST,'extra_channels') ? $_REQUEST['extra_channels'] : array()); + // For use with jquery.autocomplete for private mail completion if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) { @@ -21,9 +24,8 @@ function acl_init(&$a){ $search = $_REQUEST['query']; } - if(!(local_user())) - if($type != 'x') + if(!($type == 'x' || $type == 'c')) killme(); if ($search != "") { @@ -40,72 +42,6 @@ function acl_init(&$a){ $sql_extra = $sql_extra2 = $sql_extra3 = ""; } - // count groups and contacts - if ($type=='' || $type=='g'){ - $r = q("SELECT COUNT(`id`) AS g FROM `groups` WHERE `deleted` = 0 AND `uid` = %d $sql_extra", - intval(local_user()) - ); - $group_count = (int)$r[0]['g']; - } else { - $group_count = 0; - } - - if ($type=='' || $type=='c'){ - $r = q("SELECT COUNT(abook_id) AS c FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d AND not ( abook_flags & %d )>0 and not (xchan_flags & %d )>0 $sql_extra2" , - intval(local_user()), - intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED), - intval(XCHAN_FLAGS_DELETED) - ); - $contact_count = (int)$r[0]['c']; - - if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_user(),'system','taganyone'))) { - if(((! $r) || (! $r[0]['total'])) && $type == 'c') { - $r = q("SELECT COUNT(xchan_hash) AS c FROM xchan - WHERE not (xchan_flags & %d )>0 $sql_extra2" , - intval(XCHAN_FLAGS_DELETED) - ); - $contact_count = (int)$r[0]['c']; - } - } - - } - - elseif ($type == 'm') { - - // autocomplete for Private Messages - - - $r = q("SELECT count(xchan_hash) as c - FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and ( (abook_their_perms = null) or (abook_their_perms & %d )>0) - and not ( xchan_flags & %d )>0 - $sql_extra2 ", - intval(local_user()), - intval(PERMS_W_MAIL), - intval(XCHAN_FLAGS_DELETED) - ); - - if($r) - $contact_count = (int)$r[0]['c']; - - } - elseif (($type == 'a')||($type == 'p')) { - - // autocomplete for Contacts - - $r = q("SELECT COUNT(abook_id) AS c FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and not ( xchan_flags & %d )>0 $sql_extra2" , - intval(local_user()), - intval(XCHAN_FLAGS_DELETED) - ); - $contact_count = (int)$r[0]['c']; - - } else { - $contact_count = 0; - } - - $tot = $group_count+$contact_count; $groups = array(); $contacts = array(); @@ -142,13 +78,75 @@ function acl_init(&$a){ } if ($type=='' || $type=='c') { - $r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags + $extra_channels_sql = ''; + // Only include channels who allow the observer to view their permissions + foreach($extra_channels as $channel) { + if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) + $extra_channels_sql .= "," . intval($channel); + } + + $extra_channels_sql = substr($extra_channels_sql,1); // Remove initial comma + + // Getting info from the abook is better for local users because it contains info about permissions + if(local_user()) { + if($extra_channels_sql != '') + $extra_channels_sql = " OR (abook_channel IN ($extra_channels_sql)) and not (abook_flags & ". intval(ABOOK_FLAG_HIDDEN) . ') > 0'; + + $r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d AND not ( abook_flags & %d )>0 and not (xchan_flags & %d )>0 $sql_extra2 order by $order_extra2 xchan_name asc" , - intval(local_user()), - intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED), - intval(XCHAN_FLAGS_DELETED) - ); + WHERE (abook_channel = %d $extra_channels_sql) AND not ( abook_flags & %d )>0 and not (xchan_flags & %d )>0 $sql_extra2 order by $order_extra2 xchan_name asc" , + intval(local_user()), + intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED), + intval(XCHAN_FLAGS_DELETED) + ); + } + else { // Visitors + $r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags + FROM xchan left join xlink on xlink_link = xchan_hash + WHERE xlink_xchan = '%s' AND NOT (xchan_flags & %d) > 0 $sql_extra2 order by $order_extra2 xchan_name asc" , + dbesc(get_observer_hash()), + intval(XCHAN_FLAGS_DELETED)); + + // Find contacts of extra channels + // This is probably more complicated than it needs to be + if($extra_channels_sql) { + // Build a list of hashes that we got previously so we don't get them again + $known_hashes = array("'".get_observer_hash()."'"); + if($r) + foreach($r as $rr) + $known_hashes[] = "'".$rr['hash']."'"; + $known_hashes_sql = 'AND xchan_hash not in ('.join(',',$known_hashes).')'; + + $r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags + FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel IN ($extra_channels_sql) $known_hashes_sql AND not ( abook_flags & %d )>0 and not (xchan_flags & %d )>0 $sql_extra2 order by $order_extra2 xchan_name asc" , + intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED|ABOOK_FLAG_HIDDEN), + intval(XCHAN_FLAGS_DELETED) + ); + if($r2) + $r = array_merge($r,$r2); + + // Sort accoring to match position, then alphabetically. This could be avoided if the above two SQL queries could be combined into one, and the sorting could be done on the SQl server (like in the case of a local user) + $matchpos = function($x) use($search) { + $namepos = strpos($x['name'],$search); + $nickpos = strpos($x['nick'],$search); + // Use a large position if not found + return min($namepos === false ? 9999 : $namepos, $nickpos === false ? 9999 : $nickpos); + }; + // This could be made simpler if PHP supported stable sorting + usort($r,function($a,$b) use($matchpos) { + $pos1 = $matchpos($a); + $pos2 = $matchpos($b); + if($pos1 == $pos2) { // Order alphabetically if match position is the same + if($a['name'] == $b['name']) + return 0; + else + return ($a['name'] < $b['name']) ? -1 : 1; + } + return ($pos1 < $pos2) ? -1 : 1; + }); + } + } if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_user(),'system','taganyone'))) { if((! $r) && $type == 'c') { $r = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags @@ -266,7 +264,6 @@ function acl_init(&$a){ $items = array_merge($groups, $contacts); $o = array( - 'tot' => $tot, 'start' => $start, 'count' => $count, 'items' => $items, diff --git a/view/js/autocomplete.js b/view/js/autocomplete.js index 7c3145769..259dca1bc 100644 --- a/view/js/autocomplete.js +++ b/view/js/autocomplete.js @@ -3,13 +3,16 @@ * * require jQuery, jquery.textcomplete */ -function mysearch(term, callback, backend_url) { +function mysearch(term, callback, backend_url, extra_channels) { var postdata = { start:0, count:100, search:term, type:'c', } + + if(extra_channels) + postdata['extra_channels[]'] = extra_channels; $.ajax({ type:'POST', @@ -28,20 +31,25 @@ function format(item) { function replace(item) { // $2 ensures that prefix (@,@!) is preserved - return '$1$2'+item.nick.replace(' ','') + '+' + item.id; + var id = item.id; + // 16 chars of hash should be enough. Full hash could be used if it can be done in a visually appealing way. + // 16 chars is also the minimum length in the backend (otherwise it's interpreted as a local id). + if(id.length > 16) + id = item.id.substring(0,16); + return '$1$2'+item.nick.replace(' ','') + '+' + id; } /** * jQuery plugin 'contact_autocomplete' */ (function( $ ){ - $.fn.contact_autocomplete = function(backend_url) { + $.fn.contact_autocomplete = function(backend_url, extra_channels = null) { // Autocomplete contacts contacts = { match: /(^|\s)(@\!*)([^ \n]+)$/, index: 3, - search: function(term, callback) { mysearch(term, callback, backend_url); }, + search: function(term, callback) { mysearch(term, callback, backend_url, extra_channels); }, replace: replace, template: format, } diff --git a/view/tpl/head.tpl b/view/tpl/head.tpl index 9c9e7b970..8a32bd7f6 100755 --- a/view/tpl/head.tpl +++ b/view/tpl/head.tpl @@ -26,6 +26,8 @@ var localUser = {{if $local_user}}{{$local_user}}{{else}}false{{/if}}; var zid = {{if $zid}}'{{$zid}}'{{else}}null{{/if}}; var justifiedGalleryActive = false; + {{if $channel_hash}}var channelHash = '{{$channel_hash}}';{{/if}} + {{if $channel_id}}var channelId = '{{$channel_id}}';{{/if}}{{* Used in e.g. autocomplete *}} </script> diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl index bdbb7d09c..c23395b03 100755 --- a/view/tpl/jot-header.tpl +++ b/view/tpl/jot-header.tpl @@ -10,7 +10,7 @@ function initEditor(cb){ if(plaintext == 'none') { $("#profile-jot-text-loading").spin(false).hide(); $("#profile-jot-text").css({ 'height': 200, 'color': '#000' }); - $("#profile-jot-text").contact_autocomplete(baseurl+"/acl"); + $("#profile-jot-text").contact_autocomplete(baseurl+"/acl",[channelId]); // Also gives suggestions from current channel's connections editor = true; $("a#jot-perms-icon").colorbox({ 'inline' : true, |