76c01e44df
對齊 A v3.2.0。型別強制會把隱式轉換變成 TypeError,所以一次全檔加入 並跑完整測試(unit 451 / integration 398 全綠,無迴歸)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
229 lines
7.5 KiB
PHP
229 lines
7.5 KiB
PHP
<?php
|
||
/**
|
||
* TMDO_Entity_Registry - 全域欄位與適配器登錄中心
|
||
*
|
||
* 提供:
|
||
* - 適配器註冊(post/user/term/comment)
|
||
* - 欄位群組註冊(Schema 定義)
|
||
* - 欄位查詢 API(meta_key → field_def)
|
||
*
|
||
* @package WP_Data_Optimizer
|
||
*/
|
||
|
||
declare(strict_types=1);
|
||
|
||
// 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_Entity_Registry {
|
||
|
||
/** @var array<string, TMDO_Entity_Adapter_Interface> 實體類型 → 適配器實例 */
|
||
private static array $adapters = array();
|
||
|
||
/** @var array<string, array<string, array>> 實體類型 → 群組名 → 欄位定義陣列 */
|
||
private static array $groups = array();
|
||
|
||
/** @var array<string, array<string, array>> 實體類型 → meta_key → 欄位定義(含 group 資訊)*/
|
||
private static array $field_index = array();
|
||
|
||
/** @var array<int, array{type:string, group:string, fields:array}> 待建表的 Schema 清單 */
|
||
private static array $pending_schemas = array();
|
||
|
||
/** 合法的欄位型別 */
|
||
public const VALID_TYPES = array(
|
||
'text',
|
||
'textarea',
|
||
'integer',
|
||
'decimal',
|
||
'boolean',
|
||
'date',
|
||
'datetime',
|
||
'timestamp',
|
||
'json',
|
||
'enum',
|
||
'binary',
|
||
);
|
||
|
||
/** 合法的實體類型 */
|
||
public const VALID_ENTITY_TYPES = array( 'post', 'user', 'term', 'comment' );
|
||
|
||
public static function init(): void {
|
||
self::$adapters = array();
|
||
self::$groups = array();
|
||
self::$field_index = array();
|
||
self::$pending_schemas = array();
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// 適配器管理
|
||
// ─────────────────────────────────────────────────────────
|
||
|
||
public static function register_adapter( string $entity_type, TMDO_Entity_Adapter_Interface $adapter ): void {
|
||
if ( ! in_array( $entity_type, self::VALID_ENTITY_TYPES, true ) ) {
|
||
return;
|
||
}
|
||
self::$adapters[ $entity_type ] = $adapter;
|
||
}
|
||
|
||
public static function get_adapter( string $entity_type ): ?TMDO_Entity_Adapter_Interface {
|
||
return self::$adapters[ $entity_type ] ?? null;
|
||
}
|
||
|
||
public static function get_all_adapters(): array {
|
||
return self::$adapters;
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// 欄位群組登錄
|
||
// ─────────────────────────────────────────────────────────
|
||
|
||
/**
|
||
* 登錄一組 UAE 管理的欄位
|
||
*
|
||
* @param string $entity_type post|user|term|comment
|
||
* @param string $group_name 群組名稱(會成為表名的一部分)
|
||
* @param array $fields 欄位定義陣列,每項需有 key、type,選填:
|
||
* - required (bool)
|
||
* - default (mixed)
|
||
* - searchable (bool) 加索引
|
||
* - fulltext (bool) 全文索引(僅 text/textarea)
|
||
* - unique (bool) 唯一索引
|
||
* - options (array) enum 選項
|
||
* - label (string) 顯示名稱
|
||
*
|
||
* @return bool
|
||
*/
|
||
public static function register_group( string $entity_type, string $group_name, array $fields ): bool {
|
||
|
||
if ( ! in_array( $entity_type, self::VALID_ENTITY_TYPES, true ) ) {
|
||
return false;
|
||
}
|
||
|
||
if ( ! isset( self::$adapters[ $entity_type ] ) ) {
|
||
return false;
|
||
}
|
||
|
||
// 防重複登錄
|
||
if ( isset( self::$groups[ $entity_type ][ $group_name ] ) ) {
|
||
return false;
|
||
}
|
||
|
||
// 驗證並正規化欄位定義
|
||
$normalized = array();
|
||
|
||
foreach ( $fields as $field ) {
|
||
if ( empty( $field['key'] ) || empty( $field['type'] ) ) {
|
||
continue;
|
||
}
|
||
|
||
if ( ! in_array( $field['type'], self::VALID_TYPES, true ) ) {
|
||
continue;
|
||
}
|
||
|
||
$normalized_field = wp_parse_args(
|
||
$field,
|
||
array(
|
||
'key' => '',
|
||
'type' => 'text',
|
||
'required' => false,
|
||
'default' => null,
|
||
'searchable' => false,
|
||
'fulltext' => false,
|
||
'unique' => false,
|
||
'options' => array(),
|
||
'label' => '',
|
||
)
|
||
);
|
||
|
||
$normalized_field['group'] = $group_name;
|
||
$normalized_field['entity_type'] = $entity_type;
|
||
|
||
$normalized[] = $normalized_field;
|
||
|
||
// 建立索引以供快速查詢
|
||
self::$field_index[ $entity_type ][ $normalized_field['key'] ] = $normalized_field;
|
||
}
|
||
|
||
if ( empty( $normalized ) ) {
|
||
return false;
|
||
}
|
||
|
||
self::$groups[ $entity_type ][ $group_name ] = $normalized;
|
||
|
||
// 加入待建表佇列
|
||
self::$pending_schemas[] = array(
|
||
'type' => $entity_type,
|
||
'group' => $group_name,
|
||
'fields' => $normalized,
|
||
);
|
||
|
||
return true;
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// 查詢 API
|
||
// ─────────────────────────────────────────────────────────
|
||
|
||
/**
|
||
* 依 meta_key 查詢欄位定義
|
||
*
|
||
* @return array|null 欄位定義,或 null(非 UAE 管理欄位)
|
||
*/
|
||
public static function get_field( string $entity_type, string $meta_key ): ?array {
|
||
return self::$field_index[ $entity_type ][ $meta_key ] ?? null;
|
||
}
|
||
|
||
/**
|
||
* 取得實體類型下所有群組名稱
|
||
*
|
||
* @return array<string>
|
||
*/
|
||
public static function get_groups_for_type( string $entity_type ): array {
|
||
return array_keys( self::$groups[ $entity_type ] ?? array() );
|
||
}
|
||
|
||
/**
|
||
* 取得特定群組的完整欄位定義
|
||
*/
|
||
public static function get_group_fields( string $entity_type, string $group_name ): array {
|
||
return self::$groups[ $entity_type ][ $group_name ] ?? array();
|
||
}
|
||
|
||
/**
|
||
* 取得一個群組中所有 meta_key
|
||
*
|
||
* @return array<string>
|
||
*/
|
||
public static function get_group_keys( string $entity_type, string $group_name ): array {
|
||
$fields = self::get_group_fields( $entity_type, $group_name );
|
||
return array_column( $fields, 'key' );
|
||
}
|
||
|
||
/**
|
||
* 取得所有已登錄的欄位(跨實體、跨群組)
|
||
*/
|
||
public static function get_all_fields(): array {
|
||
return self::$field_index;
|
||
}
|
||
|
||
/**
|
||
* 取得待建表清單(供 Schema_Manager 處理)
|
||
*/
|
||
public static function get_pending_schemas(): array {
|
||
return self::$pending_schemas;
|
||
}
|
||
|
||
public static function clear_pending_schemas(): void {
|
||
self::$pending_schemas = array();
|
||
}
|
||
|
||
/**
|
||
* 判斷某個 meta_key 是否由 UAE 管理
|
||
*/
|
||
public static function is_managed( string $entity_type, string $meta_key ): bool {
|
||
return isset( self::$field_index[ $entity_type ][ $meta_key ] );
|
||
}
|
||
}
|