From c66cc991884b9efdf2a324580a19ad3f13b41080 Mon Sep 17 00:00:00 2001 From: Moferanoluwa Date: Wed, 29 Jul 2026 11:15:35 -0700 Subject: [PATCH 1/2] Add allowed post statuses setting for Text to Speech feature Text to Speech currently generates audio for any post status (including Draft and Pending), which causes stale/incorrect audio to be attached to public post previews while a post is still being actively edited through several rounds of changes. Add a "post_statuses" setting to the feature, mirroring the existing pattern already used by the post_types setting and by the Classification feature's post_statuses field: - New settings field (checkbox group) to choose allowed post statuses, defaulting to Publish only. - Enforce the setting in both audio-generation entry points: save_post_metadata() (classic editor / meta box save) and rest_handle_audio() (block editor / REST save). Fixes #1000 --- includes/Classifai/Features/TextToSpeech.php | 37 ++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/includes/Classifai/Features/TextToSpeech.php b/includes/Classifai/Features/TextToSpeech.php index ad525b3b1..43f33b4d9 100644 --- a/includes/Classifai/Features/TextToSpeech.php +++ b/includes/Classifai/Features/TextToSpeech.php @@ -255,7 +255,10 @@ public function add_meta_to_rest_api() { public function rest_handle_audio( \WP_Post $post, WP_REST_Request $request ) { $post_id = (int) $request->get_param( 'id' ); - if ( ! $this->is_feature_enabled() ) { + if ( + ! in_array( $post->post_status, $this->get_supported_post_statuses(), true ) || + ! $this->is_feature_enabled() + ) { return; } @@ -614,6 +617,7 @@ function_exists( 'as_has_scheduled_action' ) && public function save_post_metadata( int $post_id ) { if ( ! in_array( get_post_type( $post_id ), $this->get_supported_post_types(), true ) || + ! in_array( get_post_status( $post_id ), $this->get_supported_post_statuses(), true ) || ! $this->is_feature_enabled() ) { return; @@ -936,6 +940,20 @@ public function add_custom_settings_fields() { 'description' => __( 'Choose which post types support this feature.', 'classifai' ), ) ); + + add_settings_field( + 'post_statuses', + esc_html__( 'Allowed post statuses', 'classifai' ), + array( $this, 'render_checkbox_group' ), + $this->get_option_name(), + $this->get_option_name() . '_section', + array( + 'label_for' => 'post_statuses', + 'options' => \Classifai\get_post_statuses_for_language_settings(), + 'default_values' => $settings['post_statuses'], + 'description' => __( 'Choose which post statuses are allowed to generate audio, e.g. disable this for Draft to avoid generating audio for content that is still being edited.', 'classifai' ), + ) + ); } /** @@ -961,10 +979,13 @@ protected function get_post_types_select_options(): array { */ public function get_feature_default_settings(): array { return array( - 'post_types' => array( + 'post_types' => array( 'post' => 'post', ), - 'provider' => Speech::ID, + 'post_statuses' => array( + 'publish' => 'publish', + ), + 'provider' => Speech::ID, ); } @@ -985,6 +1006,16 @@ public function sanitize_default_feature_settings( array $new_settings ): array } } + $post_statuses = \Classifai\get_post_statuses_for_language_settings(); + + foreach ( array_keys( $post_statuses ) as $post_status ) { + if ( ! isset( $new_settings['post_statuses'][ $post_status ] ) ) { + $new_settings['post_statuses'][ $post_status ] = ''; + } else { + $new_settings['post_statuses'][ $post_status ] = sanitize_text_field( $new_settings['post_statuses'][ $post_status ] ); + } + } + return $new_settings; } From 683e07ba31bf74812c5ef8e4f0ce5244f5cab9c0 Mon Sep 17 00:00:00 2001 From: Moferanoluwa Date: Fri, 31 Jul 2026 13:16:08 -0700 Subject: [PATCH 2/2] Move post_statuses setting from legacy PHP settings to React UI Per review feedback: the legacy PHP settings screen (add_settings_field) is being phased out and hasn't been the default since v3.2.0, so new settings should be added to the React settings UI instead. - Remove the post_statuses add_settings_field() block from TextToSpeech::add_custom_settings_fields(). - Add the equivalent control to src/js/settings/components/feature-additional-settings/text-to-speech.js, mirroring the existing post_statuses block already used by the Classification feature's React settings (same window.classifAISettings.postStatuses data source, already localized in Admin/Settings.php - no new PHP localization needed). The default settings, sanitization, and enforcement gates added in the previous commit are unchanged - those are backend/data-layer concerns independent of which UI renders the control. --- includes/Classifai/Features/TextToSpeech.php | 14 --- .../text-to-speech.js | 93 +++++++++++++------ 2 files changed, 64 insertions(+), 43 deletions(-) diff --git a/includes/Classifai/Features/TextToSpeech.php b/includes/Classifai/Features/TextToSpeech.php index 43f33b4d9..30af4dfe2 100644 --- a/includes/Classifai/Features/TextToSpeech.php +++ b/includes/Classifai/Features/TextToSpeech.php @@ -940,20 +940,6 @@ public function add_custom_settings_fields() { 'description' => __( 'Choose which post types support this feature.', 'classifai' ), ) ); - - add_settings_field( - 'post_statuses', - esc_html__( 'Allowed post statuses', 'classifai' ), - array( $this, 'render_checkbox_group' ), - $this->get_option_name(), - $this->get_option_name() . '_section', - array( - 'label_for' => 'post_statuses', - 'options' => \Classifai\get_post_statuses_for_language_settings(), - 'default_values' => $settings['post_statuses'], - 'description' => __( 'Choose which post statuses are allowed to generate audio, e.g. disable this for Draft to avoid generating audio for content that is still being edited.', 'classifai' ), - ) - ); } /** diff --git a/src/js/settings/components/feature-additional-settings/text-to-speech.js b/src/js/settings/components/feature-additional-settings/text-to-speech.js index 701ecef24..497d74505 100644 --- a/src/js/settings/components/feature-additional-settings/text-to-speech.js +++ b/src/js/settings/components/feature-additional-settings/text-to-speech.js @@ -4,6 +4,7 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { CheckboxControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies @@ -23,36 +24,70 @@ export const TextToSpeechSettings = () => { select( STORE_NAME ).getFeatureSettings() ); const { setFeatureSettings } = useDispatch( STORE_NAME ); - const { postTypes } = window.classifAISettings; + const { postTypes, postStatuses } = window.classifAISettings; return ( - - { Object.keys( postTypes || {} ).map( ( key ) => { - return ( - { - setFeatureSettings( { - post_types: { - ...featureSettings.post_types, - [ key ]: value ? key : '0', - }, - } ); - } } - __nextHasNoMarginBottom - /> - ); - } ) } - + <> + + { Object.keys( postStatuses || {} ).map( ( key ) => { + return ( + { + setFeatureSettings( { + post_statuses: { + ...featureSettings.post_statuses, + [ key ]: value ? key : '0', + }, + } ); + } } + __nextHasNoMarginBottom + /> + ); + } ) } + + + { Object.keys( postTypes || {} ).map( ( key ) => { + return ( + { + setFeatureSettings( { + post_types: { + ...featureSettings.post_types, + [ key ]: value ? key : '0', + }, + } ); + } } + __nextHasNoMarginBottom + /> + ); + } ) } + + ); };