How to Add a Custom Post Status In WordPress

We had the task to add a new custom status for posts in WordPress, namely to the custom post type (pdf_order). The bottom line was that the client received orders in the form of records containing a PDF document with the ability to edit it.

After processing the order, the client usually sent them to the Trash, but since he was not the only system administrator, there was always the possibility that someone would press the empty trash button and it would all just vanished. And the essence of the task was to add a new status so that the records processed would not be collected in the trash but say in the completed folder.

How it was at first:

 

The Result:

Starting the task, I have immediately begun searching for a solution on wordpress.org. Here I found an article on how to do this, and at first it seemed to be a trifle, but then I faced that everything was not that simple.

Unfortunately, the example in the article turned out to be not applicable in practice. Searching, I realized that I was not the only one and that many were faced with the fact that the new status was added for records but not displayed in the admin panel and it cannot be assigned not to be displayed in a dropdown.

Googling a bit, I found a lot of solutions on how to make and add status to existing ones, but all of them were not fully satisfactory. For example, you add a new status to the list, but when you select it in the admin panel, after Status there is nothing..

And also our status is not active by default in a dropdown, which, when saved, will set the status to Pending Review.

Below we give the final code that we got, maybe it will be useful for someone.

Standard code from wordpress.org that simply logs the new status of 'completed'

function my_custom_status_creation(){
register_post_status( 'completed', array(
'label'                     => _x( 'Completed', 'post' ),
'label_count'               => _n_noop( 'Completed <span class="count">(%s)</span>', 'Completed <span class="count">(%s)</span>'),
'public'                    => true,
'exclude_from_search'       => false,
'show_in_admin_all_list'    => true,
'show_in_admin_status_list' => true
));
}
add_action( 'init', 'my_custom_status_creation' );

Adding status in the edit mode.

function add_to_post_status_dropdown()
{
global $post;
if($post->post_type != 'pdf_order')
return false;

$status = ($post->post_status == 'completed') ? "jQuery( '#post-status-display' ).text( 'Completed' ); jQuery( 'select[name=\"post_status\"]' ).val('completed');" : '';
echo "<script>
jQuery(document).ready( function() {
jQuery( 'select[name=\"post_status\"]' ).append( '<option value=\"completed\">Completed</option>' );
".$status."
});
</script>";
}

add_action( 'post_submitbox_misc_actions', 'add_to_post_status_dropdown');

The Result

Checking that we editing exactly pdf-order, if other then leaving the function.

global $post;
if($post->post_type != 'pdf_order')
return false;

Very similar feature to edit using Quick Edit mode.

function custom_status_add_in_quick_edit() {
global $post;
if($post->post_type != 'pdf_order')
return false;

echo "<script>
jQuery(document).ready( function() {
jQuery( 'select[name=\"_status\"]' ).append( '<option value=\"completed\">Completed</option>' );
});
</script>";
}
add_action('admin_footer-edit.php','custom_status_add_in_quick_edit');

Displaying category in the list of entries.

function display_archive_state( $states ) {
global $post;
$arg = get_query_var( 'post_status' );
if($arg != 'completed'){
if($post->post_status == 'completed'){
echo "<script>
jQuery(document).ready( function() {
jQuery( '#post-status-display' ).text( 'Completed' );
});
</script>";

return array('Completed');
}
}
return $states;
}
add_filter( 'display_post_states', 'display_archive_state' );

All the code:

function my_custom_status_creation(){
register_post_status( 'completed', array(
'label'                     => _x( 'Completed', 'post' ),
'label_count'               => _n_noop( 'Completed <span class="count">(%s)</span>', 'Completed <span class="count">(%s)</span>'),
'public'                    => true,
'exclude_from_search'       => false,
'show_in_admin_all_list'    => true,
'show_in_admin_status_list' => true
));
}
add_action( 'init', 'my_custom_status_creation' );

function add_to_post_status_dropdown()
{
global $post;
if($post->post_type != 'pdf_order')
return false;

$status = ($post->post_status == 'completed') ? "jQuery( '#post-status-display' ).text( 'Completed' );
jQuery( 'select[name=\"post_status\"]' ).val('completed');" : '';
echo "<script>
jQuery(document).ready( function() {
jQuery( 'select[name=\"post_status\"]' ).append( '<option value=\"completed\">Completed</option>' );
".$status."
});
</script>";
}

add_action( 'post_submitbox_misc_actions', 'add_to_post_status_dropdown');

function custom_status_add_in_quick_edit() {
global $post;
if($post->post_type != 'pdf_order')
return false;

echo "<script>
jQuery(document).ready( function() {
jQuery( 'select[name=\"_status\"]' ).append( '<option value=\"completed\">Completed</option>' );
});
</script>";
}
add_action('admin_footer-edit.php','custom_status_add_in_quick_edit');

function display_archive_state( $states ) {
global $post;
$arg = get_query_var( 'post_status' );
if($arg != 'completed'){
if($post->post_status == 'completed'){
echo "<script>
jQuery(document).ready( function() {
jQuery( '#post-status-display' ).text( 'Completed' );
});
</script>";

return array('Completed');
}
}
return $states;
}
add_filter( 'display_post_states', 'display_archive_state' );

It works in any version of the WP, at the time of writing the version WordPress 5.1. But we should note that in the new WordPress editor, it works only in a quick edit mode.