Files
roi-theme/wp-content/plugins/wp-debug/inc/cli-commands.php

544 lines
16 KiB
PHP

<?php
/**
* CLI Commands Module
*
* Comandos WP-CLI para debug y diagnóstico
*
* @package WP_Debug
* @since 1.0.0
*/
// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}
// Check if WP-CLI is available
if (!class_exists('WP_CLI')) {
return;
}
/**
* WP_Debug_CLI_Commands class
*/
class WP_Debug_CLI_Commands extends WP_CLI_Command {
/**
* Initialize CLI commands
*/
public static function init() {
if (class_exists('WP_CLI')) {
WP_CLI::add_command('debug', 'WP_Debug_CLI_Commands');
}
}
/**
* Show plugin status and modules information
*
* ## EXAMPLES
*
* wp debug status
*
* @when after_wp_load
*/
public function status($args, $assoc_args) {
WP_CLI::log('WP Debug Plugin Status');
WP_CLI::log('======================');
WP_CLI::log('');
// Plugin info
WP_CLI::log('Version: ' . WP_DEBUG_VERSION);
WP_CLI::log('Plugin Directory: ' . WP_DEBUG_PLUGIN_DIR);
WP_CLI::log('');
// Global status
$enabled = get_option('wp_debug_enabled', true);
WP_CLI::log('Plugin Status: ' . ($enabled ? 'Enabled' : 'Disabled'));
WP_CLI::log('');
// Modules status
WP_CLI::log('Modules:');
WP_CLI::log('--------');
$modules = WP_Debug_Autoloader::get_modules();
$items = array();
foreach ($modules as $module_name => $module_data) {
$module_enabled = get_option('wp_debug_module_' . $module_name, $module_data['enabled']);
$class_exists = class_exists($module_data['class']);
$items[] = array(
'module' => $module_name,
'status' => $module_enabled ? 'enabled' : 'disabled',
'loaded' => $class_exists ? 'yes' : 'no',
'class' => $module_data['class'],
);
}
WP_CLI\Utils\format_items('table', $items, array('module', 'status', 'loaded', 'class'));
// Database info
global $wpdb;
$table = $wpdb->prefix . 'wp_debug_logs';
$count = $wpdb->get_var("SELECT COUNT(*) FROM {$table}");
WP_CLI::log('');
WP_CLI::log('Database Logs: ' . number_format($count) . ' entries');
// File logs
$logs_dir = WP_CONTENT_DIR . '/logs/wp-debug';
if (file_exists($logs_dir)) {
$files = glob($logs_dir . '/debug-*.log');
WP_CLI::log('Log Files: ' . count($files));
}
WP_CLI::success('Status check complete');
}
/**
* List hooks executed
*
* ## OPTIONS
*
* [--search=<pattern>]
* : Filter hooks by pattern
*
* [--limit=<number>]
* : Limit number of results
* ---
* default: 50
* ---
*
* [--format=<format>]
* : Output format
* ---
* default: table
* options:
* - table
* - json
* - csv
* ---
*
* ## EXAMPLES
*
* wp debug hooks
* wp debug hooks --search=init
* wp debug hooks --limit=100 --format=json
*
* @when after_wp_load
*/
public function hooks($args, $assoc_args) {
if (!class_exists('WP_Debug_Hook_Monitor')) {
WP_CLI::error('Hook Monitor module is not loaded');
return;
}
$search = isset($assoc_args['search']) ? $assoc_args['search'] : '';
$limit = isset($assoc_args['limit']) ? intval($assoc_args['limit']) : 50;
$format = isset($assoc_args['format']) ? $assoc_args['format'] : 'table';
// Get hooks from transient or current execution
$transient_data = get_transient('wp_debug_hooks_data');
if (!$transient_data) {
WP_CLI::warning('No hook data available. Run a page request first.');
return;
}
$hooks = $transient_data['hooks'];
// Filter by search
if ($search) {
$hooks = array_filter($hooks, function($hook) use ($search) {
return strpos($hook['hook'], $search) !== false;
});
WP_CLI::log('Filtered by: ' . $search);
}
// Limit results
if ($limit > 0) {
$hooks = array_slice($hooks, 0, $limit);
}
if (empty($hooks)) {
WP_CLI::warning('No hooks found');
return;
}
// Prepare items for display
$items = array();
foreach ($hooks as $hook) {
$items[] = array(
'hook' => $hook['hook'],
'type' => $hook['type'],
'caller' => isset($hook['caller']) ? $hook['caller'] : 'unknown',
'args' => isset($hook['args_count']) ? $hook['args_count'] : 0,
);
}
WP_CLI\Utils\format_items($format, $items, array('hook', 'type', 'caller', 'args'));
WP_CLI::log('');
WP_CLI::log('Total hooks: ' . $transient_data['total']);
WP_CLI::log('Unique hooks: ' . $transient_data['unique']);
WP_CLI::success('Retrieved ' . count($items) . ' hooks');
}
/**
* List templates loaded
*
* ## OPTIONS
*
* [--format=<format>]
* : Output format
* ---
* default: table
* options:
* - table
* - json
* - csv
* ---
*
* [--parts]
* : Show template parts instead of main templates
*
* [--missing]
* : Show only missing template parts
*
* ## EXAMPLES
*
* wp debug templates
* wp debug templates --parts
* wp debug templates --missing
*
* @when after_wp_load
*/
public function templates($args, $assoc_args) {
if (!class_exists('WP_Debug_Template_Tracer')) {
WP_CLI::error('Template Tracer module is not loaded');
return;
}
$format = isset($assoc_args['format']) ? $assoc_args['format'] : 'table';
$show_parts = isset($assoc_args['parts']);
$show_missing = isset($assoc_args['missing']);
// Get templates from transient
$transient_data = get_transient('wp_debug_templates_data');
if (!$transient_data) {
WP_CLI::warning('No template data available. Run a page request first.');
return;
}
if ($show_missing) {
// Show missing template parts
$items = array();
foreach ($transient_data['missing'] as $part) {
$items[] = array(
'slug' => $part['slug'],
'name' => $part['name'] ? $part['name'] : 'N/A',
'file' => $part['file'],
);
}
if (empty($items)) {
WP_CLI::success('No missing templates found');
return;
}
WP_CLI\Utils\format_items($format, $items, array('slug', 'name', 'file'));
WP_CLI::warning('Found ' . count($items) . ' missing templates');
} elseif ($show_parts) {
// Show template parts
$items = array();
foreach ($transient_data['parts'] as $part) {
$items[] = array(
'slug' => $part['slug'],
'name' => $part['name'] ? $part['name'] : 'N/A',
'file' => $part['file'],
'found' => $part['found'] ? 'yes' : 'no',
);
}
if (empty($items)) {
WP_CLI::warning('No template parts found');
return;
}
WP_CLI\Utils\format_items($format, $items, array('slug', 'name', 'file', 'found'));
WP_CLI::success('Retrieved ' . count($items) . ' template parts');
} else {
// Show main templates
$items = array();
foreach ($transient_data['templates'] as $template) {
$items[] = array(
'name' => $template['name'],
'type' => $template['type'],
'path' => $template['path'],
);
}
if (empty($items)) {
WP_CLI::warning('No templates found');
return;
}
WP_CLI\Utils\format_items($format, $items, array('name', 'type', 'path'));
WP_CLI::success('Retrieved ' . count($items) . ' templates');
}
}
/**
* Show performance metrics
*
* ## OPTIONS
*
* [--format=<format>]
* : Output format
* ---
* default: table
* options:
* - table
* - json
* ---
*
* ## EXAMPLES
*
* wp debug performance
* wp debug performance --format=json
*
* @when after_wp_load
*/
public function performance($args, $assoc_args) {
if (!class_exists('WP_Debug_Profiler')) {
WP_CLI::error('Profiler module is not loaded');
return;
}
$format = isset($assoc_args['format']) ? $assoc_args['format'] : 'table';
// Get performance report
$report = WP_Debug_Profiler::get_performance_report();
if (isset($report['error'])) {
WP_CLI::warning($report['error']);
return;
}
if ($format === 'json') {
WP_CLI::log(json_encode($report, JSON_PRETTY_PRINT));
return;
}
WP_CLI::log('Performance Metrics');
WP_CLI::log('===================');
WP_CLI::log('');
// Display formatted metrics
WP_CLI::log('Execution Time: ' . $report['formatted']['execution_time']);
WP_CLI::log('Memory Current: ' . $report['formatted']['memory_current']);
WP_CLI::log('Memory Peak: ' . $report['formatted']['memory_peak']);
if ($report['formatted']['server_load']) {
WP_CLI::log('Server Load: ' . $report['formatted']['server_load']);
}
WP_CLI::log('');
// Display timers if available
if (!empty($report['metrics']['timers'])) {
WP_CLI::log('Function Timers:');
WP_CLI::log('----------------');
$items = array();
foreach ($report['metrics']['timers'] as $name => $timer) {
$items[] = array(
'name' => $name,
'time' => round($timer['elapsed'] * 1000, 2) . 'ms',
'memory' => WP_Debug_Profiler::format_bytes($timer['memory_used']),
);
}
WP_CLI\Utils\format_items('table', $items, array('name', 'time', 'memory'));
WP_CLI::log('');
}
// Display suggestions
if (!empty($report['suggestions'])) {
WP_CLI::log('Suggestions:');
WP_CLI::log('------------');
foreach ($report['suggestions'] as $suggestion) {
WP_CLI::warning($suggestion);
}
} else {
WP_CLI::success('Performance looks good!');
}
}
/**
* Export complete debug report in JSON
*
* ## OPTIONS
*
* [<file>]
* : Output file path (optional, defaults to stdout)
*
* ## EXAMPLES
*
* wp debug export
* wp debug export report.json
*
* @when after_wp_load
*/
public function export($args, $assoc_args) {
WP_CLI::log('Generating debug report...');
// Collect all data
$report = array(
'timestamp' => current_time('mysql'),
'site_url' => get_site_url(),
'wp_version' => get_bloginfo('version'),
'plugin_version' => WP_DEBUG_VERSION,
);
// Add hooks data
if (class_exists('WP_Debug_Hook_Monitor')) {
$hooks_data = get_transient('wp_debug_hooks_data');
if ($hooks_data) {
$report['hooks'] = array(
'total' => $hooks_data['total'],
'unique' => $hooks_data['unique'],
'top_10' => array_slice($hooks_data['counts'], 0, 10, true),
);
}
}
// Add templates data
if (class_exists('WP_Debug_Template_Tracer')) {
$templates_data = get_transient('wp_debug_templates_data');
if ($templates_data) {
$report['templates'] = array(
'templates' => $templates_data['templates'],
'parts_count' => count($templates_data['parts']),
'missing_count' => count($templates_data['missing']),
);
}
}
// Add performance data
if (class_exists('WP_Debug_Profiler')) {
$perf_report = WP_Debug_Profiler::get_performance_report();
if (!isset($perf_report['error'])) {
$report['performance'] = $perf_report;
}
}
// Add recent logs
if (class_exists('WP_Debug_Logger')) {
$logs = WP_Debug_Logger::get_logs(array('limit' => 50));
$report['recent_logs'] = $logs;
}
// Add module status
$modules = WP_Debug_Autoloader::get_modules();
$modules_status = array();
foreach ($modules as $module_name => $module_data) {
$modules_status[$module_name] = array(
'enabled' => get_option('wp_debug_module_' . $module_name, $module_data['enabled']),
'loaded' => class_exists($module_data['class']),
);
}
$report['modules'] = $modules_status;
// Convert to JSON
$json = json_encode($report, JSON_PRETTY_PRINT);
// Output to file or stdout
if (isset($args[0])) {
$file = $args[0];
$result = file_put_contents($file, $json);
if ($result === false) {
WP_CLI::error('Failed to write to file: ' . $file);
} else {
WP_CLI::success('Report exported to: ' . $file);
}
} else {
WP_CLI::log($json);
WP_CLI::success('Report generated successfully');
}
}
/**
* Clear old logs
*
* ## OPTIONS
*
* [--days=<days>]
* : Number of days to keep logs
* ---
* default: 7
* ---
*
* [--yes]
* : Skip confirmation
*
* ## EXAMPLES
*
* wp debug clear
* wp debug clear --days=30
* wp debug clear --yes
*
* @when after_wp_load
*/
public function clear($args, $assoc_args) {
if (!class_exists('WP_Debug_Logger')) {
WP_CLI::error('Logger module is not loaded');
return;
}
$days = isset($assoc_args['days']) ? intval($assoc_args['days']) : 7;
$yes = isset($assoc_args['yes']);
// Count logs to be deleted
global $wpdb;
$table = $wpdb->prefix . 'wp_debug_logs';
$date = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table} WHERE timestamp < %s", $date));
// Count log files to be deleted
$logs_dir = WP_CONTENT_DIR . '/logs/wp-debug';
$files_count = 0;
if (file_exists($logs_dir)) {
$files = glob($logs_dir . '/debug-*.log');
$cutoff = strtotime("-{$days} days");
foreach ($files as $file) {
if (filemtime($file) < $cutoff) {
$files_count++;
}
}
}
WP_CLI::log("Logs older than {$days} days:");
WP_CLI::log(" Database entries: {$count}");
WP_CLI::log(" Log files: {$files_count}");
if ($count == 0 && $files_count == 0) {
WP_CLI::success('No old logs to clear');
return;
}
// Ask for confirmation
if (!$yes) {
WP_CLI::confirm('Are you sure you want to delete these logs?');
}
// Clear logs
WP_CLI::log('Clearing logs...');
WP_Debug_Logger::clear_old_logs($days);
WP_CLI::success("Cleared {$count} database entries and {$files_count} log files");
}
}