'', 'embedding_model' => 'text-embedding-3-small', 'post_types' => [ 'post', 'page' ], 'related_location' => 'after_content', 'related_count' => 3, 'prefer_same_category' => false, 'related_label' => 'Related Posts', 'show_thumbnails' => true, 'enable_metabox' => true, 'enable_shortcode_block' => true, 'shortcode_default_post_type'=> 'post', 'index_max_items' => 100, 'debug_logging' => false, ]; public function __construct() { add_action( 'init', [ $this, 'register_settings_page' ], 11 ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] ); } public static function get_options() { $saved = get_option( AIT_AIRCE_OPTION_NAME, [] ); $defaults = apply_filters( 'ait_airce/defaults', self::$defaults ); if ( ! is_array( $defaults ) ) { $defaults = self::$defaults; } return array_merge( $defaults, (array) $saved ); } public static function get( $key ) { $options = self::get_options(); if ( array_key_exists( $key, $options ) ) { return apply_filters( 'ait-airce-settings-' . $key, $options[ $key ] ); } if ( array_key_exists( $key, self::$defaults ) ) { return apply_filters( 'ait-airce-settings-' . $key, self::$defaults[ $key ] ); } return apply_filters( 'ait-airce-settings-' . $key, null ); } public static function update( $key, $value ) { $options = self::get_options(); $options[ $key ] = $value; update_option( AIT_AIRCE_OPTION_NAME, $options ); } public static function reset() { update_option( AIT_AIRCE_OPTION_NAME, self::$defaults ); } /** * Return the full list of enabled post types, including Pro / integration filters. * * @return array */ public static function get_enabled_post_types() { $enabled = (array) self::get( 'post_types' ); $enabled = (array) apply_filters( 'ait_airce/enabled_post_types', $enabled ); $enabled = array_values( array_filter( array_map( 'sanitize_key', (array) $enabled ) ) ); return array_values( array_unique( $enabled ) ); } public function enqueue_admin_assets( $hook ) { if ( strpos( $hook, 'ait-airce' ) === false ) { return; } wp_enqueue_style( 'ait-airce-admin', AIT_AIRCE_URL . 'assets/css/admin.css', [], AIT_AIRCE_VERSION ); wp_enqueue_script( 'ait-airce-admin', AIT_AIRCE_URL . 'assets/js/admin.js', [ 'jquery' ], AIT_AIRCE_VERSION, true ); wp_localize_script( 'ait-airce-admin', 'AIT_AIRCE_ADMIN', [ 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'ait-airce-admin' ), ] ); } /** * Initialize SAP UI: page/tabs/sections/fields. */ public function register_settings_page() { require_once AIT_AIRCE_PATH . 'lib/simple-admin-pages/simple-admin-pages.php'; $sap = ait_airce_initialize_library( $args = array( 'version' => '2.7.3', 'theme' => 'ait', 'lib_url' => AIT_AIRCE_URL . 'lib/simple-admin-pages/', ) ); // Settings submenu page. $sap->add_page( 'submenu', [ 'id' => AIT_AIRCE_OPTION_NAME, 'title' => __( 'Settings', 'ait-ai-related-posts' ), 'menu_title' => __( 'Settings', 'ait-ai-related-posts' ), 'description' => '', 'capability' => 'manage_options', 'parent_menu' => 'ait-ai-related-posts', 'default_tab' => 'ait-airce-general-tab', ] ); // Tabs $sap->add_section( AIT_AIRCE_OPTION_NAME, [ 'id' => 'ait-airce-general-tab', 'title' => __( 'General', 'ait-ai-related-posts' ), 'is_tab' => true, 'icon' => 'text' ] ); $sap->add_section( AIT_AIRCE_OPTION_NAME, [ 'id' => 'ait-airce-tools-tab', 'title' => __( 'Tools', 'ait-ai-related-posts' ), 'is_tab' => true, 'icon' => 'admin-tools' ] ); // Sections $sap->add_section( AIT_AIRCE_OPTION_NAME, [ 'id' => 'ait-airce-general-section', 'title' => __( 'General Settings', 'ait-ai-related-posts' ), 'tab' => 'ait-airce-general-tab', 'page_id'=> 'ait-airce-settings', ] ); $sap->add_section( AIT_AIRCE_OPTION_NAME, [ 'id' => 'ait-airce-tools-section', 'title' => __( 'Index & Cache Tools', 'ait-ai-related-posts' ), 'tab' => 'ait-airce-tools-tab', 'page_id'=> 'ait-airce-settings', ] ); // Fields $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'text', [ 'id' => 'openai_api_key', 'title' => __( 'OpenAI API Key', 'ait-ai-related-posts' ), 'description' => __( 'Used to generate embeddings for semantic matching.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'select', [ 'id' => 'embedding_model', 'title' => __( 'Embedding Model', 'ait-ai-related-posts' ), 'description' => __( 'Model used to generate embeddings.', 'ait-ai-related-posts' ), 'options' => [ 'text-embedding-3-small' => __( 'text-embedding-3-small (fast/low cost)', 'ait-ai-related-posts' ), 'text-embedding-3-large' => __( 'text-embedding-3-large (higher quality)', 'ait-ai-related-posts' ), ], ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'checkbox', [ 'id' => 'post_types', 'title' => __( 'Enable for Post Types', 'ait-ai-related-posts' ), 'description' => __( 'Choose which post types automatically display related content.', 'ait-ai-related-posts' ), 'options' => [ 'post' => __( 'Posts', 'ait-ai-related-posts' ), 'page' => __( 'Pages', 'ait-ai-related-posts' ), ], ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'select', [ 'id' => 'related_location', 'title' => __( 'Default Location', 'ait-ai-related-posts' ), 'description' => __( 'Where to insert related content by default.', 'ait-ai-related-posts' ), 'options' => [ 'after_content' => __( 'After content', 'ait-ai-related-posts' ), 'after_title' => __( 'After title', 'ait-ai-related-posts' ), 'after_featured_image' => __( 'After featured image', 'ait-ai-related-posts' ), 'after_paragraph_2' => __( 'After 2nd paragraph', 'ait-ai-related-posts' ), ], ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'number', [ 'id' => 'related_count', 'title' => __( 'Related Items Count', 'ait-ai-related-posts' ), 'description' => __( 'Number of related items to display.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'toggle', [ 'id' => 'prefer_same_category', 'title' => __( 'Prefer Same Category (soft)', 'ait-ai-related-posts' ), 'description' => __( 'Soft preference only (not a hard filter).', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'text', [ 'id' => 'related_label', 'title' => __( 'Heading Label', 'ait-ai-related-posts' ), 'description' => __( 'Heading shown above related content.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'toggle', [ 'id' => 'show_thumbnails', 'title' => __( 'Show Thumbnails', 'ait-ai-related-posts' ), 'description' => __( 'Show featured image thumbnails when available.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'toggle', [ 'id' => 'enable_metabox', 'title' => __( 'Per-Post Disable Metabox', 'ait-ai-related-posts' ), 'description' => __( 'Adds a metabox to disable related content per post.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'toggle', [ 'id' => 'enable_shortcode_block', 'title' => __( 'Enable Shortcode/Block', 'ait-ai-related-posts' ), 'description' => __( 'Enable manual placement via shortcode/block.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'select', [ 'id' => 'shortcode_default_post_type', 'title' => __( 'Default Shortcode Post Type', 'ait-ai-related-posts' ), 'description' => __( 'Default post type used by shortcode/block if none is specified.', 'ait-ai-related-posts' ), 'options' => [ 'post' => __( 'Posts', 'ait-ai-related-posts' ), 'page' => __( 'Pages', 'ait-ai-related-posts' ), ] ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'number', [ 'id' => 'index_max_items', 'title' => __( 'Index Limit', 'ait-ai-related-posts' ), 'description' => __( 'Maximum number of items indexed for semantic matching. Default is 100.', 'ait-ai-related-posts' ), ] ); $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-general-section', 'toggle', [ 'id' => 'debug_logging', 'title' => __( 'Enable Debug Logging', 'ait-ai-related-posts' ), 'description' => __( 'Logs indexing and cache generation events to the debug log when enabled.', 'ait-ai-related-posts' ), ] ); // Tools tab: render HTML $sap->add_setting( AIT_AIRCE_OPTION_NAME, 'ait-airce-tools-section', 'html', [ 'id' => 'tools', 'title' => __( 'Enable Debug Logging', 'ait-ai-related-posts' ), 'description' => __( 'Logs indexing and cache generation events to the debug log when enabled.', 'ait-ai-related-posts' ), 'html' => [ $this, 'render_tools_html' ], ] ); $sap = apply_filters( 'ait_airce_settings_page', $sap, $this ); $sap->add_admin_menus(); } public function render_tools_html() { ?>