序言一旦文章预览成为前端,评论形式取决于主题如何处理它。我将在回答中假设注释表是使用标准显示的comment_form()
作用
事实上,前面的假设是不够的comment_form
可能是WordPress核心中有更多挂钩的函数。几乎每根绳子都有一个钩子。所以页面上显示的内容在很大程度上取决于插件或可以改变它的主题。
之后,comment_form
用于保存注释aPOST
到wp-comment-post.php
这也包含很多钩子,所以即使我的解决方案可以在使用二十个*主题的普通WP安装上运行,我也不能保证它也可以在一些插件或自定义主题上运行。
工作流
因此,一旦我们假设是在标准情况下,您所问的比链接问答更简单,因为评论表单不使用ajax,而且有很多挂钩可以帮助我们获得所需的结果(在前言中讨论了这一点的负面影响)。
基本上,我们必须:
当我们在等待后期预览时,在评论表单中添加一个字段,这样我们可以识别来自该表单的评论一旦我们必须打破WordPress的安全检查,以允许对挂起的帖子发表评论,那么用另一个检查取代这个检查是一个好主意:在第1点的隐藏字段中使用nonce。这可能是个好主意作为额外的安全检查,我认为只为注册用户启用评论是一个好主意(但似乎您已经只允许注册用户预览访问)。也许限制角色也是个好主意此工作流的核心部分是WordPress所做的阻止对待定帖子和草稿帖子发表评论的检查。我的想法只是想挑逗一下WordPress,让它相信我们的帖子已经发表了。我将这样做,可以作为一个例子,说明为什么应该避免全局变量,以防止我们的代码被别人嘲笑我们要做的最后一件事是,在创建注释后拦截重定向,因为标准重定向指向标准的post permalink,我们需要指向post preview permalink。首先,让我们创建一个函数,在注释表单中添加一个nonce字段,只针对允许登录的用户,并且只针对post preview。我还将编写一个函数来检查当前用户是否是允许的用户之一,这样我就可以将其用于其他作用域。在这个函数中,我放置了一个自定义过滤器挂钩,这样可以更改角色allowd。
/**
* 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)
(其中
$status
是
post_status
然后检查是否
$status_obj
是
private
或
public
否则
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 );