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
@@ -0,0 +1,148 @@
<?php
/**
* TMDO_Conflict_Detector — 偵測 UAE 與 UAEPG 同欄位衝突
*
* 背景:
* UAEPG(PostgreSQL sidecar)以 metadata filter priority 5 攔截,
* UAE 在 priority 10 攔截。若同一 meta_key 被雙方都登錄,
* UAEPG 會先短路 return,UAE 寫入永遠不執行,資料靜默遺失。
*
* 本類別在欄位登錄階段完成後(init:25)掃描雙方 Registry,
* 找出 overlap 並:
* 1. 寫入 error log(供 CI / 監控系統消化)
* 2. 在管理後台顯示紅色 admin_notices
* 3. 提供 TMDO_Conflict_Detector::get_conflicts() 與 CLI 指令 wp uae conflicts 查詢
*
* 結果 cache 在 static property 內,單 request 內不重複掃描。
*
* @package WP_Data_Optimizer
* @since 1.1.2
*/
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
defined( 'ABSPATH' ) || exit;
final class TMDO_Conflict_Detector {
/**
* @var array<int, array{entity_type:string, meta_key:string, wpdo_group:string, uaepg_group:string}>|null
*/
private static ?array $cache = null;
public static function init(): void {
// init:25 — register_default_fields 於 init:20 觸發 wpdo_register_fields,
// UAEPG 亦在 init:20 觸發 uaepg_register_fields;此時 priority 25 可確保雙邊皆完成登錄。
add_action( 'init', array( self::class, 'scan' ), 25 );
if ( is_admin() ) {
add_action( 'admin_notices', array( self::class, 'maybe_render_admin_notice' ) );
}
}
/**
* 掃描並 cache 衝突清單。
*
* @return array<int, array{entity_type:string, meta_key:string, wpdo_group:string, uaepg_group:string}>
*/
public static function scan(): array {
if ( self::$cache !== null ) {
return self::$cache;
}
if ( ! class_exists( 'UAEPG_Registry' ) ) {
return self::$cache = array();
}
$conflicts = array();
foreach ( TMDO_Entity_Registry::get_all_fields() as $entity_type => $fields_by_key ) {
foreach ( $fields_by_key as $meta_key => $wpdo_field ) {
if ( ! UAEPG_Registry::is_managed( $entity_type, $meta_key ) ) {
continue;
}
$uaepg_field = UAEPG_Registry::get_field( $entity_type, $meta_key );
$conflicts[] = array(
'entity_type' => $entity_type,
'meta_key' => $meta_key,
'wpdo_group' => $wpdo_field['group'] ?? '(unknown)',
'uaepg_group' => $uaepg_field['group'] ?? '(unknown)',
);
}
}
if ( $conflicts ) {
TMDO_Logger::error(
'field_registration_conflict',
array(
'count' => count( $conflicts ),
'fields' => $conflicts,
)
);
}
return self::$cache = $conflicts;
}
/**
* 取得衝突清單(若尚未掃描,觸發掃描)。
*/
public static function get_conflicts(): array {
return self::$cache ?? self::scan();
}
/**
* 測試用:強制清除 cache,下次 scan() 會重跑。
*
* @internal
*/
public static function reset_cache(): void {
self::$cache = null;
}
/**
* 若有衝突則輸出管理後台紅色通知。
*/
public static function maybe_render_admin_notice(): void {
$conflicts = self::get_conflicts();
if ( ! $conflicts ) {
return;
}
if ( ! TMDO_Capability::current_user_can_admin() ) {
return;
}
$count = count( $conflicts );
$lines = array();
foreach ( array_slice( $conflicts, 0, 5 ) as $c ) {
$lines[] = sprintf(
'%s / %s(UAE 群組「%s」 ↔ UAEPG 群組「%s」)',
esc_html( $c['entity_type'] ),
esc_html( $c['meta_key'] ),
esc_html( $c['wpdo_group'] ),
esc_html( $c['uaepg_group'] )
);
}
$extra = $count > 5 ? sprintf( __( '… 另有 %d 個欄位未顯示', 'uae' ), $count - 5 ) : '';
printf(
'<div class="notice notice-error"><p><strong>%s</strong></p><ul style="list-style:disc;margin-left:20px;"><li>%s</li></ul>%s<p>%s <code>wp uae conflicts</code></p></div>',
esc_html(
sprintf(
/* translators: %d: conflict count */
__( 'UAE × UAEPG 欄位衝突偵測:發現 %d 個同 meta_key 被雙方 Registry 重複登錄 — UAEPG 會搶先短路,UAE 寫入將被靜默跳過', 'uae' ),
$count
)
),
// $lines elements were each individually esc_html()'d above (lines 121-124).
// implode joins escaped strings with literal HTML markers — safe.
implode( '</li><li>', $lines ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped above.
$extra ? '<p><em>' . esc_html( $extra ) . '</em></p>' : '',
esc_html__( '查看完整清單:', 'uae' )
);
}
}