$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=] * : Filter hooks by pattern * * [--limit=] * : Limit number of results * --- * default: 50 * --- * * [--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=] * : 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=] * : 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 * * [] * : 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=] * : 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"); } }