wp_create_nonce( 'plugetune_ajax_nonce' ), 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'settings_url' => admin_url( 'edit.php?post_type=plugetune_video&page=plugetune-settings' ), ) ); $settings_tab_headers = array( 'general' => array( 'icon' => 'fas fa-sliders-h', 'title' => __( 'General Settings', 'plugetune' ), 'desc' => __( 'Configure general plugin settings, email notifications, and behavior.', 'plugetune' ), ), 'playlist' => array( 'icon' => 'fab fa-youtube', 'title' => __( 'YouTube API', 'plugetune' ), 'desc' => __( 'Configure YouTube API credentials to enable video imports.', 'plugetune' ), ), 'advanced' => array( 'icon' => 'fas fa-cogs', 'title' => __( 'Advanced', 'plugetune' ), 'desc' => __( 'Cache management, database cleanup, and other advanced tools.', 'plugetune' ), ), 'tools' => array( 'icon' => 'fas fa-tools', 'title' => __( 'Tools', 'plugetune' ), 'desc' => __( 'Import and export settings, and other utilities.', 'plugetune' ), ), ); wp_enqueue_script( 'plugetune-settings-page', plugin_dir_url( __FILE__ ) . '../assets/js/plugetune_settings-page.js', array( 'jquery' ), PLUGETUNE_VERSION, true ); wp_localize_script( 'plugetune-settings-page', 'plugetune_settings_headers', $settings_tab_headers ); } /** * Register the plugin settings options. * * @return void */ public function register_settings() { $settings = array( 'plugetune_default_img_format' => 'sanitize_key', 'plugetune_thumbnail_quality' => 'absint', 'plugetune_lazy_load' => 'sanitize_key', 'plugetune_protection' => 'sanitize_key', 'plugetune_auto_excerpt' => 'sanitize_key', 'plugetune_api_key' => 'sanitize_text_field', 'plugetune_allowed_channel_ids' => 'sanitize_text_field', 'plugetune_playlist_link' => 'esc_url_raw', 'plugetune_import_post_status' => 'sanitize_key', 'plugetune_internal_link_enable' => 'sanitize_key', 'plugetune_email_enable' => 'sanitize_key', 'plugetune_email_service' => 'sanitize_key', 'plugetune_email_api_key' => 'sanitize_text_field', 'plugetune_email_list_id' => 'sanitize_text_field', 'plugetune_thumbnail_settings_enable' => 'sanitize_key', 'plugetune_single_video_links' => 'sanitize_text_field', 'plugetune_admin_email' => 'sanitize_email', 'plugetune_email_notification_frequency' => 'sanitize_key', 'plugetune_daily_report_time' => 'sanitize_text_field', 'plugetune_weekly_report_day' => 'sanitize_key', 'plugetune_weekly_report_time' => 'sanitize_text_field', 'plugetune_email_timezone' => 'sanitize_text_field', 'plugetune_delete_data_on_uninstall' => 'sanitize_key', ); foreach ( $settings as $opt => $sanitize_callback ) { register_setting( 'plugetune_settings_group', $opt, array( 'sanitize_callback' => $sanitize_callback ) ); } add_filter( 'cron_schedules', array( $this, 'add_cron_schedules' ) ); } /** * Register the custom weekly cron schedule used by the email reports. * * @param array $schedules Existing cron schedules. * @return array */ public function add_cron_schedules( $schedules ) { $schedules['weekly'] = array( 'interval' => WEEK_IN_SECONDS, 'display' => __( 'Once Weekly', 'plugetune' ), ); return $schedules; } /** * Handle the non-AJAX settings reset form submission. * * @return void */ public function handle_reset() { if ( isset( $_POST['reset_settings'] ) && '1' === $_POST['reset_settings'] && check_admin_referer( 'plugetune_settings_group-options' ) ) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Admin-triggered one-off reset of all plugin options; caching is irrelevant here. $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'plugetune_%'" ); add_option( 'plugetune_thumbnail_quality', '90' ); add_option( 'plugetune_lazy_load', '0' ); add_option( 'plugetune_protection', '0' ); add_option( 'plugetune_default_img_format', 'webp' ); add_option( 'plugetune_auto_excerpt', '1' ); add_option( 'plugetune_import_post_status', 'publish' ); add_option( 'plugetune_admin_email', get_option( 'admin_email' ) ); add_option( 'plugetune_email_notification_frequency', 'disabled' ); add_option( 'plugetune_daily_report_time', '11:59 PM' ); add_option( 'plugetune_weekly_report_day', 'monday' ); add_option( 'plugetune_weekly_report_time', '09:00 AM' ); add_option( 'plugetune_email_timezone', 'Asia/Dhaka' ); remove_action( 'admin_notices', array( $this, 'admin_notices' ) ); wp_safe_redirect( admin_url( 'edit.php?post_type=plugetune_video&page=plugetune-settings&reset_success=1' ) ); exit; } } /** * Render the admin notices for settings save and reset results. * * @return void */ public function admin_notices() { static $notice_displayed = false; if ( $notice_displayed ) { return; } $screen = get_current_screen(); $is_settings_page = ( $screen && strpos( $screen->id, 'plugetune-settings' ) !== false ); $show_reset_notice = false; $show_saved_notice = false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display flag from plugin-generated redirect URL; no state change. if ( isset( $_GET['reset_success'] ) && '1' === $_GET['reset_success'] ) { $show_reset_notice = true; $notice_displayed = true; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display flag set by WordPress core after options.php processing. } elseif ( isset( $_GET['settings-updated'] ) && 'true' === $_GET['settings-updated'] && $is_settings_page ) { if ( ! get_transient( 'plugetune_settings_saved_notice_displayed' ) ) { set_transient( 'plugetune_settings_saved_notice_displayed', true, 5 ); $show_saved_notice = true; $notice_displayed = true; } } if ( $show_reset_notice ) { echo '

' . esc_html__( 'All settings have been reset.', 'plugetune' ) . '

'; } elseif ( $show_saved_notice ) { echo '

' . esc_html__( 'Settings saved successfully.', 'plugetune' ) . '

'; } if ( $show_reset_notice || $show_saved_notice ) { wp_register_script( 'plugetune-admin-notice-cleanup', false, array(), PLUGETUNE_VERSION, true ); wp_enqueue_script( 'plugetune-admin-notice-cleanup' ); wp_add_inline_script( 'plugetune-admin-notice-cleanup', 'if(window.history.replaceState) { window.history.replaceState(null, null, window.location.href.split("?")[0]); }' ); } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display flag set by WordPress core. if ( isset( $_GET['settings-updated'] ) && 'true' === $_GET['settings-updated'] ) { delete_option( 'plugetune_scheduled_import_status' ); } } /** * AJAX: Export the plugin settings as a JSON download. * * @return void */ public function ajax_export_settings() { check_ajax_referer( 'plugetune_ajax_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'Unauthorized' ); } global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Admin-triggered one-off export scan; caching is irrelevant for a settings dump. $settings = $wpdb->get_results( "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE 'plugetune_%'", ARRAY_A ); $export_data = array(); foreach ( $settings as $setting ) { $export_data[ $setting['option_name'] ] = maybe_unserialize( $setting['option_value'] ); } $json = wp_json_encode( $export_data, JSON_PRETTY_PRINT ); $filename = 'plugetune-settings-' . gmdate( 'Y-m-d' ) . '.json'; header( 'Content-Type: application/json' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Length: ' . strlen( $json ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Raw JSON download, not rendered as HTML. echo $json; wp_die(); } /** * AJAX: Import settings from an uploaded JSON file. * * @return void */ public function ajax_import_settings() { check_ajax_referer( 'plugetune_ajax_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Unauthorized' ) ); } if ( ! isset( $_FILES['import_file'] ) || ! isset( $_FILES['import_file']['error'] ) || ! isset( $_FILES['import_file']['tmp_name'] ) || UPLOAD_ERR_OK !== (int) $_FILES['import_file']['error'] ) { wp_send_json_error( array( 'message' => 'File upload failed' ) ); } $tmp_name = sanitize_text_field( wp_unslash( $_FILES['import_file']['tmp_name'] ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Reading a temporary upload, no remote alternative applies. $file_content = file_get_contents( $tmp_name ); $settings = json_decode( $file_content, true ); if ( ! $settings ) { wp_send_json_error( array( 'message' => 'Invalid JSON file' ) ); } $allowed_settings = array( 'plugetune_default_img_format' => 'sanitize_key', 'plugetune_thumbnail_quality' => 'absint', 'plugetune_lazy_load' => 'sanitize_key', 'plugetune_protection' => 'sanitize_key', 'plugetune_auto_excerpt' => 'sanitize_key', 'plugetune_api_key' => 'sanitize_text_field', 'plugetune_allowed_channel_ids' => 'sanitize_text_field', 'plugetune_playlist_links' => 'sanitize_text_field', 'plugetune_import_post_status' => 'sanitize_key', 'plugetune_seo_integration' => 'sanitize_key', 'plugetune_social_share' => 'sanitize_key', 'plugetune_internal_link_enable' => 'sanitize_key', 'plugetune_email_enable' => 'sanitize_key', 'plugetune_email_service' => 'sanitize_key', 'plugetune_email_api_key' => 'sanitize_text_field', 'plugetune_email_list_id' => 'sanitize_text_field', 'plugetune_delete_existing_before_import' => 'absint', 'plugetune_admin_email' => 'sanitize_email', 'plugetune_email_notification_frequency' => 'sanitize_key', 'plugetune_daily_report_time' => 'sanitize_text_field', 'plugetune_weekly_report_day' => 'sanitize_key', 'plugetune_weekly_report_time' => 'sanitize_text_field', 'plugetune_email_timezone' => 'sanitize_text_field', ); foreach ( $settings as $key => $value ) { if ( isset( $allowed_settings[ $key ] ) ) { $sanitize_callback = $allowed_settings[ $key ]; if ( is_array( $value ) ) { $value = array_map( $sanitize_callback, $value ); } else { $value = call_user_func( $sanitize_callback, $value ); } update_option( $key, $value ); } } $this->reschedule_email_reports(); wp_send_json_success( array( 'message' => 'Settings imported successfully' ) ); } /** * Reschedule the email report cron events based on the current settings. * * @return void */ private function reschedule_email_reports() { $frequency = get_option( 'plugetune_email_notification_frequency', 'disabled' ); $timezone = get_option( 'plugetune_email_timezone', 'Asia/Dhaka' ); $timestamp_daily = wp_next_scheduled( 'plugetune_daily_report' ); $timestamp_weekly = wp_next_scheduled( 'plugetune_weekly_report' ); if ( $timestamp_daily ) { wp_unschedule_event( $timestamp_daily, 'plugetune_daily_report' ); } if ( $timestamp_weekly ) { wp_unschedule_event( $timestamp_weekly, 'plugetune_weekly_report' ); } if ( 'daily' === $frequency ) { if ( ! wp_next_scheduled( 'plugetune_daily_report' ) ) { $daily_time = get_option( 'plugetune_daily_report_time', '11:59 PM' ); $schedule_time = $this->get_next_scheduled_time_with_timezone( $daily_time, 'daily', null, $timezone ); wp_schedule_event( $schedule_time, 'daily', 'plugetune_daily_report' ); } } elseif ( 'weekly' === $frequency ) { if ( ! wp_next_scheduled( 'plugetune_weekly_report' ) ) { $weekly_day = get_option( 'plugetune_weekly_report_day', 'monday' ); $weekly_time = get_option( 'plugetune_weekly_report_time', '09:00 AM' ); $schedule_time = $this->get_next_scheduled_time_with_timezone( $weekly_time, 'weekly', $weekly_day, $timezone ); wp_schedule_event( $schedule_time, 'weekly', 'plugetune_weekly_report' ); } } } /** * Normalize a timezone string to a valid PHP timezone identifier. * * @param string $timezone Timezone string to normalize. * @return string */ private function sanitize_timezone( $timezone ) { if ( strpos( $timezone, '/' ) !== false ) { return $timezone; } $utc_mappings = array( 'UTC+6' => 'Asia/Dhaka', 'UTC+5:30' => 'Asia/Kolkata', 'UTC+5' => 'Asia/Karachi', 'UTC+4' => 'Asia/Dubai', 'UTC+3' => 'Asia/Riyadh', 'UTC+9' => 'Asia/Tokyo', 'UTC+8' => 'Asia/Shanghai', 'UTC+10' => 'Australia/Sydney', 'UTC+12' => 'Pacific/Auckland', 'UTC-5' => 'America/New_York', 'UTC-6' => 'America/Chicago', 'UTC-7' => 'America/Denver', 'UTC-8' => 'America/Los_Angeles', 'UTC+0' => 'UTC', 'UTC' => 'UTC', ); if ( isset( $utc_mappings[ $timezone ] ) ) { return $utc_mappings[ $timezone ]; } return 'Asia/Dhaka'; } /** * Compute the next scheduled timestamp for a daily or weekly report. * * @param string $time Time string (e.g. "11:59 PM"). * @param string $type 'daily' or 'weekly'. * @param string|null $day Day of week for weekly reports. * @param string|null $timezone_string Timezone identifier. * @return int Unix timestamp. */ private function get_next_scheduled_time_with_timezone( $time, $type, $day = null, $timezone_string = null ) { if ( ! $timezone_string ) { $timezone_string = get_option( 'plugetune_email_timezone', 'Asia/Dhaka' ); } $timezone_string = $this->sanitize_timezone( $timezone_string ); $time_obj = DateTime::createFromFormat( 'h:i A', $time ); if ( ! $time_obj ) { $time_obj = DateTime::createFromFormat( 'H:i', $time ); } if ( ! $time_obj ) { $time_obj = new DateTime( '23:59' ); } $hour = $time_obj->format( 'H' ); $minute = $time_obj->format( 'i' ); try { $selected_timezone = new DateTimeZone( $timezone_string ); $now_in_selected_tz = new DateTime( 'now', $selected_timezone ); $current_year = $now_in_selected_tz->format( 'Y' ); $current_month = $now_in_selected_tz->format( 'm' ); $current_day = $now_in_selected_tz->format( 'd' ); if ( 'daily' === $type ) { $target_datetime = new DateTime( "{$current_year}-{$current_month}-{$current_day} {$hour}:{$minute}:00", $selected_timezone ); $target_timestamp = $target_datetime->getTimestamp(); $current_timestamp = $now_in_selected_tz->getTimestamp(); if ( $target_timestamp <= $current_timestamp ) { $target_datetime->modify( '+1 day' ); $target_timestamp = $target_datetime->getTimestamp(); } return $target_timestamp; } $day_map = array( 'monday' => 'Monday', 'tuesday' => 'Tuesday', 'wednesday' => 'Wednesday', 'thursday' => 'Thursday', 'friday' => 'Friday', 'saturday' => 'Saturday', 'sunday' => 'Sunday', ); $target_day = isset( $day_map[ $day ] ) ? $day_map[ $day ] : 'Monday'; $target_datetime = new DateTime( 'now', $selected_timezone ); $current_day_of_week = $target_datetime->format( 'l' ); if ( $current_day_of_week === $target_day ) { $target_datetime->setTime( $hour, $minute, 0 ); if ( $target_datetime->getTimestamp() <= time() ) { $target_datetime->modify( '+7 days' ); } } else { $target_datetime->modify( "next {$target_day}" ); $target_datetime->setTime( $hour, $minute, 0 ); } return $target_datetime->getTimestamp(); } catch ( Exception $e ) { $day_map = array( 'monday' => 'Monday', 'tuesday' => 'Tuesday', 'wednesday' => 'Wednesday', 'thursday' => 'Thursday', 'friday' => 'Friday', 'saturday' => 'Saturday', 'sunday' => 'Sunday', ); $target_day = isset( $day_map[ $day ] ) ? $day_map[ $day ] : 'Monday'; if ( 'daily' === $type ) { $schedule_time = strtotime( "today {$hour}:{$minute}" ); if ( $schedule_time <= time() ) { $schedule_time = strtotime( "tomorrow {$hour}:{$minute}" ); } return $schedule_time; } $schedule_time = strtotime( "next {$target_day} {$hour}:{$minute}" ); $today_time = strtotime( "today {$hour}:{$minute}" ); if ( gmdate( 'l' ) === $target_day && $today_time > time() ) { $schedule_time = $today_time; } return $schedule_time; } } /** * AJAX: Save the submitted settings. * * @return void */ public function ajax_save_settings() { check_ajax_referer( 'plugetune_ajax_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Unauthorized' ) ); } $settings_data = array(); if ( isset( $_POST['settings'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Each value is sanitized individually below. parse_str( wp_unslash( $_POST['settings'] ), $settings_data ); } unset( $settings_data['action'], $settings_data['nonce'], $settings_data['option_page'], $settings_data['_wpnonce'], $settings_data['_wp_http_referer'], $settings_data['save_settings'], $settings_data['reset_settings'] ); $allowed_settings = array( 'plugetune_default_img_format' => 'sanitize_key', 'plugetune_thumbnail_quality' => 'absint', 'plugetune_lazy_load' => 'sanitize_key', 'plugetune_protection' => 'sanitize_key', 'plugetune_auto_excerpt' => 'sanitize_key', 'plugetune_api_key' => 'sanitize_text_field', 'plugetune_allowed_channel_ids' => 'sanitize_text_field', 'plugetune_playlist_links' => 'sanitize_text_field', 'plugetune_import_post_status' => 'sanitize_key', 'plugetune_internal_link_enable' => 'sanitize_key', 'plugetune_email_enable' => 'sanitize_key', 'plugetune_email_service' => 'sanitize_key', 'plugetune_email_api_key' => 'sanitize_text_field', 'plugetune_email_list_id' => 'sanitize_text_field', 'plugetune_thumbnail_settings_enable' => 'sanitize_key', 'plugetune_single_video_links' => 'sanitize_text_field', 'plugetune_admin_email' => 'sanitize_email', 'plugetune_email_notification_frequency' => 'sanitize_key', 'plugetune_daily_report_time' => 'sanitize_text_field', 'plugetune_weekly_report_day' => 'sanitize_key', 'plugetune_weekly_report_time' => 'sanitize_text_field', 'plugetune_email_timezone' => 'sanitize_text_field', 'plugetune_delete_existing_before_import' => 'absint', 'plugetune_delete_data_on_uninstall' => 'sanitize_key', ); $checkbox_fields = array( 'plugetune_lazy_load', 'plugetune_protection', 'plugetune_auto_excerpt', 'plugetune_social_share', 'plugetune_internal_link_enable', 'plugetune_email_enable', 'plugetune_delete_existing_before_import', 'plugetune_thumbnail_settings_enable', 'plugetune_delete_data_on_uninstall', ); foreach ( $checkbox_fields as $field ) { if ( ! isset( $settings_data[ $field ] ) ) { $settings_data[ $field ] = '0'; } } if ( isset( $settings_data['plugetune_playlist_links'] ) && is_array( $settings_data['plugetune_playlist_links'] ) ) { $settings_data['plugetune_playlist_links'] = array_filter( $settings_data['plugetune_playlist_links'] ); } foreach ( $settings_data as $key => $value ) { if ( ! isset( $allowed_settings[ $key ] ) ) { continue; } $sanitize_callback = $allowed_settings[ $key ]; if ( is_array( $value ) ) { $value = array_map( $sanitize_callback, $value ); } else { if ( 'plugetune_admin_email' === $key && ! empty( $value ) && ! is_email( $value ) ) { wp_send_json_error( array( 'message' => 'Please enter a valid admin email address.' ) ); } $value = call_user_func( $sanitize_callback, $value ); } update_option( $key, $value ); } $this->reschedule_email_reports(); $api_key = get_option( 'plugetune_api_key', '' ); $channel_ids = get_option( 'plugetune_allowed_channel_ids', '' ); if ( ! empty( $api_key ) && ! empty( $channel_ids ) ) { update_option( 'plugetune_wizard_completed', true ); update_option( 'plugetune_wizard_skipped', false ); } delete_option( 'plugetune_scheduled_import_status' ); delete_transient( 'plugetune_settings_saved_notice' ); delete_transient( 'plugetune_settings_saved_notice_displayed' ); set_transient( 'plugetune_settings_saved_notice', true, 5 ); wp_send_json_success( array( 'message' => 'Settings saved successfully!' ) ); } /** * AJAX: Reset all plugin settings to their defaults. * * @return void */ public function ajax_reset_settings() { check_ajax_referer( 'plugetune_ajax_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Unauthorized' ) ); } global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Admin-triggered one-off reset of all plugin options; caching is irrelevant. $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'plugetune_%'" ); update_option( 'plugetune_thumbnail_quality', '90' ); update_option( 'plugetune_lazy_load', '0' ); update_option( 'plugetune_protection', '0' ); update_option( 'plugetune_default_img_format', 'webp' ); update_option( 'plugetune_auto_excerpt', '1' ); update_option( 'plugetune_import_post_status', 'publish' ); update_option( 'plugetune_internal_link_enable', '0' ); update_option( 'plugetune_email_enable', '0' ); update_option( 'plugetune_seo_integration', 'none' ); update_option( 'plugetune_social_share', '0' ); update_option( 'plugetune_playlist_links', array( '' ) ); update_option( 'plugetune_delete_existing_before_import', '0' ); update_option( 'plugetune_thumbnail_settings_enable', '1' ); update_option( 'plugetune_admin_email', get_option( 'admin_email' ) ); update_option( 'plugetune_email_notification_frequency', 'disabled' ); update_option( 'plugetune_daily_report_time', '11:59 PM' ); update_option( 'plugetune_weekly_report_day', 'monday' ); update_option( 'plugetune_weekly_report_time', '09:00 AM' ); update_option( 'plugetune_email_timezone', 'Asia/Dhaka' ); $this->reschedule_email_reports(); $reset_settings = array(); $settings_options = array( 'plugetune_default_img_format', 'plugetune_thumbnail_quality', 'plugetune_lazy_load', 'plugetune_protection', 'plugetune_auto_excerpt', 'plugetune_import_post_status', 'plugetune_internal_link_enable', 'plugetune_email_enable', 'plugetune_seo_integration', 'plugetune_social_share', 'plugetune_playlist_links', 'plugetune_delete_existing_before_import', 'plugetune_admin_email', 'plugetune_email_notification_frequency', 'plugetune_daily_report_time', 'plugetune_weekly_report_day', 'plugetune_weekly_report_time', 'plugetune_email_timezone', ); foreach ( $settings_options as $opt ) { $reset_settings[ $opt ] = get_option( $opt ); } wp_send_json_success( array( 'message' => 'All settings have been reset.', 'settings' => $reset_settings, ) ); } /** * Render the full settings page. * * @return void */ public function render_settings_page() { $general_settings = PlugeTune_Email_Notifications_Settings::get_instance(); $welcome_html = ''; $show_welcome = ( ! get_option( 'plugetune_wizard_completed', false ) && ! get_option( 'plugetune_wizard_skipped', false ) && ( empty( get_option( 'plugetune_api_key', '' ) ) || empty( get_option( 'plugetune_allowed_channel_ids', '' ) ) ) ); if ( $show_welcome ) { ob_start(); ?>
<?php esc_attr_e( 'PlugeTune', 'plugetune' ); ?>
'plugetune-settings-header', 'context' => 'settings', 'icon' => 'fas fa-sliders-h', 'title' => esc_html__( 'General Settings', 'plugetune' ), 'description' => esc_html__( 'Configure general plugin settings, email notifications, and behavior.', 'plugetune' ), 'version' => 'v2.0', 'notice_html' => wp_kses_post( $welcome_html ), 'buttons' => array( array( 'label' => esc_html__( 'Videos Import', 'plugetune' ), 'url' => esc_url( admin_url( 'edit.php?post_type=plugetune_video&page=plugetune-video-import' ) ), 'icon' => 'fas fa-list', ), array( 'label' => esc_html__( 'View Videos Post', 'plugetune' ), 'url' => esc_url( admin_url( 'edit.php?post_type=plugetune_video' ) ), 'icon' => 'fas fa-video', ), ), ) ); ?>
render(); ?>

render(); } else { echo '

' . esc_html__( 'Clear Cache module not loaded. Please check plugin files.', 'plugetune' ) . '

'; } ?>

render(); } else { echo '

' . esc_html__( 'Database Cleanup module not loaded. Please check plugin files.', 'plugetune' ) . '

'; } ?>

init();