I am implementing a front end AJAX comment moderation system for a site I manage but I am having a hard time getting it to work. Right now clicking on the link that approves the comment runs the proper php script but it reloads the entire page. So it works but I’d like to approve the comment using ajax without reloading the entire page, but my lack of javascript knowledge is preventing me from getting this to work. Here is the code (located in a plugin):
add_filter( 'comment_text', 'p3_comment_moderation_buttons' );
function p3_comment_moderation_buttons ( ) {
if ( is_author() || current_user_can( 'moderate_comment' ) ) {
// Adds moderation buttons under every comment
$comment_id = get_comment_ID();
$text = get_comment_text();
$nonce = wp_create_nonce( 'p3_comment_moderation' );
$p3_approve_link = admin_url('admin-ajax.php?action=p3_comment_approve&comment_id='. $comment_id.'&nonce='.$nonce);
$p3_edit_links = '<div class="p3-edit-links"><a class="p3-comment-moderation" href="' . $p3_approve_link . '" data-comment_id="' . $comment_id . '" data-nonce="' . $nonce . '">Approve</a></div>';
return $text . $p3_edit_links;
}
else{
return get_comment_text();
}
}
add_action("wp_ajax_p3_comment_approve", "p3_comment_approve");
function p3_comment_approve() {
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'p3_comment_moderation' ) ) {
exit("Go away!"); //If nonce check fails stop everything
}
$comment_id = $_REQUEST["comment_id"];
$success = wp_set_comment_status( $comment_id, 'approve' );
$success = update_comment_meta( $comment_id, 'p3_comment_status', '' );
if ( $success = true ) {
$result['type'] = 'success';
$result['comment_id'] = $_REQUEST["comment_id"];
}
else {
$result['type'] = 'error';
$result['comment_id'] = $_REQUEST["comment_id"];
echo "Something didn't work";
}
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$result = json_encode($result);
echo $result;
}
else {
header("Location: ".$_SERVER["HTTP_REFERER"]);
}
die(); // this is required to return a proper result
}
add_action( 'init', 'p3_comment_meta_script_enqueuer' );
function p3_comment_meta_script_enqueuer() {
wp_register_script( "p3_comment_meta", plugins_url().'/p3wp-comments/js/p3_comment_meta.js', array('jquery') );
wp_localize_script( "p3_comment_meta", 'p3cmetaAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' )));
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'p3_comment_meta' );
}
And the corresponding javascript:
jQuery(document).ready( function() {
jQuery(".p3-comment-moderation").click( function() {
comment_id = jQuery(this).attr("data-comment_id")
nonce = jQuery(this).attr("data-nonce")
jQuery.ajax({
type : "post",
dataType : "json",
url : p3cmetaAjax.ajaxurl,
data : {action: "p3_comment_meta", comment_id : comment_id, nonce: nonce},
success: function(response) {
if(response.type == "success") {
alert("Success!")
}
else {
alert("Something went wrong.")
}
}
})
})
})
Can anyone spot the problem?
BTW I have already modified the comment template to display unapproved comments so they can be approved on the front end. I also plan to expand this to to work with custom comment meta, and expand the javascript so it does something more useful than displaying an annoying alert
Thanks
Seems to me that the only problem is that you put the full approve url in the link, in this ways when you click the link you trigger the ajax and open the page url in the link.
To be more clear your link is something like:
thanks to the javascript, when you click on the link you launch an ajax request but, there is nothing that prevent the default link behaviour to be triggered, and so the
admin-ajax.php
is required to the browser, and thanks to theheader
statement in your code, then the page comes back again to current page.So, actually, this is what happen:
admin-ajax.php
is open by the url in thea
tagheader("Location: ".$_SERVER["HTTP_REFERER"])
statement in your codeI know that putting the full url in the link is the right way to make it works even if the user has javascript disabled, but when javascript is enabled you must prevent the default link behaviour, this can be done via the
preventDefault()
js function.So, in your javascript replace
with
After that everything should work as expected.
If, like I guess, this is the only problem, this question is a pure javascript one, so off-topic here. However, to make my answer more WordPress relevant I want add some tips (nothing that make the script work or not, just best practice and improvements).
Tip 1: Escape attributes and links
When in WordPress you output something in the html output as tag property, best practice is escape it with
esc_attr
, in general use allesc_*
function when applyableis better wrote:
I know that you getting urls and attributes from WP core functions, however once almost all output from core can be filtered is good to apply data validation (although data validation functions can filtered too…)
Tip 2: use core constant to check ajax requests
In your code there’s
to check if the current request is from ajax. In WordPress when you properly use
admin-ajax.php
(like you do) you can check ajax request looking forDOING_AJAX
constant, so the previous conditional statement becomes:Tip 3: use core function to output json and exit script
Your code
can be wrote in one line, using the core
wp_send_json
functionTip 4: avoid direct superglobals access
when you have to handle superglobals (
$_REQUEST
,$_GET
,$_POST
…) to avoid notices you should always check that the key you are looking for is setted, so youris better wrote:
However, is even better to use
filter_var
instead of accessing superglobals directly