allow moderated comments like wordpress if permissions are compatible

This commit is contained in:
zotlabs 2017-06-18 22:25:41 -07:00 committed by Mario Vavti
parent 3d6255ae24
commit 1472f85b16
13 changed files with 222 additions and 22 deletions

View file

@ -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;

View file

@ -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, '<a href="' . $siteurl . '">' . $sitename . '</a>');
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) {

View file

@ -743,8 +743,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;

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,77 @@
<?php
namespace Zotlabs\Module;
require_once('include/conversation.php');
class Moderate extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(argc() > 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;
}
}

View file

@ -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];
}

View file

@ -2323,3 +2323,70 @@ function channel_codeallowed($channel_id) {
return false;
}
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];
}

View file

@ -533,6 +533,10 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$live_update_div = '<div id="live-search"></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,

View file

@ -938,7 +938,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]),

View file

@ -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;
}

View file

@ -11,9 +11,10 @@
<input type="hidden" name="jsreload" value="{{$jsreload}}" />
<input type="hidden" name="preview" id="comment-preview-inp-{{$id}}" value="0" />
{{if $anoncomments && ! $observer}}
<div id="comment-edit-anon-{{$id}}">
{{include file="field_input.tpl" field=$authorname}}
{{include file="field_input.tpl" field=$authormail}}
<div id="comment-edit-anon-{{$id}}" style="display: none;" >
{{include file="field_input.tpl" field=$anonname}}
{{include file="field_input.tpl" field=$anonmail}}
{{include file="field_input.tpl" field=$anonurl}}
{{$anon_extras}}
</div>
{{/if}}

View file

@ -101,6 +101,17 @@
<button type="button" class="btn btn-outline-secondary btn-sm wall-item-like dropdown-toggle" data-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="fa fa-paperclip"></i></button>
<div class="dropdown-menu">{{$item.attachments}}</div>
</div>
{{/if}}
{{if $item.mode === 'moderate'}}
<div class="wall-item-tools-left btn-group">
<a href="moderate/{{$item.id}}/approve" class="btn btn-outline-secondary btn-small">{{$item.approve}}</a>
<a href="moderate/{{$item.id}}/drop" class="btn btn-outline-secondary btn-small">{{$item.delete}}</a>
</div>
{{/if}}
</div>
</div>