'array',
'sanitize_callback' => array($this, 'sanitize_debug_settings'),
));
// Debug settings section
add_settings_section(
'aipa_debug_section',
__('Debug Settings', 'ai-product-assistant'),
array($this, 'debug_section_callback'),
'ai-product-assistant-debug'
);
// Debug enable/disable
add_settings_field(
'debug_enabled',
__('Enable Debug Logging', 'ai-product-assistant'),
array($this, 'debug_enabled_callback'),
'ai-product-assistant-debug',
'aipa_debug_section'
);
// Debug level
add_settings_field(
'debug_level',
__('Debug Level', 'ai-product-assistant'),
array($this, 'debug_level_callback'),
'ai-product-assistant-debug',
'aipa_debug_section'
);
// Advanced options
add_settings_field(
'debug_advanced',
__('Advanced Options', 'ai-product-assistant'),
array($this, 'debug_advanced_callback'),
'ai-product-assistant-debug',
'aipa_debug_section'
);
// Log files management
add_settings_field(
'debug_log_files',
__('Log Files', 'ai-product-assistant'),
array($this, 'debug_log_files_callback'),
'ai-product-assistant-debug',
'aipa_debug_section'
);
// Recent logs viewer
add_settings_field(
'debug_recent_logs',
__('Recent Logs', 'ai-product-assistant'),
array($this, 'debug_recent_logs_callback'),
'ai-product-assistant-debug',
'aipa_debug_section'
);
}
/**
* Debug section description
*/
public function debug_section_callback() {
echo '
' . esc_html(__('Configure debug logging to help troubleshoot issues. Debug logs are stored securely and do not contain personal data.', 'ai-product-assistant')) . '
';
// Show current status
$settings = AIPA_Debug::get_settings();
$status_class = $settings['enabled'] ? 'notice-success' : 'notice-warning';
$status_text = $settings['enabled'] ? esc_html(__('Debug logging is ENABLED', 'ai-product-assistant')) : esc_html(__('Debug logging is DISABLED', 'ai-product-assistant'));
echo '' . esc_html($status_text) . '
';
}
/**
* Debug enabled field
*/
public function debug_enabled_callback() {
$settings = AIPA_Debug::get_settings();
$enabled = $settings['enabled'];
echo '';
echo ' ';
echo ' ' . esc_html(__('Enable debug logging', 'ai-product-assistant'));
echo ' ';
echo '' . esc_html(__('When enabled, the plugin will log detailed information to help diagnose issues.', 'ai-product-assistant')) . '
';
}
/**
* Debug level field
*/
public function debug_level_callback() {
$settings = AIPA_Debug::get_settings();
$current_level = $settings['level'];
$levels = array(
AIPA_Debug::LEVEL_ERROR => __('Error Only', 'ai-product-assistant'),
AIPA_Debug::LEVEL_WARNING => __('Warning & Error', 'ai-product-assistant'),
AIPA_Debug::LEVEL_INFO => __('Info, Warning & Error', 'ai-product-assistant'),
AIPA_Debug::LEVEL_DEBUG => __('All (Debug, Info, Warning & Error)', 'ai-product-assistant')
);
echo '';
foreach ($levels as $level => $label) {
echo '' . esc_html($label) . ' ';
}
echo ' ';
echo '';
echo esc_html(__('Higher levels include more details but create larger log files.', 'ai-product-assistant'));
echo '' . esc_html(__('Recommended:', 'ai-product-assistant')) . ' ';
echo esc_html(__('Info for general troubleshooting, Debug for detailed analysis.', 'ai-product-assistant'));
echo '
';
}
/**
* Advanced debug options
*/
public function debug_advanced_callback() {
$settings = AIPA_Debug::get_settings();
echo '';
// Test debug button
echo '';
echo '' . esc_html(__('Test Debug Logging', 'ai-product-assistant')) . ' ';
echo ' ';
echo '
';
}
/**
* Log files management
*/
public function debug_log_files_callback() {
$settings = AIPA_Debug::get_settings();
if (!$settings['enabled']) {
echo '';
echo '
' . esc_html(__('Debug logging is currently disabled. Enable it above to start collecting logs.', 'ai-product-assistant')) . '
';
echo '
';
return;
}
$log_files = AIPA_Debug::get_log_files();
if (empty($log_files)) {
echo '' . esc_html(__('No log files found yet. Logs will appear here once the plugin starts logging events.', 'ai-product-assistant')) . '
';
echo '' . esc_html(__('Try performing some actions like searching for products or analyzing your cart to generate logs.', 'ai-product-assistant')) . '
';
return;
}
echo '';
echo '
';
echo '';
echo '';
echo '' . esc_html(__('File Name', 'ai-product-assistant')) . ' ';
echo '' . esc_html(__('Size', 'ai-product-assistant')) . ' ';
echo '' . esc_html(__('Modified', 'ai-product-assistant')) . ' ';
echo '' . esc_html(__('Actions', 'ai-product-assistant')) . ' ';
echo ' ';
echo ' ';
echo '';
foreach ($log_files as $file) {
echo '';
echo '' . esc_html($file['filename']) . ' ';
echo '' . esc_html($file['readable_size']) . ' ';
echo '' . esc_html($file['readable_date']) . ' ';
echo '';
echo '' . esc_html(__('View', 'ai-product-assistant')) . ' ';
echo '' . esc_html(__('Download', 'ai-product-assistant')) . ' ';
echo '' . esc_html(__('Delete', 'ai-product-assistant')) . ' ';
echo ' ';
echo ' ';
}
echo ' ';
echo '
';
// Clear all logs button
echo '
';
echo '' . esc_html(__('Clear All Logs', 'ai-product-assistant')) . ' ';
echo '
';
echo '
';
}
/**
* Recent logs viewer
*/
public function debug_recent_logs_callback() {
$settings = AIPA_Debug::get_settings();
if (!$settings['enabled']) {
echo '';
echo '
' . esc_html(__('Enable debug logging to view recent log entries.', 'ai-product-assistant')) . '
';
echo '
';
return;
}
$log_files = AIPA_Debug::get_log_files();
if (empty($log_files)) {
echo '' . esc_html(__('No recent logs available yet.', 'ai-product-assistant')) . '
';
return;
}
// Get the most recent log file
$recent_log = $log_files[0];
$content = AIPA_Debug::read_log_file($recent_log['filename'], 50); // Last 50 lines
echo '';
echo '
' . esc_html(sprintf(
/* translators: %s: log filename */
__('Last 50 lines from %s', 'ai-product-assistant'),
$recent_log['filename']
)) . ' ';
if ($content) {
echo '
';
} else {
echo '
' . esc_html(__('No content available.', 'ai-product-assistant')) . '
';
}
echo '
';
echo '' . esc_html(__('Refresh', 'ai-product-assistant')) . ' ';
echo '
';
echo '
';
// Add log viewer modal
echo '';
echo '
× ';
echo '
';
echo '';
echo '
';
echo '
';
}
/**
* AJAX: View log file
*/
public function ajax_view_log_file() {
check_ajax_referer('aipa_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
$filename = isset($_POST['filename']) ? sanitize_file_name(wp_unslash($_POST['filename'])) : '';
$content = AIPA_Debug::read_log_file($filename, 100); // Last 100 lines
if ($content !== false) {
wp_send_json_success(array(
'content' => $content,
'filename' => $filename
));
} else {
wp_send_json_error(esc_html(__('Could not read log file.', 'ai-product-assistant')));
}
}
/**
* AJAX: Delete log file
*/
public function ajax_delete_log_file() {
check_ajax_referer('aipa_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
$filename = isset($_POST['filename']) ? sanitize_file_name(wp_unslash($_POST['filename'])) : '';
if (AIPA_Debug::delete_log_file($filename)) {
wp_send_json_success(esc_html(__('Log file deleted.', 'ai-product-assistant')));
} else {
wp_send_json_error(esc_html(__('Could not delete log file.', 'ai-product-assistant')));
}
}
/**
* AJAX: Clear all logs
*/
public function ajax_clear_all_logs() {
check_ajax_referer('aipa_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
$deleted = AIPA_Debug::clear_all_logs();
wp_send_json_success(esc_html(sprintf(
/* translators: %d: number of deleted log files */
__('Deleted %d log files.', 'ai-product-assistant'),
$deleted
)));
}
/**
* AJAX: Test debug logging
*/
public function ajax_test_debug_log() {
check_ajax_referer('aipa_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
// Test all log levels
$test_data = array('test' => true, 'timestamp' => current_time('mysql'));
AIPA_Debug::error('DEBUG_TEST', 'Test error message', $test_data);
AIPA_Debug::warning('DEBUG_TEST', 'Test warning message');
AIPA_Debug::info('DEBUG_TEST', 'Test info message');
AIPA_Debug::debug('DEBUG_TEST', 'Test debug message', $test_data);
wp_send_json_success(esc_html(__('Test messages logged successfully. Check the recent logs section.', 'ai-product-assistant')));
}
/**
* Sanitize debug settings
*/
public function sanitize_debug_settings($input) {
$sanitized = array();
$sanitized['enabled'] = !empty($input['enabled']);
$sanitized['level'] = absint($input['level']);
$sanitized['log_api_requests'] = !empty($input['log_api_requests']);
$sanitized['max_log_days'] = min(90, max(1, absint($input['max_log_days'])));
$sanitized['auto_cleanup'] = !empty($input['auto_cleanup']);
// Validate level
if (!in_array($sanitized['level'], array(1, 2, 3, 4))) {
$sanitized['level'] = AIPA_Debug::LEVEL_INFO;
}
return $sanitized;
}
/**
* AJAX: Test debug logging
*/
public function ajax_test_debug_logging() {
check_ajax_referer('aipa_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
try {
// Test all log levels
AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Debug_Test', 'Test error message');
AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Debug_Test', 'Test warning message');
AIPA_Debug::log(AIPA_Debug::LEVEL_INFO, 'Debug_Test', 'Test info message');
AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Debug_Test', 'Test debug message', array('test_data' => 'sample'));
wp_send_json_success(esc_html(__('Debug logging test completed successfully!', 'ai-product-assistant')));
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
}
/**
* AJAX: Download log file
*/
public function ajax_download_log() {
check_ajax_referer('aipa_download_log', 'nonce');
if (!current_user_can('manage_options')) {
wp_die(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
$filename = isset($_GET['filename']) ? sanitize_file_name(wp_unslash($_GET['filename'])) : '';
$log_dir = AIPA_Debug::get_log_dir();
$filepath = $log_dir . '/' . $filename;
// Security check - ensure file is within log directory
if (!file_exists($filepath) || strpos(realpath($filepath), realpath($log_dir)) !== 0) {
wp_die(esc_html(__('Invalid log file.', 'ai-product-assistant')));
}
// Output file contents using WordPress filesystem
global $wp_filesystem;
if (WP_Filesystem()) {
$content = $wp_filesystem->get_contents($filepath);
if ($content !== false) {
// Set headers for download
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . strlen($content));
header('Cache-Control: no-cache, must-revalidate');
header('Expires: 0');
// For file downloads, we need to output raw content
// This is safe because:
// 1. We've verified the file path is within our log directory
// 2. Content-Type is set to text/plain
// 3. Content-Disposition forces download
print( $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
wp_die(esc_html(__('Could not read log file.', 'ai-product-assistant')));
}
} else {
// Alternative fallback using file_get_contents for better WordPress compliance
if (file_exists($filepath)) {
$content = file_get_contents($filepath);
if ($content !== false) {
// Set headers for download
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . strlen($content));
header('Cache-Control: no-cache, must-revalidate');
header('Expires: 0');
// For file downloads, we need to output raw content
print( $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
wp_die(esc_html(__('Could not read log file.', 'ai-product-assistant')));
}
} else {
wp_die(esc_html(__('Log file not found.', 'ai-product-assistant')));
}
}
exit;
}
/**
* AJAX: Get recent logs
*/
public function ajax_get_recent_logs() {
check_ajax_referer('aipa_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(esc_html(__('Insufficient permissions.', 'ai-product-assistant')));
}
$log_files = AIPA_Debug::get_log_files();
if (empty($log_files)) {
wp_send_json_error(esc_html(__('No log files available.', 'ai-product-assistant')));
}
// Get the most recent log file
$recent_log = $log_files[0];
$content = AIPA_Debug::read_log_file($recent_log['filename'], 50); // Last 50 lines
if ($content !== false) {
wp_send_json_success(array(
'content' => $content,
'filename' => $recent_log['filename']
));
} else {
wp_send_json_error(esc_html(__('Could not read log file.', 'ai-product-assistant')));
}
}
}