tags. * * @since 1.0.5 */ class AIOPOD_Public_Transcript { /** * Serve a transcript request. * * Access is checked before anything is said about the transcript itself, so a restricted * episode answers 403 whether or not it has one. * * @since 1.0.5 * @return void */ public function handle_request() { // Never run in admin or AJAX context if ( is_admin() || wp_doing_ajax() ) { return; } $language = sanitize_text_field( (string) get_query_var( 'aiopod_transcript' ) ); if ( '' === $language ) { return; } $episode_slug = get_query_var( 'aiopod_episode' ); $format = sanitize_key( (string) get_query_var( 'aiopod_format' ) ); $episode = null; if ( ! empty( $episode_slug ) ) { $episodes = get_posts( array( 'name' => sanitize_title( $episode_slug ), 'post_type' => 'aiopod_episodes', 'post_status' => 'publish', 'posts_per_page' => 1, 'no_found_rows' => true ) ); $episode = ! empty( $episodes ) ? $episodes[0] : null; } if ( ! $episode ) { wp_die( esc_html__( 'Episode not found.', 'aio-podcast-studio' ), '', array( 'response' => 404 ) ); } if ( ! aiopod_current_user_can( 'view_aiopod_podcast', $episode->ID ) ) { wp_die( esc_html__( 'You do not have permission to view this transcript.', 'aio-podcast-studio' ), '', array( 'response' => 403 ) ); } $output = $this->get_output( $episode, $language, $format ); if ( '' === $output ) { wp_die( esc_html__( 'Transcript not found.', 'aio-podcast-studio' ), '', array( 'response' => 404 ) ); } $this->send( $output, $format, aiopod_is_content_restricted( $episode->ID ) ); } /** * Build the requested transcript. * * @since 1.0.5 * @access private * @param WP_Post $episode Episode post object. * @param string $language Requested language, or 'default' for the row in the podcast's language. * @param string $format Requested format key. * @return string The transcript, or '' when there is none to serve. */ private function get_output( $episode, $language, $format ) { if ( ! get_post_meta( $episode->ID, 'enable_transcription', true ) ) { return ''; } $language = 'default' === $language ? '' : aiopod_normalize_language_code( $language ); $transcript = null; foreach ( aiopod_get_usable_transcripts( $episode->ID ) as $row ) { if ( aiopod_normalize_language_code( $row['language'] ) === $language ) { $transcript = $row; break; } } if ( null === $transcript ) { return ''; } $loaded = aiopod_load_transcript( $transcript, $episode->ID ); if ( '' !== $loaded['error'] || ! in_array( $format, aiopod_get_transcript_output_formats( $loaded['type'] ), true ) ) { return ''; } // Built from what was loaded, so a cached transcript is never parsed again if ( ! empty( $loaded['cues'] ) ) { switch ( $format ) { case 'vtt': return aiopod_build_vtt_transcript( $loaded['cues'] ); case 'srt': return aiopod_build_srt_transcript( $loaded['cues'] ); case 'json': return aiopod_build_json_transcript( $loaded['cues'] ); case 'html': return $this->get_html_document( aiopod_build_html_transcript( $loaded['cues'] ), $episode, $transcript ); } return ''; } $output = aiopod_build_untimed_transcript( $loaded['text'], $loaded['type'], $format ); if ( 'html' === $format && '' !== $output ) { $output = $this->get_html_document( $output, $episode, $transcript ); } return $output; } /** * Wrap an HTML transcript fragment in a document of its own. * * @since 1.0.5 * @access private * @param string $fragment Escaped HTML transcript. * @param WP_Post $episode Episode post object. * @param array $transcript Transcript row. * @return string HTML document. */ private function get_html_document( $fragment, $episode, $transcript ) { $language = '' !== $transcript['language'] ? $transcript['language'] : aiopod_get_podcast_language( (int) $episode->post_parent ); /* translators: %s: Episode title */ $title = sprintf( __( 'Transcript: %s', 'aio-podcast-studio' ), get_the_title( $episode ) ); return '' . "\n" . '' . "\n" . '
' . "\n" . '' . "\n" . '