PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.0
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.0
1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.2.0 All 28 releases
xspeed / includes / class-support-snapshot.php

class-support-snapshot.php in xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN 1.3.0, at includes/class-support-snapshot.php

119 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Support_Snapshot — gather a system-info dump for support tickets.
4 *
5 * No write surface, no setting. Just a read-only aggregation of
6 * versions + environment + module config that users paste into a
7 * support email. Keeps diagnostics out of the ticket flow itself.
8 *
9 * @package XSpeed
10 */
11
12 declare(strict_types=1);
13
14 namespace XSpeed;
15
16 defined( 'ABSPATH' ) || exit;
17
18 final class Support_Snapshot {
19
20 /**
21 * Build the snapshot as a structured array. Public for the REST
22 * handler + the CLI command + the panel's "Copy to clipboard"
23 * button (it stringifies on the client side).
24 *
25 * @return array<string,mixed>
26 */
27 public static function gather(): array {
28 global $wp_version;
29 $active = self::active_module_slugs();
30 return array(
31 'generated_at' => time(),
32 'xspeed' => defined( 'XSPEED_VERSION' ) ? XSPEED_VERSION : 'unknown',
33 'xspeed_pro' => defined( 'XSPEED_PRO_VERSION' ) ? XSPEED_PRO_VERSION : 'unknown',
34 'xspeed_api' => defined( 'XSPEED_API_VERSION' ) ? XSPEED_API_VERSION : null,
35 'wordpress' => isset( $wp_version ) ? (string) $wp_version : 'unknown',
36 'php' => PHP_VERSION,
37 'mysql' => self::mysql_version(),
38 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( (string) $_SERVER['SERVER_SOFTWARE'] ) ) : 'unknown',
39 'multisite' => function_exists( 'is_multisite' ) && is_multisite(),
40 'home_url' => function_exists( 'home_url' ) ? (string) home_url() : '',
41 'memory_limit' => function_exists( 'wp_convert_hr_to_bytes' ) ? ini_get( 'memory_limit' ) : ini_get( 'memory_limit' ),
42 'active_modules' => $active,
43 'object_cache' => function_exists( 'wp_using_ext_object_cache' ) && wp_using_ext_object_cache(),
44 'license_key' => self::masked_license_key(),
45 );
46 }
47
48 /**
49 * Format the snapshot as a paste-ready Markdown block for support
50 * tickets. Public so the panel + CLI + the REST handler emit the
51 * same shape.
52 */
53 public static function to_markdown( array $snapshot ): string {
54 $lines = array( '### xSpeed support snapshot' );
55 foreach ( $snapshot as $key => $value ) {
56 if ( is_bool( $value ) ) {
57 $value = $value ? 'yes' : 'no';
58 }
59 if ( is_array( $value ) ) {
60 $value = implode( ', ', array_map( 'strval', $value ) );
61 }
62 $lines[] = sprintf( '- **%s:** %s', $key, (string) $value );
63 }
64 return implode( "\n", $lines ) . "\n";
65 }
66
67 /**
68 * Slugs of every xSpeed module that currently has an `enabled`
69 * option set to true. Doesn't reach into Module_Registry because
70 * the registry is reset between switch_to_blog calls — option
71 * scan is more portable.
72 *
73 * @return string[]
74 */
75 private static function active_module_slugs(): array {
76 $candidates = array(
77 'cache', 'minify', 'gzip', 'lazy', 'browser-cache',
78 'object-cache', 'cdn', 'cloudflare', 'database', 'preloader',
79 'heartbeat', 'bloat', 'pagespeed', 'rum', 'recommendations',
80 'images', 'migration', 'cloudflare-apo', 'custom-rules',
81 'analytics', 'critical-css', 'unused-css', 'white-label',
82 );
83 $active = array();
84 foreach ( $candidates as $slug ) {
85 $opt = get_option( 'xspeed_module_' . $slug, null );
86 if ( is_array( $opt ) && ! empty( $opt['enabled'] ) ) {
87 $active[] = $slug;
88 }
89 }
90 return $active;
91 }
92
93 /**
94 * Show the first 4 + last 4 of the license key with ••• in the
95 * middle — never log the full key, even in support dumps the
96 * user copies to ticket systems.
97 */
98 private static function masked_license_key(): string {
99 $status = get_option( 'xspeed_module_pro_status', array() );
100 $key = is_array( $status ) ? (string) ( $status['license_key'] ?? '' ) : '';
101 if ( strlen( $key ) <= 8 ) {
102 return '' === $key ? 'none' : str_repeat( '', strlen( $key ) );
103 }
104 return substr( $key, 0, 4 ) . '••••' . substr( $key, -4 );
105 }
106
107 private static function mysql_version(): string {
108 global $wpdb;
109 if ( is_object( $wpdb ) && method_exists( $wpdb, 'db_version' ) ) {
110 try {
111 return (string) $wpdb->db_version();
112 } catch ( \Throwable $e ) {
113 return 'unknown';
114 }
115 }
116 return 'unknown';
117 }
118 }
119