workflow = $workflow; $this->transitions = $transitions; } /** * Register hooks. * * @return void */ public function register_hooks() { add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ), 10, 2 ); add_action( 'admin_post_ostew_transition', array( $this, 'handle_post' ) ); add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor' ) ); // The result notice exists only for the request right after a workflow action, // so the hook is registered only on that request rather than admin-wide. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- presence check only; the notice prints no request data. if ( isset( $_GET['ostew_done'] ) || isset( $_GET['ostew_error'] ) ) { add_action( 'admin_notices', array( $this, 'admin_notice' ) ); } } /** * Add the classic metabox (skipped in the block editor — the JS panel covers that). * * @param string $post_type Post type. * @param \WP_Post $post Post. * @return void */ public function add_meta_box( $post_type, $post ) { if ( ! $this->workflow->for_post( $post ) ) { return; } $screen = get_current_screen(); if ( $screen && method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) { return; } add_meta_box( 'ostew_workflow', __( 'Editorial Workflow', 'ost-editorial-workflow' ), array( $this, 'render_meta_box' ), $post_type, 'side', 'high' ); } /** * Render the classic metabox. * * @param \WP_Post $post Post. * @return void */ public function render_meta_box( $post ) { $workflow = $this->workflow->for_post( $post ); $label = $this->workflow->status_label( $workflow, $post->post_status ); $actions = $this->workflow->allowed_actions( $post ); echo '
' . esc_html__( 'Status:', 'ost-editorial-workflow' ) . ' ' . esc_html( $label ) . '
'; if ( empty( $actions ) ) { echo '' . esc_html__( 'No workflow actions available to you at this stage.', 'ost-editorial-workflow' ) . '
'; return; } $needs_note = (bool) array_filter( wp_list_pluck( $actions, 'needs_note' ) ); echo ''; } /** * Handle the classic metabox POST. * * @return void */ public function handle_post() { $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; check_admin_referer( 'ostew_transition_' . $post_id ); if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'ost-editorial-workflow' ) ); } $action = isset( $_POST['ostew_action'] ) ? sanitize_key( wp_unslash( $_POST['ostew_action'] ) ) : ''; $note = isset( $_POST['ostew_note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['ostew_note'] ) ) : ''; $result = $this->transitions->handle( $post_id, $action, $note ); $flag = is_wp_error( $result ) ? 'ostew_error' : 'ostew_done'; wp_safe_redirect( add_query_arg( $flag, '1', get_edit_post_link( $post_id, 'url' ) ) ); exit; } /** * Enqueue + localize the block-editor panel on managed post types. * * @return void */ public function enqueue_block_editor() { $post = get_post(); if ( ! $post || ! $this->workflow->for_post( $post ) ) { return; } wp_enqueue_style( 'ost-editorial-workflow-admin', OSTEW_URL . 'assets/css/admin.css', array(), OSTEW_VERSION ); // Hide WordPress's native Submit/Publish button for users who can't publish this // item, so the workflow panel is the single control. Never hides it on already- // published posts (where it's the "Update" button an editor still needs). if ( $this->should_hide_native_button( $post ) ) { wp_add_inline_style( 'ost-editorial-workflow-admin', '.editor-post-publish-button__button,.editor-post-publish-panel__toggle{display:none!important;}' ); } wp_enqueue_script( 'ost-editorial-workflow-editor', OSTEW_URL . 'assets/js/editor.js', array( 'wp-plugins', 'wp-edit-post', 'wp-element', 'wp-components', 'wp-data', 'wp-api-fetch', 'wp-i18n' ), OSTEW_VERSION, true ); $workflow = $this->workflow->for_post( $post ); wp_localize_script( 'ost-editorial-workflow-editor', 'ostewEditor', array( 'postId' => $post->ID, 'statusLabel' => $this->workflow->status_label( $workflow, $post->post_status ), 'actions' => array_values( $this->workflow->allowed_actions( $post ) ), 'restPath' => '/' . \OST\EditorialWorkflow\Rest::NAMESPACE_V1 . '/transition', // The history meta box lands in the block editor's collapsed drawer, // so the panel links to the screen instead. 'historyUrl' => current_user_can( 'edit_others_posts' ) ? History::screen_url( $post->ID ) : '', 'historyText' => __( 'View editorial history', 'ost-editorial-workflow' ), ) ); } /** * Should the native publish/submit button be hidden for the current user? * * Hidden only when the user cannot publish this post type AND the post is not * already published (so the "Update" button on live pages is never removed). * * @param \WP_Post $post Post. * @return bool */ private function should_hide_native_button( $post ) { if ( 'publish' === $post->post_status ) { return false; } $pt = get_post_type_object( $post->post_type ); if ( ! $pt ) { return false; } return ! current_user_can( $pt->cap->publish_posts ); } /** * Success/error notice after a classic-editor transition. * * @return void */ public function admin_notice() { if ( isset( $_GET['ostew_done'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended echo '' . esc_html__( 'Workflow updated.', 'ost-editorial-workflow' ) . '
' . esc_html__( 'Workflow action could not be completed.', 'ost-editorial-workflow' ) . '