Skip to content

Instantly share code, notes, and snippets.

@franz-josef-kaiser
Created June 14, 2012 13:07
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save franz-josef-kaiser/2930190 to your computer and use it in GitHub Desktop.
Save franz-josef-kaiser/2930190 to your computer and use it in GitHub Desktop.
Add a custom post status for WP (custom) post types
<?php
// No, Thanks. Direct file access forbidden.
! defined( 'ABSPATH' ) AND exit;
// INIT
add_action( 'after_setup_theme', array( 'unavailable_post_status', 'init' ) );
class unavailable_post_status extends wp_custom_post_status
{
/**
* @access protected
* @var string
*/
static protected $instance;
/**
* Creates a new instance. Called on 'after_setup_theme'.
* May be used to access class methods from outside.
*
* @return void
*/
static public function init()
{
null === self :: $instance and self :: $instance = new self;
return self :: $instance;
}
public function __construct()
{
// Set your data here. Only "$post_status" is required.
$this->post_status = 'unavailable';
// The post types where you want to add the custom status. Allowed are string and array
$this->post_type = 'post';
// @see parent class: defaults inside add_post_status()
$this->args = array();
parent :: __construct();
}
}
<?php
// No, Thanks. Direct file access forbidden.
! defined( 'ABSPATH' ) AND exit;
/*
Plugin Name: Custom Post Status
Plugin URI: http://
Description: Adds a custom post status for posts, pages or custom post types
Author: Franz Josef Kaiser
Version: 2012-06-14.1426
Author URI: http://unserkaiser.com/
License: MIT
*/
class wp_custom_post_status
{
/**
* Name of the post status
* Must be lower case
*
* @access protected
* @var string
*/
public $post_status;
/**
* Post type (slug) where the post status should appear
*
* @access protected
* @var string/array
*/
public $post_type = array( 'post', 'page' );
/**
* Custom Args for the post status
*
* @access protected
* @var string
*/
public $args;
/**
* Construct
* @return void
*/
public function __construct()
{
#echo '<pre>'; print_r( $this ); echo '</pre>';
// We need to have at least a post status name
if ( ! isset( $this->post_status ) )
return;
add_action( 'init', array( $this, 'add_post_status' ), 0 );
foreach ( array( 'post', 'post-new' ) as $hook )
add_action( "admin_footer-{$hook}.php", array( $this,'extend_submitdiv_post_status' ) );
}
/**
* Add a new post status of "Unavailable"
*
* @return void
*/
public function add_post_status()
{
global $wp_post_statuses;
$defaults = array(
'label_count' => false
// defaults to FALSE
,'hierarchical' => false
// defaults to FALSE
,'public' => true
// If NULL, then inherits "public"
,'publicly_queryable' => null
// most important switch
,'internal' => false
// If NULL, inherits from "internal"
,'exclude_from_search' => null
// If NULL, inherits from "internal"
,'show_in_admin_all_list' => null
// If NULL, inherits from "internal"
,'show_in_admin_status_list' => null
// If NULL, will be set to FALSE
,'protected' => null
// If NULL, will be set to FALSE
,'private' => null
// not set by the core function - defaults to NULL
,'show_in_admin_all' => null
// defaults to "post"
,'capability_type' => 'post'
,'single_view_cap' => null
// @internal use only - don't touch
,'_builtin' => false
,'_edit_link' => 'post.php?post=%d'
);
// if FALSE, will take the 1st fn arg
$defaults['label'] = __(
ucwords( str_replace(
array( '_', '-' )
,array( ' ', ' ' )
,$this->post_status
) )
,'cps_textdomain'
);
// Care about counters:
// If FALSE, will be set to array( $args->label, $args->label ), which is not desired
$defaults['label_count'] = _n_noop(
"{$defaults['label']} <span class='count'>(%s)</span>"
,"{$defaults['label']} <span class='count'>(%s)</span>"
,'cps_textdomain'
);
// Register the status: Merge Args with defaults
register_post_status(
$this->post_status
,wp_parse_args(
$this->args
,$defaults
)
);
}
/**
* Adds post status to the "submitdiv" Meta Box and post type WP List Table screens
*
* @return void
*/
public function extend_submitdiv_post_status()
{
// Abort if we're on the wrong post type, but only if we got a restriction
if ( isset( $this->post_type ) )
{
global $post_type;
if ( is_array( $this->post_type ) )
{
if ( in_array( $post_type, $this->post_type ) )
return;
}
elseif ( $this->post_type !== $post_type )
{
return;
}
}
// Our post status and post type objects
global $wp_post_statuses, $post;
// Get all non-builtin post status and add them as <option>
$options = $display = '';
foreach ( $wp_post_statuses as $status )
{
if ( ! $status->_builtin )
{
// Match against the current posts status
$selected = selected( $post->post_status, $status->name, false );
// If we one of our custom post status is selected, remember it
$selected AND $display = $status->label;
// Build the options
$options .= "<option{$selected} value='{$status->name}'>{$status->label}</option>";
}
}
?>
<script type="text/javascript">
jQuery( document ).ready( function($)
{
<?php
// Add the selected post status label to the "Status: [Name] (Edit)"
if ( ! empty( $display ) ) :
?>
$( '#post-status-display' ).html( '<?php echo $display; ?>' )
<?php
endif;
// Add the options to the <select> element
?>
$( '.edit-post-status' ).on( 'click', function()
{
var select = $( '#post-status-select' ).find( 'select' );
$( select ).append( "<?php echo $options; ?>" );
} );
} );
</script>
<?php
}
}
@knutsp
Copy link

