'', 'openai_model' => 'gpt-4o', 'request_timeout' => 45, 'default_language' => 'en', 'disable_auto_alt' => false, 'overwrite_existing_alt' => false, 'alt_text_prompt_template' => '', 'alt_text_style' => 'descriptive', 'exclude_mime_types' => [], 'min_alt_text_length' => 8, 'max_alt_text_length' => 125, 'alt_text_prefix' => '', 'alt_text_suffix' => '', 'add_generated_by_notice' => false, //deprecated //Bulk & Background 'disable_skip_if_has_alt' => false, 'exclude_folders' => [], 'include_folders' => [], 'bulk_alt_limit' => 25, 'job_tick_interval_seconds' => 90, 'max_retries_per_image' => 2, // WooCommerce 'wc_enabled' => false, 'wc_include_items' => [], 'wc_use_attributes' => [], 'wc_include_gallery_images' => false, 'wc_regen_if_alt_exists' => false, 'wc_disable_queue_missing_on_save' => false, // Context-Aware 'context_enabled' => false, 'context_max_words' => 500, 'context_template' => '', // SEO 'seo_score_enabled' => false, 'keyword_required' => false, 'disable_duplicate_alt_penalty' => false, 'show_score_in_post_list' => false, 'hide_score_metabox' => false, // Analytics 'analytics_enabled' => false, 'retention_days' => 90, 'analytics_capture' => [], // Advanced 'enable_debug_mode' => false, 'enable_test_mode' => false, 'log_retention_days' => 90, 'disable_logging' => false, 'log_level' => 'verbose', 'log_to_file' => false, 'show_request_payload' => false, 'force_model_override' => '', 'blocklist_keywords' => '', ]; public function __construct() { add_action( 'init', [ $this, 'register_settings_page' ], 11 ); } public function register_settings_page() { require_once AIT_IAT_PATH . 'lib/simple-admin-pages/simple-admin-pages.php'; $sap = sap_initialize_library( $args = array( 'version' => '2.7.4', 'theme' => 'ait', 'lib_url' => AIT_IAT_URL . '/lib/simple-admin-pages/', ) ); $sap->add_page( 'submenu', array( 'id' => 'ait-iat-settings', 'title' => __( 'Settings', 'ai-image-alt-text' ), 'menu_title' => __( 'Settings', 'ai-image-alt-text' ), 'description' => '', 'capability' => 'manage_options', 'parent_menu' => 'ai-image-alt-text', 'default_tab' => 'ait-iat-license-tab', ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-license-tab', 'title' => __('License', 'ai-image-alt-text'), 'is_tab' => true, 'icon' => 'admin-network', 'rank' => 0, ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-dashboard', 'title' => __( 'Dashboard', 'ai-image-alt-text' ), 'tab' => 'ait-iat-license-tab', ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-dashboard', 'html', array( 'id' => 'ait_iat_license_grid', 'title' => __('License', 'ai-image-alt-text' ), 'html' => [ 'AIT_IAT_Dashboard', 'display_dashboard_license' ], ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-dashboard', 'html', array( 'id' => 'ait_iat_usage_grid', 'title' => __('Usage', 'ai-image-alt-text' ), 'html' => [ 'AIT_IAT_Dashboard', 'display_dashboard_usage_limits' ], ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-dashboard', 'html', array( 'id' => 'ait_iat_quick_actions_grid', 'title' => __('Quick Actions', 'ai-image-alt-text' ), 'html' => [ 'AIT_IAT_Dashboard', 'display_dashboard_quick_actions' ], ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-dashboard', 'html', array( 'id' => 'ait_iat_latest_activity_grid', 'title' => __('Latest Activity', 'ai-image-alt-text' ), 'html' => [ 'AIT_IAT_Dashboard', 'display_dashboard_latest_activity' ], ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-general-tab', 'title' => __('General', 'ai-image-alt-text'), 'is_tab' => true, 'icon' => 'text', 'rank' => 1, ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-requests', 'title' => __( 'Generation Requests', 'ai-image-alt-text' ), 'tab' => 'ait-iat-general-tab', ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-requests', 'text', array( 'id' => 'openai_api_key', 'title' => __('OpenAI API Key', 'ai-image-alt-text' ), 'description' => __('Your OpenAI API key, which will be used for the image processing requests.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-requests', 'radio', array( 'id' => 'openai_model', 'title' => __('Model', 'ai-image-alt-text' ), 'description' => __('Which OpenAI model should be used to handle the image processing requests?', 'ai-image-alt-text'), 'options' => self::get_openai_models(), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-requests', 'select', array( 'id' => 'default_language', 'title' => __('Language', 'ai-image-alt-text' ), 'description' => __('What language should the alt text be rendered in?', 'ai-image-alt-text'), 'options' => self::get_language_options(), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-requests', 'toggle', array( 'id' => 'disable_auto_alt', 'title' => __( 'Disable Upload Auto Alt Text', 'ai-image-alt-text' ), 'description' => __('Disable auto alt generation on upload.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-requests', 'toggle', array( 'id' => 'overwrite_existing_alt', 'title' => __('Overwrite Existing Alt Text', 'ai-image-alt-text' ), 'description' => __('Overwrite any existing alt text with the AI generated version on upload.', 'ai-image-alt-text'), ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-style', 'title' => __( 'Generation Style', 'ai-image-alt-text' ), 'tab' => 'ait-iat-general-tab', ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'textarea', array( 'id' => 'alt_text_prompt_template', 'title' => __('Prompt Template', 'ai-image-alt-text' ), /* translators: 1. AI text tone 2: Alt text language 3: Min alt text characters 4: Max alt text characters */ 'description' => __('Default prompt is "Describe this image %1$s for alt text. The language of the description MUST be %2$s. Use between %3$d and %4$d characters." where the first placeholder is the "Alt Text Style" setting, the second is the "Language" setting, and the final ones are the min/max character settings.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'checkbox', array( 'id' => 'additional_generation_fields', 'title' => __('Additional Generation Fields', 'ai-image-alt-text' ), 'description' => __('Which additional fields, if any, should be generated when generating the alt-text for an image?', 'ai-image-alt-text'), 'options' => [ 'caption' => __( 'Caption', 'ai-image-alt-text' ), 'title' => __( 'Title', 'ai-image-alt-text' ), 'description' => __( 'Description', 'ai-image-alt-text' ), ] ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'radio', array( 'id' => 'alt_text_style', 'title' => __('Alt Text Style', 'ai-image-alt-text' ), 'description' => __('The style of the text that will be generated.', 'ai-image-alt-text'), 'options' => [ 'descriptive' => __('Descriptive', 'ai-image-alt-text'), 'seo' => __('SEO-optimized', 'ai-image-alt-text'), 'formal' => __('Formal', 'ai-image-alt-text'), 'casual' => __('Casual', 'ai-image-alt-text'), ], ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'checkbox', array( 'id' => 'exclude_mime_types', 'title' => __('Exclude Mime Types', 'ai-image-alt-text' ), 'description' => __('Image mime types that should be excluded from having alt text generated.', 'ai-image-alt-text'), 'options' => [ 'image/jpeg' => 'JPG', 'image/png' => 'PNG', 'image/gif' => 'GIF', 'image/bmp' => 'BMP', 'image/tiff' => 'TIFF', 'image/x-icon' => 'ICO', 'image/webp' => 'WebP', 'image/avif' => 'AVIF', 'image/heic' => 'HEIC', 'image/heif' => 'HEIF', 'image/svg+xml' => 'SVG' ] ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'number', array( 'id' => 'min_alt_text_length', 'title' => __('Min Characters', 'ai-image-alt-text' ), 'description' => __('The minimum number characters that should be returned for the alt-text. Default is 8.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'number', array( 'id' => 'max_alt_text_length', 'title' => __('Max Characters', 'ai-image-alt-text' ), 'description' => __('The maximum number characters that should be returned for the alt-text. Default is 125.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'toggle', array( 'id' => 'rename_awkward_filenames', 'title' => __('Rename Image Files', 'ai-image-alt-text' ), 'description' => __('If image files have difficult to read names (ex. image-20251127-113156.jpg), should they be given a human-readable filename?', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'text', array( 'id' => 'alt_text_prefix', 'title' => __('Alt-Text Prefix', 'ai-image-alt-text' ), 'description' => __('A prefix to add to any alt-text generated by the plugin (ex. "AI-Generated").', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-style', 'text', array( 'id' => 'alt_text_suffix', 'title' => __('Alt-Text Suffix', 'ai-image-alt-text' ), 'description' => __('A suffix to add to any alt-text generated by the plugin (ex. "AI-Generated").', 'ai-image-alt-text'), ) ); // $sap->add_setting( // 'ait-iat-settings', // 'ait-iat-style', // 'toggle', // array( // 'id' => 'add_generated_by_notice', // 'title' => __('Add “AI-generated” Label', 'ai-image-alt-text' ), // 'description' => __('Adds an "(AI-generated)" disclaimer to all new alt text generations.', 'ai-image-alt-text'), // ) // ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-advanced-tab', 'title' => __('Advanced', 'ai-image-alt-text'), 'is_tab' => true, 'icon' => 'awards', 'rank' => 8, ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-debug-logging', 'title' => __( 'Debug/Logging', 'ai-image-alt-text' ), 'tab' => 'ait-iat-advanced-tab', ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-debug-logging', 'toggle', array( 'id' => 'enable_debug_mode', 'title' => __('Debug Mode', 'ai-image-alt-text' ), 'description' => __('When enabled, logs any error that are generated by the OpenAI API.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-debug-logging', 'toggle', array( 'id' => 'disable_logging', 'title' => __('Disable Logging', 'ai-image-alt-text' ), 'description' => __('Disable the keeping of logs of what alt text is generated.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-debug-logging', 'select', array( 'id' => 'log_level', 'title' => __('Log Level', 'ai-image-alt-text' ), 'description' => __('What language should the alt text be rendered in?', 'ai-image-alt-text'), 'options' => [ 'errors' => __( 'Errors', 'ai-image-alt-text' ), 'verbose' => __( 'Verbose', 'ai-image-alt-text' ), ], ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-debug-logging', 'toggle', array( 'id' => 'log_to_file', 'title' => __('Log to File', 'ai-image-alt-text' ), 'description' => __('Save all log entries into a file.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-debug-logging', 'number', array( 'id' => 'log_retention_days', 'title' => __('Log Retention Days', 'ai-image-alt-text' ), 'description' => __('The number of days for which logs should be retained. Default is 30.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-debug-logging', 'toggle', array( 'id' => 'show_request_payload', 'title' => __('Show Request Payload', 'ai-image-alt-text' ), 'description' => __('Show (redacted) payload in logs.', 'ai-image-alt-text'), ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-advanced', 'title' => __( 'Advanced', 'ai-image-alt-text' ), 'tab' => 'ait-iat-advanced-tab', ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-advanced', 'toggle', array( 'id' => 'enable_test_mode', 'title' => __('Enable Test Mode', 'ai-image-alt-text' ), 'description' => __('Alt text will be retrieved but not saved whenever a request would normally be made.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-advanced', 'text', array( 'id' => 'force_model_override', 'title' => __('Force Model Override', 'ai-image-alt-text' ), 'description' => __('The name of the model which should be used to generate alt text. Will cause errors if model does not exist or can not process image inputs.', 'ai-image-alt-text'), ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-advanced', 'textarea', array( 'id' => 'blocklist_keywords', 'title' => __('Blocklist Keywords', 'ai-image-alt-text' ), 'description' => __('A list of words which should not be included in any alt text descriptions, comma-separated.', 'ai-image-alt-text'), ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-logs-tab', 'title' => __('Logs', 'ai-image-alt-text'), 'is_tab' => true, 'icon' => 'warning', 'rank' => 9, ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-logs', 'title' => __( 'Logs', 'ai-image-alt-text' ), 'tab' => 'ait-iat-logs-tab', ) ); $sap->add_setting( 'ait-iat-settings', 'ait-iat-logs', 'html', array( 'id' => 'ait_iat_logs_table', 'title' => __('Alt Text Generation Logs', 'ai-image-alt-text' ), 'html' => [ 'AIT_IAT_Settings', 'display_alt_generation_logs' ], ) ); /** * Pro options preview only */ // "Bulk" Tab $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-bulk-tab', 'title' => __( 'Bulk', 'ai-image-alt-text' ), 'is_tab' => true, 'icon' => 'images-alt2', 'rank' => 2, //'tutorial_yt_id' => 'gV0mAkKWSXg', 'show_submit_button' => self::show_submit_button( 'can_bulk_full_library' ) ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-bulk-tab-body', 'tab' => 'ait-iat-bulk-tab', 'callback' => self::premium_info( 'bulk' ) ) ); // "WooCommerce" Tab $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-woocommerce-tab', 'title' => __( 'WooCommerce', 'ai-image-alt-text' ), 'is_tab' => true, 'icon' => 'cart', 'rank' => 3, //'tutorial_yt_id' => 'gV0mAkKWSXg', 'show_submit_button' => self::show_submit_button( 'can_woocommerce' ) ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-woocommerce-tab-body', 'tab' => 'ait-iat-woocommerce-tab', 'callback' => self::premium_info( 'woocommerce' ) ) ); // "Context‑Aware" Tab $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-context‑aware-tab', 'title' => __( 'Context‑Aware', 'ai-image-alt-text' ), 'is_tab' => true, 'icon' => 'media-document', 'rank' => 4, //'tutorial_yt_id' => 'gV0mAkKWSXg', 'show_submit_button' => self::show_submit_button( 'can_context_aware' ) ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-context‑aware-tab-body', 'tab' => 'ait-iat-context‑aware-tab', 'callback' => self::premium_info( 'context_aware' ) ) ); // "SEO Scoring" Tab $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-seo-score-tab', 'title' => __( 'SEO Score', 'ai-image-alt-text' ), 'is_tab' => true, 'icon' => 'search', 'rank' => 6, //'tutorial_yt_id' => 'gV0mAkKWSXg', 'show_submit_button' => self::show_submit_button( 'can_seo_scoring' ) ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-seo-score-tab-body', 'tab' => 'ait-iat-seo-score-tab', 'callback' => self::premium_info( 'seo_scoring' ) ) ); // "Analytics" Tab $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-analytics-tab', 'title' => __( 'Analytics', 'ai-image-alt-text' ), 'is_tab' => true, 'icon' => 'analytics', 'rank' => 7, //'tutorial_yt_id' => 'gV0mAkKWSXg', 'show_submit_button' => self::show_submit_button( 'can_analytics' ) ) ); $sap->add_section( 'ait-iat-settings', array( 'id' => 'ait-iat-analytics-tab-body', 'tab' => 'ait-iat-analytics-tab', 'callback' => self::premium_info( 'analytics' ) ) ); $sap = apply_filters( 'ait_iat_settings_page', $sap, $this ); $sap->add_admin_menus(); } public static function get_language_options() { return [ 'af' => 'Afrikaans', 'sq' => 'Shqip', 'am' => 'አማርኛ', 'ar' => 'العربية', 'hy' => 'Հայերեն', 'az' => 'Azərbaycan dili', 'bn' => 'বাংলা', 'bs' => 'Bosanski', 'bg' => 'Български', 'ca' => 'Català', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', 'hr' => 'Hrvatski', 'cs' => 'Čeština', 'da' => 'Dansk', 'nl' => 'Nederlands', 'en' => 'English', 'et' => 'Eesti', 'fi' => 'Suomi', 'fr' => 'Français', 'de' => 'Deutsch', 'el' => 'Ελληνικά', 'gu' => 'ગુજરાતી', 'he' => 'עברית', 'hi' => 'हिन्दी', 'hu' => 'Magyar', 'is' => 'Íslenska', 'id' => 'Bahasa Indonesia', 'it' => 'Italiano', 'ja' => '日本語', 'kn' => 'ಕನ್ನಡ', 'ko' => '한국어', 'lv' => 'Latviešu', 'lt' => 'Lietuvių', 'mk' => 'Македонски', 'ms' => 'Bahasa Melayu', 'ml' => 'മലയാളം', 'mr' => 'मराठी', 'ne' => 'नेपाली', 'nb' => 'Norsk Bokmål', 'fa' => 'فارسی', 'pl' => 'Polski', 'pt_BR' => 'Português do Brasil', 'pt_PT' => 'Português', 'pa' => 'ਪੰਜਾਬੀ', 'ro' => 'Română', 'ru' => 'Русский', 'sr' => 'Српски', 'si' => 'සිංහල', 'sk' => 'Slovenčina', 'sl' => 'Slovenščina', 'es' => 'Español', 'sv' => 'Svenska', 'ta' => 'தமிழ்', 'te' => 'తెలుగు', 'th' => 'ไทย', 'tr' => 'Türkçe', 'uk' => 'Українська', 'ur' => 'اردو', 'vi' => 'Tiếng Việt', 'zh_HK' => '香港中文版', ]; } public static function get_openai_models() { return [ 'gpt-5' => 'GPT-5', 'gpt-4o' => 'GPT-4o', //'gpt-4o-mini' => 'GPT-4o Mini' ]; } public static function get_options() { $saved = get_option(self::OPTION_NAME, []); return array_merge(self::$defaults, (array) $saved); } public static function get($key) { $options = self::get_options(); if ( ! empty( $options[ $key ] ) ) { return apply_filters( 'ait-iat-settings-' . $key, $options[ $key ] ); } if ( ! empty( self::$defaults[ $key ] ) ) { return apply_filters( 'ait-iat-settings-' . $key, self::$defaults[ $key ] ); } return apply_filters( 'ait-iat-settings-' . $key, null ); } public static function update($key, $value) { $options = self::get_options(); $options[$key] = $value; update_option(self::OPTION_NAME, $options); } public static function reset() { update_option(self::OPTION_NAME, self::$defaults); } public static function get_supported_mime_types() { $all_mimes = [ 'image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/tiff', 'image/x-icon', 'image/webp', 'image/avif', 'image/heic', 'image/heif', 'image/svg+xml' ]; return array_diff( $all_mimes, (array)self::get('exclude_mime_types')); } /** * Output a table of the latest alt text generations in the Logs tab. */ public static function display_alt_generation_logs() { global $wpdb; $table = $wpdb->prefix . 'ait_iat_alt_log'; $logs = $wpdb->get_results( "SELECT * FROM $table ORDER BY generated_at DESC LIMIT 100" ); if (!$logs) { echo '
' . esc_html__('No alt text logs found.', 'ai-image-alt-text') . '
'; return; } echo '| ' . esc_html__('Date', 'ai-image-alt-text') . ' | ' . esc_html__('Image', 'ai-image-alt-text') . ' | ' . esc_html__('Alt Text', 'ai-image-alt-text') . ' |
|---|---|---|
| ' . esc_html($log->generated_at) . ' | '; echo '';
if ($img_url) {
echo ' | ';
echo '' . esc_html($log->alt_text) . ' | '; echo '
' . __( 'The pro version also gives you access to the following features:', 'ai-image-alt-text' ) . '
'; switch ( $section_and_perm_type ) { case 'bulk': $content = '' . __( 'The bulk options let you generate alt text for all or some of the images missing it on your site, or regenarate alt text using a new prompt or style.', 'ai-image-alt-text' ) . '
' . __( 'Generate alt text for your product images and galleries, using context information from the product (title, description, attributes, etc.)', 'ai-image-alt-text' ) . '
' . __( 'Add context to image generation, so that post/product/etc. context is sent along with the image when alt text is being generated.', 'ai-image-alt-text' ) . '
' . __( 'Scores the alt text for various images within a post, based on how well that alt text aligns with the keyword focus from one of several major SEO plugins (Yoast, AIOSEO, RankMath, etc.)', 'ai-image-alt-text' ) . '
' . __( 'Records analytical data related to the images which have been generated on your site, such as time taken, tokens used, image ID, and more!', 'ai-image-alt-text' ) . '