在待发帖子的前端预览页面上启用评论

时间:2013-11-02 作者:Christine Cooper

我们正在允许作者合作成为编辑过程的一部分。他们将有权访问所有挂起帖子的预览页面(不是帖子编辑页面)。

我想允许这些用户在帖子处于挂起状态时发布普通评论post_status.

经研究,一个全面的解决方案posted here, 尽管该解决方案只支持通过后期编辑页面进行评论,而不是我正在寻找的预览页面。

1 个回复
最合适的回答,由SO网友:gmazzap 整理而成

序言一旦文章预览成为前端,评论形式取决于主题如何处理它。我将在回答中假设注释表是使用标准显示的comment_form() 作用

事实上,前面的假设是不够的comment_form 可能是WordPress核心中有更多挂钩的函数。几乎每根绳子都有一个钩子。所以页面上显示的内容在很大程度上取决于插件或可以改变它的主题。

之后,comment_form 用于保存注释aPOSTwp-comment-post.php 这也包含很多钩子,所以即使我的解决方案可以在使用二十个*主题的普通WP安装上运行,我也不能保证它也可以在一些插件或自定义主题上运行。

工作流

因此,一旦我们假设是在标准情况下,您所问的比链接问答更简单,因为评论表单不使用ajax,而且有很多挂钩可以帮助我们获得所需的结果(在前言中讨论了这一点的负面影响)。

基本上,我们必须:

当我们在等待后期预览时,在评论表单中添加一个字段,这样我们可以识别来自该表单的评论

/**
 * Return true if user can comment on post preview
 */
function is_a_preview_commenter() {
  // change this roles according to your needs
  $roles = array(\'administrator\', \'editor\', \'author\', \'contributor\');
  $allowed_roles = apply_filters(\'preview_comment_allowed_roles\', $roles);
  $user = wp_get_current_user();
  $inrole = array_intersect($user->roles, $allowed_roles);
  return ! empty( $inrole );
} 

/**
 * Add a nonce field for comment form in post preview for allowed users
 */
function additional_comment_fields() {
  if ( is_preview() && is_a_preview_commenter() ) {
    $nonce = wp_create_nonce(\'comment_preview\');
    echo \'<input type="hidden" name="check_the_preview" value="\' . $nonce . \'" />\';
  }
}
add_action( \'comment_form_logged_in_after\', \'additional_comment_fields\');
现在让我们来挑逗一下WordPress。WP用于检查帖子状态是否适合评论的方法是调用$status_obj = get_post_status_object($status) (其中$statuspost_status 然后检查是否$status_objprivatepublic 否则wp_die. 但唯一能get_post_status_object 是否从全局数组返回值$wp_post_statuses (键入请求的post状态的一个)伪造全局变量表示伪造get_post_status_object 还有伪造WordPress检查。

更改全局变量非常简单,但是我将进行一些检查以确保帖子来自我们(由于之前添加了nonce hidden字段),并检查当前用户是否存在以及是否允许:

/**
 * On \'wp_loaded\', when the current page is wp-comments-post.php, check if the request
 * comes from post preview, if so and also the current user is allowed replace 
 * $GLOBALS[\'wp_post_statuses\'][\'pending\'] with $GLOBALS[\'wp_post_statuses\'][\'publish\']
 */
function fake_public_pending() {
  global $pagenow;
  if ( $pagenow === \'wp-comments-post.php\' && is_a_preview_commenter() ) {
    $nonce = filter_input(INPUT_POST, \'check_the_preview\', FILTER_SANITIZE_STRING);
    if ( empty($nonce) || ! wp_verify_nonce($nonce, \'comment_preview\') ) return;
    global $wp_post_statuses;
    // let WordPress believe all pending posts are published post
    $wp_post_statuses[\'pending\'] = $wp_post_statuses[\'publish\'];
  }
}
add_action(\'wp_loaded\', \'fake_public_pending\');
现在,在从后期预览插入注释后,我们必须再次将浏览器重定向到后期预览。像往常一样,我们保证请求来自后期预览,并且当前用户有一个允许的角色

/**
 * After a comment is inserted, redirect page to post preview when request come from
 * post preview. Also check if current user role is one of the allowed
 */
function redirect_to_preview( $comment, $user ) {
  if ( ! is_a_preview_commenter() ) return;
  $nonce = filter_input(INPUT_POST, \'check_the_preview\', FILTER_SANITIZE_STRING);
  if ( empty($nonce) || ! wp_verify_nonce($nonce, \'comment_preview\') ) return;
  $link = get_permalink($comment->comment_post_ID);
  $url = add_query_arg( array(\'preview\' => \'true\'), $link );
  wp_safe_redirect("{$url}#comment-{$comment->comment_ID}", 302);
  exit();
}
add_action(\'set_comment_cookies\', \'redirect_to_preview\', 9999, 2 );

结束