I'm writing a post approval utility for the front end, because we don't want our editor to be able to access the admin dashboard. There are questions on Stack nearly identical to what I'm trying to accomplish, but that guy's problem has to do with the infinite loop issue. Otherwise, he claims his code works:
How to change post status from publish to draft using hook in wordpress?
I'm writing a plugin to do this (in my case I want to change 'draft' to 'publish'). I don't want to have to edit the functions.php in the child theme, because I want the plugin to be standalone, for any WordPress site. So all code is in my plugin's main php file.
- I can get all posts with status of 'draft'.
- I can use an html checkbox, javascript, and WP's ajax functions to select the post I want to change by ID.
The "change status" code looks like this (in the plugin main php file):
/* This function should toggle a post status from 'draft' to 'publish' */
add_action( 'wp_ajax_approvepost', 'approvepost_callback' );
add_action( 'wp_ajax_nopriv_approvepost', 'approvepost_callback' );
function approvepost_callback(){
$post = array(
'ID' => $_POST['postid'], // e.g., 28
'post_status' => 'publish',
'edit_date' => true
);
$result = wp_update_post($post,true); // (there, you like that better?)
echo $result; // I get a result of "1". The post ID is 28. wp_update_post failed?
wp_die();
}
... wp_update_post
returns a 1, so I take that to mean there were no errors. But when I refresh the front-end page, the post shows up again, meaning it is still in draft mode, and when I inspect the post in the WP admin dashboard, sure enough, it's still in draft. What am I doing wrong or missing?
UPDATE: If I execute the function from my child theme functions.php, the code works, but not by using AJAX. I have to call the function directly, like by refreshing the page, and the function returns the post ID, and the post status will change to 'publish'. As soon as I invoke the function using AJAX, the post status does not change, and the function returns a 1.
UPDATE I removed the AJAX action altogether, and defaulted to an old timey standard form submit, which refreshes the form page. Under these conditions, wp_update_post works as expected. Something about wp_update_post doesn't like to be called by AJAX. My suspicion is it has something to do with security, but whatever it is, I can't find any reference to it in the documentation.
ADDITIONAL JAVASCRIPT Some have asked to see the javascript, especially the ajax code:
jQuery(document).ready(function($){
// AJAX url
var ajax_url = approve_posts_ajax_object.ajax_url;
var data = {
'action': 'approvepost',
};
$('button#submit-approval').on("click",function(){
var checkboxes = $("input[name='post_id']");
data.postid = [];
// loop over them all
for (var i=0; i<checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
data.postid[i] = $(checkboxes[i]).val();
}
else{
data.postid[i] = "";
}
}
$.ajax({
url: ajax_url,
type: 'post',
data: data,
dataType: 'json',
success: function(response){
// Add new rows to table
approvePost(response);
}
});
});
});
function approvePost(data){
jQuery("#diag").html(data); //just want to output the callback response for now.
}
SOLUTION (so that others can see what works):
Javascript, with AJAX call:
jQuery(document).ready(function($){
// AJAX url
var ajax_url = approve_posts_ajax_object.ajax_url;
var data = {
'action': 'approvepost',
};
$('button#approval_submit').on("click",function(){
var checkboxes = $("input[name='post_id']");
data.postid = [];
// loop over them all
for (var i=0; i<checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
data.postid[i] = $(checkboxes[i]).val();
}
}
$.ajax({
url: ajax_url,
type: 'post',
data: data,
dataType: 'json',
success: function(response){
approvePost(response);
}
});
});
});
function approvePost(data){
jQuery("#diag").html("");
var string = "\n";
jQuery.each(data,function(k,v){
string += k + " = " + v + "<br>";
});
jQuery("#diag").append(string);
}
PHP (with ajax callback function, in main plugin file):
/* This is the function that toggles a post status from draft to published */
add_action( 'wp_ajax_approvepost', 'approvepost_callback' );
add_action( 'wp_ajax_nopriv_approvepost', 'approvepost_callback' );
function approvepost_callback(){
$update = array();
for($i=0;$i<count($_POST['postid']);$i++){
$post = array(
'ID' => $_POST['postid'][$i],
'post_status' => 'publish'
);
$update[$i] = wp_update_post($post);
}
echo json_encode($update);
wp_die();
}
wp_update_post
returns the post ID on success, so unless your ID is 1, then something is awry there. Try checking for awp_error
.$_POST
is unusual and likely to cause fatal errors on newer versions of PHP. It also means everything passed into the AJAX endpoint also gets returned which could lead to security issues. Was there a reason not to use the Posts endpoint of the REST API for your AJAX? This code would allow any post to be published bypassing capability security checksecho $result
withvar_dump( $result )
and try again making your AJAX call, then see what the dump outputted. And I also agreed with @HowdyMcGee, so can we see your AJAX/JS script? Did you try checking the console for any errors?