@@ -78,13 +78,13 @@ public function __construct() {
7878 }
7979
8080 /**
81- * Set up necessary hooks.
82- *
83- * We utilize this so we can register the REST route.
81+ * Set up necessary hooks even if the Feature is not available.
8482 */
8583 public function setup () {
8684 parent ::setup ();
85+
8786 add_action ( 'rest_api_init ' , [ $ this , 'register_endpoints ' ] );
87+ add_action ( 'classifai_schedule_text_to_speech_job ' , [ $ this , 'generate_text_to_speech_audio ' ], 10 , 2 );
8888
8989 if ( $ this ->is_enabled () ) {
9090 add_filter ( 'the_content ' , [ $ this , 'render_post_audio_controls ' ] );
@@ -218,11 +218,28 @@ public function add_meta_to_rest_api() {
218218 * @param WP_REST_Request $request Request object.
219219 */
220220 public function rest_handle_audio ( \WP_Post $ post , WP_REST_Request $ request ) {
221+ $ post_id = (int ) $ request ->get_param ( 'id ' );
222+
221223 if ( ! $ this ->is_feature_enabled () ) {
222224 return ;
223225 }
224226
225- $ audio_id = get_post_meta ( $ request ->get_param ( 'id ' ), self ::AUDIO_ID_KEY , true );
227+ // Ensure we have a logged in user that can edit the item.
228+ if ( ! current_user_can ( 'edit_post ' , $ post_id ) ) {
229+ return ;
230+ }
231+
232+ $ job_args = [
233+ 'post_id ' => $ post_id ,
234+ 'calling_user_id ' => get_current_user_id (),
235+ ];
236+
237+ // We return early if the job is already scheduled.
238+ if ( function_exists ( 'as_has_scheduled_action ' ) && \as_has_scheduled_action ( 'classifai_schedule_text_to_speech_job ' , $ job_args , 'classifai ' ) ) {
239+ return ;
240+ }
241+
242+ $ audio_id = get_post_meta ( $ post_id , self ::AUDIO_ID_KEY , true );
226243
227244 // Since we have dynamic generation option agnostic to meta saves we need a flag to differentiate audio generation accurately
228245 $ process_content = false ;
@@ -238,39 +255,42 @@ public function rest_handle_audio( \WP_Post $post, WP_REST_Request $request ) {
238255 ( $ process_content && null === $ request ->get_param ( 'classifai_synthesize_speech ' ) ) ||
239256 true === $ request ->get_param ( 'classifai_synthesize_speech ' )
240257 ) {
241- $ results = $ this ->run ( $ request ->get_param ( 'id ' ), 'synthesize ' );
242-
243- if ( $ results && ! is_wp_error ( $ results ) ) {
244- $ this ->save ( $ results , $ request ->get_param ( 'id ' ) );
245- delete_post_meta ( $ post ->ID , '_classifai_text_to_speech_error ' );
246- } elseif ( is_wp_error ( $ results ) ) {
247- update_post_meta (
248- $ post ->ID ,
249- '_classifai_text_to_speech_error ' ,
250- wp_json_encode (
251- [
252- 'code ' => $ results ->get_error_code (),
253- 'message ' => $ results ->get_error_message (),
254- ]
255- )
256- );
258+ if ( function_exists ( 'as_enqueue_async_action ' ) ) {
259+ \as_enqueue_async_action ( 'classifai_schedule_text_to_speech_job ' , $ job_args , 'classifai ' );
260+ update_post_meta ( $ post_id , '_classifai_text_to_speech_scheduled ' , true );
261+ } else {
262+ $ this ->generate_text_to_speech_audio ( $ post_id );
257263 }
258264 }
259265 }
260266
261267 /**
262- * Register any needed endpoints.
268+ * Register any needed endpoints and meta .
263269 */
264270 public function register_endpoints () {
265271 $ post_types = $ this ->get_supported_post_types ();
266272 foreach ( $ post_types as $ post_type ) {
267273 register_meta (
268- $ post_type ,
274+ ' post ' ,
269275 '_classifai_text_to_speech_error ' ,
270276 [
271- 'show_in_rest ' => true ,
272- 'single ' => true ,
273- 'auth_callback ' => '__return_true ' ,
277+ 'object_subtype ' => $ post_type ,
278+ 'type ' => 'string ' ,
279+ 'show_in_rest ' => true ,
280+ 'single ' => true ,
281+ 'auth_callback ' => '__return_true ' ,
282+ ]
283+ );
284+
285+ register_meta (
286+ 'post ' ,
287+ '_classifai_text_to_speech_scheduled ' ,
288+ [
289+ 'object_subtype ' => $ post_type ,
290+ 'type ' => 'boolean ' ,
291+ 'show_in_rest ' => true ,
292+ 'single ' => true ,
293+ 'auth_callback ' => '__return_true ' ,
274294 ]
275295 );
276296 }
@@ -425,7 +445,23 @@ public function render_meta_box( \WP_Post $post ) {
425445 if ( $ post_type ) {
426446 $ post_type_label = $ post_type ->labels ->singular_name ;
427447 }
428- ?>
448+
449+ $ is_as_scheduled_job =
450+ function_exists ( 'as_has_scheduled_action ' ) &&
451+ \as_has_scheduled_action (
452+ 'classifai_schedule_text_to_speech_job ' ,
453+ [
454+ 'post_id ' => (int ) $ post ->ID ,
455+ 'calling_user_id ' => get_current_user_id (),
456+ ],
457+ 'classifai '
458+ );
459+
460+ if ( $ is_as_scheduled_job ) : ?>
461+ <p>
462+ <?php esc_html_e ( 'Audio generation is in progress… ' , 'classifai ' ); ?>
463+ </p>
464+ <?php else : ?>
429465
430466 <p>
431467 <label for="classifai_synthesize_speech">
@@ -452,6 +488,8 @@ public function render_meta_box( \WP_Post $post ) {
452488 </span>
453489 </p>
454490
491+ <?php endif ; ?>
492+
455493 <?php
456494 if ( $ source_url ) {
457495 $ cache_busting_url = add_query_arg (
@@ -497,27 +535,71 @@ public function save_post_metadata( int $post_id ) {
497535 delete_post_meta ( $ post_id , self ::DISPLAY_GENERATED_AUDIO );
498536 }
499537
500- if ( isset ( $ _POST ['classifai_synthesize_speech ' ] ) ) {
501- $ results = $ this ->run ( $ post_id , 'synthesize ' );
538+ $ job_args = [
539+ 'post_id ' => (int ) $ post_id ,
540+ 'calling_user_id ' => get_current_user_id (),
541+ ];
502542
503- if ( $ results && ! is_wp_error ( $ results ) ) {
504- $ this ->save ( $ results , $ post_id );
505- delete_post_meta ( $ post_id , '_classifai_text_to_speech_error ' );
506- } elseif ( is_wp_error ( $ results ) ) {
507- update_post_meta (
508- $ post_id ,
509- '_classifai_text_to_speech_error ' ,
510- wp_json_encode (
511- [
512- 'code ' => $ results ->get_error_code (),
513- 'message ' => $ results ->get_error_message (),
514- ]
515- )
516- );
517- }
543+ // We return early if the job is already scheduled.
544+ if (
545+ ! isset ( $ _POST ['classifai_synthesize_speech ' ] )
546+ || (
547+ function_exists ( 'as_has_scheduled_action ' )
548+ && \as_has_scheduled_action ( 'classifai_schedule_text_to_speech_job ' , $ job_args , 'classifai ' )
549+ )
550+ ) {
551+ return ;
552+ }
553+
554+ // We enqueue the async action to generate the audio, if available.
555+ if ( function_exists ( 'as_enqueue_async_action ' ) ) {
556+ \as_enqueue_async_action ( 'classifai_schedule_text_to_speech_job ' , $ job_args , 'classifai ' );
557+ update_post_meta ( $ post_id , '_classifai_text_to_speech_scheduled ' , true );
558+ } else {
559+ $ this ->generate_text_to_speech_audio ( $ post_id );
518560 }
519561 }
520562
563+ /**
564+ * Generate the text to speech audio.
565+ *
566+ * @param int $post_id The post ID.
567+ * @param int|null $calling_user_id The user that made the request.
568+ */
569+ public function generate_text_to_speech_audio ( int $ post_id , ?int $ calling_user_id = null ) {
570+ $ original_user_id = get_current_user_id ();
571+
572+ if ( ! $ calling_user_id ) {
573+ $ calling_user_id = $ original_user_id ;
574+ }
575+
576+ // Set the user to the one who started the process, to avoid permission issues.
577+ wp_set_current_user ( (int ) $ calling_user_id );
578+
579+ $ results = $ this ->run ( $ post_id , 'synthesize ' );
580+
581+ if ( $ results && ! is_wp_error ( $ results ) ) {
582+ $ this ->save ( $ results , $ post_id );
583+ delete_post_meta ( $ post_id , '_classifai_text_to_speech_error ' );
584+ } elseif ( is_wp_error ( $ results ) ) {
585+ update_post_meta (
586+ $ post_id ,
587+ '_classifai_text_to_speech_error ' ,
588+ wp_json_encode (
589+ [
590+ 'code ' => $ results ->get_error_code (),
591+ 'message ' => $ results ->get_error_message (),
592+ ]
593+ )
594+ );
595+ }
596+
597+ // Restore original user.
598+ wp_set_current_user ( $ original_user_id );
599+
600+ delete_post_meta ( $ post_id , '_classifai_text_to_speech_scheduled ' );
601+ }
602+
521603 /**
522604 * Save the returned result.
523605 *
0 commit comments