esc_html(__('You do not have permission to perform this action.', 'ai-product-assistant'))));
}
}
/**
* Do Settings Sections For Group
*
* @param string $page
* @param array $fields
*/
public function do_settings_sections_for_group($page, $fields) {
global $wp_settings_fields;
if (!isset($wp_settings_fields[$page])) {
return;
}
echo '
';
}
/**
* Create statistics database table if it doesn't exist
*/
public function create_statistics_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'aipa_statistics';
// Check if table exists (necessary system check with prepared statement)
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
if($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) != $table_name) {
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_role varchar(50) NOT NULL DEFAULT 'guest',
timestamp datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
api_provider varchar(100) NOT NULL,
api_model varchar(100) NOT NULL,
request_type varchar(20) NOT NULL,
request_prompt text NOT NULL,
request_chars int(11) NOT NULL,
request_tokens int(11) NOT NULL,
response_text text NOT NULL,
response_chars int(11) NOT NULL,
response_tokens int(11) NOT NULL,
execution_time float NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}
/**
* Handle Statistics export
*/
public function handle_statistics_export() {
if (isset($_GET['action']) && $_GET['action'] === 'export_statistics' &&
isset($_GET['page']) && $_GET['page'] === 'ai-product-assistant') {
if (!isset($_GET['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['nonce'])), 'aipa_admin_nonce')) {
wp_die(esc_html(__('Security check failed.', 'ai-product-assistant')));
}
if (!current_user_can('manage_options')) {
wp_die(esc_html(__('You do not have sufficient permissions to access this page.', 'ai-product-assistant')));
}
$time_range = isset($_GET['time_range']) ? sanitize_text_field(wp_unslash($_GET['time_range'])) : 'all';
global $wpdb;
$table_name = $wpdb->prefix . 'aipa_statistics';
// Build query with predefined conditions (no user input)
$sql = "SELECT * FROM {$wpdb->prefix}aipa_statistics ";
switch ($time_range) {
case 'today':
$sql .= "WHERE DATE(timestamp) = CURDATE() ";
break;
case 'yesterday':
$sql .= "WHERE DATE(timestamp) = DATE_SUB(CURDATE(), INTERVAL 1 DAY) ";
break;
case '7days':
$sql .= "WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 7 DAY) ";
break;
case '30days':
$sql .= "WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY) ";
break;
default:
// No where clause for 'all' option
break;
}
$sql .= "ORDER BY timestamp DESC";
// Execute query (safe because no user input is interpolated)
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
$stats = $wpdb->get_results($sql, ARRAY_A);
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=aipa-statistics-' . gmdate('Y-m-d') . '.csv');
// Use WordPress-style output for CSV
echo "\xEF\xBB\xBF"; // BOM for UTF-8
// Output CSV header
$header = array(
'ID',
'User Role',
'Timestamp',
'API Provider',
'API Model',
'Request Type',
'Request Prompt',
'Request Chars',
'Request Tokens',
'Response Text',
'Response Chars',
'Response Tokens',
'Execution Time (s)'
);
echo '"' . implode('","', array_map('esc_attr', $header)) . '"' . "\n";
// Output CSV data
foreach ($stats as $row) {
$csv_row = array(
$row['id'],
$row['user_role'],
$row['timestamp'],
$row['api_provider'],
$row['api_model'],
$row['request_type'],
$row['request_prompt'],
$row['request_chars'],
$row['request_tokens'],
$row['response_text'],
$row['response_chars'],
$row['response_tokens'],
$row['execution_time']
);
echo '"' . implode('","', array_map('esc_attr', $csv_row)) . '"' . "\n";
}
exit;
}
}
/**
* Sanitize settings
*/
public function sanitize_settings($input) {
$sanitized_input = array();
// API Provider
if (isset($input['api_provider'])) {
$sanitized_input['api_provider'] = sanitize_text_field($input['api_provider']);
}
// API URL
if (isset($input['api_url'])) {
$sanitized_input['api_url'] = esc_url_raw($input['api_url']);
}
// API Model
if (isset($input['api_model'])) {
$sanitized_input['api_model'] = sanitize_text_field($input['api_model']);
}
// Custom Model (if needed)
if (isset($input['api_model_custom']) && $input['api_model'] === 'custom') {
$sanitized_input['api_model'] = sanitize_text_field($input['api_model_custom']);
}
// Format Template
if (isset($input['format_template'])) {
$sanitized_input['format_template'] = sanitize_text_field($input['format_template']);
}
// API Key
if (isset($input['api_key'])) {
$sanitized_input['api_key'] = sanitize_text_field($input['api_key']);
}
// Search Fields
$sanitized_input['search_fields'] = array(
'title' => isset($input['search_fields']['title']) ? true : false,
'short_description' => isset($input['search_fields']['short_description']) ? true : false,
'content' => isset($input['search_fields']['content']) ? true : false,
'categories' => isset($input['search_fields']['categories']) ? true : false,
'tags' => isset($input['search_fields']['tags']) ? true : false,
'brand' => isset($input['search_fields']['brand']) ? true : false,
'weight' => isset($input['search_fields']['weight']) ? true : false,
'dimensions' => isset($input['search_fields']['dimensions']) ? true : false,
'variation_data' => isset($input['search_fields']['variation_data']) ? true : false,
'attributes' => isset($input['search_fields']['attributes']) ? true : false,
'regular_price' => isset($input['search_fields']['regular_price']) ? true : false,
'sale_price' => isset($input['search_fields']['sale_price']) ? true : false
);
// Add custom fields to search fields
if (isset($input['search_fields'])) {
foreach ($input['search_fields'] as $key => $value) {
if (strpos($key, 'custom_') === 0) {
$sanitized_input['search_fields'][$key] = true;
}
}
}
// Custom Fields
if (isset($input['custom_fields'])) {
// Decode JSON with UTF-8 encoding
$json_str = stripslashes($input['custom_fields']);
$custom_fields = json_decode($json_str, true);
if (is_array($custom_fields)) {
$sanitized_custom_fields = array();
foreach ($custom_fields as $field) {
if (isset($field['meta_key']) && isset($field['description'])) {
// Preserve UTF-8 characters while still sanitizing
$meta_key = trim($field['meta_key']);
$meta_key = wp_strip_all_tags($meta_key);
// Remove control characters but keep all other Unicode characters
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
$meta_key = preg_replace('/[\x00-\x1F\x7F]/u', '', $meta_key);
$sanitized_custom_fields[] = array(
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
'meta_key' => $meta_key,
'description' => sanitize_text_field($field['description'])
);
}
}
$sanitized_input['custom_fields'] = $sanitized_custom_fields;
}
}
// Show Out of Stock
$sanitized_input['show_out_of_stock'] = isset($input['show_out_of_stock']) ? true : false;
// Show Explanation
$sanitized_input['show_explanation'] = isset($input['show_explanation']) ? true : false;
// AI Explanation Icon
if (isset($input['explanation_icon'])) {
$sanitized_input['explanation_icon'] = sanitize_text_field($input['explanation_icon']);
}
// Show Add to Cart
$sanitized_input['show_add_to_cart'] = isset($input['show_add_to_cart']) ? true : false;
// Use Native Template
$sanitized_input['use_native_template'] = isset($input['use_native_template']) ? true : false;
// Search UI Customization
if (isset($input['search_modal_title'])) {
$sanitized_input['search_modal_title'] = sanitize_text_field($input['search_modal_title']);
}
if (isset($input['search_modal_description'])) {
$sanitized_input['search_modal_description'] = sanitize_text_field($input['search_modal_description']);
}
if (isset($input['search_placeholder'])) {
$sanitized_input['search_placeholder'] = sanitize_text_field($input['search_placeholder']);
}
if (isset($input['voice_button_text'])) {
$sanitized_input['voice_button_text'] = sanitize_text_field($input['voice_button_text']);
}
if (isset($input['search_button_text'])) {
$sanitized_input['search_button_text'] = sanitize_text_field($input['search_button_text']);
}
// Search Button Icon type
$sanitized_input['button_icon_type'] = isset($input['button_icon_type']) ? sanitize_text_field($input['button_icon_type']) : 'text';
$sanitized_input['button_icon'] = isset($input['button_icon']) ? sanitize_text_field($input['button_icon']) : 'AI Search';
$sanitized_input['button_icon_image'] = isset($input['button_icon_image']) ? esc_url_raw($input['button_icon_image']) : '';
// Search Button CSS
if (isset($input['button_css'])) {
$sanitized_input['button_css'] = wp_kses($input['button_css'], array());
}
// Show Floating Button
$sanitized_input['show_floating_button'] = isset($input['show_floating_button']) ? true : false;
$sanitized_input['search_button_icon_type'] = isset($input['search_button_icon_type']) ? sanitize_text_field($input['search_button_icon_type']) : 'text';
$sanitized_input['search_button_icon'] = isset($input['search_button_icon']) ? sanitize_text_field($input['search_button_icon']) : 'AI';
$sanitized_input['search_button_icon_image'] = isset($input['search_button_icon_image']) ? esc_url_raw($input['search_button_icon_image']) : '';
if (isset($input['search_button_css'])) {
$sanitized_input['search_button_css'] = wp_kses($input['search_button_css'], array());
}
// Prompt Settings
if (isset($input['prompt_prefix'])) {
$sanitized_input['prompt_prefix'] = sanitize_textarea_field($input['prompt_prefix']);
}
if (isset($input['prompt_suffix'])) {
$sanitized_input['prompt_suffix'] = sanitize_textarea_field($input['prompt_suffix']);
}
// Cart Analysis Settings
$sanitized_input['enable_cart_analysis'] = isset($input['enable_cart_analysis']) ? true : false;
// Cart Analysis UI Customization
if (isset($input['cart_analysis_title'])) {
$sanitized_input['cart_analysis_title'] = sanitize_text_field($input['cart_analysis_title']);
}
if (isset($input['cart_analysis_description'])) {
$sanitized_input['cart_analysis_description'] = sanitize_text_field($input['cart_analysis_description']);
}
if (isset($input['cart_analysis_placeholder'])) {
$sanitized_input['cart_analysis_placeholder'] = sanitize_text_field($input['cart_analysis_placeholder']);
}
if (isset($input['cart_analysis_button_text'])) {
$sanitized_input['cart_analysis_button_text'] = sanitize_text_field($input['cart_analysis_button_text']);
}
if (isset($input['cart_analysis_css'])) {
$sanitized_input['cart_analysis_css'] = wp_kses($input['cart_analysis_css'], array());
}
// Description Length Limit
if (isset($input['description_length_limit'])) {
$sanitized_input['description_length_limit'] = max(1, intval($input['description_length_limit']));
} else {
$sanitized_input['description_length_limit'] = 500;
}
// Short Description Length Limit
if (isset($input['short_description_length_limit'])) {
$sanitized_input['short_description_length_limit'] = max(1, intval($input['short_description_length_limit']));
} else {
$sanitized_input['short_description_length_limit'] = 200;
}
// Search Batch Size
if (isset($input['search_batch_size'])) {
$sanitized_input['search_batch_size'] = intval($input['search_batch_size']);
} else {
$sanitized_input['search_batch_size'] = 100; // Default value
}
// Always enable deep search
$sanitized_input['enable_deep_search'] = true;
// Max Batches
if (isset($input['max_batches'])) {
$sanitized_input['max_batches'] = intval($input['max_batches']);
} else {
$batch_size = isset($sanitized_input['search_batch_size']) ? intval($sanitized_input['search_batch_size']) : 100;
$product_count = (int) wp_count_posts('product')->publish;
$sanitized_input['max_batches'] = $product_count > 0 ? ceil($product_count / $batch_size) : 1;
}
// Brute Force Search (Pro only; default false = use Smart Search)
$sanitized_input['enable_brute_force_search'] = isset($input['enable_brute_force_search']) ? true : false;
// AI Temperature (Pro only; default 0.2; range 0.0–2.0)
$ai_temperature = isset($input['ai_temperature']) ? (float) $input['ai_temperature'] : 0.2;
$sanitized_input['ai_temperature'] = max(0.0, min(2.0, $ai_temperature));
// AI Max Tokens (Pro only; default 4096; range 256–8192)
$ai_max_tokens = isset($input['ai_max_tokens']) ? (int) $input['ai_max_tokens'] : 4096;
$sanitized_input['ai_max_tokens'] = max(256, min(8192, $ai_max_tokens));
// Product Assistant Settings
$sanitized_input['show_product_assistant'] = isset($input['show_product_assistant']) ? true : false;
if (isset($input['product_assistant_title'])) {
$sanitized_input['product_assistant_title'] = sanitize_text_field($input['product_assistant_title']);
}
if (isset($input['product_assistant_description'])) {
$sanitized_input['product_assistant_description'] = sanitize_text_field($input['product_assistant_description']);
}
if (isset($input['product_assistant_placeholder'])) {
$sanitized_input['product_assistant_placeholder'] = sanitize_text_field($input['product_assistant_placeholder']);
}
if (isset($input['product_assistant_button_text'])) {
$sanitized_input['product_assistant_button_text'] = sanitize_text_field($input['product_assistant_button_text']);
}
if (isset($input['product_assistant_button_css'])) {
$sanitized_input['product_assistant_button_css'] = wp_kses($input['product_assistant_button_css'], array());
}
return $sanitized_input;
}
}