knutsp commented Jun 19, 2013

This was very useful and exactly what I needed. Thank you!

If you click .edit-post-status, cancels this and click again, the custom post statuses are added again and again. To avoid this I modified the script a little by introducing the var appended:

        jQuery( document ).ready( function($) 
        {
            var appended = false;
            <?php
            // Add the selected post status label to the "Status: [Name] (Edit)" 
            if ( ! empty( $display ) ) : 
            ?>
                $( '#post-status-display' ).html( '<?php echo $display; ?>' )
            <?php 
            endif; 

            // Add the options to the <select> element
            ?>
            $( '.edit-post-status' ).on( 'click', function()
            {
                if ( !appended )
                {
                    var select = $( '#post-status-select' ).find( 'select' );
                    $( select ).append( "<?php echo $options; ?>" );
                    appended = true;
                }
            } );
        } );

@gingerbeardman
Copy link

I've not been able to get this to work with Wordpress 3.5.2 - I see no changes after adding the code. Any ideas?

@alecarg
Copy link

alecarg commented Jul 4, 2013

Nice one @franz-josef-kaiser and @knutsp

I found that 'post_type' (example_post_status.php:36) is not accepting an array as an argument as stated in the comment:35. But, setting the desired post-type's slug as a string works just fine. Which leads me to think that you, @gingerbeardman , tried the same thing as I did, with no success. I see you found a solution ( http://jamescollings.co.uk/blog/wordpress-create-custom-post-status/ ), which might be a good reference for future visitors.

@michael-cannon
Copy link

The jQuery should only be called once otherwise, multiple copies are produced. Further, all added post status are added, than only those by this method.

I'll link to my fixes tomorrow when not so groggy.

@michael-cannon
Copy link

Changes made at https://github.com/michael-cannon/aihrus-framework/blob/1.1.0RC2/includes/libraries/wp_custom_post_status.php. If the link breaks, change branch to master or 1.1.0 in url.

@michael-cannon
Copy link

Also, it should be noted…

  • Doesn't affect quick and bulk edit screens
  • Doesn't include baseline defaults

I'll worry about these later.

Copy link

ghost commented Mar 25, 2014

147-148th line
if ( in_array( $post_type, $this->post_type ) ) return;

should be !in_array

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment