[ 'post', 'page' ], 'display_method' => 'auto_inject', // shortcode | auto_inject | both 'ui_style' => 'style1', // Title 'faq_title_enabled' => '1', 'faq_title_text' => 'Frequently Asked Questions', // Visibility / Schema 'schema_enabled' => '1', 'faq_visible' => '1', // Colors — Question 'q_bg' => '#ffffff', 'q_text' => '#000000', 'q_border' => '#cccccc', 'q_radius' => '10', 'q_hover_bg' => '#f5f5f5', 'q_hover_text' => '#000000', 'q_active_bg' => '#d8222b', 'q_active_text' => '#ffffff', // Colors — Answer 'a_bg' => '#ffffff', 'a_text' => '#000000', // Colors — Section title 'title_color' => '#000000', // Spacing 'q_padding_v' => '14', 'q_padding_h' => '18', 'a_padding_v' => '14', 'a_padding_h' => '18', 'item_gap' => '10', // Font 'font_family' => 'inherit', 'font_size_title' => '24', 'font_size_q' => '16', 'font_size_a' => '15', 'font_weight_q' => '600', // Schema 'use_custom_schema' => '', 'custom_schema' => '', ]; } /* ------------------------------------------------------------------ */ /* Menus */ /* ------------------------------------------------------------------ */ public function register_menus() { add_menu_page( __( 'Smart FAQ Schema', 'accordly-smart-faq-schema' ), __( 'Smart FAQ', 'accordly-smart-faq-schema' ), 'manage_options', 'sfaq-settings', [ $this, 'render_settings_page' ], 'dashicons-editor-help', 58 ); add_submenu_page( 'sfaq-settings', __( 'Settings', 'accordly-smart-faq-schema' ), __( 'Settings', 'accordly-smart-faq-schema' ), 'manage_options', 'sfaq-settings', [ $this, 'render_settings_page' ] ); add_submenu_page( 'sfaq-settings', __( 'Bulk FAQ Checker', 'accordly-smart-faq-schema' ), __( 'Bulk Checker', 'accordly-smart-faq-schema' ), 'manage_options', 'sfaq-bulk', [ SFAQ_Bulk::get_instance(), 'render_bulk_page' ] ); add_submenu_page( 'sfaq-settings', __( 'Guide & Documentation', 'accordly-smart-faq-schema' ), __( 'Guide', 'accordly-smart-faq-schema' ), 'manage_options', 'sfaq-guide', [ $this, 'render_guide_page' ] ); } /* ------------------------------------------------------------------ */ /* Settings API */ /* ------------------------------------------------------------------ */ public function register_settings() { register_setting( 'sfaq_settings_group', self::OPTION_KEY, [ 'sanitize_callback' => [ $this, 'sanitize_settings' ], ] ); } public function sanitize_settings( $input ) { $defaults = self::get_defaults(); $clean = []; $clean['post_types'] = isset( $input['post_types'] ) && is_array( $input['post_types'] ) ? array_map( 'sanitize_key', $input['post_types'] ) : $defaults['post_types']; $clean['display_method'] = in_array( $input['display_method'] ?? '', [ 'shortcode', 'auto_inject', 'both' ] ) ? $input['display_method'] : $defaults['display_method']; $clean['ui_style'] = in_array( $input['ui_style'] ?? '', [ 'style1','style2','style3','style4','style5' ] ) ? $input['ui_style'] : $defaults['ui_style']; $clean['faq_title_enabled'] = ! empty( $input['faq_title_enabled'] ) ? '1' : ''; $clean['faq_title_text'] = sanitize_text_field( $input['faq_title_text'] ?? $defaults['faq_title_text'] ); $clean['schema_enabled'] = ! empty( $input['schema_enabled'] ) ? '1' : ''; $clean['faq_visible'] = ! empty( $input['faq_visible'] ) ? '1' : ''; $color_keys = [ 'q_bg','q_text','q_border','q_hover_bg','q_hover_text','q_active_bg','q_active_text','a_bg','a_text','title_color' ]; foreach ( $color_keys as $ck ) { $clean[ $ck ] = $this->sanitize_hex( $input[ $ck ] ?? $defaults[ $ck ] ); } $clean['q_radius'] = absint( $input['q_radius'] ?? $defaults['q_radius'] ); $clean['q_padding_v'] = absint( $input['q_padding_v'] ?? $defaults['q_padding_v'] ); $clean['q_padding_h'] = absint( $input['q_padding_h'] ?? $defaults['q_padding_h'] ); $clean['a_padding_v'] = absint( $input['a_padding_v'] ?? $defaults['a_padding_v'] ); $clean['a_padding_h'] = absint( $input['a_padding_h'] ?? $defaults['a_padding_h'] ); $clean['item_gap'] = absint( $input['item_gap'] ?? $defaults['item_gap'] ); $clean['font_family'] = sanitize_text_field( $input['font_family'] ?? $defaults['font_family'] ); $clean['font_size_title'] = absint( $input['font_size_title'] ?? $defaults['font_size_title'] ); $clean['font_size_q'] = absint( $input['font_size_q'] ?? $defaults['font_size_q'] ); $clean['font_size_a'] = absint( $input['font_size_a'] ?? $defaults['font_size_a'] ); $clean['font_weight_q'] = in_array( (string)( $input['font_weight_q'] ?? '' ), [ '400','500','600','700','800' ] ) ? (string) $input['font_weight_q'] : $defaults['font_weight_q']; $clean['use_custom_schema'] = ! empty( $input['use_custom_schema'] ) ? '1' : ''; $clean['custom_schema'] = wp_kses_post( $input['custom_schema'] ?? '' ); // Bust the CSS cache when settings change delete_transient( 'sfaq_dynamic_css_v' . SFAQ_VERSION ); return $clean; } private function sanitize_hex( $hex ) { $hex = sanitize_hex_color( $hex ); return $hex ?: '#000000'; } /* ------------------------------------------------------------------ */ /* Admin Assets */ /* ------------------------------------------------------------------ */ public function enqueue_admin_assets( $hook ) { if ( strpos( $hook, 'sfaq' ) === false && $hook !== 'post.php' && $hook !== 'post-new.php' ) { return; } wp_enqueue_style( 'sfaq-admin', SFAQ_PLUGIN_URL . 'assets/css/admin.css', [], SFAQ_VERSION ); // Load frontend CSS so the Live Preview in the Styling tab renders correctly if ( ( sanitize_key( wp_unslash( $_GET['sfaq_tab'] ?? '' ) ) === 'styling' ) || strpos( $hook, 'post' ) !== false ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended wp_enqueue_style( 'sfaq-frontend-preview', SFAQ_PLUGIN_URL . 'assets/css/frontend.css', [], SFAQ_VERSION ); } wp_enqueue_script( 'sfaq-admin', SFAQ_PLUGIN_URL . 'assets/js/admin.js', [ 'jquery', 'wp-color-picker' ], SFAQ_VERSION, true ); wp_enqueue_style( 'wp-color-picker' ); // Register a virtual (no-file) style handle so wp_add_inline_style can // output a