Plugin Directory

Changeset 3479631


Ignore:
Timestamp:
03/11/2026 12:29:35 AM (3 weeks ago)
Author:
reinventwp
Message:

Deploying version 2.6.4 - improve UI podcast

Location:
natural-text-to-speech/trunk
Files:
13 added
12 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • natural-text-to-speech/trunk/components/rest/podcast.php

    r3478726 r3479631  
    1313const NATUTETO_PODCAST_META_PATH         = '_natuteto_podcast_audio_path';
    1414const NATUTETO_PODCAST_META_GENERATED_AT = '_natuteto_podcast_generated_at';
     15const NATUTETO_PODCAST_META_HASH         = '_natuteto_podcast_content_hash';
    1516const NATUTETO_PODCAST_META_ERROR        = '_natuteto_podcast_error';
    1617const NATUTETO_PODCAST_QUEUE_OPTION      = 'natuteto_podcast_queue_state';
     
    7677
    7778/**
     79 * Build a stable hash for the rendered post content.
     80 *
     81 * @param int         $post_id Post ID.
     82 * @param string|null $content Optional rendered content to hash.
     83 * @return string
     84 */
     85function natuteto_get_podcast_content_hash( $post_id, $content = null ) {
     86    if ( null === $content ) {
     87        $post = get_post( $post_id );
     88        if ( ! $post ) {
     89            return '';
     90        }
     91
     92        $content = apply_filters( 'the_content', $post->post_content );
     93    }
     94
     95    return hash( 'sha256', (string) $content );
     96}
     97
     98/**
    7899 * Build the final podcast file info for a post.
    79100 *
    80  * @param int $post_id Post ID.
     101 * @param int         $post_id      Post ID.
     102 * @param string|null $content_hash Optional content hash override.
    81103 * @return array
    82104 */
    83 function natuteto_get_podcast_file_info( $post_id ) {
     105function natuteto_get_podcast_file_info( $post_id, $content_hash = null ) {
    84106    $post_id      = absint( $post_id );
    85107    $storage_info = natuteto_get_podcast_storage_info();
     
    91113    }
    92114
    93     $slug     = sanitize_title( $slug_source );
    94     $filename = $post_id . '-' . $slug . '.mp3';
    95     $path     = $storage_info['basedir'] . '/' . $filename;
    96     $url      = natuteto_proxy_file_get_url( 'podcast' ) . rawurlencode( $filename );
     115    $slug = sanitize_title( $slug_source );
     116
     117    if ( null === $content_hash ) {
     118        $content_hash = get_post_meta( $post_id, NATUTETO_PODCAST_META_HASH, true );
     119    }
     120
     121    $content_hash = is_string( $content_hash ) ? trim( $content_hash ) : '';
     122    $hash_suffix  = '' !== $content_hash ? '-' . substr( $content_hash, 0, 16 ) : '';
     123    $filename     = $post_id . '-' . $slug . $hash_suffix . '.mp3';
     124    $path         = $storage_info['basedir'] . '/' . $filename;
     125    $url          = natuteto_proxy_file_get_url( 'podcast' ) . rawurlencode( $filename );
    97126
    98127    return array(
     128        'hash'     => $content_hash,
    99129        'filename' => $filename,
    100130        'path'     => $path,
    101131        'url'      => $url,
    102132    );
     133}
     134
     135/**
     136 * Remove stale podcast files for a post, keeping only the latest file.
     137 *
     138 * @param int    $post_id   Post ID.
     139 * @param string $keep_path Path to preserve.
     140 * @return void
     141 */
     142function natuteto_cleanup_podcast_files_for_post( $post_id, $keep_path = '' ) {
     143    global $wp_filesystem;
     144
     145    $post_id = absint( $post_id );
     146    if ( $post_id <= 0 ) {
     147        return;
     148    }
     149
     150    if ( ! $wp_filesystem ) {
     151        require_once ABSPATH . '/wp-admin/includes/file.php';
     152        WP_Filesystem();
     153    }
     154
     155    $storage_info    = natuteto_get_podcast_storage_info();
     156    $pattern         = $storage_info['basedir'] . '/' . $post_id . '-*.mp3';
     157    $candidates      = glob( $pattern );
     158    $normalized_keep = is_string( $keep_path ) && '' !== $keep_path ? wp_normalize_path( $keep_path ) : '';
     159    $normalized_base = wp_normalize_path( $storage_info['basedir'] . '/' );
     160
     161    if ( ! is_array( $candidates ) ) {
     162        return;
     163    }
     164
     165    foreach ( $candidates as $candidate ) {
     166        if ( ! is_string( $candidate ) || '' === $candidate ) {
     167            continue;
     168        }
     169
     170        $normalized_candidate = wp_normalize_path( $candidate );
     171        if ( '' !== $normalized_keep && $normalized_candidate === $normalized_keep ) {
     172            continue;
     173        }
     174
     175        if ( 0 !== strpos( $normalized_candidate, $normalized_base ) ) {
     176            continue;
     177        }
     178
     179        $wp_filesystem->delete( $candidate );
     180    }
    103181}
    104182
     
    825903 */
    826904function natuteto_podcast_generation_needed( $post_id ) {
    827     $file_info     = natuteto_get_podcast_file_info( $post_id );
     905    $stored_hash   = get_post_meta( $post_id, NATUTETO_PODCAST_META_HASH, true );
     906    $stored_hash   = is_string( $stored_hash ) ? trim( $stored_hash ) : '';
     907    $file_info     = natuteto_get_podcast_file_info( $post_id, $stored_hash );
    828908    $generated_at  = absint( get_post_meta( $post_id, NATUTETO_PODCAST_META_GENERATED_AT, true ) );
    829909    $post_modified = strtotime( (string) get_post_field( 'post_modified_gmt', $post_id ) );
     
    837917    }
    838918
    839     if ( false !== $post_modified && $post_modified > $generated_at ) {
     919    if ( '' !== $stored_hash ) {
     920        if ( false !== $post_modified && $post_modified <= $generated_at ) {
     921            return false;
     922        }
     923
     924        $current_hash = natuteto_get_podcast_content_hash( $post_id );
     925        if ( '' !== $current_hash && $stored_hash !== $current_hash ) {
     926            return true;
     927        }
     928
     929        return false;
     930    }
     931
     932    if ( '' === $stored_hash && false !== $post_modified && $post_modified > $generated_at ) {
    840933        return true;
    841934    }
     
    10491142    }
    10501143
    1051     $file_info    = natuteto_get_podcast_file_info( $post_id );
     1144    $content_hash = get_post_meta( $post_id, NATUTETO_PODCAST_META_HASH, true );
     1145    $content_hash = is_string( $content_hash ) ? trim( $content_hash ) : '';
     1146    if ( '' === $content_hash ) {
     1147        $content_hash = natuteto_get_podcast_content_hash( $post_id );
     1148    }
     1149
     1150    $file_info    = natuteto_get_podcast_file_info( $post_id, $content_hash );
    10521151    $storage_info = natuteto_get_podcast_storage_info();
    10531152
     
    10681167    update_post_meta( $post_id, NATUTETO_PODCAST_META_PATH, $file_info['path'] );
    10691168    update_post_meta( $post_id, NATUTETO_PODCAST_META_GENERATED_AT, time() );
     1169    if ( '' !== $content_hash ) {
     1170        update_post_meta( $post_id, NATUTETO_PODCAST_META_HASH, $content_hash );
     1171    }
    10701172    delete_post_meta( $post_id, NATUTETO_PODCAST_META_ERROR );
     1173
     1174    natuteto_cleanup_podcast_files_for_post( $post_id, $file_info['path'] );
    10711175
    10721176    return array(
     
    10961200    if ( '' === trim( wp_strip_all_tags( $content ) ) ) {
    10971201        return new WP_Error( 'podcast_empty_content', 'Post content is empty after rendering.', array( 'status' => 400 ) );
     1202    }
     1203
     1204    $content_hash = natuteto_get_podcast_content_hash( $post_id, $content );
     1205    if ( '' !== $content_hash ) {
     1206        update_post_meta( $post_id, NATUTETO_PODCAST_META_HASH, $content_hash );
    10981207    }
    10991208
     
    13571466    $file_info = natuteto_get_podcast_file_info( $post_id );
    13581467    $meta_path = get_post_meta( $post_id, NATUTETO_PODCAST_META_PATH, true );
    1359 
    1360     $path = is_string( $meta_path ) && '' !== $meta_path ? $meta_path : $file_info['path'];
    1361     $url  = $file_info['url'];
    1362 
    1363     if ( ! file_exists( $path ) ) {
    1364         return null;
     1468    $meta_url  = get_post_meta( $post_id, NATUTETO_PODCAST_META_URL, true );
     1469
     1470    if ( is_string( $meta_path ) && '' !== $meta_path && file_exists( $meta_path ) ) {
     1471        $path = $meta_path;
     1472        $url  = is_string( $meta_url ) && '' !== $meta_url ? $meta_url : $file_info['url'];
     1473    } else {
     1474        $path = $file_info['path'];
     1475        $url  = $file_info['url'];
     1476        if ( ! file_exists( $path ) ) {
     1477            return null;
     1478        }
    13651479    }
    13661480
     
    13851499    if ( ! $feed || empty( $feed['enabled'] ) ) {
    13861500        status_header( 404 );
    1387         echo 'Podcast feed not found. Goto plugin setting -> Enable podcast RSS';
     1501        echo 'Podcast feed not found. Goto plugin setting -> Podcast & Export Audio -> Enable podcast RSS';
    13881502        exit;
    13891503    }
  • natural-text-to-speech/trunk/natural-text-to-speech.php

    r3478732 r3479631  
    44 * Plugin URI:  https://wordpress.org/plugins/natural-text-to-speech
    55 * Description: Read aloud your posts using natural, human-like voices and highlights sentences and words as they are spoken. Available in Free and Pro versions! Start now with 20,000 free characters / month.
    6  * Version:     2.6.3
     6 * Version:     2.6.4
    77 * Author:      Reinvent WP
    88 * Author URI:  https://reinventwp.com
     
    2020 * serious issues with the options, so no if ( ! defined() ).}}
    2121 */
    22 define( 'NATUTETO_VERSION', '2.6.3' );
     22define( 'NATUTETO_VERSION', '2.6.4' );
    2323
    2424if ( ! defined( 'NATUTETO_PLUGIN_DIR' ) ) {
  • natural-text-to-speech/trunk/readme.txt

    r3478732 r3479631  
    44Requires at least: 5.0
    55Tested up to: 6.9
    6 Stable tag: 2.6.3
    7 Version: 2.6.3
     6Stable tag: 2.6.4
     7Version: 2.6.4
    88Requires PHP: 7.4
    99License: GPLv2 or later
     
    479479== Changelog ==
    480480
     481= 2.6.4 =
     482* Enhance Podcast setting UI
     483
    481484= 2.6.3 =
    482485* Improve Post to Podcast feature
Note: See TracChangeset for help on using the changeset viewer.