is_pro_active() ) { $this->pro_setting_fields['post_types'] = $this->add_post_types_field( $term_id ); $this->pro_setting_fields['user_roles'] = $this->add_user_roles_field( $term_id ); } else { $this->pro_setting_fields['post_types'] = $this->add_disabled_post_types_field(); $this->pro_setting_fields['user_roles'] = $this->add_disabled_user_roles_field(); } } /** * Add the Pro-enabled post types Settings field. * * @param int|string $term_id Term ID, when editing an existing status. * * @return array */ private function add_post_types_field( $term_id = '' ) { $enabled_post_types = []; if ( ! empty( $term_id ) && 0 !== absint( $term_id ) ) { $enabled_post_types = get_term_meta( absint( $term_id ), 'post_types', true ); } $custom_post_types = get_post_types( [ '_builtin' => false, 'show_ui' => 'true', ], 'objects' ); $custom_post_types = array_diff_key( $custom_post_types, array_fill_keys( [ 'lazyblocks', 'lazyblocks_templates', 'attachment', 'wp_block', 'wp_navigation', ], true ) ); $post_types = []; foreach ( $custom_post_types as $custom_post_type ) { $post_types[ $custom_post_type->name ] = $custom_post_type->label; } $post_types = array_merge( [ 'post' => 'Post', 'page' => 'Page', ], $post_types ); $checked = []; foreach ( $post_types as $post_type_name => $post_type_label ) { if ( is_array( $enabled_post_types ) && in_array( $post_type_name, $enabled_post_types, true ) ) { $checked[] = $post_type_name; } } return [ 'id' => 'post-status-post-types', 'type' => 'checkboxes', 'choices' => $post_types, 'checked' => $checked, 'name' => 'poststatus[post_types][]', 'label' => __( 'Enable for these post types', 'admin-optimizer' ), 'required' => false, ]; } /** * Add the Pro-enabled user roles Settings field. * * @param int|string $term_id Term ID, when editing an existing status. * * @return array */ private function add_user_roles_field( $term_id = '' ) { $enabled_user_roles = []; if ( ! empty( $term_id ) && 0 !== absint( $term_id ) ) { $enabled_user_roles = get_term_meta( absint( $term_id ), 'user_roles', true ); } $roles = get_editable_roles(); $checked = [ 'administrator' ]; $role_fields = []; foreach ( $roles as $role => $details ) { if ( 'subscriber' === $role ) { continue; } $name = translate_user_role( $details['name'] ); $role_fields[ $role ] = $name; if ( ! empty( $enabled_user_roles ) && in_array( $role, $enabled_user_roles, true ) ) { $checked[] = $role; } } return [ 'id' => 'post-status-user-roles', 'type' => 'checkboxes', 'choices' => $role_fields, 'checked' => $checked, 'disabled' => [ 'administrator' ], 'name' => 'poststatus[user_roles][]', 'label' => __( 'Enable for these user roles', 'admin-optimizer' ), 'required' => false, ]; } /** * Add the disabled (upsell) post types Settings field. * * @return array */ private function add_disabled_post_types_field() { $custom_post_types = get_post_types( [ '_builtin' => false, 'show_ui' => 'true', ], 'objects' ); $custom_post_types = array_diff_key( $custom_post_types, array_fill_keys( [ 'lazyblocks', 'lazyblocks_templates', 'attachment', 'wp_block', 'wp_navigation', ], true ) ); $post_types = []; $disabled = [ 'post', 'page' ]; foreach ( $custom_post_types as $custom_post_type ) { $post_types[ $custom_post_type->name ] = $custom_post_type->label; $disabled[] = $custom_post_type->name; } $post_types = array_merge( [ 'post' => 'Post', 'page' => 'Page', ], $post_types ); return [ 'id' => 'post-status-post-types', 'type' => 'checkboxes', 'choices' => $post_types, 'checked' => [], 'disabled' => $disabled, 'name' => 'poststatus-post-types[]', 'label' => __( 'Enable for these post types', 'admin-optimizer' ), 'required' => false, ]; } /** * Add the disabled (upsell) user roles Settings field. * * @return array */ private function add_disabled_user_roles_field() { $roles = get_editable_roles(); $role_fields = []; $disabled = []; foreach ( $roles as $role => $details ) { if ( 'subscriber' === $role ) { continue; } $name = translate_user_role( $details['name'] ); $role_fields[ $role ] = $name; $disabled[] = $role; } return [ 'id' => 'post-status-post-types', 'type' => 'checkboxes', 'choices' => $role_fields, 'checked' => [], 'disabled' => $disabled, 'name' => 'poststatus-user-roles][]', 'label' => __( 'Enable for these user roles', 'admin-optimizer' ), 'required' => false, ]; } /** * Add Settings fields * * @return void */ private function add_setting_fields() { $this->setting_fields = [ 'name' => [ 'id' => 'post-status-name', 'type' => 'text', 'name' => 'poststatus[name]', 'value' => '', 'label' => __( 'Name', 'admin-optimizer' ), 'description' => __( 'The name of the custom post status.', 'admin-optimizer' ), 'required' => true, ], 'slug' => [ 'id' => 'post-status-slug', 'type' => 'text', 'name' => 'poststatus[slug]', 'value' => '', 'label' => __( 'Slug', 'admin-optimizer' ), 'description' => __( 'The "slug" is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'admin-optimizer' ), 'required' => true, ], 'description' => [ 'id' => 'post-status-description', 'type' => 'textarea', 'name' => 'poststatus[description]', 'value' => '', 'label' => __( 'Description', 'admin-optimizer' ), 'description' => __( 'Describe what this custom post status is used for.', 'admin-optimizer' ), 'required' => true, ], ]; } /** * Render Settings page * * @return void */ public function render_settings_page() { $this->add_setting_fields(); $this->add_pro_setting_fields(); $message = ''; $error = false; $action = $_REQUEST['action'] ?? ''; //phpcs:ignore $render_setting_fields = true; if ( in_array( $action, [ 'add', 'save-edit', 'edit', 'delete', 'bulk-delete' ], true ) ) { $response = $this->handle_post_data( $action ); extract( $response ); //phpcs:ignore } if ( $render_setting_fields ) : ?> 'message', 'additional_classes' => array( $class ), 'dismissible' => true, ] ); } ?>

output_setting_fields( $this->setting_fields ); ?> is_pro_active() ) : ?> output_setting_fields( $this->pro_setting_fields ); ?>

', '' ); echo wp_kses( $upgrade_message, 'a' ); ?>

output_setting_fields( $this->pro_setting_fields ); ?>

prepare_items(); $poststatus_list_table->display(); ?>
true ]; switch ( $action ) { case 'add': check_admin_referer( 'add-post-status', 'nonce' ); $post_status = isset( $_REQUEST['poststatus'] ) ? wp_unslash( $_REQUEST['poststatus'] ) : []; //phpcs:ignore if ( empty( $post_status['name'] ) ) { $response['message'] = __( 'A name is required for this term.', 'admin-optimizer' ); $response['error'] = true; } else { $new_post_status = []; $new_post_status['slug'] = sanitize_title_with_dashes( ! empty( $post_status['slug'] ) ? $post_status['slug'] : $post_status['name'] ); $new_post_status['description'] = ! empty( $post_status['description'] ) ? sanitize_textarea_field( $post_status['description'] ) : ''; if ( $this->is_core_post_status_slug( $new_post_status['slug'] ) ) { $response['message'] = sprintf( /* translators: %s: post status slug. */ __( 'The slug "%s" is reserved for a WordPress core post status. Please choose a different slug.', 'admin-optimizer' ), $new_post_status['slug'] ); $response['error'] = true; break; } $post_status_arr = wp_insert_term( $post_status['name'], Post_Status::TERM_KEY, $new_post_status ); if ( $post_status_arr && ! is_wp_error( $post_status_arr ) ) { if ( $this->is_pro_active() ) { $this->save_post_status_restrictions( $post_status_arr['term_id'], $post_status ); } $response['message'] = __( 'Post Status added successfully.', 'admin-optimizer' ); } else { if ( is_wp_error( $post_status_arr ) ) { $response['message'] = $post_status_arr->get_error_message(); } else { $response['message'] = __( 'There was an error adding the post status.', 'admin-optimizer' ); } $response['error'] = true; } } break; case 'delete': if ( ! isset( $_REQUEST['term_id'] ) ) { break; } $post_status_id = (int) $_REQUEST['term_id']; check_admin_referer( 'delete-post-status_' . $post_status_id, 'nonce' ); if ( ! current_user_can( 'delete_term', $post_status_id ) ) { wp_die( '

' . esc_html( 'You need a higher level of permission.' ) . '

' . '

' . esc_html( 'Sorry, you are not allowed to delete this item.' ) . '

', 403 ); } $result = wp_delete_term( $post_status_id, Post_Status::TERM_KEY ); if ( $this->is_pro_active() ) { $this->rebuild_post_type_status_option(); } if ( $result ) { $response['message'] = __( 'Post Status deleted successfully.', 'admin-optimizer' ); } else { $response['message'] = __( 'Post Status does not exist.', 'admin-optimizer' ); $response['error'] = true; } break; case 'bulk-delete': check_admin_referer( 'bulk-custom_statuses' ); $delete_poststatus = $_REQUEST['delete_poststatus'] ? array_map( 'absint', wp_unslash( $_REQUEST['delete_poststatus'] ) ) : []; //phpcs:ignore if ( empty( $delete_poststatus ) || ! is_array( $delete_poststatus ) ) { break; } $has_error = false; foreach ( $delete_poststatus as $post_status_id ) { if ( ! current_user_can( 'delete_term', $post_status_id ) ) { wp_die( '

' . esc_html( 'You need a higher level of permission.' ) . '

' . '

' . esc_html( 'Sorry, you are not allowed to delete this item.' ) . '

', 403 ); } $result = wp_delete_term( $post_status_id, Post_Status::TERM_KEY ); if ( ! $result || is_wp_error( $result ) ) { $response['message'] = __( 'Post Status does not exist.', 'admin-optimizer' ); $response['error'] = true; $has_error = true; break; } } if ( $this->is_pro_active() ) { $this->rebuild_post_type_status_option(); } if ( ! $has_error ) { $response['message'] = __( 'Post Status deleted successfully.', 'admin-optimizer' ); } break; case 'edit': if ( ! isset( $_REQUEST['term_id'] ) ) { break; } $post_status_id = (int) $_REQUEST['term_id']; check_admin_referer( 'edit-post-status_' . $post_status_id, 'nonce' ); $this->render_edit_page( $post_status_id ); $response['render_setting_fields'] = false; break; case 'save-edit': if ( ! isset( $_REQUEST['term_id'] ) ) { wp_die( esc_html( 'You attempted to save a post status with improper parameter. Please try again!' ) ); } $post_status_id = (int) $_REQUEST['term_id']; check_admin_referer( 'save-edit-post-status_' . $post_status_id, 'nonce' ); $post_status = $_REQUEST['poststatus'] ?? []; //phpcs:ignore if ( ! term_exists( $post_status_id, Post_Status::TERM_KEY ) ) { wp_die( esc_html( 'You attempted to edit a post status that does not exist. Perhaps it was deleted?' ) ); } $name = ! empty( $post_status['name'] ) ? sanitize_text_field( $post_status['name'] ) : ''; if ( empty( $name ) ) { $response['message'] = __( 'Post Status name cannot be empty.', 'admin-optimizer' ); $response['error'] = true; $this->render_edit_page( $post_status_id, $response['message'], $response['error'] ); $response['render_setting_fields'] = false; break; } $slug = sanitize_title_with_dashes( $post_status['slug'] ?? $post_status['name'] ); $description = ! empty( $post_status['description'] ) ? sanitize_textarea_field( $post_status['description'] ) : ''; if ( $this->is_core_post_status_slug( $slug ) ) { $response['message'] = sprintf( /* translators: %s: post status slug. */ __( 'The slug "%s" is reserved for a WordPress core post status. Please choose a different slug.', 'admin-optimizer' ), $slug ); $response['error'] = true; $this->render_edit_page( $post_status_id, $response['message'], $response['error'] ); $response['render_setting_fields'] = false; break; } wp_update_term( $post_status_id, Post_Status::TERM_KEY, [ 'name' => $name, 'slug' => $slug, 'description' => $description, ] ); if ( $this->is_pro_active() ) { $this->save_post_status_restrictions( $post_status_id, $post_status ); } $response['message'] = __( 'Post status updated successfully', 'admin-optimizer' ); break; } return $response; } /** * Sanitize and save one status's Pro post-type/user-role restrictions * as term meta, then rebuild the two lookup options * (`Post_Status::POST_TYPE_OPTION_NAME` / `::USER_ROLE_OPTION_NAME`) * that `Post_Status_Pro`'s `adminoptim_post_status_visible_statuses` * filter callback reads. Only called while Pro is active. * * @param int $term_id The custom status term ID. * @param array $post_status Raw, unslashed `poststatus` request data. * * @return void */ private function save_post_status_restrictions( $term_id, array $post_status ) { $post_types = ! empty( $post_status['post_types'] ) && is_array( $post_status['post_types'] ) ? array_map( 'sanitize_text_field', $post_status['post_types'] ) : [ 'post' ]; foreach ( $post_types as $key => $post_type ) { if ( ! post_type_exists( $post_type ) ) { unset( $post_types[ $key ] ); } } if ( empty( $post_types ) ) { $post_types = [ 'post' ]; } $user_roles = ! empty( $post_status['user_roles'] ) && is_array( $post_status['user_roles'] ) ? array_map( 'sanitize_text_field', $post_status['user_roles'] ) : []; $user_roles[] = 'administrator'; $user_roles = array_unique( $user_roles ); update_term_meta( $term_id, 'post_types', $post_types ); update_term_meta( $term_id, 'user_roles', $user_roles ); $this->rebuild_post_type_status_option(); $this->rebuild_user_roles_status_option(); } /** * Rebuild the post-type => [status slugs] lookup option from every * custom status's `post_types` term meta. * * @return void */ private function rebuild_post_type_status_option() { $post_statuses = Post_Status::get_custom_post_statuses(); $post_types_option = []; if ( ! empty( $post_statuses ) && ! is_wp_error( $post_statuses ) ) { foreach ( $post_statuses as $post_status ) { $post_types = get_term_meta( $post_status->term_id, 'post_types', true ); if ( ! empty( $post_types ) && is_array( $post_types ) ) { foreach ( $post_types as $post_type ) { $post_types_option[ $post_type ][] = $post_status->slug; } } } } update_option( Post_Status::POST_TYPE_OPTION_NAME, $post_types_option ); } /** * Rebuild the user-role => [status slugs] lookup option from every * custom status's `user_roles` term meta. * * @return void */ private function rebuild_user_roles_status_option() { $post_statuses = Post_Status::get_custom_post_statuses(); $user_roles_option = []; if ( ! empty( $post_statuses ) && ! is_wp_error( $post_statuses ) ) { foreach ( $post_statuses as $post_status ) { $user_roles = get_term_meta( $post_status->term_id, 'user_roles', true ); if ( ! empty( $user_roles ) && is_array( $user_roles ) ) { foreach ( $user_roles as $role ) { $user_roles_option[ $role ][] = $post_status->slug; } } } } update_option( Post_Status::USER_ROLE_OPTION_NAME, $user_roles_option ); } /** * Check whether a slug is reserved by WordPress core post statuses. * * @param string $slug Post status slug. * * @return bool */ private function is_core_post_status_slug( $slug ) { $core_statuses = get_post_stati( [ '_builtin' => true ], 'names' ); return in_array( sanitize_key( $slug ), $core_statuses, true ); } /** * Render Settings fields * * @param array $setting_fields A list of settings fields to output. * * @return void */ private function output_setting_fields( $setting_fields ) { if ( ! empty( $setting_fields ) ) { foreach ( $setting_fields as $field ) { $required_class = $field['required'] ? ' form-required' : ''; switch ( $field['type'] ) { case 'text': ?>

term_id ) ) { wp_die( '

' . esc_html( 'You need a higher level of permission.' ) . '

' . '

' . esc_html( 'Sorry, you are not allowed to edit this item.' ) . '

', 403 ); } $this->add_pro_setting_fields( $term_id ); ?>


'message', 'additional_classes' => array( $class ), 'dismissible' => true, ] ); } ?>
is_pro_active() ) : ?> output_setting_fields( $this->pro_setting_fields ); ?>

', '' ); echo wp_kses( $upgrade_message, 'a' ); ?>

output_setting_fields( $this->pro_setting_fields ); ?>