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 ); } } }