fix(2meet-data-optimizer): report entity group name collisions instead of silently dropping
- register_group() keeps the first definition but records a field diff (added/removed/changed) when the same entity/group is re-registered differently; identical re-registration stays silent - Surface collisions via Site Health (wpdo_entity_group_collisions), the admin Doctor tab, and wp wpdo doctor; warning log throttled to once a day - Verify: EntityRegistryCollisionTest (7); core unit 613 / integration 432, HP 141/49, WC 10/22 OK - PR: PR-017
This commit is contained in:
@@ -31,6 +31,9 @@ final class TMDO_Entity_Registry {
|
||||
/** @var array<int, array{type:string, group:string, fields:array}> 待建表的 Schema 清單 */
|
||||
private static array $pending_schemas = array();
|
||||
|
||||
/** @var array<string, array> "entity/group" → 同名群組以不同定義重複註冊的紀錄 */
|
||||
private static array $collisions = array();
|
||||
|
||||
/** 合法的欄位型別 */
|
||||
public const VALID_TYPES = array(
|
||||
'text',
|
||||
@@ -54,6 +57,7 @@ final class TMDO_Entity_Registry {
|
||||
self::$groups = array();
|
||||
self::$field_index = array();
|
||||
self::$pending_schemas = array();
|
||||
self::$collisions = array();
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────
|
||||
@@ -105,11 +109,6 @@ final class TMDO_Entity_Registry {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 防重複登錄
|
||||
if ( isset( self::$groups[ $entity_type ][ $group_name ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 驗證並正規化欄位定義
|
||||
$normalized = array();
|
||||
|
||||
@@ -141,15 +140,25 @@ final class TMDO_Entity_Registry {
|
||||
$normalized_field['entity_type'] = $entity_type;
|
||||
|
||||
$normalized[] = $normalized_field;
|
||||
|
||||
// 建立索引以供快速查詢
|
||||
self::$field_index[ $entity_type ][ $normalized_field['key'] ] = $normalized_field;
|
||||
}
|
||||
|
||||
if ( empty( $normalized ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 防重複登錄:相同定義(init:1 重新觸發)靜默略過;定義不同則記錄衝突,保留先註冊者。
|
||||
if ( isset( self::$groups[ $entity_type ][ $group_name ] ) ) {
|
||||
if ( self::$groups[ $entity_type ][ $group_name ] !== $normalized ) {
|
||||
self::record_collision( $entity_type, $group_name, self::$groups[ $entity_type ][ $group_name ], $normalized );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 建立索引以供快速查詢
|
||||
foreach ( $normalized as $normalized_field ) {
|
||||
self::$field_index[ $entity_type ][ $normalized_field['key'] ] = $normalized_field;
|
||||
}
|
||||
|
||||
self::$groups[ $entity_type ][ $group_name ] = $normalized;
|
||||
|
||||
// 加入待建表佇列
|
||||
@@ -162,6 +171,51 @@ final class TMDO_Entity_Registry {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 記錄同名群組衝突(每個 entity/group 每請求一筆),並寫入 warning。
|
||||
*
|
||||
* 註冊每個請求都會跑,warning 以 transient 節流為每天一次,避免灌爆 wpdo_errors。
|
||||
*/
|
||||
private static function record_collision( string $entity_type, string $group_name, array $existing, array $incoming ): void {
|
||||
$id = $entity_type . '/' . $group_name;
|
||||
if ( isset( self::$collisions[ $id ] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$old = array_column( $existing, null, 'key' );
|
||||
$new = array_column( $incoming, null, 'key' );
|
||||
|
||||
$changed = array();
|
||||
foreach ( array_intersect_key( $new, $old ) as $key => $field ) {
|
||||
if ( $field !== $old[ $key ] ) {
|
||||
$changed[] = (string) $key;
|
||||
}
|
||||
}
|
||||
|
||||
self::$collisions[ $id ] = array(
|
||||
'entity_type' => $entity_type,
|
||||
'group' => $group_name,
|
||||
'added' => array_map( 'strval', array_keys( array_diff_key( $new, $old ) ) ),
|
||||
'removed' => array_map( 'strval', array_keys( array_diff_key( $old, $new ) ) ),
|
||||
'changed' => $changed,
|
||||
);
|
||||
|
||||
$throttle = 'tmdo_group_collision_' . md5( (string) wp_json_encode( self::$collisions[ $id ] ) );
|
||||
if ( class_exists( 'TMDO_Logger' ) && false === get_transient( $throttle ) ) {
|
||||
set_transient( $throttle, 1, DAY_IN_SECONDS );
|
||||
TMDO_Logger::warning( 'entity_group_collision', self::$collisions[ $id ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 本請求偵測到的同名群組衝突(第二份定義已被捨棄)。
|
||||
*
|
||||
* @return array<int, array{entity_type:string, group:string, added:string[], removed:string[], changed:string[]}>
|
||||
*/
|
||||
public static function get_collisions(): array {
|
||||
return array_values( self::$collisions );
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────
|
||||
// 查詢 API
|
||||
// ─────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user