chore: initial snapshot of 2meet-data-optimizer v0.1.0

Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
2026-07-31 05:06:36 +08:00
commit d36bb954d1
206 changed files with 66538 additions and 0 deletions
+272
View File
@@ -0,0 +1,272 @@
<?php
/**
* TMDO_Export — Report export endpoints (v2.5.0 M14).
*
* Three export types
* 1. health — wp_wpdo_audit op='health_check_daily' over last N days
* 2. snapshots — wp_wpdo_snapshots metadata (no inline_blob payload)
* 3. monthly — wpdo_monthly_summary_history (latest + up to 12 archives)
*
* Triggered via admin GETtools.php?page=wp-data-optimizer&wpdo_export=health&format=csv&days=30
* Capability: manage_options + nonce.
*
* Filenameswpdo-{type}-{site_slug}-{YYYYMMDD}.{csv|json}
*
* @package WP_Data_Optimizer
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Stateless static export handler.
*/
class TMDO_Export {
public const NONCE = 'wpdo_export';
/**
* Hook into admin_init to handle export requests.
*
* @return void
*/
public static function register(): void {
add_action( 'admin_init', array( __CLASS__, 'maybe_handle' ), 1 );
}
/**
* Detect + serve an export request.
*
* @return void
*/
public static function maybe_handle(): void {
if ( ! isset( $_GET['wpdo_export'] ) ) {
return;
}
if ( ! TMDO_Capability::current_user_can_admin() ) {
return;
}
if ( ! check_admin_referer( self::NONCE ) ) {
return;
}
$type = sanitize_key( wp_unslash( (string) $_GET['wpdo_export'] ) );
$format = sanitize_key( wp_unslash( (string) ( $_GET['format'] ?? 'csv' ) ) );
$days = isset( $_GET['days'] ) ? max( 1, min( 365, (int) $_GET['days'] ) ) : 30;
if ( ! in_array( $format, array( 'csv', 'json' ), true ) ) {
$format = 'csv';
}
switch ( $type ) {
case 'health':
self::send_health( $format, $days );
break;
case 'snapshots':
self::send_snapshots( $format );
break;
case 'monthly':
self::send_monthly( $format );
break;
}
}
/**
* Build a download URL with nonce.
*
* @param string $type health|snapshots|monthly.
* @param string $format csv|json.
* @param int $days For health only.
* @return string
*/
public static function url( string $type, string $format = 'csv', int $days = 30 ): string {
$args = array(
'page' => '2meet-data-optimizer',
'wpdo_export' => $type,
'format' => $format,
);
if ( 'health' === $type ) {
$args['days'] = $days;
}
return wp_nonce_url( add_query_arg( $args, admin_url( 'tools.php' ) ), self::NONCE );
}
// ─── handlers ──────────────────────────────────────────────────────
/**
* Send health export.
*
* @param string $format csv|json.
* @param int $days Number of days to include.
* @return void
*/
private static function send_health( string $format, int $days ): void {
global $wpdb;
$audit = $wpdb->prefix . 'wpdo_audit';
$exists = (int) $wpdb->get_var(
$wpdb->prepare( // phpcs:ignore WordPress.DB
'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
$audit
)
);
$rows = array();
if ( 1 === $exists ) {
$raw = (array) $wpdb->get_results(
$wpdb->prepare( // phpcs:ignore WordPress.DB
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- {$audit} is a trusted table name via $wpdb->prefix
"SELECT ts, op, value_after FROM `{$audit}` WHERE op = 'health_check_daily' AND ts >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d DAY) ORDER BY ts DESC",
$days
),
ARRAY_A
);
foreach ( $raw as $r ) {
$ctx = isset( $r['value_after'] ) ? json_decode( (string) $r['value_after'], true ) : array();
if ( ! is_array( $ctx ) ) {
$ctx = array();
}
$rows[] = array(
'ts' => (string) $r['ts'],
'critical' => (int) ( $ctx['critical'] ?? 0 ),
'recommended' => (int) ( $ctx['recommended'] ?? 0 ),
'duration_ms' => (int) ( $ctx['duration_ms'] ?? 0 ),
'autoload_kb' => (int) ( $ctx['autoload_kb'] ?? 0 ),
'conflicts' => (int) ( $ctx['conflicts'] ?? 0 ),
'module_suggestions_count' => (int) ( $ctx['module_suggestions_count'] ?? 0 ),
);
}
}
$headers = array( 'ts', 'critical', 'recommended', 'duration_ms', 'autoload_kb', 'conflicts', 'module_suggestions_count' );
self::respond( $format, 'health', $headers, $rows );
}
/**
* Send snapshots export.
*
* @param string $format csv|json.
* @return void
*/
private static function send_snapshots( string $format ): void {
global $wpdb;
$snap = $wpdb->prefix . 'wpdo_snapshots';
$exists = (int) $wpdb->get_var(
$wpdb->prepare( // phpcs:ignore WordPress.DB
'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
$snap
)
);
$rows = array();
if ( 1 === $exists ) {
$rows = (array) $wpdb->get_results(
"SELECT snapshot_id, trigger_type, size_bytes, row_count, storage, file_path, file_sha256, notes, created_at, expires_at FROM `{$snap}` ORDER BY created_at DESC", // phpcs:ignore WordPress.DB
ARRAY_A
);
}
$headers = array( 'snapshot_id', 'trigger_type', 'size_bytes', 'row_count', 'storage', 'file_path', 'file_sha256', 'notes', 'created_at', 'expires_at' );
self::respond( $format, 'snapshots', $headers, $rows );
}
/**
* Send monthly summary export.
*
* @param string $format csv|json.
* @return void
*/
private static function send_monthly( string $format ): void {
$latest = (array) get_option( 'wpdo_monthly_summary_latest', array() );
$history = (array) get_option( 'wpdo_monthly_summary_history', array() );
$all = array();
if ( ! empty( $latest ) ) {
$all[] = $latest;
}
foreach ( $history as $h ) {
if ( is_array( $h ) ) {
$all[] = $h;
}
}
if ( 'json' === $format ) {
self::respond_json( 'monthly', $all );
return;
}
// Flatten for CSV — top-level metric only.
$rows = array();
foreach ( $all as $row ) {
$health = (array) ( $row['health'] ?? array() );
$snap = (array) ( $row['snapshots'] ?? array() );
$rows[] = array(
'period_start' => (string) ( $row['period_start'] ?? '' ),
'period_end' => (string) ( $row['period_end'] ?? '' ),
'generated_at' => (string) ( $row['generated_at'] ?? '' ),
'health_total' => (int) ( $health['total'] ?? 0 ),
'health_success' => (int) ( $health['success'] ?? 0 ),
'health_critical' => (int) ( $health['critical'] ?? 0 ),
'snapshots_total' => (int) ( $snap['total'] ?? 0 ),
'snapshots_bytes' => (int) ( $snap['total_bytes'] ?? 0 ),
'autoload_size' => (int) ( $row['autoload_size'] ?? 0 ),
);
}
$headers = array( 'period_start', 'period_end', 'generated_at', 'health_total', 'health_success', 'health_critical', 'snapshots_total', 'snapshots_bytes', 'autoload_size' );
self::respond_csv( 'monthly', $headers, $rows );
}
// ─── output helpers ────────────────────────────────────────────────
/**
* Dispatch to csv or json responder.
*
* @param string $format csv|json.
* @param string $type Export type slug.
* @param array $headers Column headers.
* @param array $rows Data rows.
* @return void
*/
private static function respond( string $format, string $type, array $headers, array $rows ): void {
if ( 'json' === $format ) {
self::respond_json( $type, $rows );
return;
}
self::respond_csv( $type, $headers, $rows );
}
/**
* Send CSV response.
*
* @param string $type Export type slug.
* @param array $headers Column headers.
* @param array $rows Data rows.
* @return void
*/
private static function respond_csv( string $type, array $headers, array $rows ): void {
$body = TMDO_CSV_Writer::build( $headers, $rows );
self::send_attachment( $type, 'csv', 'text/csv; charset=UTF-8', $body );
}
/**
* Send JSON response.
*
* @param string $type Export type slug.
* @param array $rows Data rows.
* @return void
*/
private static function respond_json( string $type, array $rows ): void {
$body = wp_json_encode( $rows, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
self::send_attachment( $type, 'json', 'application/json; charset=UTF-8', (string) $body );
}
/**
* Send file attachment response.
*
* @param string $type Export type slug.
* @param string $ext File extension.
* @param string $mime MIME type.
* @param string $body File body content.
* @return void
*/
private static function send_attachment( string $type, string $ext, string $mime, string $body ): void {
$site_slug = sanitize_title( (string) get_option( 'blogname', 'site' ) ) ?: 'site';
$filename = sprintf( 'wpdo-%s-%s-%s.%s', $type, $site_slug, gmdate( 'Ymd' ), $ext );
nocache_headers();
header( 'Content-Type: ' . $mime );
header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
header( 'Content-Length: ' . strlen( $body ) );
echo $body; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
exit;
}
}