Creating an admin meta box to save post as pending

The workflow when using WordPress to change a draft post to pending involves several clicks and button presses, especially on mobile

workflow

So to simplify my process I would like to create a meta box that just has a save as pending button. ( I have a plugin that takes pending posts and publishes them to a schedule, so having a single button would be fine)

My code

add_action( 'add_meta_boxes', 'wp_cfc_register_meta_boxes' );
add_action( 'save_post', 'wp_cfc_save_meta_box' );


/**
 * Register meta box(es).
 */
function wp_cfc_register_meta_boxes() {
    add_meta_box( 'wp_cfc_pending_meta', __( 'Add to Pending Queue', 'textdomain' ), 'wp_cfc_display_callback', 'post' );

}

/**
 * Meta box display callback.
 * @param WP_Post $post Current post object.
 */
function wp_cfc_display_callback( $post ) {

    wp_nonce_field( 'wp_cfc_pending_meta_box_nonce', 'meta_box_nonce' );
    // Display code/markup goes here. Don't forget to include nonces!
    ?>
    <div id="minor-publishing-actions">
        <div id="save-action">
            <input name="original_publish" type="hidden" id="original_publish" value='pending'" />
            <?php submit_button( __( 'Save as Pending' ), 'secondary button-large', 'Publish', false ); ?>
        </div>
    </div>
    <?php
}

/**
 * Save meta box content.
 * @param int $post_id Post ID
 */
function wp_cfc_save_meta_box( $post_id ) {

    // make post id is set otherwise we'd be in trouble
    if(!isset($post_id)) return;

    $cfc_post = array ( 'ID' => $post_id, 'post_status' => 'pending');

    // Bail if we're doing an auto save
    if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;

    // if our nonce isn't there, or we can't verify it, bail
    if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'wp_cfc_pending_meta_box_nonce' ) ) return;

    // if our current user can't edit this post, bail
    if( !current_user_can( 'edit_post' ) ) return;

    // check it's a post and the update the post setting it to pending
    if( isset( $_POST['wp_cfc_save_meta_box']) ) {
        remove_action('save_post', 'wp_cfc_save_meta_box'); //if you don't unhook the function you'll have an infinite loop
            wp_update_post($cfc_post);
        add_action('save_post', 'wp_cfc_save_meta_box'); //rehook the function
    }

}`

The button can be pressed and is displayed as expected, the post is updated according to the message back from WordPress but the post status is not set. My method seems to be called on the normal post setting changes too.

I am the only user and I am admin, it’s not practicable to simply change user roles as sometimes I need to set an actual publish date etc. This button is simply to speed up my workflow.

I cannot find anyone doing anything similar, but hopefully someone can see what I am missing?

Solutions Collecting From Web of "Creating an admin meta box to save post as pending"

The reason your code does not work is that the if-statement checking isset( $_POST['wp_cfc_save_meta_box']) never evaluates to true. Your code generating the submit button,

<?php submit_button( __( 'Save as Pending' ), 'secondary button-large', 'Publish', false ); ?>

yields the following HTML:

<input type="submit" name="Publish" id="Publish" class="button button-large" value="Save as Pending"  />

WordPress’ submit_button function takes several arguments, the third of which is $name. This is used as the HTML name attribute of the submit button input element, and is passed in the $POST array on submission of the form. Thus, instead of the desired $_POST['wp_cfc_save_meta_box'], $_POST['Publish'] becomes set. To tackle the problem, change the $name$ parameter to 'wp_cfc_save_meta_box'. This yields

<?php submit_button( __( 'Save as Pending' ), 'secondary button-large', 'wp_cfc_save_meta_box', false ); ?>

By the way…

You could make this a little bit prettier and utilize the post_submitbox_misc_actions action to add the button to the original Publish met box instead of a custom meta box.