get_results($sql, ARRAY_A); if ($wpdb->last_error) { throw new \RuntimeException("SQL error: " . $wpdb->last_error); } return ['sql' => $sql, 'rows' => $results, 'count' => count($results ?? [])]; } public static function listTables(array $args): array { global $wpdb; $prefix = $args['prefix'] ?? $wpdb->prefix; $tables = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->esc_like($prefix)}%'"); $result = []; foreach ($tables as $t) { $info = $wpdb->get_row("SELECT TABLE_ROWS, DATA_LENGTH+INDEX_LENGTH as SIZE FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='$t'", ARRAY_A); $result[] = [ 'table' => $t, 'rows' => (int)($info['TABLE_ROWS'] ?? 0), 'size' => size_format((int)($info['SIZE'] ?? 0)), ]; } return ['tables' => $result, 'count' => count($result), 'prefix' => $prefix]; } public static function describeTable(array $args): array { global $wpdb; $table = sanitize_text_field($args['table'] ?? ''); if (empty($table)) throw new \RuntimeException("table is required."); // Accept the table name with or without the WP prefix. // If the caller passes "wp_posts" and the actual prefix is "mwp_", try both. if (strpos($table, $wpdb->prefix) !== 0) { // Maybe they passed "wp_posts" on a site with a different prefix — strip any leading wp_ and re-add correct prefix $stripped = preg_replace('/^wp_/', '', $table); $candidate = $wpdb->prefix . $stripped; // Verify the candidate exists $exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $candidate)); if ($exists) { $table = $candidate; } else { // Last attempt: use exactly as given $exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table)); if (!$exists) { throw new \RuntimeException("Table not found: {$args['table']}. WP prefix is: {$wpdb->prefix}"); } } } $columns = $wpdb->get_results("DESCRIBE `$table`", ARRAY_A); if ($wpdb->last_error) throw new \RuntimeException($wpdb->last_error); return ['table' => $table, 'columns' => $columns, 'count' => count($columns)]; } }