$defaults['aiovg_images_settings']['width'], 'ratio' => $defaults['aiovg_images_settings']['ratio'], 'size' => $defaults['aiovg_images_settings']['size'] ); if ( isset( $image_settings['ratio'] ) ) { $images_settings['ratio'] = $image_settings['ratio']; } if ( isset( $videos_settings['ratio'] ) ) { $images_settings['ratio'] = $videos_settings['ratio']; } update_option( 'aiovg_images_settings', $images_settings ); } // Insert the featured images settings $featured_images_settings = get_option( 'aiovg_featured_images_settings' ); if ( ! is_array( $featured_images_settings ) || empty( $featured_images_settings ) ) { $featured_images_settings = array( 'enabled' => $defaults['aiovg_featured_images_settings']['enabled'], 'download_external_images' => $defaults['aiovg_featured_images_settings']['download_external_images'], 'hide_on_single_video_pages' => $defaults['aiovg_featured_images_settings']['hide_on_single_video_pages'] ); update_option( 'aiovg_featured_images_settings', $featured_images_settings ); } // Insert the likes / dislikes settings $likes_settings = get_option( 'aiovg_likes_settings' ); if ( ! is_array( $likes_settings ) || empty( $likes_settings ) ) { $likes_settings = array( 'like_button' => $defaults['aiovg_likes_settings']['like_button'], 'dislike_button' => $defaults['aiovg_likes_settings']['dislike_button'], 'login_required_to_vote' => $defaults['aiovg_likes_settings']['login_required_to_vote'] ); update_option( 'aiovg_likes_settings', $likes_settings ); } // Insert the related videos settings $related_videos_settings = get_option( 'aiovg_related_videos_settings' ); if ( ! is_array( $related_videos_settings ) || empty( $related_videos_settings ) ) { $related_videos_settings = array( 'title' => $defaults['aiovg_related_videos_settings']['title'], 'columns' => isset( $videos_settings['columns'] ) ? $videos_settings['columns'] : $defaults['aiovg_videos_settings']['columns'], 'limit' => isset( $videos_settings['limit'] ) ? $videos_settings['limit'] : $defaults['aiovg_videos_settings']['limit'], 'orderby' => isset( $videos_settings['orderby'] ) ? $videos_settings['orderby'] : $defaults['aiovg_videos_settings']['orderby'], 'order' => isset( $videos_settings['order'] ) ? $videos_settings['order'] : $defaults['aiovg_videos_settings']['order'], 'display' => array( 'pagination' => 'pagination' ) ); update_option( 'aiovg_related_videos_settings', $related_videos_settings ); } $new_related_videos_settings = array(); if ( ! array_key_exists( 'title', $related_videos_settings ) ) { $new_related_videos_settings['title'] = __( 'You may also like', 'all-in-one-video-gallery' ); } if ( count( $new_related_videos_settings ) ) { update_option( 'aiovg_related_videos_settings', array_merge( $related_videos_settings, $new_related_videos_settings ) ); } // Insert the missing socialshare settings $socialshare_settings = get_option( 'aiovg_socialshare_settings' ); if ( ! is_array( $socialshare_settings ) || empty( $socialshare_settings ) ) { $socialshare_settings = $defaults['aiovg_socialshare_settings']; update_option( 'aiovg_socialshare_settings', $socialshare_settings ); } $new_socialshare_settings = array(); if ( ! array_key_exists( 'open_graph_tags', $socialshare_settings ) ) { $new_socialshare_settings['open_graph_tags'] = $defaults['aiovg_socialshare_settings']['open_graph_tags']; } if ( ! array_key_exists( 'twitter_username', $socialshare_settings ) ) { $new_socialshare_settings['twitter_username'] = $defaults['aiovg_socialshare_settings']['twitter_username']; } if ( count( $new_socialshare_settings ) ) { update_option( 'aiovg_socialshare_settings', array_merge( $socialshare_settings, $new_socialshare_settings ) ); } // Insert the missing general settings $general_settings = get_option( 'aiovg_general_settings' ); if ( ! is_array( $general_settings ) || empty( $general_settings ) ) { $general_settings = $defaults['aiovg_general_settings']; update_option( 'aiovg_general_settings', $general_settings ); } $new_general_settings = array(); if ( ! array_key_exists( 'primary_color', $general_settings ) ) { if ( array_key_exists( 'theme_color', $player_settings ) && '#00b2ff' !== $player_settings['theme_color'] ) { $new_general_settings['primary_color'] = $player_settings['theme_color']; } else { $new_general_settings['primary_color'] = $defaults['aiovg_general_settings']['primary_color']; } } if ( ! array_key_exists( 'lazyloading', $general_settings ) ) { if ( array_key_exists( 'lazyloading', $player_settings ) ) { $new_general_settings['lazyloading'] = $player_settings['lazyloading']; } else { $new_general_settings['lazyloading'] = $defaults['aiovg_general_settings']['lazyloading']; } } if ( ! array_key_exists( 'statistics', $general_settings ) ) { if ( array_key_exists( 'statistics', $player_settings ) ) { $new_general_settings['statistics'] = $player_settings['statistics']; } else { $new_general_settings['statistics'] = $defaults['aiovg_general_settings']['statistics']; } } if ( ! array_key_exists( 'maybe_flush_rewrite_rules', $general_settings ) ) { $new_general_settings['maybe_flush_rewrite_rules'] = $defaults['aiovg_general_settings']['maybe_flush_rewrite_rules']; } if ( ! array_key_exists( 'delete_media_files', $general_settings ) ) { $new_general_settings['delete_media_files'] = $defaults['aiovg_general_settings']['delete_media_files']; } if ( count( $new_general_settings ) ) { update_option( 'aiovg_general_settings', array_merge( $general_settings, $new_general_settings ) ); } // Insert the api settings $api_settings = get_option( 'aiovg_api_settings' ); if ( ! is_array( $api_settings ) || empty( $api_settings ) ) { $automations_settings = get_option( 'aiovg_automations_settings' ); if ( ! is_array( $automations_settings ) || empty( $automations_settings ) ) { $automations_settings = array(); } $defaults = array( 'youtube_api_key' => isset( $automations_settings['youtube_api_key'] ) ? $automations_settings['youtube_api_key'] : '', 'vimeo_access_token' => isset( $general_settings['vimeo_access_token'] ) ? $general_settings['vimeo_access_token'] : '' ); update_option( 'aiovg_api_settings', $defaults ); } // Insert the missing page settings $page_settings = get_option( 'aiovg_page_settings' ); if ( ! is_array( $page_settings ) || empty( $page_settings ) ) { $page_settings = $defaults['aiovg_page_settings']; update_option( 'aiovg_page_settings', $page_settings ); } if ( ! array_key_exists( 'tag', $page_settings ) ) { aiovg_insert_missing_pages(); } // Insert / Update the restrictions settings $restrictions_settings = get_option( 'aiovg_restrictions_settings' ); if ( ! is_array( $restrictions_settings ) || empty( $restrictions_settings ) ) { $restrictions_settings = $defaults['aiovg_restrictions_settings']; update_option( 'aiovg_restrictions_settings', $restrictions_settings ); } if ( ! array_key_exists( 'show_restricted_label', $restrictions_settings ) ) { update_option( 'aiovg_restrictions_settings', array_merge( $defaults['aiovg_restrictions_settings'], $restrictions_settings ) ); } // Insert the trailer settings $trailer_settings = get_option( 'aiovg_trailer_settings' ); if ( ! is_array( $trailer_settings ) || empty( $trailer_settings ) ) { $trailer_settings = $defaults['aiovg_trailer_settings']; update_option( 'aiovg_trailer_settings', $trailer_settings ); } // Insert the privacy settings $privacy_settings = get_option( 'aiovg_privacy_settings' ); if ( ! is_array( $privacy_settings ) || empty( $privacy_settings ) ) { $privacy_settings = $defaults['aiovg_privacy_settings']; update_option( 'aiovg_privacy_settings', $privacy_settings ); } // Insert the bunny stream settings $bunny_stream_settings = get_option( 'aiovg_bunny_stream_settings' ); if ( ! is_array( $bunny_stream_settings ) || empty( $bunny_stream_settings ) ) { $bunny_stream_settings = $defaults['aiovg_bunny_stream_settings']; update_option( 'aiovg_bunny_stream_settings', $bunny_stream_settings ); } // Remove the unfiltered_html capability from editors aiovg_remove_unfiltered_html_capability_from_editors(); // Create the email leads table (safe to call on every upgrade — dbDelta is idempotent) aiovg_email_capture_create_table(); // Delete the unwanted plugin options delete_option( 'aiovg_image_settings' ); // Force rewrite rules flush on next load delete_option( 'aiovg_rewrite_rules_flushed' ); } } /** * Handle form actions. * * @since 1.6.5 */ public function handle_form_actions() { if ( 'POST' == $_SERVER['REQUEST_METHOD'] && ! empty( $_POST['issues'] ) && isset( $_POST['aiovg_issues_nonce'] ) ) { // Verify that the nonce is valid if ( wp_verify_nonce( $_POST['aiovg_issues_nonce'], 'aiovg_fix_ignore_issues' ) ) { $action_type = isset( $_POST['action_type'] ) ? sanitize_text_field( wp_unslash( $_POST['action_type'] ) ) : ''; $redirect_url = admin_url( 'admin.php?page=all-in-one-video-gallery&tab=issues' ); // Fix Issues if ( 'apply_fix' === $action_type ) { $this->fix_issues(); $redirect_url = add_query_arg( array( 'section' => 'found', 'success' => 1 ), $redirect_url ); } // Ignore Issues if ( 'ignore' === $action_type ) { $this->ignore_issues(); $redirect_url = add_query_arg( array( 'section' => 'ignored', 'success' => 1 ), $redirect_url ); } // Redirect wp_redirect( $redirect_url ); exit; } } } /** * Add plugin's main menu and "Dashboard" menu. * * @since 1.6.5 */ public function admin_menu() { add_menu_page( __( 'All-in-One Video Gallery', 'all-in-one-video-gallery' ), __( 'Video Gallery', 'all-in-one-video-gallery' ), 'manage_aiovg_options', 'all-in-one-video-gallery', array( $this, 'display_dashboard_content' ), 'dashicons-playlist-video', 5 ); add_submenu_page( 'all-in-one-video-gallery', __( 'All-in-One Video Gallery - Dashboard', 'all-in-one-video-gallery' ), __( 'Dashboard', 'all-in-one-video-gallery' ), 'manage_aiovg_options', 'all-in-one-video-gallery', array( $this, 'display_dashboard_content' ) ); } /** * Display dashboard page content. * * @since 1.6.5 */ public function display_dashboard_content() { $tabs = array( 'shortcode-builder' => __( 'Shortcode Builder', 'all-in-one-video-gallery' ), 'help' => __( 'Help & Tutorials', 'all-in-one-video-gallery' ) ); $active_tab = isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : 'shortcode-builder'; // Issues $issues = $this->check_issues(); if ( count( $issues['found'] ) || 'issues' == $active_tab ) { $tabs['issues'] = __( 'Issues Found', 'all-in-one-video-gallery' ); } // Validate active tab if ( ! in_array( $active_tab, array_keys( $tabs ) ) ) { $active_tab = 'shortcode-builder'; } require_once AIOVG_PLUGIN_DIR . 'admin/partials/dashboard.php'; } /** * Check for plugin issues. * * @since 1.6.5 * @return array $issues Array of issues found. */ public function check_issues() { $issues = array( 'found' => array(), 'ignored' => array() ); $_issues = get_option( 'aiovg_issues', $issues ); $ignored = $_issues['ignored']; // Check: pages_misconfigured $page_settings = aiovg_get_option( 'aiovg_page_settings' ); $pages = aiovg_get_custom_pages_list(); foreach ( $pages as $key => $page ) { $issue_found = 0; $post_id = isset( $page_settings[ $key ] ) ? $page_settings[ $key ] : 0; $pattern = ''; if ( ! empty( $pages[ $key ]['content'] ) ) { $pattern = rtrim( $pages[ $key ]['content'], ']' ); } if ( $post_id > 0 ) { $post = get_post( $post_id ); if ( empty( $post ) || 'publish' != $post->post_status ) { $issue_found = 1; } elseif ( ! empty( $pattern ) && false === strpos( $post->post_content, $pattern ) ) { $issue_found = 1; } } else { $issue_found = 1; } if ( $issue_found ) { if ( in_array( 'pages_misconfigured', $ignored ) ) { $issues['ignored'][] = 'pages_misconfigured'; } else { $issues['found'][] = 'pages_misconfigured'; } break; } } $issues = apply_filters( 'aiovg_check_issues', $issues ); // Update update_option( 'aiovg_issues', $issues ); // Return return $issues; } /** * Apply fixes. * * @since 1.6.5 */ public function fix_issues() { $fixed = array(); // Apply the fixes $_issues = aiovg_sanitize_array( $_POST['issues'] ); foreach ( $_issues as $issue ) { switch ( $issue ) { case 'pages_misconfigured': global $wpdb; $page_settings = aiovg_get_option( 'aiovg_page_settings' ); $pages = aiovg_get_custom_pages_list(); foreach ( $pages as $key => $page ) { $issue_found = 0; $post_id = isset( $page_settings[ $key ] ) ? $page_settings[ $key ] : 0; $pattern = ''; if ( ! empty( $pages[ $key ]['content'] ) ) { $pattern = rtrim( $pages[ $key ]['content'], ']' ); } if ( $post_id > 0 ) { $post = get_post( $post_id ); if ( empty( $post ) || 'publish' != $post->post_status ) { $issue_found = 1; } elseif ( ! empty( $pattern ) && false === strpos( $post->post_content, $pattern ) ) { $issue_found = 1; } } else { $issue_found = 1; } if ( $issue_found ) { $insert_id = 0; if ( ! empty( $pattern ) ) { $query = $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE `post_content` LIKE %s", '%' . $wpdb->esc_like( sanitize_text_field( $pattern ) ) . '%' ); $ids = $wpdb->get_col( $query ); } else { $ids = array(); } if ( ! empty( $ids ) ) { $insert_id = $ids[0]; // If the page is not published if ( 'publish' != get_post_status( $insert_id ) ) { wp_update_post( array( 'ID' => $insert_id, 'post_status' => 'publish' ) ); } } else { $insert_id = wp_insert_post( array( 'post_title' => $pages[ $key ]['title'], 'post_content' => $pages[ $key ]['content'], 'post_status' => 'publish', 'post_author' => 1, 'post_type' => 'page', 'comment_status' => 'closed' ) ); } $page_settings[ $key ] = $insert_id; } } update_option( 'aiovg_page_settings', $page_settings ); $fixed[] = $issue; break; } } $fixed = apply_filters( 'aiovg_fix_issues', $fixed ); // Update $issues = get_option( 'aiovg_issues', array( 'found' => array(), 'ignored' => array() )); foreach ( $issues['found'] as $index => $issue ) { if ( in_array( $issue, $fixed ) ) { unset( $issues['found'][ $index ] ); } } foreach ( $issues['ignored'] as $index => $issue ) { if ( in_array( $issue, $fixed ) ) { unset( $issues['ignored'][ $index ] ); } } update_option( 'aiovg_issues', $issues ); } /** * Ignore issues. * * @since 1.6.5 */ public function ignore_issues() { $ignored = array(); // Ignore the issues $_issues = aiovg_sanitize_array( $_POST['issues'] ); foreach ( $_issues as $issue ) { switch ( $issue ) { case 'pages_misconfigured': $ignored[] = $issue; break; } } $ignored = apply_filters( 'aiovg_ignore_issues', $ignored ); // Update $issues = get_option( 'aiovg_issues', array( 'found' => array(), 'ignored' => array() )); foreach ( $issues['found'] as $index => $issue ) { if ( in_array( $issue, $ignored ) ) { unset( $issues['found'][ $index ] ); } } $issues['ignored'] = array_merge( $issues['ignored'], $ignored ); update_option( 'aiovg_issues', $issues ); } /** * Get details of the given issue. * * @since 1.6.5 * @param string $issue Issue code. * @return array Issue details. */ public function get_issue_details( $issue ) { $issues_list = array( 'pages_misconfigured' => array( 'title' => __( 'Pages Misconfigured', 'all-in-one-video-gallery' ), 'description' => sprintf( __( 'During activation, our plugin adds few pages dynamically on your website that are required for the internal logic of the plugin. We found some of those pages are missing, misconfigured or having a wrong shortcode.', 'all-in-one-video-gallery' ), esc_url( admin_url( 'admin.php?page=aiovg_settings&tab=advanced§ion=aiovg_page_settings' ) ) ) ) ); $issues_list = apply_filters( 'aiovg_get_issues_list', $issues_list ); return isset( $issues_list[ $issue ] ) ? $issues_list[ $issue ] : ''; } /** * Register the stylesheets for the admin area. * * @since 1.0.0 * @param string $hook The current admin page. */ public function enqueue_styles( $hook ) { global $post_type; wp_enqueue_style( 'wp-color-picker' ); wp_enqueue_style( AIOVG_PLUGIN_SLUG . '-magnific-popup', AIOVG_PLUGIN_URL . 'vendor/magnific-popup/magnific-popup.min.css', array(), '1.2.0', 'all' ); wp_register_style( AIOVG_PLUGIN_SLUG . '-driverjs', AIOVG_PLUGIN_URL . 'vendor/driverjs/driver.css', array(), '1.3.4', 'all' ); if ( ! defined( 'AIOVG_DISABLE_TOUR' ) || ! AIOVG_DISABLE_TOUR ) { if ( current_user_can( 'manage_aiovg_options' ) ) { if ( in_array( $hook, array( 'post-new.php', 'post.php' ) ) && 'aiovg_videos' === $post_type ) { $current_user_id = get_current_user_id(); $video_form_tour = get_user_meta( $current_user_id, 'aiovg_video_form_tour', true ); if ( 'completed' != $video_form_tour ) { wp_enqueue_style( AIOVG_PLUGIN_SLUG . '-driverjs' ); } } } } if ( isset( $_GET['page'] ) && 'aiovg_import_export' === $_GET['page'] ) { wp_enqueue_style( AIOVG_PLUGIN_SLUG . '-flatpickr', AIOVG_PLUGIN_URL . 'vendor/flatpickr/flatpickr.min.css', array(), '4.6.13', 'all' ); } wp_enqueue_style( AIOVG_PLUGIN_SLUG . '-admin', AIOVG_PLUGIN_URL . 'admin/assets/css/admin.min.css', array(), AIOVG_PLUGIN_VERSION, 'all' ); } /** * Register the JavaScript for the admin area. * * @since 1.0.0 * @param string $hook The current admin page. */ public function enqueue_scripts( $hook ) { global $post_type; $post_id = 0; $screen = get_current_screen(); if ( $screen && 'aiovg_videos' === $screen->post_type && ! empty( $_GET['post'] ) ) { $post_id = absint( $_GET['post'] ); } if ( ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'all-in-one-video-gallery', 'aiovg_settings', 'aiovg_import_export' ) ) ) || ( in_array( $hook, array( 'post-new.php', 'post.php' ) ) && 'aiovg_videos' === $post_type ) || ( isset( $_GET['taxonomy'] ) && in_array( $_GET['taxonomy'], array( 'aiovg_categories' ) ) ) ) { wp_enqueue_media(); } wp_enqueue_script( 'wp-color-picker' ); wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-magnific-popup', AIOVG_PLUGIN_URL . 'vendor/magnific-popup/magnific-popup.min.js', array( 'jquery' ), '1.2.0', array( 'strategy' => 'defer' ) ); wp_register_script( AIOVG_PLUGIN_SLUG . '-driverjs', AIOVG_PLUGIN_URL . 'vendor/driverjs/driver.js.iife.js', array( 'jquery' ), '1.3.4', array( 'strategy' => 'defer' ) ); if ( ! defined( 'AIOVG_DISABLE_TOUR' ) || ! AIOVG_DISABLE_TOUR ) { if ( current_user_can( 'manage_aiovg_options' ) ) { if ( in_array( $hook, array( 'post-new.php', 'post.php' ) ) && 'aiovg_videos' === $post_type ) { $current_user_id = get_current_user_id(); $video_form_tour = get_user_meta( $current_user_id, 'aiovg_video_form_tour', true ); if ( 'completed' != $video_form_tour ) { wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-driverjs' ); } } } } if ( in_array( $hook, array( 'post-new.php', 'post.php' ) ) && 'aiovg_videos' === $post_type ) { if ( aiovg_has_bunny_stream_enabled() ) { wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-tus', AIOVG_PLUGIN_URL . 'vendor/tus/tus.min.js', array( 'jquery' ), '4.3.1', array( 'strategy' => 'defer' ) ); } } wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-admin', AIOVG_PLUGIN_URL . 'admin/assets/js/admin.min.js', array( 'jquery' ), AIOVG_PLUGIN_VERSION, array( 'strategy' => 'defer' ) ); wp_localize_script( AIOVG_PLUGIN_SLUG . '-admin', 'aiovg_admin', array( 'site_url' => get_site_url(), 'post_id' => $post_id, 'ajax_nonce' => wp_create_nonce( 'aiovg_ajax_nonce' ), 'i18n' => array( 'copied' => __( 'Copied!', 'all-in-one-video-gallery' ), 'no_issues_selected' => __( 'Please select at least one issue.', 'all-in-one-video-gallery' ), 'no_video_selected' => __( 'No video selected. The last added video will be displayed.', 'all-in-one-video-gallery' ), 'quality_exists' => __( 'Sorry, there is already a video with this quality level.', 'all-in-one-video-gallery' ), 'remove' => __( 'Remove', 'all-in-one-video-gallery' ), 'preparing_upload' => __( 'Preparing upload', 'all-in-one-video-gallery' ), 'cancel_upload' => __( 'Cancel', 'all-in-one-video-gallery' ), 'upload_status' => __( 'Uploaded %d%', 'all-in-one-video-gallery' ), 'upload_processing' => __( 'Processing: Your video is being processed. This usually happens quickly, but during busy times, it may take a little longer. You can safely continue and save the form — no need to wait. The video will automatically become playable once processing is complete.', 'all-in-one-video-gallery' ), 'trailer' => __( 'Trailer', 'all-in-one-video-gallery' ) ) ) ); wp_register_script( AIOVG_PLUGIN_SLUG . '-import-export', AIOVG_PLUGIN_URL . 'admin/assets/js/import-export.min.js', array( AIOVG_PLUGIN_SLUG . '-admin' ), AIOVG_PLUGIN_VERSION, array( 'strategy' => 'defer' ) ); if ( isset( $_GET['page'] ) && 'aiovg_import_export' === $_GET['page'] ) { wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-flatpickr', AIOVG_PLUGIN_URL . 'vendor/flatpickr/flatpickr.min.js', array( 'jquery' ), '4.6.13', array( 'strategy' => 'defer' ) ); wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-import-export' ); wp_localize_script( AIOVG_PLUGIN_SLUG . '-import-export', 'aiovg_import_export', array( 'i18n' => array( 'fields_required' => __( 'Please fill in all required fields.', 'all-in-one-video-gallery' ), 'preparing_import' => __( 'Preparing import.', 'all-in-one-video-gallery' ), 'preparing_export' => __( 'Preparing export.', 'all-in-one-video-gallery' ), 'fetching_csv_columns' => __( 'Please wait while we fetch the column headers from your CSV file.', 'all-in-one-video-gallery' ), 'csv_columns_loaded' => __( 'CSV columns loaded successfully. You can proceed with the import now.', 'all-in-one-video-gallery' ), 'import_folder_failed_status_heading' => __( 'Sorry, some videos could not be imported. Please try again later.', 'all-in-one-video-gallery' ), 'import_csv_error_status_heading' => __( 'Some items could not be imported from the CSV. Please review the details below.', 'all-in-one-video-gallery' ), 'export_zip_success_status_heading' => __( 'Your export is ready. Download the ZIP files below.', 'all-in-one-video-gallery' ), 'export_zip_failed_status_heading' => __( 'Sorry, the following videos could not be exported because their file size exceeds the maximum allowed ZIP size.', 'all-in-one-video-gallery' ), 'export_zip_empty_status' => sprintf( __( 'Your export is complete. %s video records processed, and %s skipped. However, no ZIP file was created because no files were found.', 'all-in-one-video-gallery' ), '%%exported%%', '%%skipped%%' ), 'request_failed' => __( 'Something went wrong. Please check your server or try again.', 'all-in-one-video-gallery' ) ) ) ); } // Enqueue import-export.js on video pages when email capture is globally enabled if ( current_user_can( 'manage_aiovg_options' ) ) { $email_capture_settings = aiovg_get_option( 'aiovg_email_capture_settings' ); if ( ! empty( $email_capture_settings['enable_email_capture'] ) ) { $is_videos_list = ( 'edit.php' === $hook && isset( $_GET['post_type'] ) && 'aiovg_videos' === $_GET['post_type'] ); $is_video_edit = ( in_array( $hook, array( 'post-new.php', 'post.php' ) ) && 'aiovg_videos' === $post_type ); if ( $is_videos_list || $is_video_edit ) { wp_enqueue_script( AIOVG_PLUGIN_SLUG . '-import-export' ); } } } } /** * Add a post display state for special AIOVG pages in the page list table. * * @since 2.5.8 * @param array $post_states An array of post display states. * @param WP_Post $post The current post object. */ public function add_display_post_states( $post_states, $post ) { $page_settings = aiovg_get_option( 'aiovg_page_settings' ); if ( isset( $page_settings['category'] ) && $page_settings['category'] == $post->ID ) { $post_states['aiovg_page_for_category'] = __( 'Video Category Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['tag'] ) && $page_settings['tag'] == $post->ID ) { $post_states['aiovg_page_for_tag'] = __( 'Video Tag Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['search'] ) && $page_settings['search'] == $post->ID ) { $post_states['aiovg_page_for_search'] = __( 'Search Results Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['user_videos'] ) && $page_settings['user_videos'] == $post->ID ) { $post_states['aiovg_page_for_user_videos'] = __( 'User Videos Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['player'] ) && $page_settings['player'] == $post->ID ) { $post_states['aiovg_page_for_player'] = __( 'Player Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['user_dashboard'] ) && $page_settings['user_dashboard'] == $post->ID ) { $post_states['aiovg_page_for_user_dashboard'] = __( 'User Dashboard Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['video_form'] ) && $page_settings['video_form'] == $post->ID ) { $post_states['aiovg_page_for_video_form'] = __( 'Video Form Page', 'all-in-one-video-gallery' ); } if ( isset( $page_settings['playlist'] ) && $page_settings['playlist'] == $post->ID ) { $post_states['aiovg_page_for_playlist'] = __( 'My Playlists Page', 'all-in-one-video-gallery' ); } return $post_states; } /** * Add a settings link on the plugin listing page. * * @since 1.0.0 * @param array $links An array of plugin action links. * @return string $links Array of filtered plugin action links. */ public function plugin_action_links( $links ) { $settings_link = sprintf( '%s', esc_url( admin_url( 'admin.php?page=aiovg_settings' ) ), __( 'Settings', 'all-in-one-video-gallery' ) ); array_unshift( $links, $settings_link ); return $links; } /** * Extend MIME type recognition for media and streaming files. * * Adds support for WebVTT (.vtt) and SRT (.srt) subtitle uploads, * and registers MIME types for HLS (.m3u8) and MPEG-DASH (.mpd) * playlist files to ensure proper file type validation within WordPress. * The HLS and DASH file types are not permitted for upload, but are * recognized to avoid MIME type mismatches during playback or external * media reference checks. * * @since 3.0.0 * @param array $mimes Array of allowed mime types. * @return array Filtered mime types array. */ public function add_mime_types( $mimes ) { $mimes['vtt'] = 'text/vtt'; $mimes['srt'] = 'application/x-subrip'; $mimes['m3u8'] = 'application/x-mpegurl'; $mimes['mpd'] = 'application/dash+xml'; return $mimes; } /** * Ensure WordPress properly recognizes .vtt and .srt files. * * @since 1.5.7 * @param array $types File data array containing 'ext', 'type', and 'proper_filename' keys. * @param string $file Full path to the file. * @param string $filename The name of the file (may differ from $file due to $filename being in a tmp directory). * @param array $mimes Key is the file extension with value as the mime type. * @return array $types Filtered file data array. */ public function add_filetype_and_ext( $types, $file, $filename, $mimes ) { $type = wp_check_filetype( $filename, $mimes ); if ( 'vtt' === $type['ext'] ) { $types['ext'] = 'vtt'; $types['type'] = 'text/vtt'; } if ( 'srt' === $type['ext'] ) { $types['ext'] = 'srt'; // Prioritize standard MIME but fall back safely if ( in_array( $type['type'], array( 'application/x-subrip', 'text/srt', 'text/plain' ) ) ) { $types['type'] = $type['type']; // Use whichever the server assigns } else { $types['type'] = 'application/x-subrip'; // Safe default } } return $types; } /** * Validate uploaded WebVTT (.vtt) and SubRip (.srt) subtitle files. * * Uses real MIME detection via finfo (preferred and more secure). * Falls back to structure-based validation if finfo is unavailable. * * @since 4.5.8 * @param array $file Reference to a single element from the `$_FILES` array. * @return array Modified file array or error response. */ public function wp_handle_upload_prefilter( $file ) { $filename = strtolower( $file['name'] ); // Only handle VTT/SRT uploads if ( substr( $filename, -4 ) !== '.vtt' && substr( $filename, -4 ) !== '.srt' ) { return $file; } // Real MIME detection if ( function_exists( 'finfo_open' ) ) { $finfo = finfo_open( FILEINFO_MIME_TYPE ); $real_mime = finfo_file( $finfo, $file['tmp_name'] ); finfo_close( $finfo ); $allowed_mimes = array( 'text/vtt', 'application/x-subrip', 'text/srt', 'text/plain' ); if ( ! in_array( $real_mime, $allowed_mimes, true ) ) { $file['error'] = __( 'Upload blocked — file MIME type is not a valid subtitle format.', 'all-in-one-video-gallery' ); return $file; } return $file; // MIME safe — no further checks needed } // Fallback — Subtitle structure validation if ( substr( $filename, -4 ) === '.vtt' ) { $handle = fopen( $file['tmp_name'], 'r' ); $first_line = trim( fgets( $handle ) ); fclose( $handle ); if ( strpos( $first_line, 'WEBVTT' ) !== 0 ) { $file['error'] = __( 'Invalid WebVTT file — must start with "WEBVTT".', 'all-in-one-video-gallery' ); } } // Fallback Validate SRT if ( substr( $filename, -4 ) === '.srt' ) { $handle = fopen( $file['tmp_name'], 'r' ); $first_line = trim( fgets( $handle ) ); $second_line = trim( fgets( $handle ) ); fclose( $handle ); $valid_index = preg_match( '/^\d+$/', $first_line ); $valid_time = preg_match( '/^\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}$/', $second_line ); if ( ! $valid_index || ! $valid_time ) { $file['error'] = __( 'Invalid SRT file — does not follow standard SubRip formatting.', 'all-in-one-video-gallery' ); } } return $file; } /** * Flags rewrite rules for flushing on the next request when relevant options change. * * @since 4.7.3 * @param string $option Option name being updated. * @param mixed $old Previous option value. * @param mixed $value Updated option value. */ public function force_rewrite_rules_on_settings_update( $option, $old, $value ) { if ( in_array( $option, array( 'aiovg_page_settings', 'aiovg_permalink_settings' ), true ) ) { // Force rewrite rules flush on next load delete_option( 'aiovg_rewrite_rules_flushed' ); } } /** * Flags rewrite rules for flushing when an assigned AIOVG page * or its translation is updated. * * @since 4.7.3 * @param int $post_id Post ID. * @param WP_Post $post Post object. * @param bool $update Whether this is an existing post update. */ public function force_rewrite_rules_on_page_update( $post_id, $post, $update ) { // Avoid autosaves & revisions if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) { return; } // Only act on updates (not new pages) if ( ! $update ) { return; } // Defensive capability check if ( ! current_user_can( 'edit_page', $post_id ) ) { return; } $page_settings = aiovg_get_option( 'aiovg_page_settings' ); $permalink_settings = aiovg_get_option( 'aiovg_permalink_settings' ); if ( ! empty( $permalink_settings['video_archive_page'] ) ) { $page_settings['video_archive_page'] = (int) $permalink_settings['video_archive_page']; } if ( empty( $page_settings ) ) { return; } // Normalize assigned page IDs $assigned_pages = array_map( 'intval', $page_settings ); // Direct Match (Fast Path) if ( in_array( (int) $post_id, $assigned_pages, true ) ) { delete_option( 'aiovg_rewrite_rules_flushed' ); return; } // Check for Polylang translations if ( function_exists( 'pll_get_post_translations' ) ) { foreach ( $assigned_pages as $assigned_id ) { $translations = pll_get_post_translations( $assigned_id ); if ( empty( $translations ) ) { continue; } if ( in_array( (int) $post_id, array_map( 'intval', $translations ), true ) ) { delete_option( 'aiovg_rewrite_rules_flushed' ); return; } } } // Check for WPML translations (TRID-based) if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { $element_type = apply_filters( 'wpml_element_type', 'page' ); $current_trid = apply_filters( 'wpml_element_trid', null, $post_id, $element_type ); if ( ! empty( $current_trid ) ) { foreach ( $assigned_pages as $assigned_id ) { $assigned_trid = apply_filters( 'wpml_element_trid', null, $assigned_id, $element_type ); if ( (int) $current_trid === (int) $assigned_trid ) { delete_option( 'aiovg_rewrite_rules_flushed' ); return; } } } } } /** * Store user meta. * * @since 4.0.1 */ public function ajax_callback_store_user_meta() { check_ajax_referer( 'aiovg_ajax_nonce', 'security' ); $user_id = get_current_user_id(); if ( ! $user_id ) { wp_die(); } if ( ! current_user_can( 'manage_aiovg_options' ) ) { wp_die(); } $key = isset( $_POST['key'] ) ? sanitize_key( $_POST['key'] ) : ''; $allowed_keys = array( 'aiovg_video_form_tour', 'aiovg_automation_form_tour' ); if ( ! in_array( $key, $allowed_keys ) ) { wp_die(); } $value = isset( $_POST['value'] ) ? trim( $_POST['value'] ) : 0; if ( 'completed' !== $value ) { $value = (int) $value; } update_user_meta( $user_id, $key, $value ); wp_die(); } }