ad7acc40b7
- The four public REST routes say why they are public (viewable posts only, show_in_rest fields only, per_page cap, one view per IP per post per hour).
- Admin ternary echoes of literal strings are escaped for their context: esc_attr() in attributes, esc_html() for text; the object-cache badge is an if/else and aria-current is always printed ("false" off the current tab).
- Exceptions in the migration engine and the health cron go to TMDO_Logger instead of error_log().
- Verify: audit greps (ternary echoes 23 → 0, error_log outside the logger 0); dev36 renders 8 admin tabs with the change, no PHP notice, one aria-current="page" each.
- PR: PR-078
254 lines
13 KiB
PHP
254 lines
13 KiB
PHP
<?php
|
||
/**
|
||
* Term Stress Test template (v2.13.0).
|
||
*
|
||
* Full async + polling UI mirroring Post / User Stress Test:
|
||
* 1. 設定並啟動測試(form: taxonomy / target / mode / batch_size + Start/Cancel)
|
||
* 2. 即時進度(progress bar + processed/target/rate/ETA/peak memory)
|
||
* 3. Benchmark 報告(write metrics + DB sizes + query performance)
|
||
*
|
||
* Variables in scope from render_term_stress_test():
|
||
* $state — TMDO_Term_Stress_Tester::get_progress(false) output
|
||
* $test_term_count — int, terms matching wpdo-stress- slug prefix
|
||
* $taxonomies — array<slug,label> of available taxonomies
|
||
*
|
||
* @package WP_Data_Optimizer
|
||
*/
|
||
|
||
// phpcs:ignore WPDO.AntiEAV -- platform admin UI: stress test SQL example display
|
||
|
||
declare(strict_types=1);
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
$status_str = (string) ( $state['status'] ?? 'idle' );
|
||
$is_running = ( 'running' === $status_str || 'benchmarking' === $status_str );
|
||
$current_mode = class_exists( 'TMDO_Mode_Manager' ) ? TMDO_Mode_Manager::get( 'term' ) : 'disabled';
|
||
$mode_color = 'aeav_only' === $current_mode ? '#28a745' : ( 'shadow_read' === $current_mode ? '#dba617' : '#dc3545' );
|
||
$mode_optimal = 'aeav_only' === $current_mode;
|
||
$mode_text_cls = 'aeav_only' === $current_mode ? 'wpdo-text-success' : ( 'shadow_read' === $current_mode ? 'wpdo-text-amber' : 'wpdo-text-danger' );
|
||
$mode_card_cls = $mode_optimal ? 'ok' : 'warn';
|
||
$settings_url = admin_url( 'tools.php?page=wp-data-optimizer&tab=settings' );
|
||
|
||
global $wpdb;
|
||
$flat_hp_taxonomy = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wpdo_term_hp_taxonomy" );
|
||
$flat_misc = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wpdo_term_misc" );
|
||
$total_terms = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->terms}" );
|
||
$total_termmeta = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->termmeta}" );
|
||
?>
|
||
|
||
<div class="wpdo-term-stress-test-tab">
|
||
<h2><?php esc_html_e( 'Term Entity 壓力測試 & Benchmark', '2meet-data-optimizer' ); ?></h2>
|
||
|
||
<div class="wpdo-notice-error">
|
||
⚠️ <strong><?php esc_html_e( '此工具僅供開發 / 測試環境使用。', '2meet-data-optimizer' ); ?></strong>
|
||
<?php esc_html_e( '會建立大量測試 term 並 seed 對應 hp_taxonomy 群組 keys。請勿在生產環境執行。', '2meet-data-optimizer' ); ?>
|
||
</div>
|
||
|
||
<p class="description">
|
||
<?php esc_html_e( '透過自動產生大量測試 term,評估 term entity 反 EAV 系統在不同規模下的寫入吞吐與查詢效能。所有測試 term 均以 wpdo-stress- 為 slug 前綴,可一鍵清除。', '2meet-data-optimizer' ); ?>
|
||
</p>
|
||
|
||
<!-- Diagnose snapshot -->
|
||
<div class="wpdo-card wpdo-mt-3">
|
||
<h3 class="wpdo-mt-0"><?php esc_html_e( '當前 Term Entity 狀態', '2meet-data-optimizer' ); ?></h3>
|
||
<table class="widefat striped">
|
||
<tr>
|
||
<td><?php esc_html_e( 'wp_terms', '2meet-data-optimizer' ); ?></td>
|
||
<td><strong><?php echo esc_html( number_format_i18n( $total_terms ) ); ?></strong></td>
|
||
<td><?php esc_html_e( 'wp_termmeta', '2meet-data-optimizer' ); ?></td>
|
||
<td><strong><?php echo esc_html( number_format_i18n( $total_termmeta ) ); ?></strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td><?php esc_html_e( 'Mode', '2meet-data-optimizer' ); ?></td>
|
||
<td><strong class="<?php echo esc_attr( $mode_text_cls ); ?>"><?php echo esc_html( $current_mode ); ?></strong></td>
|
||
<td><?php esc_html_e( 'Ratio', '2meet-data-optimizer' ); ?></td>
|
||
<td><strong>1:<?php echo esc_html( (string) ( $total_terms > 0 ? round( $total_termmeta / $total_terms, 2 ) : 0 ) ); ?></strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>wpdo_term_hp_taxonomy</code></td>
|
||
<td><strong><?php echo esc_html( number_format_i18n( $flat_hp_taxonomy ) ); ?></strong> rows</td>
|
||
<td><code>wpdo_term_misc</code></td>
|
||
<td><strong><?php echo esc_html( number_format_i18n( $flat_misc ) ); ?></strong> rows</td>
|
||
</tr>
|
||
<tr>
|
||
<td colspan="2"><?php esc_html_e( 'Stress 測試 term 數', '2meet-data-optimizer' ); ?></td>
|
||
<td colspan="2"><strong id="wpdo-tst-count" class="wpdo-count-danger"><?php echo esc_html( number_format_i18n( $test_term_count ) ); ?></strong></td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- 驗證反 EAV 優化指南 -->
|
||
<div class="wpdo-card wpdo-mode-card wpdo-mode-card--<?php echo esc_attr( $mode_card_cls ); ?>">
|
||
<h3 class="wpdo-mt-0 wpdo-h3-sm">
|
||
<?php if ( $mode_optimal ) : ?>
|
||
✅ <?php esc_html_e( 'Term Mode = aeav_only — 已具備驗證優化的條件', '2meet-data-optimizer' ); ?>
|
||
<?php else : ?>
|
||
⚠️
|
||
<?php
|
||
printf(
|
||
/* translators: %s: current mode */
|
||
esc_html__( 'Term Mode = %s — 此模式下壓力測試結果不會展示完整反 EAV 優化效果', '2meet-data-optimizer' ),
|
||
'<code class="wpdo-code-white">' . esc_html( $current_mode ) . '</code>'
|
||
);
|
||
?>
|
||
<?php endif; ?>
|
||
</h3>
|
||
<p class="wpdo-mt-1">
|
||
<strong><?php esc_html_e( '想看 wp_termmeta 真實減量?必須兩條件同時滿足:', '2meet-data-optimizer' ); ?></strong>
|
||
</p>
|
||
<ol class="wpdo-list-ol-tight">
|
||
<li>
|
||
<?php
|
||
printf(
|
||
/* translators: 1: open code, 2: close code */
|
||
esc_html__( 'Term mode 設為 %1$saeav_only%2$s(前往設定 tab → Entity Bridge → Term entity)', '2meet-data-optimizer' ),
|
||
'<code class="wpdo-code-white">',
|
||
'</code>'
|
||
);
|
||
?>
|
||
<?php if ( ! $mode_optimal ) : ?>
|
||
<a href="<?php echo esc_url( $settings_url ); ?>" class="button button-small wpdo-ml-2">→ <?php esc_html_e( '前往設定', '2meet-data-optimizer' ); ?></a>
|
||
<?php endif; ?>
|
||
</li>
|
||
<li>
|
||
<?php esc_html_e( '寫入模式選 🐢 Realistic(走 wp_insert_term + Hook Bus,會被攔截短路 wp_termmeta)', '2meet-data-optimizer' ); ?>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
|
||
<div class="wpdo-grid-2col">
|
||
|
||
<!-- Left: Configure & Start -->
|
||
<div class="wpdo-card">
|
||
<h3 class="wpdo-mt-0"><?php esc_html_e( '1. 設定並啟動測試', '2meet-data-optimizer' ); ?></h3>
|
||
|
||
<table class="form-table wpdo-mt-0">
|
||
<tr>
|
||
<th class="wpdo-th-main"><label for="wpdo-tst-taxonomy"><?php esc_html_e( 'Taxonomy', '2meet-data-optimizer' ); ?></label></th>
|
||
<td>
|
||
<select id="wpdo-tst-taxonomy" class="regular-text">
|
||
<?php foreach ( $taxonomies as $slug => $label ) : ?>
|
||
<option value="<?php echo esc_attr( $slug ); ?>" <?php selected( $slug, 'listing_category' ); ?>>
|
||
<?php echo esc_html( $slug . ' — ' . $label ); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<p class="description"><?php esc_html_e( '建議用 HivePress 自訂 taxonomy(listing_category / listing_tag 等)— seed 後 hp_sort_order/hp_default/hp_icon 三 keys 走 hp_taxonomy 群組。', '2meet-data-optimizer' ); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wpdo-tst-target"><?php esc_html_e( '要建立的 term 數', '2meet-data-optimizer' ); ?></label></th>
|
||
<td>
|
||
<input type="number" id="wpdo-tst-target" min="1" max="100000" value="500" class="regular-text" />
|
||
<p class="description"><?php esc_html_e( '常用:100 / 500 / 1,000 / 10,000(上限 100,000)', '2meet-data-optimizer' ); ?></p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th><label><?php esc_html_e( '寫入模式', '2meet-data-optimizer' ); ?></label></th>
|
||
<td>
|
||
<label class="wpdo-label-block">
|
||
<input type="radio" name="wpdo-tst-mode" value="fast" checked />
|
||
<strong>Fast</strong> — <?php esc_html_e( '直接 $wpdb->insert,跳過 WP filter chain(最快,但不測 Hook Bus)', '2meet-data-optimizer' ); ?>
|
||
</label>
|
||
<label class="wpdo-label-block">
|
||
<input type="radio" name="wpdo-tst-mode" value="realistic" />
|
||
<strong>Realistic</strong> — <?php esc_html_e( '走 wp_insert_term + update_term_meta(較慢,模擬生產路徑 + 觸發 Hook Bus)', '2meet-data-optimizer' ); ?>
|
||
</label>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wpdo-tst-batch"><?php esc_html_e( '批次大小', '2meet-data-optimizer' ); ?></label></th>
|
||
<td>
|
||
<input type="number" id="wpdo-tst-batch" min="1" max="1000" value="200" class="small-text" />
|
||
<p class="description"><?php esc_html_e( '每批 8 秒 wall-clock 上限。Fast 建議 200-1000;Realistic 建議 10-30。', '2meet-data-optimizer' ); ?></p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<p>
|
||
<button type="button" class="button button-primary button-large" id="wpdo-tst-start" <?php disabled( $is_running ); ?>>
|
||
<?php esc_html_e( '🚀 啟動壓力測試', '2meet-data-optimizer' ); ?>
|
||
</button>
|
||
<button type="button" class="button" id="wpdo-tst-cancel" <?php disabled( ! $is_running ); ?>>
|
||
<?php esc_html_e( '⏹ 取消', '2meet-data-optimizer' ); ?>
|
||
</button>
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Right: Cleanup + Re-run benchmark -->
|
||
<div class="wpdo-card">
|
||
<h3 class="wpdo-mt-0"><?php esc_html_e( '清除測試資料', '2meet-data-optimizer' ); ?></h3>
|
||
<p>
|
||
<?php esc_html_e( '目前 stress test term 數:', '2meet-data-optimizer' ); ?>
|
||
<strong id="wpdo-tst-count-mirror" class="wpdo-count-danger">
|
||
<?php echo esc_html( number_format_i18n( $test_term_count ) ); ?>
|
||
</strong>
|
||
</p>
|
||
<p class="description">
|
||
<?php esc_html_e( '一鍵清除所有 slug 前綴 wpdo-stress- 的 term,連同 wp_termmeta + wp_term_taxonomy + flat 表的對應 row。', '2meet-data-optimizer' ); ?>
|
||
</p>
|
||
<p>
|
||
<button type="button" class="button button-secondary" id="wpdo-tst-cleanup" <?php disabled( $is_running || 0 === $test_term_count ); ?>>
|
||
<?php esc_html_e( '🗑 清除全部測試 term', '2meet-data-optimizer' ); ?>
|
||
</button>
|
||
</p>
|
||
|
||
<hr class="wpdo-hr-section" />
|
||
|
||
<p>
|
||
<button type="button" class="button" id="wpdo-tst-rerun-bench" <?php disabled( $is_running || 0 === $test_term_count ); ?>>
|
||
<?php esc_html_e( '📊 重跑 Benchmark(不新增資料)', '2meet-data-optimizer' ); ?>
|
||
</button>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Progress card (live) -->
|
||
<div id="wpdo-tst-progress-card" class="wpdo-card wpdo-mt-3<?php echo esc_attr( $is_running ? '' : ' wpdo-hidden' ); ?>">
|
||
<h3 class="wpdo-mt-0"><?php esc_html_e( '2. 即時進度', '2meet-data-optimizer' ); ?></h3>
|
||
<div class="wpdo-bar-section">
|
||
<div class="wpdo-bar-header">
|
||
<span>
|
||
<strong id="wpdo-tst-pg-status"><?php echo esc_html( $status_str ); ?></strong>
|
||
· <code id="wpdo-tst-pg-taxonomy"><?php echo esc_html( (string) ( $state['taxonomy'] ?? '' ) ); ?></code>
|
||
· <span id="wpdo-tst-pg-mode"><?php echo esc_html( (string) ( $state['mode'] ?? '' ) ); ?></span> mode
|
||
</span>
|
||
<span id="wpdo-tst-pg-pct" class="wpdo-bar-pct"><?php echo esc_html( (string) ( $state['pct'] ?? 0 ) ); ?>%</span>
|
||
</div>
|
||
<div class="wpdo-bar-track">
|
||
<div id="wpdo-tst-pg-bar" class="wpdo-bar-fill" style="--wpdo-bar-width:<?php echo esc_attr( (string) ( $state['pct'] ?? 0 ) ); ?>%"></div>
|
||
</div>
|
||
</div>
|
||
<table class="wpdo-stats-table">
|
||
<tr>
|
||
<td class="wpdo-td-muted"><?php esc_html_e( '已建立', '2meet-data-optimizer' ); ?></td>
|
||
<td class="wpdo-td-val"><span id="wpdo-tst-pg-processed"><?php echo esc_html( (string) ( $state['processed'] ?? 0 ) ); ?></span> / <span id="wpdo-tst-pg-target"><?php echo esc_html( (string) ( $state['target'] ?? 0 ) ); ?></span></td>
|
||
<td class="wpdo-td-muted"><?php esc_html_e( '速率', '2meet-data-optimizer' ); ?></td>
|
||
<td class="wpdo-td-val"><span id="wpdo-tst-pg-rate"><?php echo esc_html( (string) ( $state['rate_per_sec'] ?? 0 ) ); ?></span> terms/sec</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="wpdo-td-muted"><?php esc_html_e( '已耗時', '2meet-data-optimizer' ); ?></td>
|
||
<td class="wpdo-td"><span id="wpdo-tst-pg-elapsed"><?php echo esc_html( (string) ( $state['elapsed_sec'] ?? 0 ) ); ?></span> 秒</td>
|
||
<td class="wpdo-td-muted"><?php esc_html_e( '預估剩餘', '2meet-data-optimizer' ); ?></td>
|
||
<td class="wpdo-td"><span id="wpdo-tst-pg-eta"><?php echo esc_html( (string) ( $state['eta_sec'] ?? 0 ) ); ?></span> 秒</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="wpdo-td-muted"><?php esc_html_e( '完成批次', '2meet-data-optimizer' ); ?></td>
|
||
<td class="wpdo-td"><span id="wpdo-tst-pg-batches"><?php echo esc_html( (string) ( $state['batches_done'] ?? 0 ) ); ?></span></td>
|
||
<td class="wpdo-td-muted"><?php esc_html_e( 'PHP Peak Mem', '2meet-data-optimizer' ); ?></td>
|
||
<td class="wpdo-td"><span id="wpdo-tst-pg-mem"><?php echo esc_html( (string) round( ( (int) ( $state['peak_memory'] ?? 0 ) ) / 1048576, 1 ) ); ?></span> MB</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Benchmark report -->
|
||
<div id="wpdo-tst-bench-card" class="wpdo-card wpdo-mt-3<?php echo esc_attr( ! empty( $state['benchmark'] ) ? '' : ' wpdo-hidden' ); ?>">
|
||
<h3 class="wpdo-mt-0"><?php esc_html_e( '3. Benchmark 報告', '2meet-data-optimizer' ); ?></h3>
|
||
<div id="wpdo-tst-bench-content"></div>
|
||
</div>
|
||
|
||
</div>
|