Files
igny8/igny8-ai-seo-wp-plugin/ai/openai-api.php
2025-11-11 21:16:37 +05:00

1730 lines
68 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* ==========================
* 🔐 IGNY8 FILE RULE HEADER
* ==========================
* @file : openai-api.php
* @location : /ai/openai-api.php
* @type : AI Integration
* @scope : Global
* @allowed : AI API calls, OpenAI integration, AI processing
* @reusability : Globally Reusable
* @notes : Central OpenAI API integration for all AI features
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* OpenAI API Functions
* Centralized API for all OpenAI functionality including personalization
*/
/**
* Log field detection process for debugging and monitoring
*/
function igny8_log_field_detection_process($level, $message) {
$timestamp = current_time('Y-m-d H:i:s');
$log_entry = "[{$timestamp}] [{$level}] {$message}";
// Log to WordPress debug log
error_log("IGNY8 Field Detection: {$log_entry}");
// Store in database for admin viewing
global $wpdb;
// Check if logs table exists and has the correct structure
$table_name = $wpdb->prefix . 'igny8_logs';
$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'");
if ($table_exists) {
// Get table structure to determine correct column names
$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name");
$column_names = array_column($columns, 'Field');
// Prepare data based on actual table structure
$log_data = [
'timestamp' => $timestamp,
'post_id' => get_queried_object_id(),
'user_id' => get_current_user_id(),
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
];
// Insert based on actual table structure
if (in_array('log_type', $column_names) && in_array('message', $column_names) && in_array('data', $column_names)) {
// New structure from install.php
$wpdb->insert(
$table_name,
[
'log_type' => 'field_detection',
'message' => "[{$level}] {$message}",
'data' => json_encode($log_data),
'user_id' => get_current_user_id()
],
['%s', '%s', '%s', '%d']
);
} else {
// Fallback: just log to error log if table structure doesn't match
error_log("IGNY8: Logs table structure mismatch, skipping database log");
}
} else {
error_log("IGNY8: Logs table does not exist, skipping database log");
}
}
/**
* Build combined content for personalization
*/
function igny8_build_combined_content($for_field_detection = false, $post_id = null) {
// Check if Content Engine is enabled and use Content Engine-specific settings
$content_engine_status = get_option('igny8_content_engine_global_status', 'enabled');
// Use provided post_id or fall back to queried object
if ($post_id === null) {
$post_id = get_queried_object_id();
}
$post_type = get_post_type($post_id);
$enabled_post_types = get_option('igny8_content_engine_enabled_post_types', []);
if ($content_engine_status === 'enabled' && in_array($post_type, $enabled_post_types)) {
// Use Content Engine-specific settings
$include_context = get_option('igny8_content_engine_include_page_context', '0') === '1';
$input_scope = get_option('igny8_content_engine_input_scope', '300');
} else {
// Use global settings
$include_context = get_option('igny8_include_page_context', '0') === '1';
$input_scope = get_option('igny8_input_scope', '300');
}
$final_content = '';
// ✅ Use PageContent from form if available
if (!empty($_POST['PageContent'])) {
$final_content .= "[SOURCE:PageContent from form]\n\n";
$final_content .= trim(sanitize_text_field($_POST['PageContent']));
} else {
// ✅ Fallback to raw post content or term description
$queried = get_post($post_id);
if ($queried instanceof WP_Post) {
// 🎯 Post/page/product — use post content with proper scope
$raw_content = get_post_field('post_content', $queried->ID);
if (!empty($raw_content)) {
$final_content .= "[SOURCE:Post Content]\n\n";
// Apply scope logic - only add dynamic messages for field detection
if ($for_field_detection) {
// Add dynamic messages for field detection
if ($input_scope === 'title') {
$final_content .= "Use this blog/page title to define the fields:\n\n";
$final_content .= get_the_title($queried->ID);
} elseif ($input_scope === '300') {
$final_content .= "Use these 300 words to define the fields:\n\n";
$final_content .= wp_trim_words(strip_tags($raw_content), 300, '...');
} elseif ($input_scope === '600') {
$final_content .= "Use these 600 words to define the fields:\n\n";
$final_content .= wp_trim_words(strip_tags($raw_content), 600, '...');
} else {
$final_content .= "Use this whole content to define the fields:\n\n";
$final_content .= strip_tags($raw_content);
}
} else {
// For content generation, just add content without dynamic messages
if ($input_scope === 'title') {
$final_content .= get_the_title($queried->ID);
} elseif ($input_scope === '300') {
$final_content .= wp_trim_words(strip_tags($raw_content), 300, '...');
} elseif ($input_scope === '600') {
$final_content .= wp_trim_words(strip_tags($raw_content), 600, '...');
} else {
$final_content .= strip_tags($raw_content);
}
}
}
} elseif (isset($queried->description) && !empty($queried->description)) {
// 🏷️ Archive (term) — use term description
$final_content .= "[SOURCE:Term Description]\n\n";
$final_content .= wp_trim_words(strip_tags($queried->description), 300, '...');
}
}
return trim($final_content) ?: 'No content available.';
}
/**
* Check content for moderation violations using OpenAI's moderation API
*/
function igny8_check_moderation($text, $api_key) {
$res = wp_remote_post('https://api.openai.com/v1/moderations', [
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json',
],
'body' => json_encode(['input' => $text]),
'timeout' => 20,
]);
if (is_wp_error($res)) {
return ['flagged' => false, 'error' => $res->get_error_message()];
}
$body = json_decode(wp_remote_retrieve_body($res), true);
return [
'flagged' => $body['results'][0]['flagged'] ?? false,
'categories' => $body['results'][0]['categories'] ?? [],
];
}
/**
* Test OpenAI API connection
*/
function igny8_test_connection($api_key, $with_response = false) {
// Get the current model setting
$model = get_option('igny8_model', 'gpt-4.1');
if ($with_response) {
// Test with actual API call
// Prepare request body with model-specific parameters
$request_body = [
'model' => $model,
'messages' => [
[
'role' => 'user',
'content' => 'test ping, reply with: OK! Ping Received. Also tell me: what is your maximum token limit that I can use in 1 request?'
]
]
];
// Model-specific parameters
$request_body['temperature'] = 0.7;
// Log the complete request to file
$log_data = [
'timestamp' => current_time('mysql'),
'model' => $model,
'request_body' => $request_body,
'headers' => [
'Authorization' => 'Bearer ' . substr($api_key, 0, 10) . '...',
'Content-Type' => 'application/json'
]
];
$log_file = ABSPATH . 'igny8_api_request_log.json';
file_put_contents($log_file, json_encode($log_data, JSON_PRETTY_PRINT));
error_log("Igny8 Debug: Complete API request logged to: " . $log_file);
$res = wp_remote_post('https://api.openai.com/v1/chat/completions', [
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json',
],
'body' => json_encode($request_body),
'timeout' => 15,
]);
} else {
// Simple connection test without API call
$res = wp_remote_get('https://api.openai.com/v1/models', [
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
],
'timeout' => 10,
]);
}
if (is_wp_error($res)) {
return $res->get_error_message();
}
$code = wp_remote_retrieve_response_code($res);
$body = wp_remote_retrieve_body($res);
// Log the complete response to file
if ($with_response) {
$response_log_data = [
'timestamp' => current_time('mysql'),
'response_code' => $code,
'response_body' => json_decode($body, true),
'raw_response' => $body
];
$response_log_file = ABSPATH . 'igny8_api_response_log.json';
file_put_contents($response_log_file, json_encode($response_log_data, JSON_PRETTY_PRINT));
error_log("Igny8 Debug: Complete API response logged to: " . $response_log_file);
}
if ($code >= 200 && $code < 300) {
if ($with_response) {
// Handle API response test
$response_data = json_decode($body, true);
if (isset($response_data['choices'][0]['message']['content'])) {
$response_text = trim($response_data['choices'][0]['message']['content']);
// Extract token usage information
$input_tokens = $response_data['usage']['prompt_tokens'] ?? 0;
$output_tokens = $response_data['usage']['completion_tokens'] ?? 0;
$total_tokens = $response_data['usage']['total_tokens'] ?? 0;
// Calculate cost using model rates
$rates = igny8_get_model_rates($model);
$cost = ($input_tokens * $rates['in'] + $output_tokens * $rates['out']) / 1000000;
return [
'success' => true,
'message' => 'API connection and response test successful!',
'model_used' => $model,
'response' => $response_text,
'tokens_used' => $input_tokens . ' / ' . $output_tokens,
'total_tokens' => $total_tokens,
'cost' => '$' . number_format($cost, 4),
'full_response' => $response_data
];
} else {
return [
'success' => false,
'message' => 'API responded but no content received',
'response' => $body
];
}
} else {
// Handle simple connection test
return [
'success' => true,
'message' => 'API connection successful!',
'model_used' => $model,
'response' => 'Connection verified without API call'
];
}
} else {
return [
'success' => false,
'message' => 'HTTP ' . $code . ' ' . $body
];
}
}
/**
* Log API call with cost calculation and error handling
*/
function igny8_log_api_call($model, $input_tokens, $output_tokens, $api_id = null, $status = 'success', $error_message = '') {
global $wpdb;
try {
// Calculate cost using model rates
$cost_data = igny8_calculate_api_cost($model, $input_tokens, $output_tokens);
// Debug logging for cost calculation
error_log("Igny8 Cost Debug: Model=$model, Input=$input_tokens, Output=$output_tokens");
error_log("Igny8 Cost Debug: Calculated total_cost=" . $cost_data['total_cost']);
// Prepare log data with sanitization
$log_data = [
'event_type' => 'api_call',
'api_id' => $api_id ? esc_sql($api_id) : null,
'status' => esc_sql($status),
'level' => $status === 'success' ? 'info' : 'error',
'message' => sprintf(
'Model: %s | Input: %d tokens | Output: %d tokens | Cost: %s',
esc_sql($model),
intval($input_tokens),
intval($output_tokens),
igny8_format_cost($cost_data['total_cost'])
),
'context' => wp_json_encode([
'model' => $model,
'input_tokens' => intval($input_tokens),
'output_tokens' => intval($output_tokens),
'total_cost' => $cost_data['total_cost'],
'input_cost' => $cost_data['input_cost'],
'output_cost' => $cost_data['output_cost'],
'error_message' => $error_message
]),
'source' => 'openai_api',
'user_id' => get_current_user_id(),
'created_at' => current_time('mysql')
];
// Insert with error handling
$result = $wpdb->insert(
$wpdb->prefix . 'igny8_logs',
$log_data,
['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s']
);
if ($result === false) {
error_log('Igny8 API Logging Error: ' . $wpdb->last_error);
} else {
error_log("Igny8 Cost Debug: Successfully stored cost=" . $cost_data['total_cost'] . " in database");
}
// Maintain 50 row limit for performance
igny8_maintain_logs_limit();
} catch (Exception $e) {
error_log('Igny8 API Logging Exception: ' . $e->getMessage());
}
}
/**
* Maintain logs table limit for performance
*/
function igny8_maintain_logs_limit() {
global $wpdb;
// Keep only the 50 most recent logs
$wpdb->query("
DELETE FROM {$wpdb->prefix}igny8_logs
WHERE id NOT IN (
SELECT id FROM (
SELECT id FROM {$wpdb->prefix}igny8_logs
ORDER BY created_at DESC
LIMIT 50
) AS latest_logs
)
");
}
/**
* Call OpenAI API for content generation
*/
function igny8_call_openai($prompt, $api_key, $model) {
// Debug logging for CRON context
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: Starting API call - Model: " . $model . ", Prompt length: " . strlen($prompt));
}
$body_data = [
'model' => $model,
'messages' => [['role' => 'user', 'content' => $prompt]],
];
// Model-specific parameters
$body_data['temperature'] = 0.7;
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: Request body prepared - Temperature: " . $body_data['temperature']);
}
// Log the complete request to file
$log_data = [
'timestamp' => current_time('mysql'),
'model' => $model,
'request_body' => $body_data,
'headers' => [
'Authorization' => 'Bearer ' . substr($api_key, 0, 10) . '...',
'Content-Type' => 'application/json'
],
'prompt_length' => strlen($prompt),
'prompt_preview' => substr($prompt, 0, 200) . '...'
];
$log_file = ABSPATH . 'igny8_all_api_requests.json';
// Read existing logs and append new one
$existing_logs = [];
if (file_exists($log_file)) {
$existing_content = file_get_contents($log_file);
if (!empty($existing_content)) {
$existing_logs = json_decode($existing_content, true) ?: [];
}
}
// Add new request to logs
$existing_logs[] = $log_data;
// Keep only last 50 requests to prevent file from growing too large
if (count($existing_logs) > 50) {
$existing_logs = array_slice($existing_logs, -50);
}
file_put_contents($log_file, json_encode($existing_logs, JSON_PRETTY_PRINT));
error_log("Igny8 Debug: API request logged to: " . $log_file);
$args = [
'body' => json_encode($body_data),
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $api_key,
],
'timeout' => 60,
];
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: Making HTTP request to OpenAI API...");
}
$response = wp_remote_post('https://api.openai.com/v1/chat/completions', $args);
if (is_wp_error($response)) {
// Log API error with detailed information
$error_message = $response->get_error_message();
$error_code = $response->get_error_code();
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: HTTP request failed - " . $error_message);
}
// Enhanced error logging
igny8_log_api_call($model, 0, 0, null, 'error', $error_message);
// Log detailed error information
$error_details = [
'error_code' => $error_code,
'error_message' => $error_message,
'model' => $model,
'api_key_configured' => !empty($api_key),
'prompt_length' => strlen($prompt),
'timestamp' => current_time('mysql'),
'request_url' => 'https://api.openai.com/v1/chat/completions'
];
// Log to AI events for debug module
igny8_log_ai_event('OpenAI HTTP Error', 'ai', 'api_call', 'error', 'HTTP request failed', 'Error: ' . $error_message . ' | Details: ' . json_encode($error_details));
return 'Error: ' . $error_message;
}
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: HTTP request successful, processing response...");
}
$response_code = wp_remote_retrieve_response_code($response);
$response_body = wp_remote_retrieve_body($response);
$response_data = json_decode($response_body, true);
// Check for HTTP errors (non-200 status codes)
if ($response_code !== 200) {
$error_message = "HTTP {$response_code} error";
if (isset($response_data['error']['message'])) {
$error_message .= ": " . $response_data['error']['message'];
}
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: HTTP error - " . $error_message);
}
// Log detailed HTTP error
$error_details = [
'http_code' => $response_code,
'error_message' => $error_message,
'model' => $model,
'api_key_configured' => !empty($api_key),
'response_body' => $response_body,
'timestamp' => current_time('mysql')
];
igny8_log_ai_event('OpenAI HTTP Error', 'ai', 'api_call', 'error', 'HTTP ' . $response_code . ' error', 'Error: ' . $error_message . ' | Details: ' . json_encode($error_details));
return 'Error: ' . $error_message;
}
if (defined('DOING_CRON') && DOING_CRON) {
error_log("Igny8 OpenAI Call: Response decoded - Has data: " . ($response_data ? 'Yes' : 'No'));
if ($response_data && isset($response_data['choices'])) {
error_log("Igny8 OpenAI Call: Response has " . count($response_data['choices']) . " choices");
}
}
// Log the complete response to file
$response_log_data = [
'timestamp' => current_time('mysql'),
'model' => $model,
'response_code' => wp_remote_retrieve_response_code($response),
'response_body' => $response_data,
'raw_response' => $response_body
];
$response_log_file = ABSPATH . 'igny8_all_api_responses.json';
// Read existing response logs and append new one
$existing_response_logs = [];
if (file_exists($response_log_file)) {
$existing_content = file_get_contents($response_log_file);
if (!empty($existing_content)) {
$existing_response_logs = json_decode($existing_content, true) ?: [];
}
}
// Add new response to logs
$existing_response_logs[] = $response_log_data;
// Keep only last 50 responses to prevent file from growing too large
if (count($existing_response_logs) > 50) {
$existing_response_logs = array_slice($existing_response_logs, -50);
}
file_put_contents($response_log_file, json_encode($existing_response_logs, JSON_PRETTY_PRINT));
error_log("Igny8 Debug: API response logged to: " . $response_log_file);
// Extract API response data for logging
$api_id = $response_data['id'] ?? null;
$usage = $response_data['usage'] ?? [];
$input_tokens = $usage['prompt_tokens'] ?? 0;
$output_tokens = $usage['completion_tokens'] ?? 0;
// Log successful API call
igny8_log_api_call($model, $input_tokens, $output_tokens, $api_id, 'success');
return $response_data['choices'][0]['message']['content'] ?? 'No response.';
}
/**
* Get content scope based on settings
*/
function igny8_get_content_scope($post_id, $scope) {
$content = igny8_build_combined_content(true);
return $content;
}
/**
* Generate personalized content
*/
function igny8_generate_content($post_id, $field_inputs, $options = []) {
global $wpdb;
$api_key = get_option('igny8_api_key');
$model = get_option('igny8_model', 'gpt-4.1');
if (empty($api_key)) {
return ['success' => false, 'message' => 'OpenAI API key not configured'];
}
// Build inputs string
$inputs_string = '';
foreach ($field_inputs as $key => $value) {
if ($key !== 'PageContent' && !empty($value)) {
$inputs_string .= ucfirst($key) . ': ' . $value . "\n";
}
}
// Get content
$content = igny8_build_combined_content(false, $post_id);
// Get rewrite prompt
$rewrite_prompt = get_option('igny8_content_engine_rewrite_prompt', 'Rewrite the following content to be personalized for a reader with these characteristics:
[INPUTS]
Original content:
[CONTENT]
Make the content feel like it was written specifically for this person while maintaining the original message and tone.');
$prompt = str_replace(['[INPUTS]', '[CONTENT]'], [$inputs_string, $content], $rewrite_prompt);
// Log the final prompt being sent to OpenAI
igny8_log_field_detection_process('INFO', 'Final prompt being sent to OpenAI:');
igny8_log_field_detection_process('INFO', 'INPUTS: ' . $inputs_string);
igny8_log_field_detection_process('INFO', 'CONTENT: ' . substr($content, 0, 200) . '...');
igny8_log_field_detection_process('INFO', 'PROMPT: ' . substr($prompt, 0, 500) . '...');
// Call OpenAI
$generated_content = igny8_call_openai($prompt, $api_key, $model);
if (strpos($generated_content, 'Error:') === 0) {
return ['success' => false, 'message' => $generated_content];
}
// Save variation if requested
$variation_id = null;
if ($options['save_variation'] ?? false) {
$variation_id = igny8_save_variation($post_id, $field_inputs, $generated_content);
}
return [
'success' => true,
'content' => $generated_content,
'variation_id' => $variation_id,
'message' => 'Content generated successfully'
];
}
/**
* Save content variation
*/
function igny8_save_variation($post_id, $field_inputs, $content) {
global $wpdb;
$fields_hash = md5(wp_json_encode($field_inputs));
$fields_json = wp_json_encode($field_inputs);
// Check if variation already exists
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM {$wpdb->prefix}igny8_variations WHERE post_id = %d AND fields_hash = %s",
$post_id, $fields_hash
));
if ($existing) {
// Update existing variation
$wpdb->update(
$wpdb->prefix . 'igny8_variations',
[
'content' => $content,
'created_at' => current_time('mysql')
],
['id' => $existing],
['%s', '%s'],
['%d']
);
return $existing;
} else {
// Insert new variation
$wpdb->insert(
$wpdb->prefix . 'igny8_variations',
[
'post_id' => $post_id,
'fields_hash' => $fields_hash,
'fields_json' => $fields_json,
'content' => $content,
'created_at' => current_time('mysql')
],
['%d', '%s', '%s', '%s', '%s']
);
return $wpdb->insert_id;
}
}
/**
* Get cached variation
*/
function igny8_get_cached_variation($post_id, $field_inputs) {
global $wpdb;
$fields_hash = md5(wp_json_encode($field_inputs));
$variation = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}igny8_variations WHERE post_id = %d AND fields_hash = %s",
$post_id, $fields_hash
));
return $variation ? (array) $variation : null;
}
/**
* Register shortcode [igny8]
*/
/**
* Automatically inject Igny8 shortcode into content
*/
function igny8_inject_shortcode_into_content($content) {
// Only run on frontend
if (is_admin()) {
return $content;
}
// Check if Content Engine is enabled globally
$global_status = get_option('igny8_content_engine_global_status', 'enabled');
if ($global_status !== 'enabled') {
return $content;
}
// Get current post type
$post_type = get_post_type();
if (!$post_type) {
return $content;
}
// Check if this post type is enabled for personalization
$enabled_post_types = get_option('igny8_content_engine_enabled_post_types', []);
if (!in_array($post_type, $enabled_post_types)) {
return $content;
}
// Get insertion position
$insertion_position = get_option('igny8_content_engine_insertion_position', 'before');
// Get display mode
$display_mode = get_option('igny8_content_engine_display_mode', 'always');
// Check if we should show personalization based on display mode
if ($display_mode === 'logged_in' && !is_user_logged_in()) {
return $content;
}
if ($display_mode === 'logged_out' && is_user_logged_in()) {
return $content;
}
// Inject shortcode based on position
$shortcode = '[igny8]';
switch ($insertion_position) {
case 'before':
return $shortcode . $content;
case 'after':
return $content . $shortcode;
case 'replace':
return $shortcode;
default:
return $shortcode . $content;
}
}
// Hook into the_content filter
add_filter('the_content', 'igny8_inject_shortcode_into_content');
// Register AJAX actions
add_action('wp_ajax_igny8_get_fields', 'igny8_ajax_get_fields');
add_action('wp_ajax_nopriv_igny8_get_fields', 'igny8_ajax_get_fields');
add_action('wp_ajax_igny8_generate_custom', 'igny8_ajax_generate_custom');
add_action('wp_ajax_nopriv_igny8_generate_custom', 'igny8_ajax_generate_custom');
add_action('wp_ajax_igny8_save_content_manual', 'igny8_ajax_save_content_manual');
add_action('wp_ajax_nopriv_igny8_save_content_manual', 'igny8_ajax_save_content_manual');
add_action('wp_ajax_igny8_test_personalize', 'igny8_ajax_test_personalize');
add_action('wp_ajax_nopriv_igny8_test_personalize', 'igny8_ajax_test_personalize');
/**
* AJAX Handler for getting personalization fields
*/
function igny8_ajax_get_fields() {
try {
// Log the start of field detection process
igny8_log_field_detection_process('START', 'Field detection process initiated');
// Debug logging
error_log('IGNY8 AJAX Debug - Request method: ' . $_SERVER['REQUEST_METHOD']);
error_log('IGNY8 AJAX Debug - GET params: ' . print_r($_GET, true));
error_log('IGNY8 AJAX Debug - POST params: ' . print_r($_POST, true));
// Check nonce for security - handle both GET and POST
$nonce_param = isset($_GET['nonce']) ? $_GET['nonce'] : (isset($_POST['nonce']) ? $_POST['nonce'] : '');
if (!wp_verify_nonce($nonce_param, 'igny8_ajax_nonce')) {
igny8_log_field_detection_process('ERROR', 'Security check failed - invalid nonce');
wp_send_json_error('Security check failed - invalid nonce');
}
$post_id = isset($_GET['post_id']) ? absint($_GET['post_id']) : 0;
$form_fields = isset($_GET['form_fields']) ? sanitize_text_field($_GET['form_fields']) : '';
if (!$post_id) {
igny8_log_field_detection_process('ERROR', 'Invalid post ID: ' . $post_id);
wp_send_json_error('Invalid post ID');
}
igny8_log_field_detection_process('INFO', 'Processing post ID: ' . $post_id);
// Get content for field detection
$content = igny8_build_combined_content(true, $post_id);
if (empty($content)) {
igny8_log_field_detection_process('ERROR', 'No content found for field detection');
wp_send_json_error('No content found for field detection');
}
igny8_log_field_detection_process('INFO', 'Content retrieved successfully. Length: ' . strlen($content));
// Check if field detection is enabled
$field_mode = get_option('igny8_content_engine_field_mode', 'auto');
igny8_log_field_detection_process('INFO', 'Field detection mode: ' . $field_mode);
if ($field_mode === 'auto') {
// Use AI to detect fields
igny8_log_field_detection_process('INFO', 'Starting AI field detection');
$api_key = get_option('igny8_api_key');
$model = get_option('igny8_model', 'gpt-4.1');
$detection_prompt = get_option('igny8_content_engine_detection_prompt', '');
if (empty($api_key)) {
igny8_log_field_detection_process('ERROR', 'OpenAI API key not configured');
wp_send_json_error('OpenAI API key not configured. Please set it in Personalize > Settings.');
}
if (empty($detection_prompt)) {
igny8_log_field_detection_process('ERROR', 'Detection prompt not configured');
wp_send_json_error('Detection prompt not configured. Please set it in Personalize > Settings.');
}
// Replace [CONTENT] placeholder in prompt
$prompt = str_replace('[CONTENT]', $content, $detection_prompt);
igny8_log_field_detection_process('INFO', 'Prompt prepared for OpenAI API');
// Call OpenAI for field detection
$response = igny8_call_openai($prompt, $api_key, $model, 1000);
if (strpos($response, 'Error:') === 0) {
igny8_log_field_detection_process('ERROR', 'OpenAI API error: ' . $response);
$fields = []; // Fallback to empty fields on API error
} else {
igny8_log_field_detection_process('INFO', 'OpenAI API response received successfully');
// Try to parse the JSON response
$fields_data = json_decode($response, true);
if ($fields_data) {
// Handle both formats: array of fields or object with fields property
if (is_array($fields_data) && isset($fields_data[0]) && is_array($fields_data[0])) {
// Direct array format: [field1, field2, ...]
$fields = $fields_data;
igny8_log_field_detection_process('SUCCESS', 'Fields detected successfully (array format): ' . count($fields) . ' fields');
} elseif (isset($fields_data['fields']) && is_array($fields_data['fields'])) {
// Object format: {fields: [field1, field2, ...]}
$fields = $fields_data['fields'];
igny8_log_field_detection_process('SUCCESS', 'Fields detected successfully (object format): ' . count($fields) . ' fields');
} else {
igny8_log_field_detection_process('ERROR', 'Invalid JSON structure - neither array nor object with fields property');
igny8_log_field_detection_process('ERROR', 'Raw OpenAI response: ' . $response);
$fields = []; // Fallback to empty fields
}
// Log each detected field
if (!empty($fields)) {
foreach ($fields as $field) {
igny8_log_field_detection_process('FIELD', 'Detected field: ' . $field['label'] . ' (type: ' . $field['type'] . ')');
}
}
} else {
igny8_log_field_detection_process('ERROR', 'Failed to parse OpenAI response as valid JSON');
igny8_log_field_detection_process('ERROR', 'Raw OpenAI response: ' . $response);
$fields = []; // Fallback to empty fields
}
}
} else {
// Use fixed fields from configuration
igny8_log_field_detection_process('INFO', 'Using manual field configuration');
$fields = [];
$fixed_fields_config = get_option('igny8_content_engine_fixed_fields_config', []);
if (!empty($fixed_fields_config)) {
// Use the configured fields directly
$fields = $fixed_fields_config;
igny8_log_field_detection_process('SUCCESS', 'Using configured fields: ' . count($fields) . ' fields');
} elseif (!empty($form_fields)) {
// Fallback to form_fields parameter if no config
$field_names = explode(',', $form_fields);
foreach ($field_names as $field_name) {
$fields[] = [
'label' => trim($field_name),
'type' => 'text',
'options' => 'Example 1, Example 2'
];
}
igny8_log_field_detection_process('INFO', 'Using fallback fields from parameter: ' . count($fields) . ' fields');
}
}
// If no fields were generated, provide a fallback
if (empty($fields)) {
igny8_log_field_detection_process('ERROR', 'No fields could be generated');
// Provide more detailed error information
$error_details = [
'field_mode' => $field_mode,
'api_key_set' => !empty(get_option('igny8_api_key')),
'detection_prompt_set' => !empty(get_option('igny8_content_engine_detection_prompt')),
'content_length' => strlen($content),
'post_id' => $post_id
];
igny8_log_field_detection_process('ERROR', 'Field generation failed - Details: ' . json_encode($error_details));
wp_send_json_error([
'message' => 'No fields could be generated. Please check your settings and try again.',
'details' => $error_details
]);
}
igny8_log_field_detection_process('INFO', 'Generating form HTML for ' . count($fields) . ' fields');
// Generate form HTML with progress messages
ob_start();
?>
<div class="igny8-field-detection-results">
<div class="igny8-detection-status">
<div class="igny8-status-message igny8-success">
✅ <strong>Field Detection Complete!</strong> Found <?php echo count($fields); ?> personalization fields.
</div>
<div class="igny8-detection-details">
<small>
<?php if ($field_mode === 'auto'): ?>
Fields were automatically detected using AI analysis of your content.
<?php else: ?>
Fields were loaded from your manual configuration.
<?php endif; ?>
</small>
</div>
</div>
<form id="igny8-form" method="post">
<div class="igny8-form-fields">
<?php foreach ($fields as $index => $field): ?>
<div class="igny8-form-field">
<label for="igny8-field-<?php echo esc_attr(sanitize_title($field['label'])); ?>">
<?php echo esc_html($field['label']); ?>
<?php if ($field_mode === 'auto'): ?>
<span class="igny8-field-source">🤖 AI Detected</span>
<?php endif; ?>
</label>
<?php if ($field['type'] === 'select' && isset($field['options'])): ?>
<select name="<?php echo esc_attr($field['label']); ?>" id="igny8-field-<?php echo esc_attr(sanitize_title($field['label'])); ?>">
<option value="">Choose your <?php echo esc_html(strtolower($field['label'])); ?>...</option>
<?php
$options = is_array($field['options']) ? $field['options'] : explode(',', $field['options']);
foreach ($options as $option):
$option = trim($option);
if (!empty($option)):
?>
<option value="<?php echo esc_attr($option); ?>"><?php echo esc_html($option); ?></option>
<?php
endif;
endforeach;
?>
</select>
<?php else: ?>
<?php
$placeholder = '';
if (isset($field['examples']) && is_array($field['examples'])) {
$placeholder = 'e.g. ' . implode(', ', array_filter($field['examples']));
} elseif (isset($field['options'])) {
$placeholder = 'e.g. ' . $field['options'];
}
if (empty($placeholder)) {
$placeholder = 'Enter your ' . strtolower($field['label']);
}
?>
<input type="text"
name="<?php echo esc_attr($field['label']); ?>"
id="igny8-field-<?php echo esc_attr(sanitize_title($field['label'])); ?>"
placeholder="<?php echo esc_attr($placeholder); ?>"
required>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<div class="igny8-form-actions">
<button type="submit" class="button igny8-generate-btn">
<span class="igny8-btn-text">Generate Personalized Content</span>
<span class="igny8-btn-icon">✨</span>
</button>
</div>
</form>
</div>
<style>
.igny8-field-detection-results {
margin: 20px 0;
padding: 20px;
border: 1px solid #e1e5e9;
border-radius: 8px;
background: #f8f9fa;
}
.igny8-detection-status {
margin-bottom: 20px;
padding: 15px;
border-radius: 6px;
background: #d4edda;
border: 1px solid #c3e6cb;
}
.igny8-status-message {
font-size: 16px;
margin-bottom: 8px;
}
.igny8-status-message.igny8-success {
color: #155724;
}
.igny8-detection-details {
color: #6c757d;
font-size: 14px;
}
.igny8-field-source {
font-size: 12px;
color: #007cba;
font-weight: normal;
margin-left: 8px;
}
.igny8-form-field {
margin: 15px 0;
}
.igny8-form-field label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #333;
}
.igny8-form-field input,
.igny8-form-field select {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
transition: border-color 0.3s ease;
}
.igny8-form-field input:focus,
.igny8-form-field select:focus {
outline: none;
border-color: #007cba;
box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.2);
}
.igny8-generate-btn {
background: linear-gradient(135deg, #007cba 0%, #005a87 100%);
color: white;
border: none;
padding: 15px 30px;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 8px;
}
.igny8-generate-btn:hover {
background: linear-gradient(135deg, #005a87 0%, #004466 100%);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 124, 186, 0.3);
}
.igny8-btn-icon {
font-size: 18px;
}
</style>
<?php
$form_html = ob_get_clean();
igny8_log_field_detection_process('SUCCESS', 'Form HTML generated successfully');
wp_send_json_success($form_html);
} catch (Exception $e) {
igny8_log_field_detection_process('ERROR', 'Exception occurred: ' . $e->getMessage());
error_log('Igny8 AJAX Error: ' . $e->getMessage());
error_log('Igny8 AJAX Trace: ' . $e->getTraceAsString());
wp_send_json_error('Error: ' . $e->getMessage());
}
}
/**
* AJAX Handler for generating personalized content
*/
function igny8_ajax_generate_custom() {
try {
// Log the start of content generation process
igny8_log_field_detection_process('START', 'Content generation process initiated');
// Check nonce for security
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce')) {
igny8_log_field_detection_process('ERROR', 'Security check failed for content generation');
wp_send_json_error('Security check failed');
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
if (!$post_id) {
igny8_log_field_detection_process('ERROR', 'Invalid post ID for content generation: ' . $post_id);
wp_send_json_error('Invalid post ID');
}
igny8_log_field_detection_process('INFO', 'Generating content for post ID: ' . $post_id);
// Get field inputs from form
$field_inputs = [];
foreach ($_POST as $key => $value) {
if ($key !== 'action' && $key !== 'nonce' && $key !== 'post_id') {
$field_inputs[sanitize_text_field($key)] = sanitize_text_field($value);
}
}
igny8_log_field_detection_process('INFO', 'Field inputs collected: ' . count($field_inputs) . ' fields');
// Log each field input
foreach ($field_inputs as $key => $value) {
igny8_log_field_detection_process('FIELD', 'Field input: ' . $key . ' = ' . $value);
}
// Generate personalized content
igny8_log_field_detection_process('INFO', 'Starting OpenAI content generation');
$result = igny8_generate_content($post_id, $field_inputs, []);
if ($result['success']) {
igny8_log_field_detection_process('SUCCESS', 'Content generated successfully. Length: ' . strlen($result['content']));
// Return enhanced content with generation details
$enhanced_content = '
<div class="igny8-content-generation-results">
<div class="igny8-generation-status">
<div class="igny8-status-message igny8-success">
✨ <strong>Personalized Content Generated!</strong>
</div>
<div class="igny8-generation-details">
<small>
Content was personalized using AI based on your inputs.
Generated on ' . current_time('F j, Y \a\t g:i A') . '
</small>
</div>
</div>
<div class="igny8-personalized-content">
<div class="igny8-content-body">
' . wp_kses_post($result['content']) . '
</div>
' . (current_user_can('manage_options') ? '
<div class="igny8-content-actions">
<button type="button" class="button igny8-save-btn" onclick="igny8SaveContent(' . $post_id . ', this, ' . json_encode($field_inputs) . ')">
<span class="igny8-btn-text">Save This Content</span>
<span class="igny8-btn-icon">💾</span>
</button>
<button type="button" class="button igny8-regenerate-btn" onclick="igny8RegenerateContent()">
<span class="igny8-btn-text">Regenerate</span>
<span class="igny8-btn-icon">🔄</span>
</button>
</div>' : '') . '
</div>
</div>
<style>
.igny8-content-generation-results {
margin: 20px 0;
}
.igny8-generation-status {
margin-bottom: 20px;
padding: 15px;
border-radius: 6px;
background: #d4edda;
border: 1px solid #c3e6cb;
}
.igny8-status-message {
font-size: 16px;
margin-bottom: 8px;
}
.igny8-status-message.igny8-success {
color: #155724;
}
.igny8-generation-details {
color: #6c757d;
font-size: 14px;
}
.igny8-personalized-content {
border: 1px solid #e1e5e9;
border-radius: 8px;
background: #ffffff;
overflow: hidden;
}
.igny8-content-body {
padding: 25px;
line-height: 1.8;
font-size: 16px;
color: #333;
}
.igny8-content-actions {
padding: 20px 25px;
border-top: 1px solid #e1e5e9;
background: #f8f9fa;
display: flex;
gap: 15px;
align-items: center;
}
.igny8-save-btn, .igny8-regenerate-btn {
background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 6px;
}
.igny8-regenerate-btn {
background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
}
.igny8-save-btn:hover {
background: linear-gradient(135deg, #1e7e34 0%, #155724 100%);
transform: translateY(-1px);
box-shadow: 0 3px 8px rgba(40, 167, 69, 0.3);
}
.igny8-regenerate-btn:hover {
background: linear-gradient(135deg, #495057 0%, #343a40 100%);
transform: translateY(-1px);
box-shadow: 0 3px 8px rgba(108, 117, 125, 0.3);
}
.igny8-btn-icon {
font-size: 16px;
}
</style>';
wp_send_json_success($enhanced_content);
} else {
igny8_log_field_detection_process('ERROR', 'Content generation failed: ' . $result['message']);
wp_send_json_error($result['message']);
}
} catch (Exception $e) {
igny8_log_field_detection_process('ERROR', 'Exception in content generation: ' . $e->getMessage());
error_log('Igny8 Content Generation Error: ' . $e->getMessage());
error_log('Igny8 Content Generation Trace: ' . $e->getTraceAsString());
wp_send_json_error('Error: ' . $e->getMessage());
}
}
/**
* AJAX Handler for saving content manually
*/
function igny8_ajax_save_content_manual() {
try {
// Check nonce for security
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce')) {
wp_send_json_error('Security check failed');
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
$content = isset($_POST['content']) ? wp_kses_post($_POST['content']) : '';
$field_inputs = isset($_POST['field_inputs']) ? json_decode(stripslashes($_POST['field_inputs']), true) : [];
if (!$post_id || empty($content)) {
wp_send_json_error('Invalid post ID or content');
}
// Save content variation
$result = igny8_save_variation($post_id, $field_inputs, $content);
if ($result) {
wp_send_json_success('Content saved successfully');
} else {
wp_send_json_error('Failed to save content');
}
} catch (Exception $e) {
wp_send_json_error('Error: ' . $e->getMessage());
}
}
/**
* Simple test AJAX handler
*/
function igny8_ajax_test_personalize() {
try {
// Check nonce for security
$nonce_param = isset($_GET['nonce']) ? $_GET['nonce'] : (isset($_POST['nonce']) ? $_POST['nonce'] : '');
if (!wp_verify_nonce($nonce_param, 'igny8_ajax_nonce')) {
wp_send_json_error('Security check failed - invalid nonce');
}
wp_send_json_success([
'message' => 'Personalization AJAX is working!',
'post_id' => get_queried_object_id(),
'timestamp' => current_time('mysql')
]);
} catch (Exception $e) {
wp_send_json_error('Error: ' . $e->getMessage());
}
}
/**
* AJAX Handler for testing API connection
*/
function igny8_ajax_test_api() {
// Check nonce for security
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'igny8_ajax_nonce')) {
wp_send_json_error('Security check failed');
}
// Check permissions
if (!current_user_can('edit_posts')) {
wp_send_json_error('Insufficient permissions');
}
// Get API key
$api_key = get_option('igny8_api_key', '');
if (empty($api_key)) {
wp_send_json_error(['message' => 'API key not configured']);
}
// Check if response test is requested
$with_response = isset($_POST['with_response']) && $_POST['with_response'] === '1';
// Test the connection
$result = igny8_test_connection($api_key, $with_response);
// Handle the new response format
if (is_array($result)) {
if ($result['success']) {
$response_data = [
'message' => $result['message'],
'model_used' => $result['model_used'],
'response' => $result['response']
];
// Add cost and token information if available
if (isset($result['full_response']['usage'])) {
$usage = $result['full_response']['usage'];
$model = $result['model_used'];
$cost_data = igny8_calculate_api_cost($model, $usage['prompt_tokens'], $usage['completion_tokens']);
$response_data['tokens'] = $usage['prompt_tokens'] . ' / ' . $usage['completion_tokens'];
$response_data['cost'] = igny8_format_cost($cost_data['total_cost']);
}
wp_send_json_success($response_data);
} else {
wp_send_json_error([
'message' => $result['message'],
'details' => $result['response'] ?? ''
]);
}
} else {
// Handle legacy string responses
if ($result === true) {
wp_send_json_success(['message' => 'Connection successful']);
} else {
$error_message = is_string($result) ? $result : 'Connection failed';
wp_send_json_error(['message' => $error_message]);
}
}
}
// Register the test AJAX handler
add_action('wp_ajax_igny8_test_personalize', 'igny8_ajax_test_personalize');
add_action('wp_ajax_nopriv_igny8_test_personalize', 'igny8_ajax_test_personalize');
// Register the API test AJAX handler
add_action('wp_ajax_igny8_test_api', 'igny8_ajax_test_api');
// Register the test field detection AJAX handler
add_action('wp_ajax_igny8_test_field_detection', 'igny8_ajax_test_field_detection');
// Register debug AJAX handler
add_action('wp_ajax_igny8_debug_personalization', 'igny8_ajax_debug_personalization');
add_action('wp_ajax_nopriv_igny8_debug_personalization', 'igny8_ajax_debug_personalization');
// Register test field detection with sample content
add_action('wp_ajax_igny8_test_sample_field_detection', 'igny8_ajax_test_sample_field_detection');
// Register save variation AJAX handler
add_action('wp_ajax_igny8_save_variation', 'igny8_ajax_save_variation');
/**
* AJAX Handler for testing field detection
*/
function igny8_ajax_test_field_detection() {
try {
// Check nonce for security
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce')) {
wp_send_json_error('Security check failed');
}
// Check permissions
if (!current_user_can('edit_posts')) {
wp_send_json_error('Insufficient permissions');
}
$content = isset($_POST['content']) ? sanitize_textarea_field($_POST['content']) : '';
if (empty($content)) {
wp_send_json_error('No content provided for testing');
}
// Log the test
igny8_log_field_detection_process('INFO', 'Field detection test initiated by admin');
// Check if field detection is enabled
$field_mode = get_option('igny8_content_engine_field_mode', 'auto');
if ($field_mode === 'auto') {
// Use AI to detect fields
$api_key = get_option('igny8_api_key');
$model = get_option('igny8_model', 'gpt-4.1');
$detection_prompt = get_option('igny8_content_engine_detection_prompt', '');
if (empty($api_key)) {
wp_send_json_error('OpenAI API key not configured');
}
if (empty($detection_prompt)) {
wp_send_json_error('Detection prompt not configured');
}
// Replace [CONTENT] placeholder in prompt
$prompt = str_replace('[CONTENT]', $content, $detection_prompt);
// Call OpenAI for field detection
$response = igny8_call_openai($prompt, $api_key, $model, 1000);
if (strpos($response, 'Error:') === 0) {
wp_send_json_error('OpenAI API error: ' . $response);
} else {
// Try to parse the JSON response
$fields_data = json_decode($response, true);
if ($fields_data) {
// Handle both formats: array of fields or object with fields property
if (is_array($fields_data) && isset($fields_data[0]) && is_array($fields_data[0])) {
// Direct array format: [field1, field2, ...] - convert to expected format
$fields_data = ['fields' => $fields_data];
igny8_log_field_detection_process('SUCCESS', 'Test field detection successful (array format): ' . count($fields_data['fields']) . ' fields detected');
} elseif (isset($fields_data['fields']) && is_array($fields_data['fields'])) {
// Object format: {fields: [field1, field2, ...]}
igny8_log_field_detection_process('SUCCESS', 'Test field detection successful (object format): ' . count($fields_data['fields']) . ' fields detected');
} else {
igny8_log_field_detection_process('ERROR', 'Test field detection failed: Invalid JSON structure');
wp_send_json_error('Invalid JSON structure - neither array nor object with fields property');
}
wp_send_json_success($fields_data);
} else {
igny8_log_field_detection_process('ERROR', 'Test field detection failed: Invalid JSON response');
wp_send_json_error('Failed to parse OpenAI response as valid JSON');
}
}
} else {
// Use fixed fields from configuration
$fixed_fields_config = get_option('igny8_content_engine_fixed_fields_config', []);
if (!empty($fixed_fields_config)) {
$fields_data = ['fields' => $fixed_fields_config];
igny8_log_field_detection_process('SUCCESS', 'Test field detection successful: ' . count($fixed_fields_config) . ' configured fields');
wp_send_json_success($fields_data);
} else {
igny8_log_field_detection_process('ERROR', 'Test field detection failed: No configured fields');
wp_send_json_error('No fields configured for manual mode');
}
}
} catch (Exception $e) {
igny8_log_field_detection_process('ERROR', 'Exception in test field detection: ' . $e->getMessage());
wp_send_json_error('Error: ' . $e->getMessage());
}
}
/**
* Debug AJAX handler to check personalization setup
*/
function igny8_ajax_debug_personalization() {
try {
// Check nonce for security
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce')) {
wp_send_json_error('Security check failed');
}
$debug_info = [
'timestamp' => current_time('mysql'),
'wordpress_version' => get_bloginfo('version'),
'plugin_version' => get_option('igny8_version', 'unknown'),
'current_user' => wp_get_current_user()->user_login,
'is_admin' => current_user_can('manage_options'),
'ajax_url' => admin_url('admin-ajax.php'),
'post_id' => get_queried_object_id(),
'post_type' => get_post_type(),
];
// Check Content Engine settings
$debug_info['content_engine'] = [
'global_status' => get_option('igny8_content_engine_global_status', 'not_set'),
'enabled_post_types' => get_option('igny8_content_engine_enabled_post_types', []),
'display_mode' => get_option('igny8_content_engine_display_mode', 'not_set'),
'insertion_position' => get_option('igny8_content_engine_insertion_position', 'not_set'),
'teaser_text' => get_option('igny8_content_engine_teaser_text', 'not_set'),
'field_mode' => get_option('igny8_content_engine_field_mode', 'not_set'),
'detection_prompt' => get_option('igny8_content_engine_detection_prompt', 'not_set'),
'api_key_set' => !empty(get_option('igny8_api_key', '')),
'model' => get_option('igny8_model', 'not_set'),
];
// Check if shortcode would be injected
$debug_info['shortcode_injection'] = [
'content_filter_active' => has_filter('the_content', 'igny8_inject_shortcode_into_content'),
'would_show_personalization' => igny8_should_show_personalization(),
'post_type_enabled' => igny8_is_post_type_enabled_for_personalization(),
];
// Check database tables
global $wpdb;
$debug_info['database'] = [
'logs_table_exists' => $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}igny8_logs'") ? true : false,
'variations_table_exists' => $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}igny8_variations'") ? true : false,
'logs_count' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}igny8_logs") ?: 0,
];
wp_send_json_success($debug_info);
} catch (Exception $e) {
wp_send_json_error('Debug error: ' . $e->getMessage());
}
}
/**
* Check if personalization should be shown for current context
*/
function igny8_should_show_personalization() {
// Only run on frontend
if (is_admin()) {
return false;
}
// Check if Content Engine is enabled globally
$global_status = get_option('igny8_content_engine_global_status', 'enabled');
if ($global_status !== 'enabled') {
return false;
}
// Get current post type
$post_type = get_post_type();
if (!$post_type) {
return false;
}
// Check if this post type is enabled for personalization
$enabled_post_types = get_option('igny8_content_engine_enabled_post_types', []);
if (!in_array($post_type, $enabled_post_types)) {
return false;
}
// Get display mode
$display_mode = get_option('igny8_content_engine_display_mode', 'always');
// Check if we should show personalization based on display mode
if ($display_mode === 'logged_in' && !is_user_logged_in()) {
return false;
}
if ($display_mode === 'logged_out' && is_user_logged_in()) {
return false;
}
return true;
}
/**
* Check if current post type is enabled for personalization
*/
function igny8_is_post_type_enabled_for_personalization() {
$post_type = get_post_type();
if (!$post_type) {
return false;
}
$enabled_post_types = get_option('igny8_content_engine_enabled_post_types', []);
return in_array($post_type, $enabled_post_types);
}
/**
* Test field detection with sample cabinet content
*/
function igny8_ajax_test_sample_field_detection() {
try {
// Check nonce for security
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce')) {
wp_send_json_error('Security check failed');
}
// Check permissions
if (!current_user_can('edit_posts')) {
wp_send_json_error('Insufficient permissions');
}
// Sample cabinet content
$sample_content = "Revamp Your Space with Style and Utility Introducing our exquisite Chic Wood Countertop Cabinet, a seamless fusion of sophistication and functionality tailored for your kitchen or bathroom. Crafted with precision, this cabinet is meticulously designed to elevate your home's aesthetic while offering a streamlined solution for organizing your essentials. Highlight Features Dual Window Doors: Transparent panels provide a clear view of neatly arranged items, safeguarding them from dust and moisture. Multi-Purpose Storage: Perfect for stowing spice jars, vanity beauty essentials, and other petite necessities. Premium Wood Construction: Crafted with high-quality wood for enduring durability and a touch of natural warmth that enhances any decor. Compact Design: Tailored to fit seamlessly on countertops, delivering exceptional space-saving prowess. Where and When to Utilize? Versatile in its application, this cabinet thrives in diverse environments. Whether adorning your kitchen to keep spices and condiments accessible or gracing the bathroom to house beauty and skincare essentials, its compact stature renders it a perfect fit for small apartments, dormitories, or any space craving efficient organization.";
// Get detection prompt
$detection_prompt = get_option('igny8_content_engine_detection_prompt', '');
if (empty($detection_prompt)) {
wp_send_json_error('Detection prompt not configured');
}
// Replace [CONTENT] placeholder in prompt
$prompt = str_replace('[CONTENT]', $sample_content, $detection_prompt);
// Get API settings
$api_key = get_option('igny8_api_key');
$model = get_option('igny8_model', 'gpt-4.1');
if (empty($api_key)) {
wp_send_json_error('OpenAI API key not configured');
}
// Call OpenAI for field detection
$response = igny8_call_openai($prompt, $api_key, $model, 1000);
if (strpos($response, 'Error:') === 0) {
wp_send_json_error('OpenAI API error: ' . $response);
} else {
// Try to parse the JSON response
$fields_data = json_decode($response, true);
if ($fields_data && isset($fields_data['fields'])) {
wp_send_json_success([
'message' => 'Field detection test successful',
'sample_content' => $sample_content,
'detected_fields' => $fields_data,
'raw_response' => $response
]);
} else {
wp_send_json_error([
'message' => 'Failed to parse OpenAI response as valid JSON',
'raw_response' => $response
]);
}
}
} catch (Exception $e) {
wp_send_json_error('Error: ' . $e->getMessage());
}
}
/**
* AJAX Handler for saving content variations
*/
function igny8_ajax_save_variation() {
try {
// Check nonce for security
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce')) {
wp_send_json_error('Security check failed');
}
// Check if user has permission to save content
if (!current_user_can('manage_options')) {
wp_send_json_error('Insufficient permissions');
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
$content = isset($_POST['content']) ? wp_kses_post($_POST['content']) : '';
$field_inputs = isset($_POST['field_inputs']) ? json_decode(stripslashes($_POST['field_inputs']), true) : [];
if (!$post_id || empty($content)) {
wp_send_json_error('Missing required data');
}
// Save to variations table
global $wpdb;
$table_name = $wpdb->prefix . 'igny8_variations';
$result = $wpdb->insert(
$table_name,
[
'post_id' => $post_id,
'field_inputs' => json_encode($field_inputs),
'personalized_content' => $content,
'created_at' => current_time('mysql'),
'created_by' => get_current_user_id()
],
['%d', '%s', '%s', '%s', '%d']
);
if ($result === false) {
wp_send_json_error('Failed to save variation to database');
}
wp_send_json_success([
'variation_id' => $wpdb->insert_id,
'message' => 'Content variation saved successfully'
]);
} catch (Exception $e) {
wp_send_json_error('Error: ' . $e->getMessage());
}
}