settings = new Post_Status_Settings();
add_action( 'init', [ $this, 'register_post_status' ] );
// Add custom statuses to the post states.
add_filter( 'display_post_states', [ $this, 'add_custom_post_states' ], 9, 2 );
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_scripts' ] );
add_filter( 'admin_body_class', [ $this, 'add_admin_body_class' ] );
}
/**
* Register Post Status
*
* @return void
*/
public function register_post_status() {
// Register 'post_status' taxonomy to store user created post statuses.
if ( ! taxonomy_exists( self::TERM_KEY ) ) {
$args = [
'hierarchical' => false,
'label' => false,
'query_var' => false,
'rewrite' => false,
'show_ui' => false,
];
register_taxonomy( self::TERM_KEY, 'post', $args );
}
$custom_post_statuses = self::get_custom_post_statuses();
if ( ! empty( $custom_post_statuses ) ) {
foreach ( $custom_post_statuses as $custom_status ) {
// translators: %1$s: custom status name %2$s post count.
$singular = sprintf( __( '%1$s (%2$s)', 'admin-optimizer' ), $custom_status->name, '%s' );
// translators: %1$s: custom status name %2$s post count.
$plural = sprintf( __( '%1$s (%2$s)', 'admin-optimizer' ), $custom_status->name, '%s' );
$label_count = [
0 => $singular,
1 => $plural,
'singular' => $singular,
'plural' => $plural,
'context' => null,
'domain' => 'admin-optimizer',
];
register_post_status(
$custom_status->slug,
[
'label' => $custom_status->name,
'protected' => true,
'_builtin' => false,
'label_count' => $label_count,
]
);
}
}
}
/**
* Get user defined custom post status
*
* @param array $extra_args Extra arguments.
*
* @return int[]|string|string[]|\WP_Error|\WP_Term[]
*/
public static function get_custom_post_statuses( $extra_args = [] ) {
$default_args = [
'taxonomy' => self::TERM_KEY,
'hide_empty' => false,
];
if ( ! empty( $extra_args ) ) {
$args = array_unique( array_merge( $default_args, $extra_args ) );
} else {
$args = $default_args;
}
return get_terms( $args );
}
/**
* Get core statuses that should be available alongside custom statuses.
*
* @return array[]
*/
private static function get_default_editor_statuses() {
return [
[
'slug' => 'pending',
'name' => __( 'Pending Review', 'admin-optimizer' ),
],
[
'slug' => 'draft',
'name' => __( 'Draft', 'admin-optimizer' ),
],
];
}
/**
* Get the custom post statuses visible for the given post type to the
* current user. Free makes every custom status available everywhere;
* this is the sole hook Pro uses (`adminoptim_post_status_visible_statuses`)
* to restrict availability by post type and user role.
*
* @param string $post_type Post type context.
*
* @return \WP_Term[]
*/
private function get_visible_custom_statuses( $post_type ) {
$custom_post_statuses = self::get_custom_post_statuses();
if ( empty( $custom_post_statuses ) || is_wp_error( $custom_post_statuses ) ) {
$custom_post_statuses = [];
}
return apply_filters( 'adminoptim_post_status_visible_statuses', $custom_post_statuses, $post_type );
}
/**
* Check if any custom statuses are available for the given post type.
*
* @param string $post_type Post type context.
*
* @return bool
*/
private function has_available_custom_statuses( $post_type ) {
return ! empty( $this->get_visible_custom_statuses( $post_type ) );
}
/**
* Add custom post status class to eligible block editor screens.
*
* @param string $classes Admin body classes.
*
* @return string
*/
public function add_admin_body_class( $classes ) {
global $pagenow, $post;
$screen = get_current_screen();
if ( ! $screen || ! $screen->is_block_editor() ) {
return $classes;
}
if ( ! in_array( $pagenow, [ 'post.php', 'post-new.php', 'page.php', 'page-new.php' ], true ) ) {
return $classes;
}
$post_type = $post->post_type ?? ( isset( $_GET['post_type'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) : 'post' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( $this->has_available_custom_statuses( $post_type ) ) {
$classes .= ' adminoptimizer-custom-statuses';
}
return $classes;
}
/**
* Render the settings page
*
* @return void
*/
public function render_settings_page() {
$this->settings->render_settings_page();
}
/**
* Add custom post states
*
* @param array $states Post States.
* @param \WP_Post $post Post object.
*
* @return mixed
*/
public function add_custom_post_states( $states, $post ) {
/* Receive the post status object by post status name */
$post_status_object = get_post_status_object( $post->post_status );
/* Checks if the label exists */
if ( in_array( $post_status_object->label, $states, true ) ) {
return $states;
}
$queried_status = $_REQUEST['post_status'] ?? ''; //phpcs:ignore
if ( $queried_status === $post_status_object->name ) {
// No need to display the post status if a specific status was already requested.
return $states;
}
$states[ $post_status_object->name ] = $post_status_object->label;
return $states;
}
/**
* Enqueue scripts for block editor
*
* @return void
*/
public function enqueue_block_scripts() {
global $pagenow, $post;
$screen = get_current_screen();
if ( in_array( $pagenow, [ 'post.php', 'edit.php', 'post-new.php', 'page.php', 'edit-pages.php', 'page-new.php' ], true ) ) {
$post_type = $post->post_type ?? ( isset( $_GET['post_type'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) : 'post' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( $screen->is_block_editor() && $this->has_available_custom_statuses( $post_type ) ) {
$asset_file = self::MODULE_PATH . 'block/dist/index.asset.php';
$asset = file_exists( $asset_file )
? include $asset_file
: [
'dependencies' => [ 'react-jsx-runtime', 'wp-components', 'wp-data', 'wp-editor', 'wp-i18n', 'wp-plugins' ],
'version' => ADMINOPTIMIZER_VERSION,
];
wp_enqueue_script(
'adminoptimizer-block-custom-status',
self::MODULE_URL . 'block/dist/index.js',
$asset['dependencies'],
$asset['version'],
true
);
wp_enqueue_style(
'adminoptimizer-block-custom-status',
self::MODULE_URL . 'assets/css/custom-post-status.min.css',
[],
ADMINOPTIMIZER_VERSION
);
$block_custom_statuses = self::get_default_editor_statuses();
$localized_slugs = wp_list_pluck( $block_custom_statuses, 'slug' );
$custom_post_statuses = $this->get_visible_custom_statuses( $post_type );
if ( ! empty( $custom_post_statuses ) ) {
foreach ( $custom_post_statuses as $custom_status ) {
if ( in_array( $custom_status->slug, $localized_slugs, true ) ) {
continue;
}
$block_custom_statuses[] = [
'slug' => $custom_status->slug,
'name' => $custom_status->name,
];
$localized_slugs[] = $custom_status->slug;
}
}
wp_localize_script( 'adminoptimizer-block-custom-status', 'adminoptimizerCustomStatuses', $block_custom_statuses );
wp_set_script_translations(
'adminoptimizer-block-custom-status',
'admin-optimizer',
ADMINOPTIMIZER_PATH . 'languages'
);
}
}
}
/**
* Enqueue scripts
*
* @return void
*/
public function admin_enqueue_scripts() {
global $pagenow, $post;
$screen = get_current_screen();
if ( in_array( $pagenow, [ 'post.php', 'edit.php', 'post-new.php' ], true ) ) {
if ( ! $screen->is_block_editor() ) {
wp_enqueue_script( 'adminoptimizer-append-custom-status', self::MODULE_URL . 'assets/js/custom-status-classic.min.js', [ 'jquery' ], ADMINOPTIMIZER_VERSION, true );
}
$post_type = $post->post_type ?? 'post';
$custom_statuses = [];
$post_status = $post->post_status ?? '';
$current_post_status = [];
$custom_post_statuses = $this->get_visible_custom_statuses( $post_type );
if ( ! empty( $custom_post_statuses ) ) {
foreach ( $custom_post_statuses as $custom_status ) {
$custom_status_obj = [
'slug' => $custom_status->slug,
'name' => $custom_status->name,
];
$custom_statuses[] = $custom_status_obj;
if ( $post_status === $custom_status->slug ) {
$current_post_status['slug'] = $custom_status->slug;
$current_post_status['name'] = $custom_status->name;
}
}
}
wp_localize_script( 'adminoptimizer-append-custom-status', 'adminoptimizerCustomStatuses', $custom_statuses );
wp_localize_script( 'adminoptimizer-append-custom-status', 'adminoptimizerCurrentStatus', $current_post_status );
}
}
}