From b917cf1eccc62f5f533c0a61ffd699764b39e404 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 18 Jun 2017 22:25:41 -0700 Subject: allow moderated comments like wordpress if permissions are compatible --- Zotlabs/Access/PermissionLimits.php | 2 +- Zotlabs/Lib/Enotify.php | 11 +++++- Zotlabs/Lib/ThreadItem.php | 8 +++- Zotlabs/Lib/ThreadStream.php | 2 +- Zotlabs/Module/Item.php | 31 +++++++++++++-- Zotlabs/Module/Moderate.php | 77 +++++++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Channel.php | 2 +- include/channel.php | 66 +++++++++++++++++++++++++++++++ include/conversation.php | 22 +++++++---- include/items.php | 2 +- view/js/main.js | 2 + view/tpl/comment_item.tpl | 7 ++-- view/tpl/search_item.tpl | 11 ++++++ 13 files changed, 221 insertions(+), 22 deletions(-) create mode 100644 Zotlabs/Module/Moderate.php diff --git a/Zotlabs/Access/PermissionLimits.php b/Zotlabs/Access/PermissionLimits.php index 909b654d5..8caeedb91 100644 --- a/Zotlabs/Access/PermissionLimits.php +++ b/Zotlabs/Access/PermissionLimits.php @@ -10,7 +10,7 @@ class PermissionLimits { $perms = Permissions::Perms(); $limits = array(); foreach($perms as $k => $v) { - if(strstr($k,'view')) + if(strstr($k,'view') || $k === 'post_comments') $limits[$k] = PERMS_PUBLIC; else $limits[$k] = PERMS_SPECIFIC; diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php index a10675a87..114021568 100644 --- a/Zotlabs/Lib/Enotify.php +++ b/Zotlabs/Lib/Enotify.php @@ -170,6 +170,7 @@ class Enotify { xchan_query($p); + $moderated = (($p[0]['item_blocked'] = ITEM_MODERATED) ? true : false); $item_post_type = item_post_type($p[0]); // $private = $p[0]['item_private']; @@ -208,13 +209,21 @@ class Enotify { // Before this we have the name of the replier on the subject rendering // differents subjects for messages on the same thread. - $subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']); + if($moderated) + $subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']); + else + $subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']); $preamble = sprintf( t('%1$s, %2$s commented on an item/conversation you have been following.'), $recip['channel_name'], $sender['xchan_name']); $epreamble = $dest_str; $sitelink = t('Please visit %s to view and/or reply to the conversation.'); $tsitelink = sprintf( $sitelink, $siteurl ); $hsitelink = sprintf( $sitelink, '' . $sitename . ''); + if($moderated) { + $tsitelink .= "\n\n" . sprintf( t('Please visit %s to approve or reject this comment.'), z_root() . '/moderate' ); + $hsitelink .= "\n\n" . sprintf( t('Please visit %s to approve or reject this comment.'), z_root() . '/moderate' ); + } + } if ($params['type'] == NOTIFY_LIKE) { diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index ff4e3205e..50c67c466 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -741,8 +741,12 @@ class ThreadItem { '$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false), '$encrypt' => t('Encrypt text'), '$cipher' => $conv->get_cipher(), - '$sourceapp' => \App::$sourcename - + '$sourceapp' => \App::$sourcename, + '$observer' => get_observer_hash(), + '$anoncomments' => perm_is_allowed($conv->get_profile_owner(),'','post_comments'), + '$anonname' => [ 'anonname', t('Your full name (required)'),'','' ], + '$anonmail' => [ 'anonmail', t('Your email address (required)'),'','' ], + '$anonurl' => [ 'anonurl', t('Your website URL (optional)'),'','' ] )); return $comment_box; diff --git a/Zotlabs/Lib/ThreadStream.php b/Zotlabs/Lib/ThreadStream.php index beb626f31..1fd746c38 100644 --- a/Zotlabs/Lib/ThreadStream.php +++ b/Zotlabs/Lib/ThreadStream.php @@ -158,7 +158,7 @@ class ThreadStream { if(intval($item->get_data_value('item_nocomment'))) { $item->set_commentable(false); } - elseif(($this->observer) && (! $item->is_commentable())) { + elseif(! $item->is_commentable()) { if((array_key_exists('owner',$item->data)) && intval($item->data['owner']['abook_self'])) $item->set_commentable(perm_is_allowed($this->profile_owner,$ob_hash,'post_comments')); else diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index ec36c22d8..952ecf487 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -33,7 +33,7 @@ class Item extends \Zotlabs\Web\Controller { // This will change. Figure out who the observer is and whether or not // they have permission to post here. Else ignore the post. - if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'commenter'))) + if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'anonname'))) return; $uid = local_channel(); @@ -77,7 +77,7 @@ class Item extends \Zotlabs\Web\Controller { call_hooks('post_local_start', $_REQUEST); - // logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA); + // logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA); $api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false); @@ -205,10 +205,29 @@ class Item extends \Zotlabs\Web\Controller { $route = $parent_item['route']; } + + $moderated = false; - if(! $observer) + if(! $observer) { $observer = \App::get_observer(); + if(! $observer) { + $observer = anon_identity_init($_REQUEST); + if($observer) { + $moderated = true; + $remote_xchan = $remote_observer = $observer; + } + } + } + if(! $observer) { + notice( t('Permission denied.') . EOL) ; + if($api_source) + return ( [ 'success' => false, 'message' => 'permission denied' ] ); + if(x($_REQUEST,'return')) + goaway(z_root() . "/" . $return_path ); + killme(); + } + if($parent) { logger('mod_item: item_post parent=' . $parent); $can_comment = false; @@ -312,7 +331,7 @@ class Item extends \Zotlabs\Web\Controller { $walltowall = false; $walltowall_comment = false; - if($remote_xchan) + if($remote_xchan && ! $moderated) $observer = $remote_observer; if($observer) { @@ -996,6 +1015,10 @@ class Item extends \Zotlabs\Web\Controller { \Zotlabs\Daemon\Master::Summon(array('Notifier', $notify_type, $post_id)); logger('post_complete'); + + if($moderated) { + info(t('Your comment is awaiting approval.') . EOL); + } // figure out how to return, depending on from whence we came diff --git a/Zotlabs/Module/Moderate.php b/Zotlabs/Module/Moderate.php new file mode 100644 index 000000000..b7f05e4b2 --- /dev/null +++ b/Zotlabs/Module/Moderate.php @@ -0,0 +1,77 @@ + 2) { + $post_id = intval(argv(1)); + if(! $post_id) + goaway(z_root() . '/moderate'); + + $action = argv(2); + + $r = q("select * from item where uid = %d and id = %d and item_blocked = %d limit 1", + intval(local_channel()), + intval($post_id), + intval(ITEM_MODERATED) + ); + + + + if($r) { + if($action === 'approve') { + q("update item set item_blocked = 0 where uid = %d and id = %d", + intval(local_channel()), + intval($post_id) + ); + notice( t('Comment approved') . EOL); + } + elseif($action === 'drop') { + drop_item($post_id,false); + notice( t('Comment deleted') . EOL); + } + } + + $r = q("select * from item where id = %d", + intval($post_id) + ); + if($r) { + xchan_query($r); + $sync_item = fetch_post_tags($r); + build_sync_packet(local_channel(),array('item' => array(encode_item($sync_item[0],true)))); + } + goaway(z_root() . '/moderate'); + } + + $r = q("select item.id as item_id, item.* from item where item.uid = %d and item_blocked = %d and item_deleted = 0 order by created desc limit 60", + intval(local_channel()), + intval(ITEM_MODERATED) + ); + + if($r) { + xchan_query($r); + $items = fetch_post_tags($r,true); + } + else { + $items = array(); + } + + $o = conversation($a,$items,'moderate',false,'traditional'); + + return $o; + + } + +} \ No newline at end of file diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 7c30ef93e..3e6adcf8d 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -324,7 +324,7 @@ class Channel { foreach($global_perms as $k => $perm) { $options = array(); foreach($perm_opts as $opt) { - if((! strstr($k,'view')) && $opt[1] == PERMS_PUBLIC) + if(((! strstr($k,'view')) && $k !== 'post_comments') && $opt[1] == PERMS_PUBLIC) continue; $options[$opt[1]] = $opt[0]; } diff --git a/include/channel.php b/include/channel.php index b06c1994f..86fa2a63a 100644 --- a/include/channel.php +++ b/include/channel.php @@ -2306,3 +2306,69 @@ function channel_codeallowed($channel_id) { } +function anon_identity_init($reqvars) { + + $x = [ 'request_vars' => $reqvars, 'xchan' => null, 'success' => 'unset' ]; + call_hooks('anon_identity_init',$x); + if($x['success'] !== 'unset' && intval($x['success']) && $x['xchan']) + return $x['xchan']; + + // allow a captcha handler to over-ride + if($x['success'] !== 'unset' && (intval($x['success']) === 0)) + return false; + + + $anon_name = strip_tags(trim($reqvars['anonname'])); + $anon_email = strip_tags(trim($reqvars['anonmail'])); + $anon_url = strip_tags(trim($reqvars['anonurl'])); + + if(! ($anon_name && $anon_email)) { + logger('anonymous commenter did not complete form'); + return false; + } + + if(! validate_email($anon_email)) { + logger('enonymous email not valid'); + return false; + } + + if(! $anon_url) + $anon_url = z_root(); + + $x = q("select * from xchan where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'unknown' limit 1", + dbesc($anon_email), + dbesc($anon_email) + ); + + if(! $x) { + xchan_store_lowlevel([ + 'xchan_guid' => $anon_email, + 'xchan_hash' => $anon_email, + 'xchan_name' => $anon_name, + 'xchan_url' => $anon_url, + 'xchan_network' => 'unknown', + 'xchan_name_date' => datetime_convert() + ]); + + $x = q("select * from xchan where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'unknown' limit 1", + dbesc($anon_email), + dbesc($anon_email) + ); + + $photo = z_root() . '/' . get_default_profile_photo(300); + $photos = import_xchan_photo($photo,$anon_email); + $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'unknown' ", + dbesc(datetime_convert()), + dbesc($photos[0]), + dbesc($photos[1]), + dbesc($photos[2]), + dbesc($photos[3]), + dbesc($anon_email), + dbesc($anon_email) + ); + + } + + return $x[0]; + +} \ No newline at end of file diff --git a/include/conversation.php b/include/conversation.php index 3f9ee5cfa..2eac2adde 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -533,6 +533,10 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $live_update_div = '' . "\r\n"; } + elseif ($mode === 'moderate') { + $profile_owner = local_channel(); + } + elseif ($mode === 'photos') { $profile_onwer = App::$profile['profile_uid']; $page_writeable = ($profile_owner == local_channel()); @@ -577,7 +581,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ if($items) { - if($mode === 'network-new' || $mode === 'search' || $mode === 'community') { + if(in_array($mode, [ 'network-new', 'search', 'community', 'moderate' ])) { // "New Item View" on network page or search page results // - just loop through the items and format them minimally for display @@ -609,14 +613,14 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent'])) continue; - $nickname = $item['nickname']; +// $nickname = $item['nickname']; } - else - $nickname = App::$user['nickname']; +// else +// $nickname = App::$user['nickname']; - $profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']); - if($item['author-link'] && (! $item['author-name'])) - $profile_name = $item['author-link']; +// $profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']); +// if($item['author-link'] && (! $item['author-name'])) +// $profile_name = $item['author-link']; $sp = false; $profile_link = best_link_url($item,$sp); @@ -625,7 +629,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ else $profile_link = zid($profile_link); - $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']); +// $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']); $profile_name = $item['author']['xchan_name']; $profile_link = $item['author']['xchan_url']; @@ -679,6 +683,8 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ 'template' => $tpl, 'toplevel' => 'toplevel_item', 'mode' => $mode, + 'approve' => t('Approve'), + 'delete' => t('Delete'), 'id' => (($preview) ? 'P0' : $item['item_id']), 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, $profile_url), 'profile_url' => $profile_link, diff --git a/include/items.php b/include/items.php index e79707aeb..9e1d5c1ba 100755 --- a/include/items.php +++ b/include/items.php @@ -906,7 +906,7 @@ function import_author_unknown($x) { $photos = import_xchan_photo($x['photo']['src'],$x['url']); if($photos) { - $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_url = '%s' and xchan_network = 'unknown'", + $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' and xchan_network = 'unknown'", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), diff --git a/view/js/main.js b/view/js/main.js index 38b9754a1..6c42531ea 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -13,6 +13,7 @@ function commentOpenUI(obj, id) { $("#comment-edit-text-" + id).attr('tabindex','9'); $("#comment-edit-submit-" + id).attr('tabindex','10'); $("#comment-tools-" + id).show(); + $("#comment-edit-anon-" + id).show(); } }; @@ -41,6 +42,7 @@ function commentOpen(obj, id) { $("#comment-edit-text-" + id).addClass("comment-edit-text-full"); $("#comment-edit-text-" + id).removeClass("comment-edit-text-empty"); $("#mod-cmnt-wrap-" + id).show(); + $("#comment-edit-anon-" + id).show(); openMenu("comment-tools-" + id); return true; } diff --git a/view/tpl/comment_item.tpl b/view/tpl/comment_item.tpl index 92eeac056..02b0c527c 100755 --- a/view/tpl/comment_item.tpl +++ b/view/tpl/comment_item.tpl @@ -11,9 +11,10 @@ {{if $anoncomments && ! $observer}} -
- {{include file="field_input.tpl" field=$authorname}} - {{include file="field_input.tpl" field=$authormail}} + {{/if}} diff --git a/view/tpl/search_item.tpl b/view/tpl/search_item.tpl index 66618a216..4ca6378b8 100755 --- a/view/tpl/search_item.tpl +++ b/view/tpl/search_item.tpl @@ -101,6 +101,17 @@
+ {{/if}} + {{if $item.mode === 'moderate'}} + +
+ {{$item.approve}} + {{$item.delete}} + +
+ + + {{/if}} -- cgit v1.2.3