option_key, $this->option_key, [ 'sanitize_callback' => [$this, 'sanitize_settings'], 'type' => 'object' ] ); add_settings_section( 'actosync_main', '', function() {}, $this->option_key ); // Add settings fields add_settings_field( 'api_token', __('API Token (JWT)', 'actosync-ai-connect'), [$this, 'render_field_api_token'], $this->option_key, 'actosync_main' ); add_settings_field( 'widget_id', __('Widget ID', 'actosync-ai-connect'), [$this, 'render_field_widget_id'], $this->option_key, 'actosync_main' ); add_settings_field( 'agent_id', __('Agent ID', 'actosync-ai-connect'), [$this, 'render_field_agent_id'], $this->option_key, 'actosync_main' ); add_settings_field( 'user_id', __('ActoSync User ID', 'actosync-ai-connect'), [$this, 'render_field_user_id'], $this->option_key, 'actosync_main' ); add_settings_field( 'agent_name', __('Agent Name', 'actosync-ai-connect'), [$this, 'render_field_agent_name'], $this->option_key, 'actosync_main' ); add_settings_field( 'auto_insert', __('Auto-insert on pages', 'actosync-ai-connect'), [$this, 'render_field_auto_insert'], $this->option_key, 'actosync_main' ); add_settings_section( 'actosync_suggestions', __('AI Smart Shopping Suggestions', 'actosync-ai-connect'), [$this, 'render_suggestions_section'], $this->option_key ); $suggestion_fields = [ 'enable_smart_suggestions' => __('Enable Smart Suggestions', 'actosync-ai-connect'), 'max_suggestion_chips' => __('Max suggestion chips', 'actosync-ai-connect'), 'suggest_on_widget_closed' => __('Suggest on widget closed', 'actosync-ai-connect'), 'auto_refresh_suggestions' => __('Auto-refresh suggestions', 'actosync-ai-connect'), 'followup_suggestions' => __('Follow-up suggestions', 'actosync-ai-connect'), 'product_recommendations' => __('Product recommendations', 'actosync-ai-connect'), 'cross_sell_suggestions' => __('Cross-sell suggestions', 'actosync-ai-connect'), 'upsell_suggestions' => __('Upsell suggestions', 'actosync-ai-connect'), 'personalize_suggestions' => __('Personalize suggestions', 'actosync-ai-connect'), 'suggestion_delay_seconds' => __('Delay before showing (seconds)', 'actosync-ai-connect'), ]; foreach ($suggestion_fields as $field_key => $field_label) { add_settings_field( $field_key, $field_label, [$this, 'render_suggestion_field'], $this->option_key, 'actosync_suggestions', ['field_key' => $field_key] ); } } /** * Sanitize settings input */ public function sanitize_settings($input) { if (!is_array($input)) { return []; } $sanitized = []; $sanitized['api_token'] = $this->validate_jwt_token($input['api_token'] ?? ''); $sanitized['widget_id'] = sanitize_text_field($input['widget_id'] ?? ''); $sanitized['agent_id'] = sanitize_text_field($input['agent_id'] ?? ''); $sanitized['user_id'] = sanitize_text_field($input['user_id'] ?? ''); $sanitized['agent_name'] = sanitize_text_field($input['agent_name'] ?? 'AI Assistant'); $sanitized['auto_insert'] = !empty($input['auto_insert']) ? 1 : 0; $api = new ActoSync_API(); $defaults = $api->get_default_suggestion_settings(); $sanitized['enable_smart_suggestions'] = !empty($input['enable_smart_suggestions']) ? 1 : 0; $sanitized['max_suggestion_chips'] = max(3, min(8, (int) ($input['max_suggestion_chips'] ?? $defaults['max_suggestion_chips']))); $sanitized['suggest_on_widget_closed'] = !empty($input['suggest_on_widget_closed']) ? 1 : 0; $sanitized['auto_refresh_suggestions'] = !empty($input['auto_refresh_suggestions']) ? 1 : 0; $sanitized['followup_suggestions'] = !empty($input['followup_suggestions']) ? 1 : 0; $sanitized['product_recommendations'] = !empty($input['product_recommendations']) ? 1 : 0; $sanitized['cross_sell_suggestions'] = !empty($input['cross_sell_suggestions']) ? 1 : 0; $sanitized['upsell_suggestions'] = !empty($input['upsell_suggestions']) ? 1 : 0; $sanitized['personalize_suggestions'] = !empty($input['personalize_suggestions']) ? 1 : 0; $sanitized['suggestion_delay_seconds'] = max(0, min(15, (int) ($input['suggestion_delay_seconds'] ?? $defaults['suggestion_delay_seconds']))); return $sanitized; } /** * Validate JWT token format */ private function validate_jwt_token($token) { $token = trim($token); if (empty($token)) { return ''; } $parts = explode('.', $token); if (count($parts) !== 3) { add_settings_error( $this->option_key, 'invalid_jwt', __('Invalid JWT token format. Must contain three parts separated by dots.', 'actosync-ai-connect') ); return ''; } return sanitize_text_field($token); } /** * Render API Token field */ public function render_field_api_token() { $opts = get_option($this->option_key, []); $value = $opts['api_token'] ?? ''; printf( '', esc_attr($this->option_key), esc_attr($value) ); } /** * Render Widget ID field */ public function render_field_widget_id() { $opts = get_option($this->option_key, []); $value = $opts['widget_id'] ?? ''; printf( '', esc_attr($this->option_key), esc_attr($value) ); } /** * Render Agent ID field */ public function render_field_agent_id() { $opts = get_option($this->option_key, []); $value = $opts['agent_id'] ?? ''; printf( '', esc_attr($this->option_key), esc_attr($value) ); } /** * Render User ID field */ public function render_field_user_id() { $opts = get_option($this->option_key, []); $value = $opts['user_id'] ?? ''; printf( '', esc_attr($this->option_key), esc_attr($value) ); } /** * Render Agent Name field */ public function render_field_agent_name() { $opts = get_option($this->option_key, []); $value = $opts['agent_name'] ?? 'AI Assistant'; printf( '', esc_attr($this->option_key), esc_attr($value) ); } /** * Render suggestions section description. */ public function render_suggestions_section() { echo '
' . esc_html__( 'Configure AI-driven contextual shopping suggestions shown beside the chat icon and after each reply.', 'actosync-ai-connect' ) . '
'; } /** * Render a smart suggestion settings field. * * @param array $args */ public function render_suggestion_field($args) { $field_key = $args['field_key'] ?? ''; $opts = get_option($this->option_key, []); $api = new ActoSync_API(); $defaults = $api->get_default_suggestion_settings(); if ($field_key === 'max_suggestion_chips') { $value = (int) ($opts[$field_key] ?? $defaults[$field_key]); printf( '', esc_attr($this->option_key), esc_attr($field_key), absint($value) ); return; } if ($field_key === 'suggestion_delay_seconds') { $value = (int) ($opts[$field_key] ?? $defaults[$field_key]); printf( '', esc_attr($this->option_key), esc_attr($field_key), absint($value) ); return; } $checked = !isset($opts[$field_key]) ? !empty($defaults[$field_key]) : !empty($opts[$field_key]); printf( '', esc_attr($this->option_key), esc_attr($field_key), checked($checked, true, false) ); } /** * Render Auto-insert checkbox */ public function render_field_auto_insert() { $opts = get_option($this->option_key, []); printf( '', esc_attr($this->option_key), checked(!empty($opts['auto_insert']), true, false), esc_html__('Auto-insert on all pages', 'actosync-ai-connect') ); } /** * Render settings page */ public function render_settings_page() { if (!current_user_can('manage_options')) { wp_die(esc_html__('Unauthorized', 'actosync-ai-connect')); } ?> [actosync_chat_widget]