Server IP : 52.91.253.208 / Your IP : 3.143.239.44 [ Web Server : Apache System : Linux ip-172-26-9-9 4.19.0-25-cloud-amd64 #1 SMP Debian 4.19.289-1 (2023-07-24) x86_64 User : daemon ( 1) PHP Version : 7.3.18 Disable Function : NONE Domains : 3 Domains MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /opt/bitnami/apps/wordpress/htdocs/wp-content/plugins/amazon-polly/admin/ |
Upload File : |
<?php /** * The admin-specific functionality of the plugin. * * @link amazon.com * @since 1.0.0 * * @package Amazonpolly * @subpackage Amazonpolly/admin */ /** * The admin-specific functionality of the plugin.f * * Defines the plugin name, version, and two examples hooks for how to * enqueue the admin-specific stylesheet and JavaScript. * * @package Amazonpolly * @subpackage Amazonpolly/admin * @author AWS Labs */ class Amazonpolly_Admin { /** * The list of countries which are supported for translate functionality. * * @since 2.0.0 * @access private * @var array $translate_langs List of languages. */ private $translate_langs = array( 'en', 'de', 'es', 'fr', 'pt' ); /** * The ID of this plugin. * * @since 1.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 1.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; /** * The polly client * * @since 1.0.0 * @access private * @var Object $polly_client Client for polly interactions */ private $polly_client; /** * Amazon Translate client * * @since 2.0.0 * @access private * @var Object $translate_client AWS Amazon Translate client. */ private $translate_client; /** * Amazon S3 file handler. * * @since 2.2.0 * @access private * @var Object $s3_file_handler handler for S3 storage */ private $s3_file_handler; /** * Local file handler. * * @since 2.2.0 * @access private * @var Object $local_file_handler handler for local storage */ private $local_file_handler; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of this plugin. * @param string $version The version of this plugin. */ public function __construct( $plugin_name, $version ) { $this->plugin_name = $plugin_name; $this->version = $version; $this->s3_file_handler = new AmazonAI_S3FileHandler(); $this->local_file_handler = new AmazonAI_LocalFileHandler(); $this->translator = new AmazonAI_Translator(); } /** * Register meta box for 'Enable Amazon Polly' on post creation form. * * @since 1.0.0 */ public function amazon_polly_field_checkbox() { $post_types_supported = $this->amazon_polly_get_posttypes_array(); add_meta_box( 'amazon_polly_box_id', // This is HTML id of the box on edit screen. 'Amazon Polly', // Title of the box. 'amazon_polly_box_content', // Function to be called to display the checkboxes, see the function below. $post_types_supported, // On which edit screen the box should appear. 'normal', // Part of page where the box should appear. 'high' // Priority of the box. ); } /** * Run when deleting a post. * * @param string $post_id ID of the post which is gonna to be deleted. * @since 1.0.0 */ public function amazon_polly_delete_post( $post_id ) { // Check if this isn't an auto save. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } $this->delete_post_audio( $post_id ); } /** * Add Amazon Pollu QuickTag button. * * @since 1.0.7 */ public function amazon_polly_add_quicktags() { $is_ssml_enabled = $this->amazon_polly_is_ssml_enabled(); if ( $is_ssml_enabled ) { if ( wp_script_is( 'quicktags' ) ) { ?> <script type="text/javascript"> QTags.addButton( 'eg_ssmlbreak', 'SSML Break', '<ssml><break time="1s"/></ssml>','','', 'Amazon Polly SSML Break Tag', 111 ); </script> <?php } } } /** * Important. Run whenever new post is being created (or updated). The method executes Amazon Polly API to create audio file. * * @since 1.0.0 */ public function amazon_polly_save_post( $post_id, $post, $updated ) { // Check if this isn't an auto save. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // Check to make sure this is not a new post creation. if ( ! $updated ) { return; } $is_quick_edit = isset($_POST['_inline_edit']) && wp_verify_nonce($_POST['_inline_edit'], 'inlineeditnonce'); $is_polly_nonce_ok = isset( $_POST['amazon-polly-post-nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['amazon-polly-post-nonce'] ), 'amazon-polly' ); // Check if this post is saved in 'regular' way. if ( $is_polly_nonce_ok || $is_quick_edit ) { $is_post_available = isset( $_POST['content'] ); // Input var okay. $is_polly_enabled = isset( $_POST['amazon_polly_enable'] ); // Input var okay. $is_post_id_available = isset( $post_id ); // Input var okay. $is_key_valid = ( get_option( 'amazon_polly_valid_keys' ) === '1' ); // If this is quick edit, we need to check other place to see if polly was already enabled for this post. if ( $is_post_id_available && $is_quick_edit ) { if ( 1 == get_post_meta( $post_id, 'amazon_polly_enable', true)) { $is_polly_enabled = true; } } if ( $is_post_id_available && $is_post_available && $is_polly_enabled && $is_key_valid ) { wp_nonce_field( 'amazon_polly', 'amazon_polly_sample_rate' ); $voice_id = get_option( 'amazon_polly_voice_id' ); $sample_rate = get_option( 'amazon_polly_sample_rate' ); $clean_text = $this->clean_text( $post_id ); $sentences = $this->break_text( $clean_text ); $wp_filesystem = $this->prepare_wp_filesystem(); $this->convert_to_audio( $post_id, $sample_rate, $voice_id, $sentences, $wp_filesystem, '' ); $src_lang = $this->get_src_lang(); update_post_meta( $post_id, 'amazon_polly_transcript_' . $src_lang, $clean_text ); update_post_meta( $post_id, 'amazon_polly_transcript_source_lan', $src_lang ); } if ( $is_post_id_available && ! $is_polly_enabled ) { $this->delete_post_audio( $post_id ); update_post_meta( $post_id, 'amazon_polly_enable', 0 ); update_post_meta( $post_id, 'amazon_polly_audio_location', '' ); } } } /** * Delets audio for specific post. * * @param string $post_id ID of the post for which audio should be deleted. * @since 1.0.0 */ public function delete_post_audio( $post_id ) { $audio_location = get_post_meta( $post_id, 'amazon_polly_audio_location', true ); $file = 'amazon_polly_' . $post_id . '.mp3'; $wp_filesystem = $this->prepare_wp_filesystem(); // Deleting audio file. $fileHandler = $this->getFileHandler(); $fileHandler->delete($wp_filesystem, $file, $this->translate_langs, $post_id); } /** * Register the stylesheets for the admin area. * * @since 1.0.0 */ public function enqueue_styles() { wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/amazonpolly-admin.css', array(), $this->version, 'all' ); wp_enqueue_style( 'jquery-ui-core' ); wp_enqueue_style( 'jquery-ui-progressbar' ); wp_enqueue_style( 'jquery-ui', '//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css', array(), '1.21.1', 'all' ); } /** * Register the JavaScript for the admin area. * * @since 1.0.0 */ public function enqueue_scripts() { wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/amazonpolly-admin.js', array( 'jquery' ), $this->version, false ); wp_enqueue_script( 'jquery-ui-core' ); wp_enqueue_script( 'jquery-ui-progressbar' ); $nonce_array = array( 'nonce' => wp_create_nonce( 'pollyajaxnonce' ), ); wp_localize_script( 'jquery', 'pollyajax', $nonce_array ); } /** * Add an options page under the Settings submenu * * @since 1.0.0 */ public function amazon_polly_add_options_page() { $this->plugin_screen_hook_suffix = add_options_page( __( 'Amazon Polly Settings', 'amazon-polly' ), __( 'Amazon Polly', 'amazon-polly' ), 'manage_options', $this->plugin_name, array( $this, 'amazon_polly_display_options_page' ) ); } /** * Adds options page for Amazon Polly. * * @since 1.0.0 */ public function amazon_polly_display_options_page() { include_once 'partials/amazonpolly-admin-display.php'; } /** * Register all settings for options page. * * @since 1.0.0 */ public function amazon_polly_register_settings() { // ************************************************* * // ***************** GENERAL SECTION **************** * add_settings_section( 'amazon_polly_general', __( 'General', 'amazonpolly' ), array( $this, 'amazon_polly_general_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_access_key', __( 'AWS access key:', 'amazonpolly' ), array( $this, 'amazon_polly_access_key_cb' ), $this->plugin_name, 'amazon_polly_general', array( 'label_for' => 'amazon_polly_access_key' ) ); add_settings_field( 'amazon_polly_secret_key', __( 'AWS secret key:', 'amazonpolly' ), array( $this, 'amazon_polly_secret_key_cb' ), $this->plugin_name, 'amazon_polly_general', array( 'label_for' => 'amazon_polly_secret_key' ) ); add_settings_field( 'amazon_polly_region', __( 'AWS Region:', 'amazonpolly' ), array( $this, 'amazon_polly_region_cb' ), $this->plugin_name, 'amazon_polly_general', array( 'label_for' => 'amazon_polly_region' ) ); // ************************************************* * // ***************** PLAYER SECTION **************** * add_settings_section( 'amazon_polly_playersettings', __( 'Player settings', 'amazonpolly' ), array( $this, 'amazon_polly_playersettings_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_position', __( 'Player position:', 'amazonpolly' ), array( $this, 'amazon_polly_position_cb' ), $this->plugin_name, 'amazon_polly_playersettings', array( 'label_for' => 'amazon_polly_position' ) ); add_settings_field( 'amazon_polly_player_label', __( 'Player label:', 'amazonpolly' ), array( $this, 'amazon_polly_player_label_cb' ), $this->plugin_name, 'amazon_polly_playersettings', array( 'label_for' => 'amazon_polly_player_label' ) ); add_settings_field( 'amazon_polly_defconf', __( 'New post default:', 'amazonpolly' ), array( $this, 'amazon_polly_defconf_cb' ), $this->plugin_name, 'amazon_polly_playersettings', array( '' => 'amazon_polly_defconf' ) ); add_settings_field( 'amazon_polly_autoplay', __( 'Autoplay:', 'amazonpolly' ), array( $this, 'amazon_polly_autoplay_cb' ), $this->plugin_name, 'amazon_polly_playersettings', array( 'label_for' => 'amazon_polly_autoplay' ) ); // ************************************************* * // ************* POLLY SETTINGS SECTION ************ * add_settings_section( 'amazon_polly_pollysettings', __( 'Amazon Polly settings', 'amazonpolly' ), array( $this, 'amazon_polly_pollysettings_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_sample_rate', __( 'Sample rate:', 'amazonpolly' ), array( $this, 'amazon_polly_sample_rate_cb' ), $this->plugin_name, 'amazon_polly_pollysettings', array( 'label_for' => 'amazon_polly_sample_rate' ) ); add_settings_field( 'amazon_polly_voice_id', __( 'Voice name:', 'amazonpolly' ), array( $this, 'amazon_polly_voice_id_cb' ), $this->plugin_name, 'amazon_polly_pollysettings', array( 'label_for' => 'amazon_polly_voice_id' ) ); add_settings_field( 'amazon_polly_auto_breaths', __( 'Automated breaths:', 'amazonpolly' ), array( $this, 'amazon_polly_auto_breaths_cb' ), $this->plugin_name, 'amazon_polly_pollysettings', array( 'label_for' => 'amazon_polly_auto_breaths_id' ) ); add_settings_field( 'amazon_polly_ssml', __( 'Enable SSML support:', 'amazonpolly' ), array( $this, 'amazon_polly_ssml_cb' ), $this->plugin_name, 'amazon_polly_pollysettings', array( 'label_for' => 'amazon_polly_ssml' ) ); add_settings_field( 'amazon_polly_lexicons', __( 'Lexicons:', 'amazonpolly' ), array( $this, 'amazon_polly_lexicons_cb' ), $this->plugin_name, 'amazon_polly_pollysettings', array( 'label_for' => 'amazon_polly_lexicons' ) ); add_settings_field( 'amazon_polly_speed', __( 'Audio speed [%]:', 'amazonpolly' ), array( $this, 'amazon_polly_speed_cb' ), $this->plugin_name, 'amazon_polly_pollysettings', array( 'label_for' => 'amazon_polly_speed' ) ); // ************************************************* * // ************** STORAGE SECTION ************** * add_settings_section( 'amazon_polly_storage', __( 'Cloud storage', 'amazonpolly' ), array( $this, 'amazon_polly_storage_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_s3', __( 'Store audio in Amazon S3:', 'amazonpolly' ), array( $this, 'amazon_polly_s3_cb' ), $this->plugin_name, 'amazon_polly_storage', array( 'label_for' => 'amazon_polly_s3' ) ); add_settings_field( 'amazon_polly_cloudfront', __( 'Amazon CloudFront (CDN) domain name:', 'amazonpolly' ), array( $this, 'amazon_polly_cloudfront_cb' ), $this->plugin_name, 'amazon_polly_storage', array( 'label_for' => 'amazon_polly_cloudfront' ) ); // ************************************************* * // ************** PODCAST SECTION ************** * add_settings_section( 'amazon_polly_podcast', __( 'Amazon Pollycast', 'amazonpolly' ), array( $this, 'amazon_pollycast_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_podcast_enabled', __( 'Pollycast enabled:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_enabled_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_enabled' ) ); add_settings_field( 'amazon_polly_podcast_email', __( 'iTunes contact email:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_email_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_email' ) ); add_settings_field( 'amazon_polly_podcast_category', __( 'iTunes category:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_category_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_category' ) ); add_settings_field( 'amazon_polly_podcast_explicit', __( 'iTunes explicit content:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_explicit_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_explicit' ) ); add_settings_field( 'amazon_polly_podcast_icon', __( 'iTunes image:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_icon_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_icon' ) ); add_settings_field( 'amazon_polly_podcast_feedsize', __( 'Feed size:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_feedsize_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_feedsize' ) ); add_settings_field( 'amazon_polly_podcast_post_cat', __( 'Post categories:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_post_cat_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_post_cat' ) ); add_settings_field( 'amazon_polly_podcast_https', __( 'Use HTTPS for audio files:', 'amazonpolly' ), array( $this, 'amazon_polly_podcast_https_cb' ), $this->plugin_name, 'amazon_polly_podcast', array( 'label_for' => 'amazon_polly_podcast_https' ) ); // ************************************************* * // ************** ADDITIONAL SECTION ************** * add_settings_section( 'amazon_polly_additional', __( 'Additional configuration', 'amazonpolly' ), array( $this, 'amazon_polly_additional_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_update_all', __( 'Bulk update all posts:', 'amazonpolly' ), array( $this, 'amazon_polly_update_all_cb' ), $this->plugin_name, 'amazon_polly_additional', array( 'label_for' => 'amazon_polly_update_all' ) ); add_settings_field( 'amazon_polly_add_post_title', __( 'Add post title to audio:', 'amazonpolly' ), array( $this, 'amazon_polly_add_post_title_cb' ), $this->plugin_name, 'amazon_polly_additional', array( 'label_for' => 'amazon_polly_add_post_title' ) ); add_settings_field( 'amazon_polly_add_post_excerpt', __( 'Add post excerpt to audio:', 'amazonpolly' ), array( $this, 'amazon_polly_add_post_excerpt_cb' ), $this->plugin_name, 'amazon_polly_additional', array( 'label_for' => 'amazon_polly_add_post_excerpt' ) ); add_settings_field( 'amazon_polly_posttypes', __( 'Post types:', 'amazonpolly' ), array( $this, 'amazon_polly_posttypes_cb' ), $this->plugin_name, 'amazon_polly_additional', array( 'label_for' => 'amazon_polly_posttypes' ) ); // ************************************************* * // ************** TRANSLATION SECTION ************** * add_settings_section( 'amazon_polly_trans', __( 'Amazon Translate configuration', 'amazonpolly' ), array( $this, 'amazon_polly_trans_cb' ), $this->plugin_name ); add_settings_field( 'amazon_polly_trans_enabled', __( 'Enable translation support:', 'amazonpolly' ), array( $this, 'amazon_polly_trans_enabled_cb' ), $this->plugin_name, 'amazon_polly_trans', array( 'label_for' => 'amazon_polly_trans_enabled' ) ); add_settings_field( 'amazon_polly_transcript_enabled', __( 'Show transcript:', 'amazonpolly' ), array( $this, 'amazon_polly_transcript_enabled_cb' ), $this->plugin_name, 'amazon_polly_trans', array( 'label_for' => 'amazon_polly_transcript_enabled' ) ); add_settings_field( 'amazon_polly_trans_src_lang', __( 'Source language:', 'amazonpolly' ), array( $this, 'amazon_polly_trans_src_lang_cb' ), $this->plugin_name, 'amazon_polly_trans', array( 'label_for' => 'amazon_polly_trans_src_lang' ) ); add_settings_field( 'amazon_polly_trans_langs_src_label', __( 'Source language label:', 'amazonpolly' ), array( $this, 'amazon_polly_trans_langs_src_label_cb' ), $this->plugin_name, 'amazon_polly_trans', array( 'label_for' => 'amazon_polly_trans_langs_src_label' ) ); add_settings_field( 'amazon_polly_trans_langs_label', __( 'Translations label:', 'amazonpolly' ), array( $this, 'amazon_polly_trans_langs_label_cb' ), $this->plugin_name, 'amazon_polly_trans', array( 'label_for' => 'amazon_polly_trans_langs_label' ) ); add_settings_field( 'amazon_polly_trans_langs', __( 'Target languages:', 'amazonpolly' ), array( $this, 'amazon_polly_trans_langs_cb' ), $this->plugin_name, 'amazon_polly_trans', array( 'label_for' => 'amazon_polly_trans_langs' ) ); add_option( 'amazon_polly_trans_validated' ); // ************************************************* * $selected_region = get_option( 'amazon_polly_region' ); if ( empty( $selected_region ) ) { update_option( 'amazon_polly_region', 'us-east-1' ); $selected_region = 'us-east-1'; } if ( empty( get_option( 'amazon_polly_access_key' ) ) ) { // Set AWS SDK settings. $aws_sdk_config = array( 'region' => $selected_region, 'version' => 'latest', ); } else { // Set AWS SDK settings. $aws_sdk_config = array( 'region' => $selected_region, 'version' => 'latest', 'credentials' => array( 'key' => get_option( 'amazon_polly_access_key' ), 'secret' => get_option( 'amazon_polly_secret_key' ), ), ); }//end if // Create an SDK class to use config. $sdk = new Aws\Sdk( $aws_sdk_config ); $this->s3_file_handler->set_s3_client( $sdk->createS3() ); $this->translate_client = $sdk->createTranslate(); $this->polly_client = $sdk->createPolly(); register_setting( $this->plugin_name, 'amazon_polly_access_key', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_secret_key', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_s3', 'strval' ); if ( $this->amazon_polly_is_ok() ) { register_setting( $this->plugin_name, 'amazon_polly_podcast_enabled', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_cloudfront', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_region', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_sample_rate', 'intval' ); register_setting( $this->plugin_name, 'amazon_polly_voice_id', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_ssml', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_auto_breaths', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_position', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_player_label', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_defconf', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_autoplay', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_speed', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_feedsize', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_email', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_category', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_explicit', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_post_cat', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_https', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_settings_hash', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_podcast_explicit', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_add_post_title', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_add_post_excerpt', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_posttypes', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_lexicons', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans_enabled', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_transcript_enabled', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans_src_lang', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans_langs_src_label', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans_langs_label', 'strval' ); foreach ( $this->translate_langs as $lan ) { register_setting( $this->plugin_name, 'amazon_polly_trans_langs_' . $lan, 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans_langs_' . $lan . '_voice', 'strval' ); register_setting( $this->plugin_name, 'amazon_polly_trans_langs_' . $lan . '_label', 'strval' ); } }//end if $this->amazon_polly_validate_credentials(); $is_s3_enabled = $this->amazon_polly_is_s3_enabled(); if ( $this->amazon_polly_is_ok() ) { if ( $is_s3_enabled ) { $this->getFileHandler()->prepare_s3_bucket(); } } } /** * Method returns file handler which is reponsible for communicating with proper storage location. * * @since 2.0.3 */ private function getFileHandler() { if ( $this->amazon_polly_is_s3_enabled() ) { return $this->s3_file_handler; } else { return $this->local_file_handler; } } /** * Method retrievies post which ID was provided, and clean it. * * @since 1.0.12 * @param string $post_id ID of the post for which test (content) should be prepapred for conversion. */ private function clean_text( $post_id ) { // Depending on the plugin configurations, post's title will be added to the audio. if ( $this->amazon_polly_is_title_adder_enabled() ) { $clean_text = get_the_title( $post_id ) . '. **AMAZONPOLLY*SSML*BREAK*time=***1s***SSML** '; } else { $clean_text = ''; } // Depending on the plugin configurations, post's excerpt will be added to the audio. if ( $this->amazon_polly_is_excerpt_adder_enabled() ) { $my_excerpt = apply_filters('the_excerpt', get_post_field('post_excerpt', $post_id)); $clean_text = $clean_text . $my_excerpt . ' **AMAZONPOLLY*SSML*BREAK*time=***1s***SSML** '; } $clean_text = $clean_text . get_post_field( 'post_content', $post_id ); $clean_text = apply_filters( 'amazon_polly_content', $clean_text ); $clean_text = str_replace( ' ', ' ', $clean_text ); $clean_text = do_shortcode( $clean_text ); $is_ssml_enabled = $this->amazon_polly_is_ssml_enabled(); if ( $is_ssml_enabled ) { $clean_text = $this->amazon_polly_encode_ssml_tags( $clean_text ); } $clean_text = strip_tags( $clean_text, '<break>' ); $clean_text = esc_html( $clean_text ); $clean_text = str_replace( ' ', ' ', $clean_text ); $clean_text = preg_replace("/https:\/\/([^\s]+)/", "", $clean_text); // $clean_text = str_replace( '-AMAZONPOLLY-ONLYAUDIO-START-', '', $clean_text ); // $clean_text = str_replace( '-AMAZONPOLLY-ONLYAUDIO-END-', '', $clean_text ); // $clean_text = preg_replace( '/-AMAZONPOLLY-ONLYWORDS-START-[\S\s]*?-AMAZONPOLLY-ONLYWORDS-END-/', '', $clean_text ); $clean_text_temp = ''; $paragraphs = explode( "\n", $clean_text ); foreach ( $paragraphs as $paragraph ) { $paragraph_size = strlen( trim( $paragraph ) ); if ( $paragraph_size > 0 ) { $clean_text_temp = $clean_text_temp . "\n" . $paragraph; } } $clean_text = $clean_text_temp; $clean_text = html_entity_decode( $clean_text, ENT_QUOTES, 'UTF-8' ); $clean_text = str_replace( '&', ' and ', $clean_text ); $clean_text = str_replace( '<', ' ', $clean_text ); $clean_text = str_replace( '>', ' ', $clean_text ); return $clean_text; } /** * Method breakes input text into smaller parts. * * @since 1.0.0 * @param string $text Text which should be broken. */ private function break_text( $text ) { $text = str_replace( '-AMAZONPOLLY-ONLYAUDIO-START-', '', $text ); $text = str_replace( '-AMAZONPOLLY-ONLYAUDIO-END-', '', $text ); $text = preg_replace( '/-AMAZONPOLLY-ONLYWORDS-START-[\S\s]*?-AMAZONPOLLY-ONLYWORDS-END-/', '', $text ); $parts = []; if ( ! empty( $text ) ) { $part_id = 0; $paragraphs = explode( "\n", $text ); foreach ( $paragraphs as $paragraph ) { $paragraph_size = strlen( trim( $paragraph ) ); if ( $paragraph_size > 0 ) { if ( $paragraph_size <= 2800 ) { $parts[ $part_id ] = $paragraph . ' **AMAZONPOLLY*SSML*BREAK*time=***500ms***SSML** '; $part_id++; } else { $words = explode( ' ', $paragraph ); $current_part = ''; $last_part = ''; foreach ( $words as $word ) { $word_length = strlen( $word ); $current_part_length = strlen( $current_part ); if ( $word_length + $current_part_length < 2800 ) { $current_part = $current_part . $word . ' '; $last_part = $current_part; } else { $current_part = $current_part . $word . ' '; $parts[ $part_id ] = $current_part; $part_id++; $current_part = ''; $last_part = ''; } } $parts[ $part_id ] = $last_part . ' **AMAZONPOLLY*SSML*BREAK*time=***500ms***SSML** '; $part_id++; }//end if }//end if }//end foreach }//end if // Modify speed $parts = $this->modify_speed( $parts ); return $parts; } /** * Method update sentences (input of the method), and modify their speed, * by adding SSML prosody tag for each sentence. * * @param string $sentences Sentences which should be updated. * @since 1.0.5 */ private function modify_speed( $sentences ) { $new_sentences = []; $new_sentence_id = 0; $speed = $this->amazon_polly_get_speed(); if ( 100 !== $speed ) { foreach ( $sentences as $sentence ) { $new_sentence = '<prosody rate="' . $speed . '%">' . $sentence . '</prosody>'; $new_sentences[ $new_sentence_id ] = $new_sentence; $new_sentence_id++; } } return $new_sentences; } /** * Method execute Amazon Polly API and convert content which was provided to audio file. * * @param string $post_id ID of the posts which is being converted. * @param string $sample_rate Sample rate for speech conversion. * @param string $voice_id Amazon Polly voice ID. * @param string $sentences Sentences which should be converted to audio. * @param string $wp_filesystem Reference to WP File system variable. * @param string $lang Language * @since 1.0.0 */ private function convert_to_audio( $post_id, $sample_rate, $voice_id, $sentences, $wp_filesystem, $lang ) { foreach ( $this->translate_langs as $lan ) { if ( $lan == $lang ) { $voice_id = get_option( 'amazon_polly_trans_langs_' . $lan . '_voice' ); } } $sample_rate_values = array( '22050', '16000', '8000' ); if ( ! in_array( $sample_rate, $sample_rate_values, true ) ) { $sample_rate = '22050'; } $upload_dir = wp_upload_dir()['basedir']; $file_prefix = 'amazon_polly_'; $file_name = $file_prefix . $post_id . $lang . '.mp3'; $file_temp_full_name = trailingslashit($upload_dir) . 'temp_' . $file_name; $dir_final_full_name = trailingslashit($upload_dir); if ( get_option('uploads_use_yearmonth_folders') ) { $dir_final_full_name .= get_the_date( 'Y', $post_id ) . '/' . get_the_date( 'm', $post_id ) . "/"; } $file_final_full_name = $dir_final_full_name . $file_name; // Delete temporary file if already exists. if ( $wp_filesystem->exists( $file_temp_full_name ) ) { $wp_filesystem->delete( $file_temp_full_name ); } // Delete final file if already exists. if ( $wp_filesystem->exists( $file_final_full_name ) ) { $wp_filesystem->delete( $file_final_full_name ); } $first_part = true; foreach ( $sentences as $key => $text_content ) { // Depending on the plugin configuration SSML tags for automated breaths sound will be added. $is_breaths_enabled = $this->amazon_polly_is_auto_breaths_enabled(); if ( $is_breaths_enabled ) { $text_content = '<amazon:auto-breaths>' . $text_content . '</amazon:auto-breaths>'; } // If plugin SSML support option is enabled, plugin will try to decode all SSML tags. $is_ssml_enabled = $this->amazon_polly_is_ssml_enabled(); if ( $is_ssml_enabled ) { $text_content = $this->amazon_polly_decode_ssml_tags( $text_content ); } $text_content = str_replace( '**AMAZONPOLLY*SSML*BREAK*time=***500ms***SSML**', '<break time="500ms"/>', $text_content ); $text_content = str_replace( '**AMAZONPOLLY*SSML*BREAK*time=***1s***SSML**', '<break time="500ms"/>', $text_content ); $amazon_polly_mark_value = 'wp-plugin-awslabs'; $amazon_polly_mark_value = apply_filters( 'amazon_polly_mark_value', $amazon_polly_mark_value ); $ssml_text_content = '<speak><mark name="' . esc_attr( $amazon_polly_mark_value ) . '"/>' . $text_content . '</speak>'; $lexicons = $this->get_lexicons(); $lexicons_array = explode( ' ', $lexicons ); if ( ! empty( $lexicons ) and ( count( $lexicons_array ) > 0 ) ) { $result = $this->polly_client->synthesizeSpeech( array( 'OutputFormat' => 'mp3', 'SampleRate' => $sample_rate, 'Text' => $ssml_text_content, 'TextType' => 'ssml', 'VoiceId' => $voice_id, 'LexiconNames' => $lexicons_array, ) ); } else { $result = $this->polly_client->synthesizeSpeech( array( 'OutputFormat' => 'mp3', 'SampleRate' => $sample_rate, 'Text' => $ssml_text_content, 'TextType' => 'ssml', 'VoiceId' => $voice_id, ) ); }//end if // Grab the stream and output to a file. $contents = $result['AudioStream']->getContents(); // Save first part of the audio stream in the parial temporary file. $wp_filesystem->put_contents( $file_temp_full_name . '_part_' . $key, $contents ); // Merge new temporary file with previous ones. if ( $first_part ) { $wp_filesystem->put_contents( $file_temp_full_name, $contents ); $first_part = false; } else { $this->remove_id3( $file_temp_full_name . '_part_' . $key ); $merged_file = $wp_filesystem->get_contents( $file_temp_full_name ) . $wp_filesystem->get_contents( $file_temp_full_name . '_part_' . $key ); $wp_filesystem->put_contents( $file_temp_full_name, $merged_file ); } // Deleting partial audio file. $wp_filesystem->delete( $file_temp_full_name . '_part_' . $key ); }//end foreach // Saving audio file in final destination. $fileHandler = $this->getFileHandler(); $audio_location_link = $fileHandler->save($wp_filesystem, $file_temp_full_name, $dir_final_full_name, $file_final_full_name, $post_id, $file_name); // This will bust the browser cache when a content revision is made. $audio_location_link = add_query_arg( 'version', time(), $audio_location_link ); // We are using a hash of these values to improve the speed of queries. $amazon_polly_settings_hash = md5( $voice_id . $sample_rate . $fileHandler->get_type() ); if ( $lang == '' ) { update_post_meta( $post_id, 'amazon_polly_audio_link_location', $audio_location_link ); update_post_meta( $post_id, 'amazon_polly_audio_location', $fileHandler->get_type() ); } else { update_post_meta( $post_id, 'amazon_polly_translation_' . $lang, '1' ); } // Update post meta data. update_post_meta( $post_id, 'amazon_polly_enable', 1 ); update_post_meta( $post_id, 'amazon_polly_voice_id', get_option( 'amazon_polly_voice_id' ) ); update_post_meta( $post_id, 'amazon_polly_sample_rate', $sample_rate ); update_post_meta( $post_id, 'amazon_polly_settings_hash', $amazon_polly_settings_hash ); } /** * Method removes ID3 tag from audio file * * @param string $filename File for which tag should be removed. * @since 1.0.0 */ public function remove_id3( $filename ) { // Temporary file - without IDv3 tag. $temp_filename = $filename . 'temp'; // Original file with IDv3 tag. $source_file = fopen( $filename, 'r+b' ); // IDv3 header has got 10 bytes. $id3_header = fread( $source_file, 10 ); // Calculating the total size of IDv3 tag. $int_value = 0; $byte_word = substr( $id3_header, 6, 4 ); $byte_word_length = strlen( $byte_word ); for ( $i = 0; $i < $byte_word_length; $i++ ) { $int_value += ( ord( $byte_word{$i} ) & 0x7F ) * pow( 2, ( $byte_word_length - 1 - $i ) * 7 ); } $offset = ( (int) $int_value ) + 10; // Recreating file without the IDv3 tag bytes. rewind( $source_file ); fseek( $source_file, $offset ); $temp_file = fopen( $temp_filename, 'w+b' ); while ( $buffer = fread( $source_file, 32768 ) ) { fwrite( $temp_file, $buffer, strlen( $buffer ) ); } // Swapping files. fclose( $temp_file ); unlink( $filename ); rename( $temp_filename, $filename ); } /** * Method prepare WP_Filesystem variable for interacting with local file system. * * @since 1.0.0 */ private function prepare_wp_filesystem() { $url = wp_nonce_url( admin_url( 'post-new.php' ) ); $creds = request_filesystem_credentials( $url ); if ( ! WP_Filesystem( $creds ) ) { request_filesystem_credentials( $url ); return true; } global $wp_filesystem; return $wp_filesystem; } /** * Render the text for the general section * * @since 1.0.0 */ public function amazon_polly_general_cb() { $nonce = wp_create_nonce( 'amazon-polly' ); echo '<input type="hidden" name="amazon-polly-admin" value="' . esc_attr( $nonce ) . '" />'; } /** * Render the Access Key input for this plugin * * @since 1.0.0 */ public function amazon_polly_access_key_cb() { $access_key = get_option( 'amazon_polly_access_key' ); echo '<input type="text" class="regular-text" name="amazon_polly_access_key" id="amazon_polly_access_key" value="' . esc_attr( $access_key ) . '" autocomplete="off"> '; echo '<p class="description" id="amazon_polly_access_key">Required only if you aren\'t using IAM roles</p>'; } /** * Render the Secret Key input for this plugin * * @since 1.0.0 */ public function amazon_polly_secret_key_cb() { $secret_key = get_option( 'amazon_polly_secret_key' ); echo '<input type="password" class="regular-text" name="amazon_polly_secret_key" id="amazon_polly_secret_key" value="' . esc_attr( $secret_key ) . '" autocomplete="off"> '; echo '<p class="description" id="amazon_polly_access_key">Required only if you aren\'t using IAM roles</p>'; } /** * Render the Automated Breath input. * * @since 1.0.7 */ public function amazon_polly_auto_breaths_cb() { if ( $this->amazon_polly_is_ok() ) { echo '<input type="checkbox" name="amazon_polly_auto_breaths" id="amazon_polly_auto_breaths" ' . $this->amazon_polly_checked_validator( 'amazon_polly_auto_breaths' ) . '> '; echo '<p class="description" for="amazon_polly_auto_breaths">If enabled, Amazon Polly automatically creates breathing noises at appropriate intervals</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the enable Source language label input. * * @since 2.0.0 */ public function amazon_polly_trans_langs_src_label_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_translation_enabled() ) { $value = $this->replace_if_empty( get_option( 'amazon_polly_trans_langs_src_label' ), 'English' ); echo '<input type="text" class="regular-text" name="amazon_polly_trans_langs_src_label" id="amazon_polly_trans_langs_src_label" value="' . esc_attr( $value ) . '"> '; } else { echo '<p class="description">Amazon Translate needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the enable Translation input. * * @since 2.0.0 */ public function amazon_polly_trans_langs_label_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_translation_enabled() ) { $trans_label = $this->replace_if_empty( get_option( 'amazon_polly_trans_langs_label' ), 'Listen in other languages: ' ); echo '<input type="text" class="regular-text" name="amazon_polly_trans_langs_label" id="amazon_polly_trans_langs_label" value="' . esc_attr( $trans_label ) . '"> '; } else { echo '<p class="description">Amazon Translate needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the input which will be responsible for providing information if * transcript of the content in other languages should be visible. * * @since 2.0.0 */ public function amazon_polly_transcript_enabled_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_translation_enabled() ) { echo '<input type="checkbox" name="amazon_polly_transcript_enabled" id="amazon_polly_transcript_enabled" ' . $this->amazon_polly_checked_validator( 'amazon_polly_transcript_enabled' ) . ' > '; } else { echo '<p class="description">Amazon Translate needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Utility function which checks if checkbox for option input should be checked. * * @param string $option Name of the option which should be checked. * @since 2.0.0 */ private function amazon_polly_checked_validator( $option ) { $option_value = get_option( $option, 'on' ); if ( empty( $option_value ) ) { return ''; } else { return ' checked '; } } /** * Render the enable Translation input. * * @since 2.0.0 */ public function amazon_polly_trans_enabled_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_s3_enabled() ) { $start_value = $this->amazon_polly_checked_validator( 'amazon_polly_trans_enabled' ); $translate_accessible = $this->translator->is_translate_accessible($this->translate_client); $supported_regions = array( 'us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1' ); $selected_region = get_option( 'amazon_polly_region', '' ); if ( in_array( $selected_region, $supported_regions ) ) { echo '<input type="checkbox" name="amazon_polly_trans_enabled" id="amazon_polly_trans_enabled" ' . $this->amazon_polly_checked_validator( 'amazon_polly_trans_enabled' ) . '> '; if ( 'checked' == trim($start_value)) { if ( !$translate_accessible ) { echo '<p class="description"><b>Amazon Translate not accessible. You need to update your IAM policy.</b></p>'; } } } else { echo '<p class="description">You need to use one of following regions: N.Virginia, Ohio, Oregon, Ireland</p>'; update_option( 'amazon_polly_trans_enabled', '' ); } } else { echo '<p class="description">Amazon S3 Storage needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Podcast enabled input. * * @since 1.0.7 */ public function amazon_polly_podcast_enabled_cb() { if ( $this->amazon_polly_is_ok() ) { echo '<input type="checkbox" name="amazon_polly_podcast_enabled" id="amazon_polly_podcast_enabled" ' . $this->amazon_polly_checked_validator( 'amazon_polly_podcast_enabled' ) . '> '; echo '<p class="description" for="amazon_polly_podcast_enabled">If enabled, Amazon Pollycast will be generated</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the HTTPS podcast input. * * @since 4.0.5 */ public function amazon_polly_podcast_https_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { echo '<input type="checkbox" name="amazon_polly_podcast_https" id="amazon_polly_podcast_https" ' . $this->amazon_polly_checked_validator( 'amazon_polly_podcast_https' ) . '> '; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Add post title to audio input. * * @since 1.0.7 */ public function amazon_polly_add_post_title_cb() { if ( $this->amazon_polly_is_ok() ) { echo '<input type="checkbox" name="amazon_polly_add_post_title" id="amazon_polly_add_post_title" ' . $this->amazon_polly_checked_validator( 'amazon_polly_add_post_title' ) . '> '; echo '<p class="description" for="amazon_polly_add_post_title">If enabled, each audio file will start from post title.</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Add post excerpt to audio input. * * @since 2.0.0 */ public function amazon_polly_add_post_excerpt_cb() { if ( $this->amazon_polly_is_ok() ) { echo '<input type="checkbox" name="amazon_polly_add_post_excerpt" id="amazon_polly_add_post_excerpt" ' . $this->amazon_polly_checked_validator( 'amazon_polly_add_post_excerpt' ) . '> '; echo '<p class="description" for="amazon_polly_add_post_excerpt">If enabled, each audio file will have post excerpt at the beginning.</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Default Configuration input. * * @since 1.0.0 */ public function amazon_polly_defconf_cb() { if ( $this->amazon_polly_is_ok() ) { $selected_defconf = get_option( 'amazon_polly_defconf' ); $defconf_values = [ 'Amazon Polly enabled', 'Amazon Polly disabled' ]; echo '<select name="amazon_polly_defconf" id="amazon_polly_defconf" >'; foreach ( $defconf_values as $defconf ) { echo '<option value="' . esc_attr( $defconf ) . '" '; if ( strcmp( $selected_defconf, $defconf ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( $defconf ) . '</option>'; } echo '</select>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Position input. * * @since 1.0.0 */ public function amazon_polly_position_cb() { if ( $this->amazon_polly_is_ok() ) { $selected_position = get_option( 'amazon_polly_position' ); $positions_values = array( 'Before post', 'After post', 'Do not show' ); echo '<select name="amazon_polly_position" id="amazon_polly_position" >'; foreach ( $positions_values as $position ) { echo '<option value="' . esc_attr( $position ) . '" '; if ( strcmp( $selected_position, $position ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( $position ) . '</option>'; } echo '</select>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Player Label input. * * @since 1.0.12 */ public function amazon_polly_lexicons_cb() { if ( $this->validate_credentials() ) { $lexicons = $this->get_lexicons(); echo '<input type="text" class="regular-text" name="amazon_polly_lexicons" id="amazon_polly_lexicons" value="' . esc_attr( $lexicons ) . '"> '; echo '<p class="description" for="amazon_polly_lexicons">Specify lexicons names (seperated by space), which you have uploaded to your AWS account</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Player Label input. * * @since 1.0.3 */ public function amazon_polly_player_label_cb() { if ( $this->amazon_polly_is_ok() ) { $player_label = get_option( 'amazon_polly_player_label' ); echo '<input type="text" class="regular-text" name="amazon_polly_player_label" id="amazon_polly_player_label" value="' . esc_attr( $player_label ) . '"> '; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Post Type input box. * * @since 1.0.7 */ public function amazon_polly_posttypes_cb() { if ( $this->amazon_polly_is_ok() ) { $posttypes = $this->amazon_polly_get_posttypes(); echo '<input type="text" class="regular-text" name="amazon_polly_posttypes" id="amazon_polly_posttypes" value="' . esc_attr( $posttypes ) . '"> '; echo '<p class="description" for="amazon_polly_posttypes">Post types in your WordPress environment</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the text for the Amazon Polly settings section * * @since 1.0.7 */ public function amazon_polly_pollysettings_cb() { } /** * Render the text for Player settings section * * @since 1.0.7 */ public function amazon_polly_playersettings_cb() { } /** * Render the text for the storage section * * @since 1.0.0 */ public function amazon_polly_storage_cb() { } /** * Render the text for the translation section * * @since 2.0.0 */ public function amazon_polly_trans_cb() { } /** * Render the text for the additional section * * @since 1.0.0 */ public function amazon_polly_additional_cb() { } /** * Render the 'store in S3' input. * * @since 1.0.0 */ public function amazon_polly_s3_cb() { if ( $this->amazon_polly_is_ok() ) { $selected_s3 = get_option( 'amazon_polly_s3' ); $s3_bucket_name = $this->get_bucket_name(); $message = ''; if ( empty( $s3_bucket_name ) ) { $checkbox_disabled = ''; } else { $checkbox_disabled = ''; } if ( empty( $selected_s3 ) ) { $checked = ' '; $bucket_name_visibility = 'display:none'; } else { $checked = ' checked '; $bucket_name_visibility = ' '; } echo '<input type="checkbox" name="amazon_polly_s3" id="amazon_polly_s3" ' . esc_attr( $checked ) . ' ' . esc_attr( $checkbox_disabled ) . '> <p class="description">' . esc_attr( $message ) . '</p>'; $is_s3_enabled = $this->amazon_polly_is_s3_enabled(); if ( $is_s3_enabled ) { echo '<label for="amazon_polly_s3" id="amazon_polly_s3_bucket_name_box" style="' . esc_attr( $bucket_name_visibility ) . '"> Your S3 Bucket name is <b>' . esc_attr( $s3_bucket_name ) . '</b></label>'; } echo '<p class="description">Audio files are saved on and streamed from Amazon S3. Learn more <a target="_blank" href="https://aws.amazon.com/s3">https://aws.amazon.com/s3</a></p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; }//end if } /** * Render the 'use CloudFront' input. * * @since 1.0.0 */ public function amazon_polly_cloudfront_cb() { if ( $this->amazon_polly_is_ok() ) { $is_s3_enabled = $this->amazon_polly_is_s3_enabled(); if ( $is_s3_enabled ) { $cloudfront_domain_name = get_option( 'amazon_polly_cloudfront' ); $s3_enabled = get_option( 'amazon_polly_s3' ); if ( empty( $s3_enabled ) ) { $disabled = ' disabled="disabled" '; } else { $disabled = ' '; } echo '<input type="text" name="amazon_polly_cloudfront" class="regular-text" "id="amazon_polly_cloudfront" value="' . esc_attr( $cloudfront_domain_name ) . '" ' . esc_attr( $disabled ) . '> '; echo '<p class="description">If you have set up CloudFront distribution for your S3 bucket, the name of the domain. For additional information and pricing, see: <a target="_blank" href="https://aws.amazon.com/cloudfront">https://aws.amazon.com/cloudfront</a> </p>'; } else { echo '<p class="description">Amazon S3 Storage needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; }//end if } /** * Render the enable SSML input. * * @since 1.0.7 */ public function amazon_polly_ssml_cb() { if ( $this->amazon_polly_is_ok() ) { $is_s3_enabled = $this->amazon_polly_is_s3_enabled(); if ( $is_s3_enabled ) { $is_ssml_enabled = $this->amazon_polly_is_ssml_enabled(); if ( $is_ssml_enabled ) { $checked = ' checked '; } else { $checked = ' '; } echo '<input type="checkbox" name="amazon_polly_ssml" id="amazon_polly_ssml" ' . esc_attr( $checked ) . '> '; } else { echo '<p class="description">Amazon S3 Storage needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the autoplay input. * * @since 1.0.0 */ public function amazon_polly_autoplay_cb() { if ( $this->amazon_polly_is_ok() ) { $selected_autoplay = get_option( 'amazon_polly_autoplay' ); if ( empty( $selected_autoplay ) ) { $checked = ' '; } else { $checked = ' checked '; } echo '<input type="checkbox" name="amazon_polly_autoplay" id="amazon_polly_autoplay" ' . esc_attr( $checked ) . '> '; echo '<p class="description" for="amazon_polly_autoplay">Automatically play audio content when page loads</p>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the autoplay input. * * @since 1.0.5 */ public function amazon_polly_speed_cb() { if ( $this->amazon_polly_is_ok() ) { $speed = $this->amazon_polly_get_speed(); echo '<input type="number" name="amazon_polly_speed" id="amazon_polly_speed" value="' . esc_attr( $speed ) . '">'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Return post type value. * * @since 1.0.7 */ public function amazon_polly_get_posttypes() { $posttypes = get_option( 'amazon_polly_posttypes', 'post' ); return $posttypes; } /** * Return post type value array. * * @since 1.0.7 */ public function amazon_polly_get_posttypes_array() { $posttypes_array = get_option( 'amazon_polly_posttypes', 'post' ); $posttypes_array = explode( ' ', $posttypes_array ); $posttypes_array = apply_filters( 'amazon_polly_post_types', $posttypes_array ); return $posttypes_array; } /** * Check if AWS credentials are correct * * @since 1.0.7 */ private function amazon_polly_is_ok() { $this->amazon_polly_validate_credentials(); $is_key_valid = ( get_option( 'amazon_polly_valid_keys' ) === '1' ); if ( $is_key_valid ) { return true; } else { update_option( 'amazon_polly_trans_validated', '' ); return false; } } /** * Check if Translation is enabled. * * @since 2.0.0 */ public function amazon_polly_is_translation_enabled() { $translation_enabled = get_option( 'amazon_polly_trans_enabled', '' ); if ( empty( $translation_enabled ) ) { $result = false; } else { $result = true; } $is_s3_enabled = $this->amazon_polly_is_s3_enabled(); if ( $is_s3_enabled ) { return $result; } return false; } /** * Check if SSML is enabled. * * @since 1.0.7 */ public function amazon_polly_is_ssml_enabled() { $ssml_enabled = get_option( 'amazon_polly_ssml', 'on' ); if ( empty( $ssml_enabled ) ) { $result = false; } else { $result = true; } $is_s3_enabled = $this->amazon_polly_is_s3_enabled(); if ( $is_s3_enabled ) { return $result; } return false; } /** * Return speed for audio files. * * @since 1.0.5 */ public function amazon_polly_get_speed() { $speed = get_option( 'amazon_polly_speed' ); if ( empty( $speed ) ) { $speed = '100'; } if ( intval( $speed ) < 20 ) { $speed = '20'; } if ( intval( $speed ) > 200 ) { $speed = '200'; } update_option( 'amazon_polly_speed', $speed ); return $speed; } /** * Checks if pollycast is enabled. * * @since 1.0.7 */ public function amazon_polly_is_podcast_enabled() { $value = get_option( 'amazon_polly_podcast_enabled', 'on' ); if ( empty( $value ) ) { $result = false; } else { $result = true; } return $result; } /** * Checks if auto breaths are enabled. * * @since 1.0.7 */ public function amazon_polly_is_auto_breaths_enabled() { $value = get_option( 'amazon_polly_auto_breaths', 'on' ); if ( empty( $value ) ) { $result = false; } else { $result = true; } return $result; } /** * Checks if post title should be added. * * @since 1.0.7 */ public function amazon_polly_is_title_adder_enabled() { $value = get_option( 'amazon_polly_add_post_title', 'on' ); if ( empty( $value ) ) { $result = false; } else { $result = true; } return $result; } /** * Checks if post title should be added. * * @since 1.0.7 */ public function amazon_polly_is_excerpt_adder_enabled() { $value = get_option( 'amazon_polly_add_post_excerpt', 'on' ); if ( empty( $value ) ) { $result = false; } else { $result = true; } return $result; } /** * Render the region input. * * @since 1.0.3 */ public function amazon_polly_region_cb() { if ( $this->amazon_polly_is_ok() ) { $selected_region = get_option( 'amazon_polly_region' ); $regions = array( 'us-east-1' => 'US East (N. Virginia)', 'us-east-2' => 'US East (Ohio)', 'us-west-1' => 'US West (N. California)', 'us-west-2' => 'US West (Oregon)', 'eu-west-1' => 'EU (Ireland)', 'eu-west-2' => 'EU (London)', 'eu-west-3' => 'EU (Paris)', 'eu-central-1' => 'EU (Frankfurt)', 'ca-central-1' => 'Canada (Central)', 'sa-east-1' => 'South America (Sao Paulo)', 'ap-southeast-1' => 'Asia Pacific (Singapore)', 'ap-northeast-1' => 'Asia Pacific (Tokyo)', 'ap-southeast-2' => 'Asia Pacific (Sidney)', 'ap-northeast-2' => 'Asia Pacific (Seoul)', 'ap-south-1' => 'Asia Pacific (Mumbai)', ); echo '<select name="amazon_polly_region" id="amazon_polly_region" >'; foreach ( $regions as $region_name => $region_label ) { echo '<option label="' . esc_attr( $region_label ) . '" value="' . esc_attr( $region_name ) . '" '; if ( strcmp( $selected_region, $region_name ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr__($region_label, $this->plugin_name) . '</option>'; } echo '</select>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; }//end if } /** * Render the translation target languages input. * * @since 2.0.0 */ public function amazon_polly_trans_langs_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_translation_enabled() ) { $src_lang = $this->get_src_lang(); $voice_list = $this->polly_client->describeVoices(); usort( $voice_list['Voices'], 'sort_voices' ); echo '<table>'; $this->show_translate_option( $src_lang, $voice_list, 'en', 'English', 'English' ); $this->show_translate_option( $src_lang, $voice_list, 'es', 'Spanish', 'Español' ); $this->show_translate_option( $src_lang, $voice_list, 'de', 'German', 'Deutsch' ); $this->show_translate_option( $src_lang, $voice_list, 'fr', 'French', 'Français' ); $this->show_translate_option( $src_lang, $voice_list, 'pt', 'Portuguese', 'Português' ); echo '</table>'; } else { echo '<p class="description">Amazon Translate needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; }//end if } /** * Render the translation target languages input. * * @param string $language_label Label which should be used for this language. * @param string $language_name Name (in english) of this language. * @param string $lanuage Language code. * @param string $voice_list List of available voices. * @param string $src_lang Source Language (code). * @since 2.0.0 */ private function show_translate_option( $src_lang, $voice_list, $lanuage, $language_name, $language_label ) { if ( empty( $src_lang ) ) { $src_lang = 'en'; } if ( $src_lang == $lanuage ) { return; } $lan_option = 'amazon_polly_trans_langs_' . $lanuage; $lan_voice_option = 'amazon_polly_trans_langs_' . $lanuage . '_voice'; $lan_label_option = 'amazon_polly_trans_langs_' . $lanuage . '_label'; $disabled = ''; if ( ( $src_lang == $lanuage ) or ( 'en' == $lanuage ) ) { $disabled = 'disabled'; } echo '<tr>'; echo '<td><input type="checkbox" name="' . $lan_option . '" id="' . $lan_option . '" ' . $this->check_if_lang_checked( $lan_option, $src_lang ) . ' ' . $disabled . '>' . $language_name . ' </td><td>'; $voice_id = get_option( $lan_voice_option ); echo '  Voice: <select name="' . $lan_voice_option . '" id="' . $lan_voice_option . '">'; foreach ( $voice_list['Voices'] as $voice ) { if ( strpos( $voice['LanguageName'], $language_name ) !== false ) { echo '<option value="' . esc_attr( $voice['Id'] ) . '" '; if ( strcmp( $voice_id, $voice['Id'] ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( $voice['LanguageName'] ) . ' - ' . esc_attr( $voice['Id'] ) . '</option>'; } } echo '</select>'; $lan_label = $this->replace_if_empty( get_option( $lan_label_option, $language_label ), $language_label ); echo '</td><td>Label: <input type="text" class="regular-text" name="' . $lan_label_option . '" id="' . $lan_label_option . '" value="' . esc_attr( $lan_label ) . '" ></td> '; echo '</tr>'; } private function replace_if_empty( $value, $new_value ) { if ( ! empty( $value ) ) { return $value; } else { return $new_value; } } /** * Checks if checkbox should be checked for specific language. * * @since 2.0.0 */ private function check_if_lang_checked( $lang_code ) { $value = get_option( $lang_code, '' ); if ( 'amazon_polly_trans_langs_en' == $lang_code ) { return ' checked '; } if ( empty( $value ) ) { return ''; } else { return ' checked '; } } /** * Checks if checkbox should be checked for specific language. * * @since 2.0.0 */ private function check_if_translate( $lang_code ) { foreach ( $this->translate_langs as $supported_lan ) { if ( $supported_lan == $lang_code ) { $value = get_option( 'amazon_polly_trans_langs_' . $supported_lan, '' ); if ( 'en' == $lang_code ) { $value = 'on'; } } } if ( empty( $value ) ) { return false; } else { return true; } } /** * Render the translation source language input. * * @since 2.0.0 */ public function amazon_polly_trans_src_lang_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_translation_enabled() ) { $selected_src_lang = $this->get_src_lang(); $langs = array( 'en' => 'English', 'de' => 'German', 'es' => 'Spanish', 'fr' => 'French', 'pt' => 'Portuguese', ); echo '<select name="amazon_polly_trans_src_lang" id="amazon_polly_trans_src_lang" >'; foreach ( $langs as $lang_name => $lang_label ) { echo '<option label="' . esc_attr( $lang_label ) . '" value="' . esc_attr( $lang_name ) . '" '; if ( strcmp( $selected_src_lang, $lang_name ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr__($lang_label, $this->plugin_name) . '</option>'; } echo '</select>'; } else { echo '<p class="description">Amazon Translate needs to be enabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Sample Rate input for this plugin * * @since 1.0.0 */ public function amazon_polly_sample_rate_cb() { if ( $this->amazon_polly_is_ok() ) { $sample_rate = get_option( 'amazon_polly_sample_rate' ); $sample_array = array( '22050', '16000', '8000' ); echo '<select name="amazon_polly_sample_rate" id="amazon_polly_sample_rate" >'; foreach ( $sample_array as $rate ) { echo '<option value="' . esc_attr( $rate ) . '" '; if ( strcmp( $sample_rate, $rate ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( $rate ) . '</option>'; } echo '</select>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Validate if AWS credentials are proper. * * @since 1.0.0 */ private function amazon_polly_validate_credentials() { try { $voice_list = $this->polly_client->describeVoices(); update_option( 'amazon_polly_valid_keys', '1' ); } catch ( Exception $e ) { update_option( 'amazon_polly_valid_keys', '0' ); } } /** * Validate if AWS credentials are proper. * * @since 1.0.0 */ private function validate_credentials() { try { $voice_list = $this->polly_client->describeVoices(); return true; } catch ( Exception $e ) { return false; } } /** * Render the Polly Voice input for this plugin * * @since 1.0.0 */ public function amazon_polly_voice_id_cb() { /** * Compare two voices for ordering purpose. * * @param string $voice1 First voice. * @param string $voice2 Second voice. * @since 1.0.0 */ function sort_voices( $voice1, $voice2 ) { return strcmp( $voice1['LanguageName'], $voice2['LanguageName'] ); } if ( $this->amazon_polly_is_ok() ) { $voice_id = get_option( 'amazon_polly_voice_id' ); $voice_list = $this->polly_client->describeVoices(); echo '<select name="amazon_polly_voice_id" id="amazon_polly_voice_id">'; usort( $voice_list['Voices'], 'sort_voices' ); foreach ( $voice_list['Voices'] as $voice ) { echo '<option value="' . esc_attr( $voice['Id'] ) . '" '; if ( strcmp( $voice_id, $voice['Id'] ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( $voice['LanguageName'] ) . ' - ' . esc_attr( $voice['Id'] ) . '</option>'; } echo '</select>'; } else { $voice_id = get_option( 'amazon_polly_voice_id' ); echo '<input type="hidden" name="amazon_polly_voice_id" id="amazon_polly_voice_id" value="' . esc_attr( $voice_id ) . '">'; echo '<p>Please verify your AWS Credentials are accurate</p>'; }//end if } /** * Render the Update All input for this plugin * * @since 1.0.0 */ public function amazon_polly_update_all_cb() { if ( $this->amazon_polly_is_ok() ) { $message = $this->get_price_message_for_update_all(); echo '<p>'; echo '<button type="button" class="button" name="amazon_polly_update_all" id="amazon_polly_update_all">Bulk Update</button>'; echo '<label id="label_amazon_polly_update_all" for="amazon_polly_update_all"> Changes must be saved before proceeding with a bulk update.</label>'; echo '</p>'; echo '<div id="amazon_polly_bulk_update_div">'; echo '<p id="amazon_polly_update_all_pricing_message" class="description">' . esc_html( $message ) . '</p>'; echo '<p><button type="button" class="button button-primary" id="amazon_polly_batch_transcribe" >Bulk Update</button></p>'; echo '<div id="amazon-polly-progressbar"><div class="amazon-polly-progress-label">Loading...</div></div>'; echo '</div>'; } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Podcast section description. * * @since 1.0.0 */ public function amazon_pollycast_cb() { if ( $this->amazon_polly_is_podcast_enabled() ) { echo '<p>Amazon Pollycast available at: <a target = "_blank" href="' . esc_attr( get_feed_link( 'amazon-pollycast' ) ) . '">' . esc_html( get_feed_link( 'amazon-pollycast' ) ) . '</a></p>'; echo '<p>Submit your Amazon Pollycast to iTunes iConnect: <a target = "_blank" href="https://podcastsconnect.apple.com/">' . esc_html( 'https://podcastsconnect.apple.com/' ) . '</a></p>'; } } /** * Render UI for setting Amazon Pollycast feedsize * * @since 2.0.3 */ public function amazon_polly_podcast_feedsize_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { $value = get_option( 'amazon_polly_podcast_feedsize', 20 ); echo '<input type="number" name="amazon_polly_podcast_feedsize" id="amazon_polly_podcast_feedsize" value="' . esc_attr( $value ) . '"/>'; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the possibility for specify category of posts which will be added in feed. * * @since 2.0.4 */ public function amazon_polly_podcast_post_cat_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { $value = get_option( 'amazon_polly_podcast_post_cat' ); echo '<input class="regular-text" name="amazon_polly_podcast_post_cat" id="amazon_polly_podcast_post_cat" value="' . esc_attr( $value ) . '"/>'; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Update All input for this plugin * * @since 1.0.0 */ public function amazon_polly_podcast_email_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { $selected_email = get_option( 'amazon_polly_podcast_email' ); echo '<input class="regular-text" name="amazon_polly_podcast_email" id="amazon_polly_podcast_email" value="' . esc_attr( $selected_email ) . '"/>'; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Update All input for this plugin * * @since 1.0.0 */ public function amazon_polly_podcast_category_cb() { $default_category = 'News & Politics'; $select_categories = array( 'Arts', 'Business', 'Comedy', 'Education', 'Games & Hobbies', 'Government & Organizations', 'Health', 'Kids', 'Music', 'News & Politics', 'Religion', 'Science & Medicine', 'Society & Culture', 'Sports & Recreation', 'Technology', 'TV & Film', ); if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { $selected_category = get_option( 'amazon_polly_podcast_category' ); if ( ! $selected_category ) { $selected_category = 'News & Politics'; } echo '<select name="amazon_polly_podcast_category" id="amazon_polly_podcast_category">'; foreach ( $select_categories as $category ) { echo '<option value="' . esc_attr( $category ) . '" '; if ( strcmp( $selected_category, $category ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( $category ) . '</option>'; } echo '</select>'; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; }//end if } /** * Render the Update All input for this plugin * * @since 1.0.0 */ public function amazon_polly_podcast_explicit_cb() { $select_explicits = array( 'yes', 'no', ); if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { $selected_explicit = get_option( 'amazon_polly_podcast_explicit' ); echo '<select name="amazon_polly_podcast_explicit" id="amazon_polly_podcast_explicit">'; foreach ( $select_explicits as $explicit ) { echo '<option value="' . esc_attr( $explicit ) . '" '; if ( strcmp( $selected_explicit, $explicit ) === 0 ) { echo 'selected="selected"'; } echo '>' . esc_attr( ucfirst( $explicit ) ) . '</option>'; } echo '</select>'; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Render the Update All input for this plugin * * @since 1.0.0 */ public function amazon_polly_podcast_icon_cb() { if ( $this->amazon_polly_is_ok() ) { if ( $this->amazon_polly_is_podcast_enabled() ) { $query['autofocus[section]'] = 'amazonpolly'; $section_link = add_query_arg( $query, admin_url( 'customize.php' ) ); echo '<p>Upload a podcast icon using the <a target="_blank" href="' . esc_url( $section_link ) . '">Customizer</a>.</p>'; } else { echo '<p class="description">Amazon Pollycast is disabled</p>'; } } else { echo '<p>Please verify your AWS Credentials are accurate</p>'; } } /** * Checks how many posts should be converted. * * @since 1.0.0 */ public function get_num_posts_needing_transcription() { $post_types_supported = $this->amazon_polly_get_posttypes_array(); $amazon_polly_voice_id = get_option( 'amazon_polly_voice_id' ); $amazon_polly_sample_rate = get_option( 'amazon_polly_sample_rate' ); $amazon_polly_audio_location = ( 'on' === get_option( 'amazon_polly_s3' ) ) ? 's3' : 'local'; $args = array( 'posts_per_page' => '-1', 'post_type' => $post_types_supported, 'meta_query' => array( 'relation' => 'AND', array( 'key' => 'amazon_polly_audio_link_location', 'compare' => 'EXISTS', ), array( 'key' => 'amazon_polly_voice_id', 'value' => $amazon_polly_voice_id, 'compare' => '=', ), array( 'key' => 'amazon_polly_sample_rate', 'value' => $amazon_polly_sample_rate, 'compare' => '=', ), array( 'key' => 'amazon_polly_audio_location', 'value' => $amazon_polly_audio_location, 'compare' => '=', ), ), ); $query = new WP_Query( $args ); return count( $query->posts ); } /** * Method returns lexicons specified in plugin configuration. * * @since 1.0.12 */ private function get_lexicons() { $lexicons = get_option( 'amazon_polly_lexicons', '' ); $lexicons = trim( $lexicons ); return $lexicons; } /** * Calculate the total price of converting all posts into audio. * * @since 1.0.0 */ private function get_price_message_for_update_all() { $post_types_supported = $this->amazon_polly_get_posttypes_array(); $number_of_characters = 0; $posts_per_page = apply_filters( 'amazon_polly_posts_per_page', 5 ); $count_posts = wp_count_posts()->publish; $max_count_posts = 100; // Retrieving the number of characters in all posts. $paged = 0; $post_count = 0; do { $paged++; $wp_query = new WP_Query( array( 'posts_per_page' => $posts_per_page, 'post_type' => $post_types_supported, 'fields' => 'ids', 'paged' => $paged, ) ); $number_of_posts = $wp_query->max_num_pages; while ( $wp_query->have_posts() ) { $post_count++; $wp_query->the_post(); $post_id = get_the_ID(); $clean_text = $this->clean_text( $post_id ); $post_sentences = $this->break_text( $clean_text ); if ( ! empty( $post_sentences ) ) { foreach ( $post_sentences as $sentence ) { $sentence = str_replace( '**AMAZONPOLLY*SSML*BREAK*time=***1s***SSML**', '', $sentence ); $sentence = str_replace( '**AMAZONPOLLY*SSML*BREAK*time=***500ms***SSML**', '', $sentence ); $number_of_characters += strlen( $sentence ); } } } // If we reached the number of posts which we wanted to read, we stop // reading next posts. if ( $post_count >= $max_count_posts ) { break; } } while ( $paged < $number_of_posts ); // Price for converting single character according to Amazon Polly pricing. $amazon_polly_price = 0.000004; // Estimating average number of characters per post. if ( 0 !== $post_count ) { $post_chars_count_avg = $number_of_characters / $post_count; } else { $post_chars_count_avg = 0; } // Estimating the total price of convertion of all posts. $total_price = $amazon_polly_price * $count_posts * $post_chars_count_avg; $message = 'You are about to convert ' . number_format( $count_posts, 0, '.', ',' ) . ' pieces of text-based content, which totals approximately ' . number_format( $number_of_characters, 0, '.', ',' ) . ' characters. Based on the Amazon Polly pricing ($4 dollars per 1 million characters) it will cost you about $' . $total_price . ' to convert all of your content into to speech-based audio. Some or all of your costs might be covered by the Free Tier (conversion of 5 million characters per month for free, for the first 12 months, starting from the first request for speech). Learn more https://aws.amazon.com/polly/'; return $message; } public function amazon_polly_ajax_translate() { check_ajax_referer( 'pollyajaxnonce', 'nonce' ); $post_id = $_POST['post_id']; $phase = $_POST['phase']; $langs = $_POST['langs']; $step = ''; $percentage = 0; $message = ''; $all_langs = []; $index = 0; $src_lang = get_post_meta( $post_id, 'amazon_polly_transcript_source_lan', true ); if ( empty( $src_lang ) ) { $message = 'Amazon Translate functionality needs to be enabled before publishing the post'; $step = 'done'; $percentage = 100; } else { foreach ( $this->translate_langs as $supported_lan ) { if ( $this->check_if_translate( $supported_lan ) and ( $supported_lan != $src_lang ) ) { $all_langs[ $index ] = $supported_lan; $index++; } } if ( 'start' == $phase ) { $langs = $all_langs; } else { if ( ( $key = array_search( 'en', $langs ) ) !== false ) { $language_code = 'en'; unset( $langs[ $key ] ); } else { $language_code = array_shift( $langs ); } if ( 'en' == $language_code ) { $clean_text = $this->clean_text( $post_id ); } else { $clean_text = get_post_meta( $post_id, 'amazon_polly_transcript_en', true ); $src_lang = 'en'; } $wp_filesystem = $this->prepare_wp_filesystem(); if ( $this->check_if_translate( $language_code ) and ( $language_code != $src_lang ) ) { $translated_text = $this->translator->translate( $this->translate_client, $clean_text, $src_lang, $language_code); update_post_meta( $post_id, 'amazon_polly_transcript_' . $language_code, $translated_text ); $sentences = $this->break_text( $translated_text ); $this->convert_to_audio( $post_id, '', '', $sentences, $wp_filesystem, $language_code ); } $percentage = 100 - ( count( $langs ) / $index ) * 100; }//end if if ( empty( $langs ) ) { $step = 'done'; $message = 'Translation completed!'; } }//end if $next_langs = $langs; if ( ( 'en' != $src_lang ) && ( $key = array_search( 'en', $next_langs ) ) !== false ) { $next_lang = 'en'; } else { $next_lang = array_shift( $next_langs ); } if ( ! empty( $next_lang ) ) { $message = 'Translating from ' . $this->amazon_polly_map( $src_lang ) . ' to ' . $this->amazon_polly_map( $next_lang ); } else { $message = 'Translation completed!'; } if ( empty( $src_lang ) ) { $message = 'Amazon Translate functionality needs to be enabled before publishing the post'; } echo wp_json_encode( array( 'step' => $step, 'langs' => $langs, 'percentage' => $percentage, 'message' => $message, ) ); wp_die(); } private function amazon_polly_map( $code ) { switch ( $code ) { case 'en': return 'English'; case 'fr': return 'French'; case 'de': return 'German'; case 'pt': return 'Portuguese'; case 'es': return 'Spanish'; } return 'N/A'; } /** * Batch process the post transcriptions. * * @since 1.0.0 */ public function amazon_polly_ajax_transcribe() { check_ajax_referer( 'pollyajaxnonce', 'nonce' ); $batch_size = 1; $post_types_supported = $this->amazon_polly_get_posttypes_array(); $amazon_polly_voice_id = get_option( 'amazon_polly_voice_id' ); $amazon_polly_sample_rate = get_option( 'amazon_polly_sample_rate' ); $amazon_polly_audio_location = ( 'on' === get_option( 'amazon_polly_s3' ) ) ? 's3' : 'local'; // We are using a hash of these values to improve the speed of queries. $amazon_polly_settings_hash = md5( $amazon_polly_voice_id . $amazon_polly_sample_rate . $amazon_polly_audio_location ); $args = array( 'posts_per_page' => $batch_size, 'post_type' => $post_types_supported, 'meta_query' => array( 'relation' => 'OR', array( 'key' => 'amazon_polly_audio_link_location', 'compare' => 'NOT EXISTS', ), array( 'key' => 'amazon_polly_voice_id', 'value' => $amazon_polly_voice_id, 'compare' => '!=', ), array( 'key' => 'amazon_polly_sample_rate', 'value' => $amazon_polly_sample_rate, 'compare' => '!=', ), array( 'key' => 'amazon_polly_audio_location', 'value' => $amazon_polly_audio_location, 'compare' => '!=', ), ), ); $query = new WP_Query( $args ); $post_ids = wp_list_pluck( $query->posts, 'ID' ); if ( is_array( $post_ids ) && ! empty( $post_ids ) ) { foreach ( $post_ids as $post_id ) { $clean_text = $this->clean_text( $post_id ); $sentences = $this->break_text( $clean_text ); $wp_filesystem = $this->prepare_wp_filesystem(); $this->convert_to_audio( $post_id, $amazon_polly_sample_rate, $amazon_polly_voice_id, $sentences, $wp_filesystem, '' ); } } else { $step = 'done'; } $percentage = $this->get_percentage_complete(); echo wp_json_encode( array( 'step' => $step, 'percentage' => $percentage, ) ); wp_die(); } /** * Calculate the percentage complete. * * @since 1.0.0 */ public function get_percentage_complete() { $total_posts = 0; $post_types_supported = $this->amazon_polly_get_posttypes_array(); $posts_needing_translation = $this->get_num_posts_needing_transcription(); foreach ( $post_types_supported as $post_type ) { $post_type_count = wp_count_posts( $post_type )->publish; $total_posts += $post_type_count; } if ( 0 >= $total_posts || 0 >= $posts_needing_translation ) { $percentage = 100; } else { $percentage = round( $posts_needing_translation / $total_posts * 100, 2 ); } return $percentage; } /** * Adds a Settings action link to the Plugins page. * * @since 1.0.0 * @param string $links A list of plugin action links. */ public function plugin_add_settings_link( $links ) { $settings_link = '<a href="options-general.php?page=amazonpolly">' . __( 'Settings' ) . '</a>'; array_unshift( $links, $settings_link ); return $links; } /** * Get S3 bucket name. The method uses filter 'amazon_polly_s3_bucket_name, * which allows to use customer S3 bucket name instead of default one. * * @since 1.0.6 */ private function get_bucket_name() { $s3_bucket_name = get_option( 'amazon_polly_s3_bucket' ); $s3_bucket_name = apply_filters( 'amazon_polly_s3_bucket_name', $s3_bucket_name ); return $s3_bucket_name; } /** * Configure supported HTML tags. * * @since 1.0.7 * @param string $tags supported tags. */ public function amazon_polly_allowed_tags_kses( $tags ) { $tags['ssml'] = true; $tags['speak'] = true; $tags['break'] = array( 'time' => true, ); return $tags; } /** * Configure supported HTML tags. * * @since 1.0.7 * @param string $tags supported tags. */ public function amazon_polly_allowed_tags_tinymce( $tags ) { $ssml_tags = array( 'ssml', 'speak', 'break[time|whatever]', 'emphasis[level]', 'lang', 'mark', 'paragraph', 'phoneme', 'prosody', 's', 'say-as', 'sub', 'w', 'amazon:breath', 'amazon:auto-breaths', 'amazon:effect[name]', 'amazon:effect[phonation]', 'amazon:effect[vocal-tract-length]', 'amazon:effect[name]', ); $tags['extended_valid_elements'] = implode( ',', $ssml_tags ); return $tags; } /** * Returns source language. * * @since 2.0.0 */ private function get_src_lang() { $value = get_option( 'amazon_polly_trans_src_lang', 'en' ); if ( empty($value) ) { $value = 'en'; } return $value; } /** * Checks if auto breaths are enabled. * * @since 1.0.7 */ public function amazon_polly_is_s3_enabled() { $value = get_option( 'amazon_polly_s3', 'on' ); if ( empty( $value ) ) { $result = false; } else { $result = true; } return $result; } /** * Encode SSML tags. * * @since 1.0.7 * @param string $text text which should be encoded. */ private function amazon_polly_encode_ssml_tags( $text ) { $text = preg_replace( '/<ssml><break ([\S\s]*?)["\'](.*?)["\'](.*?)<\/ssml>/', '**AMAZONPOLLY*SSML*BREAK*$1***$2***SSML**', $text ); return $text; } /** * Encode SSML tags. * * @since 1.0.7 * @param string $text text which should be decoded. */ private function amazon_polly_decode_ssml_tags( $text ) { $text = preg_replace( '/(\*\*AMAZONPOLLY\*SSML\*BREAK\*)(.*?)(\*\*\*)(.*?)(\*\*\*SSML\*\*)/', '<break $2"$4"/>', $text ); return $text; } }