build: 移植 PHPCS + PHPStan L6 品質 gate(PR-I 前半)

- phpcs.xml(自 A 移植):ruleset 改名、*/tools/* 例外換成 */back-compat/*、
  中文註解全域排除 Squiz.Commenting.InlineComment.InvalidEndChar、
  interface 別名檔排除 OneObjectStructurePerFile
- 檔頭正規化:16 個檔案的 declare(strict_types=1) 與前導 // 註解移到
  file docblock 之後,並移除 <?php 後多餘空行(phpcbf 另自動修 190 處)
- phpstan.neon + .phpstan/stubs.php(TMDO_ 與 WPDO_ 兩套常數)+
  重新產生的 phpstan-baseline.neon(710 errors,A 的 3877 行 baseline
  因前綴與路徑不同無法沿用)

現況:PHPCS 0 errors / 0 warnings、PHPStan L6 No errors、
unit 451 / integration 398 GREEN

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 06:22:00 +08:00
parent 76c01e44df
commit f524ea3f16
23 changed files with 4356 additions and 340 deletions
+4 -3
View File
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform diagnostic: raw meta inspection for FSM state advisor
/**
* TMDO_FSM_Advisor — Recommends the next FSM state per module (v2.4.0 M12).
*
@@ -24,6 +21,10 @@ declare(strict_types=1);
* @package WP_Data_Optimizer
*/
// phpcs:ignore WPDO.AntiEAV -- platform diagnostic: raw meta inspection for FSM state advisor
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+113 -113
View File
@@ -17,121 +17,121 @@ if ( ! defined( 'ABSPATH' ) ) {
// ── 公開合約類別(Phase 1 凍結,不可移除)─────────────────────────────
$tmdo_class_aliases = array(
'TMDO_API' => 'WPDO_API',
'TMDO_Schema_Registry' => 'WPDO_Schema_Registry',
'TMDO_Entity_Registry' => 'WPDO_Entity_Registry',
'TMDO_Custom_Table_Registry' => 'WPDO_Custom_Table_Registry',
'TMDO_Feature_Flags' => 'WPDO_Feature_Flags',
'TMDO_DB' => 'WPDO_DB',
'TMDO_Crypto' => 'WPDO_Crypto',
'TMDO_Logger' => 'WPDO_Logger',
'TMDO_Capability' => 'WPDO_Capability',
'TMDO_Safe_Unserialize' => 'WPDO_Safe_Unserialize',
'TMDO_API' => 'WPDO_API',
'TMDO_Schema_Registry' => 'WPDO_Schema_Registry',
'TMDO_Entity_Registry' => 'WPDO_Entity_Registry',
'TMDO_Custom_Table_Registry' => 'WPDO_Custom_Table_Registry',
'TMDO_Feature_Flags' => 'WPDO_Feature_Flags',
'TMDO_DB' => 'WPDO_DB',
'TMDO_Crypto' => 'WPDO_Crypto',
'TMDO_Logger' => 'WPDO_Logger',
'TMDO_Capability' => 'WPDO_Capability',
'TMDO_Safe_Unserialize' => 'WPDO_Safe_Unserialize',
// Engine / Migration / Adapterssecond-tier,部分 sister plugin 已直接呼叫)
'TMDO_Hook_Bus' => 'WPDO_Hook_Bus',
'TMDO_Mode_Manager' => 'WPDO_Mode_Manager',
'TMDO_Migration_Engine' => 'WPDO_Migration_Engine',
'TMDO_Migration_Orchestrator' => 'WPDO_Migration_Orchestrator',
'TMDO_Entity_Migration_Engine' => 'WPDO_Entity_Migration_Engine',
'TMDO_Entity_Health' => 'WPDO_Entity_Health',
'TMDO_Schema_Manager' => 'WPDO_Schema_Manager',
'TMDO_Sync_Bridge' => 'WPDO_Sync_Bridge',
'TMDO_Query_Router' => 'WPDO_Query_Router',
'TMDO_Post_Query_Router' => 'WPDO_Post_Query_Router',
'TMDO_Hook_Bus_Bridge' => 'WPDO_Hook_Bus_Bridge',
'TMDO_Conflict_Monitor' => 'WPDO_Conflict_Monitor',
'TMDO_Compatibility' => 'WPDO_Compatibility',
'TMDO_Installer' => 'WPDO_Installer',
'TMDO_Cache_Layer' => 'WPDO_Cache_Layer',
'TMDO_Zone_Classifier' => 'WPDO_Zone_Classifier',
'TMDO_Core' => 'WPDO_Core',
'TMDO_REST_API' => 'WPDO_REST_API',
'TMDO_Snapshot_Manager' => 'WPDO_Snapshot_Manager',
'TMDO_Snapshot_Writer' => 'WPDO_Snapshot_Writer',
'TMDO_Snapshot_Reader' => 'WPDO_Snapshot_Reader',
'TMDO_Snapshot_Pruner' => 'WPDO_Snapshot_Pruner',
'TMDO_FSM_Guard' => 'WPDO_FSM_Guard',
'TMDO_Site_Health' => 'WPDO_Site_Health',
'TMDO_Health_Cron' => 'WPDO_Health_Cron',
'TMDO_Email_Notifier' => 'WPDO_Email_Notifier',
'TMDO_Slack_Notifier' => 'WPDO_Slack_Notifier',
'TMDO_Discord_Notifier' => 'WPDO_Discord_Notifier',
'TMDO_Telegram_Notifier' => 'WPDO_Telegram_Notifier',
'TMDO_Monthly_Summary' => 'WPDO_Monthly_Summary',
'TMDO_Site_Metrics_Collector' => 'WPDO_Site_Metrics_Collector',
'TMDO_FSM_Advisor' => 'WPDO_FSM_Advisor',
'TMDO_Module_Detector' => 'WPDO_Module_Detector',
'TMDO_FSM_Automator' => 'WPDO_FSM_Automator',
'TMDO_Module_Rules' => 'WPDO_Module_Rules',
'TMDO_CSV_Writer' => 'WPDO_CSV_Writer',
'TMDO_Export' => 'WPDO_Export',
'TMDO_CLI' => 'WPDO_CLI',
'TMDO_CLI_V2' => 'WPDO_CLI_V2',
'TMDO_CLI_Member' => 'WPDO_CLI_Member',
'TMDO_CLI_Post' => 'WPDO_CLI_Post',
'TMDO_CLI_Term_Comment' => 'WPDO_CLI_Term_Comment',
'TMDO_Member_Fields' => 'WPDO_Member_Fields',
'TMDO_Post_Fields' => 'WPDO_Post_Fields',
'TMDO_Points_Manager' => 'WPDO_Points_Manager',
'TMDO_Demo_Entity_Counter' => 'WPDO_Demo_Entity_Counter',
'TMDO_Postmeta_Cleaner' => 'WPDO_Postmeta_Cleaner',
'TMDO_Termmeta_Cleaner' => 'WPDO_Termmeta_Cleaner',
'TMDO_Commentmeta_Cleaner' => 'WPDO_Commentmeta_Cleaner',
'TMDO_Post_Stress_Tester' => 'WPDO_Post_Stress_Tester',
'TMDO_User_Stress_Tester' => 'WPDO_User_Stress_Tester',
'TMDO_Term_Stress_Tester' => 'WPDO_Term_Stress_Tester',
'TMDO_Comment_Stress_Tester' => 'WPDO_Comment_Stress_Tester',
'TMDO_Post_Shadow_Verifier' => 'WPDO_Post_Shadow_Verifier',
'TMDO_Hook_Bus' => 'WPDO_Hook_Bus',
'TMDO_Mode_Manager' => 'WPDO_Mode_Manager',
'TMDO_Migration_Engine' => 'WPDO_Migration_Engine',
'TMDO_Migration_Orchestrator' => 'WPDO_Migration_Orchestrator',
'TMDO_Entity_Migration_Engine' => 'WPDO_Entity_Migration_Engine',
'TMDO_Entity_Health' => 'WPDO_Entity_Health',
'TMDO_Schema_Manager' => 'WPDO_Schema_Manager',
'TMDO_Sync_Bridge' => 'WPDO_Sync_Bridge',
'TMDO_Query_Router' => 'WPDO_Query_Router',
'TMDO_Post_Query_Router' => 'WPDO_Post_Query_Router',
'TMDO_Hook_Bus_Bridge' => 'WPDO_Hook_Bus_Bridge',
'TMDO_Conflict_Monitor' => 'WPDO_Conflict_Monitor',
'TMDO_Compatibility' => 'WPDO_Compatibility',
'TMDO_Installer' => 'WPDO_Installer',
'TMDO_Cache_Layer' => 'WPDO_Cache_Layer',
'TMDO_Zone_Classifier' => 'WPDO_Zone_Classifier',
'TMDO_Core' => 'WPDO_Core',
'TMDO_REST_API' => 'WPDO_REST_API',
'TMDO_Snapshot_Manager' => 'WPDO_Snapshot_Manager',
'TMDO_Snapshot_Writer' => 'WPDO_Snapshot_Writer',
'TMDO_Snapshot_Reader' => 'WPDO_Snapshot_Reader',
'TMDO_Snapshot_Pruner' => 'WPDO_Snapshot_Pruner',
'TMDO_FSM_Guard' => 'WPDO_FSM_Guard',
'TMDO_Site_Health' => 'WPDO_Site_Health',
'TMDO_Health_Cron' => 'WPDO_Health_Cron',
'TMDO_Email_Notifier' => 'WPDO_Email_Notifier',
'TMDO_Slack_Notifier' => 'WPDO_Slack_Notifier',
'TMDO_Discord_Notifier' => 'WPDO_Discord_Notifier',
'TMDO_Telegram_Notifier' => 'WPDO_Telegram_Notifier',
'TMDO_Monthly_Summary' => 'WPDO_Monthly_Summary',
'TMDO_Site_Metrics_Collector' => 'WPDO_Site_Metrics_Collector',
'TMDO_FSM_Advisor' => 'WPDO_FSM_Advisor',
'TMDO_Module_Detector' => 'WPDO_Module_Detector',
'TMDO_FSM_Automator' => 'WPDO_FSM_Automator',
'TMDO_Module_Rules' => 'WPDO_Module_Rules',
'TMDO_CSV_Writer' => 'WPDO_CSV_Writer',
'TMDO_Export' => 'WPDO_Export',
'TMDO_CLI' => 'WPDO_CLI',
'TMDO_CLI_V2' => 'WPDO_CLI_V2',
'TMDO_CLI_Member' => 'WPDO_CLI_Member',
'TMDO_CLI_Post' => 'WPDO_CLI_Post',
'TMDO_CLI_Term_Comment' => 'WPDO_CLI_Term_Comment',
'TMDO_Member_Fields' => 'WPDO_Member_Fields',
'TMDO_Post_Fields' => 'WPDO_Post_Fields',
'TMDO_Points_Manager' => 'WPDO_Points_Manager',
'TMDO_Demo_Entity_Counter' => 'WPDO_Demo_Entity_Counter',
'TMDO_Postmeta_Cleaner' => 'WPDO_Postmeta_Cleaner',
'TMDO_Termmeta_Cleaner' => 'WPDO_Termmeta_Cleaner',
'TMDO_Commentmeta_Cleaner' => 'WPDO_Commentmeta_Cleaner',
'TMDO_Post_Stress_Tester' => 'WPDO_Post_Stress_Tester',
'TMDO_User_Stress_Tester' => 'WPDO_User_Stress_Tester',
'TMDO_Term_Stress_Tester' => 'WPDO_Term_Stress_Tester',
'TMDO_Comment_Stress_Tester' => 'WPDO_Comment_Stress_Tester',
'TMDO_Post_Shadow_Verifier' => 'WPDO_Post_Shadow_Verifier',
'TMDO_Term_Comment_Shadow_Verifier' => 'WPDO_Term_Comment_Shadow_Verifier',
'TMDO_Term_Comment_Backfill' => 'WPDO_Term_Comment_Backfill',
'TMDO_Term_Comment_Misc_Bucket' => 'WPDO_Term_Comment_Misc_Bucket',
'TMDO_Term_Comment_Garbage_Filter' => 'WPDO_Term_Comment_Garbage_Filter',
'TMDO_Setup_Wizard' => 'WPDO_Setup_Wizard',
'TMDO_Dashboard_Widget' => 'WPDO_Dashboard_Widget',
'TMDO_Help_Tabs' => 'WPDO_Help_Tabs',
'TMDO_Admin' => 'WPDO_Admin',
'TMDO_V2_Upgrader' => 'WPDO_V2_Upgrader',
'TMDO_SQLite_Compat' => 'WPDO_SQLite_Compat',
'TMDO_Type_Caster' => 'WPDO_Type_Caster',
'TMDO_Audit_Logger' => 'WPDO_Audit_Logger',
'TMDO_Shadow_Diff_Logger' => 'WPDO_Shadow_Diff_Logger',
'TMDO_Conflict_Detector' => 'WPDO_Conflict_Detector',
'TMDO_Cache_Orchestrator' => 'WPDO_Cache_Orchestrator',
'TMDO_Query_Compiler' => 'WPDO_Query_Compiler',
'TMDO_Auto_Promoter' => 'WPDO_Auto_Promoter',
'TMDO_Adapter_Post' => 'WPDO_Adapter_Post',
'TMDO_Adapter_User' => 'WPDO_Adapter_User',
'TMDO_Adapter_Term' => 'WPDO_Adapter_Term',
'TMDO_Adapter_Comment' => 'WPDO_Adapter_Comment',
'TMDO_Options_Manager' => 'WPDO_Options_Manager',
'TMDO_Hot_Migration' => 'WPDO_Hot_Migration',
'TMDO_Warm_Migration' => 'WPDO_Warm_Migration',
'TMDO_Cold_Migration' => 'WPDO_Cold_Migration',
'TMDO_Archive_Migration' => 'WPDO_Archive_Migration',
'TMDO_Migration_Base' => 'WPDO_Migration_Base',
'TMDO_Post_Migration' => 'WPDO_Post_Migration',
'TMDO_Zone_Hot' => 'WPDO_Zone_Hot',
'TMDO_Zone_Warm' => 'WPDO_Zone_Warm',
'TMDO_Zone_Cold' => 'WPDO_Zone_Cold',
'TMDO_Zone_Router' => 'WPDO_Zone_Router',
'TMDO_Routing_Predicate' => 'WPDO_Routing_Predicate',
'TMDO_Migration_Phase_Base' => 'WPDO_Migration_Phase_Base',
'TMDO_Phase_Diagnose' => 'WPDO_Phase_Diagnose',
'TMDO_Phase_Backup' => 'WPDO_Phase_Backup',
'TMDO_Phase_Demote' => 'WPDO_Phase_Demote',
'TMDO_Phase_Install_Schema' => 'WPDO_Phase_Install_Schema',
'TMDO_Phase_Backfill_Bulk' => 'WPDO_Phase_Backfill_Bulk',
'TMDO_Phase_Backfill_Unserialize' => 'WPDO_Phase_Backfill_Unserialize',
'TMDO_Phase_Promote_Shadow' => 'WPDO_Phase_Promote_Shadow',
'TMDO_Phase_Verify_Sample' => 'WPDO_Phase_Verify_Sample',
'TMDO_Phase_Promote_Aeav' => 'WPDO_Phase_Promote_Aeav',
'TMDO_Phase_Cleanup' => 'WPDO_Phase_Cleanup',
'TMDO_Phase_Completed' => 'WPDO_Phase_Completed',
'TMDO_Zone_Archive' => 'WPDO_Zone_Archive',
'TMDO_Interceptor_Base' => 'WPDO_Interceptor_Base',
'TMDO_Standard_Post_Interceptor' => 'WPDO_Standard_Post_Interceptor',
'TMDO_Query_Interceptor_Base' => 'WPDO_Query_Interceptor_Base',
'TMDO_Abstract_Notifier' => 'WPDO_Abstract_Notifier',
'TMDO_Term_Comment_Backfill' => 'WPDO_Term_Comment_Backfill',
'TMDO_Term_Comment_Misc_Bucket' => 'WPDO_Term_Comment_Misc_Bucket',
'TMDO_Term_Comment_Garbage_Filter' => 'WPDO_Term_Comment_Garbage_Filter',
'TMDO_Setup_Wizard' => 'WPDO_Setup_Wizard',
'TMDO_Dashboard_Widget' => 'WPDO_Dashboard_Widget',
'TMDO_Help_Tabs' => 'WPDO_Help_Tabs',
'TMDO_Admin' => 'WPDO_Admin',
'TMDO_V2_Upgrader' => 'WPDO_V2_Upgrader',
'TMDO_SQLite_Compat' => 'WPDO_SQLite_Compat',
'TMDO_Type_Caster' => 'WPDO_Type_Caster',
'TMDO_Audit_Logger' => 'WPDO_Audit_Logger',
'TMDO_Shadow_Diff_Logger' => 'WPDO_Shadow_Diff_Logger',
'TMDO_Conflict_Detector' => 'WPDO_Conflict_Detector',
'TMDO_Cache_Orchestrator' => 'WPDO_Cache_Orchestrator',
'TMDO_Query_Compiler' => 'WPDO_Query_Compiler',
'TMDO_Auto_Promoter' => 'WPDO_Auto_Promoter',
'TMDO_Adapter_Post' => 'WPDO_Adapter_Post',
'TMDO_Adapter_User' => 'WPDO_Adapter_User',
'TMDO_Adapter_Term' => 'WPDO_Adapter_Term',
'TMDO_Adapter_Comment' => 'WPDO_Adapter_Comment',
'TMDO_Options_Manager' => 'WPDO_Options_Manager',
'TMDO_Hot_Migration' => 'WPDO_Hot_Migration',
'TMDO_Warm_Migration' => 'WPDO_Warm_Migration',
'TMDO_Cold_Migration' => 'WPDO_Cold_Migration',
'TMDO_Archive_Migration' => 'WPDO_Archive_Migration',
'TMDO_Migration_Base' => 'WPDO_Migration_Base',
'TMDO_Post_Migration' => 'WPDO_Post_Migration',
'TMDO_Zone_Hot' => 'WPDO_Zone_Hot',
'TMDO_Zone_Warm' => 'WPDO_Zone_Warm',
'TMDO_Zone_Cold' => 'WPDO_Zone_Cold',
'TMDO_Zone_Router' => 'WPDO_Zone_Router',
'TMDO_Routing_Predicate' => 'WPDO_Routing_Predicate',
'TMDO_Migration_Phase_Base' => 'WPDO_Migration_Phase_Base',
'TMDO_Phase_Diagnose' => 'WPDO_Phase_Diagnose',
'TMDO_Phase_Backup' => 'WPDO_Phase_Backup',
'TMDO_Phase_Demote' => 'WPDO_Phase_Demote',
'TMDO_Phase_Install_Schema' => 'WPDO_Phase_Install_Schema',
'TMDO_Phase_Backfill_Bulk' => 'WPDO_Phase_Backfill_Bulk',
'TMDO_Phase_Backfill_Unserialize' => 'WPDO_Phase_Backfill_Unserialize',
'TMDO_Phase_Promote_Shadow' => 'WPDO_Phase_Promote_Shadow',
'TMDO_Phase_Verify_Sample' => 'WPDO_Phase_Verify_Sample',
'TMDO_Phase_Promote_Aeav' => 'WPDO_Phase_Promote_Aeav',
'TMDO_Phase_Cleanup' => 'WPDO_Phase_Cleanup',
'TMDO_Phase_Completed' => 'WPDO_Phase_Completed',
'TMDO_Zone_Archive' => 'WPDO_Zone_Archive',
'TMDO_Interceptor_Base' => 'WPDO_Interceptor_Base',
'TMDO_Standard_Post_Interceptor' => 'WPDO_Standard_Post_Interceptor',
'TMDO_Query_Interceptor_Base' => 'WPDO_Query_Interceptor_Base',
'TMDO_Abstract_Notifier' => 'WPDO_Abstract_Notifier',
);
foreach ( $tmdo_class_aliases as $tmdo_class => $wpdo_alias ) {
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
/**
* TMDO_Comment_Stress_Tester — Async stress fixture generator for comment entity (v2.13.1).
*
@@ -23,6 +20,10 @@ declare(strict_types=1);
* @since 2.13.1
*/
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+4 -3
View File
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform shadow verifier: must read raw meta to verify zone correctness
/**
* TMDO_Post_Shadow_Verifier — Sample-and-compare flat vs wp_postmeta (v2.10.3).
*
@@ -24,6 +21,10 @@ declare(strict_types=1);
* @since 2.10.3
*/
// phpcs:ignore WPDO.AntiEAV -- platform shadow verifier: must read raw meta to verify zone correctness
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+4 -3
View File
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
/**
* TMDO_Post_Stress_Tester — Bulk fixture generator for post entity migration (v2.9.4).
*
@@ -28,6 +25,10 @@ declare(strict_types=1);
* @since 2.9.4
*/
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+4 -3
View File
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
/**
* TMDO_Term_Stress_Tester — Async stress fixture generator for term entity (v2.13.0).
*
@@ -24,6 +21,10 @@ declare(strict_types=1);
* @since 2.13.0
*/
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+4 -3
View File
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
/**
* TMDO_User_Stress_Tester — User entity 壓力測試 / Benchmark 工具
*
@@ -18,6 +15,10 @@ declare(strict_types=1);
* @since 2.6.7
*/
// phpcs:ignore WPDO.AntiEAV -- platform stress tester: intentional raw meta SQL for baseline comparison
declare(strict_types=1);
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare,Generic.CodeAnalysis.UnusedFunctionParameter,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.PHP.YodaConditions,WordPress.WP.AlternativeFunctions.rand_mt_rand,WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- 測試工具:mt_rand 用於杜撰測試資料;serialize() 為 WP capabilities 標準格式
defined( 'ABSPATH' ) || exit;
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform diagnostic: raw meta inspection for site health
/**
* TMDO_Site_Health — WordPress Site Health integration (v2.2.0 M3).
*
@@ -19,6 +16,10 @@ declare(strict_types=1);
* @package WP_Data_Optimizer
*/
// phpcs:ignore WPDO.AntiEAV -- platform diagnostic: raw meta inspection for site health
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@@ -1,7 +1,4 @@
<?php
declare(strict_types=1);
// phpcs:ignore WPDO.AntiEAV -- platform migration tool: WPDO v1->v2 legacy post meta migration
/**
* TMDO_Post_Migration — Post entity migration core (v2.9.3).
*
@@ -35,6 +32,10 @@ declare(strict_types=1);
* @since 2.9.3
*/
// phpcs:ignore WPDO.AntiEAV -- platform migration tool: WPDO v1->v2 legacy post meta migration
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+175 -175
View File
@@ -31,183 +31,183 @@ if ( ! defined( 'ABSPATH' ) ) {
// the same trait body in memory.
if ( ! trait_exists( 'TMDO_Anti_EAV_Aware' ) ) {
trait TMDO_Anti_EAV_Aware {
trait TMDO_Anti_EAV_Aware {
/**
* Plugin slug used as provider identifier when registering fields/tables.
*
* Partner plugins SHOULD override this with their canonical slug
* (e.g. 'tmos-core', 'tmos-events'). Default returns lowercased class name
* for backward compatibility with older partner plugins that didn't define
* a slug.
*/
protected function plugin_slug(): string {
return strtolower( static::class );
}
/**
* Attach the three `wpdo_register_*` hooks to the corresponding
* `on_register_*` methods. Call once during plugin boot.
*
* Idempotent — safe to call multiple times because WP de-dupes
* identical (action, callback) pairs.
*/
protected function bind_anti_eav_hooks(): void {
add_action( 'wpdo_register_fields', array( $this, 'on_register_fields' ), 10, 1 );
add_action( 'wpdo_register_custom_tables', array( $this, 'on_register_custom_tables' ), 10, 1 );
add_action( 'wpdo_register_entity_fields', array( $this, 'on_register_entity_fields' ), 10, 0 );
}
// ── Hook handlers (override in subclass) ─────────────────────────────────
/**
* Register hot/warm/cold/archive zone field mappings.
*
* Override in subclass and call `$this->register_field( $registry, [...] )`
* for each post-meta key the plugin manages.
*
* @param TMDO_Schema_Registry $registry The shared field registry.
*/
public function on_register_fields( TMDO_Schema_Registry $registry ): void {
// Default no-op. Override in subclass.
}
/**
* Register custom tables owned by this plugin.
*
* Override in subclass and call `$this->register_custom_table( $r, [...] )`
* for each table.
*
* @param TMDO_Custom_Table_Registry $r The shared custom-table registry.
*/
public function on_register_custom_tables( TMDO_Custom_Table_Registry $r ): void {
// Default no-op. Override in subclass.
}
/**
* Register entity field groups (user / term / comment / post metadata).
*
* Override in subclass and call `$this->register_entity_fields( $type, $group, [...] )`
* for each logical field group the plugin contributes.
*/
public function on_register_entity_fields(): void {
// Default no-op. Override in subclass.
}
// ── Sugar wrappers around WPDO public API ────────────────────────────────
/**
* Register a single zone field via TMDO_Schema_Registry.
*
* @param TMDO_Schema_Registry $registry Provided by the `wpdo_register_fields` hook.
* @param array<string,mixed> $field_def Field definition (post_type, meta_key, zone, ...).
*/
protected function register_field( TMDO_Schema_Registry $registry, array $field_def ): void {
$registry->register( $this->plugin_slug(), $field_def );
}
/**
* Register a custom table via TMDO_Custom_Table_Registry.
*
* @param TMDO_Custom_Table_Registry $r Provided by the `wpdo_register_custom_tables` hook.
* @param array<string,mixed> $table_def Table definition (table_name, primary_key, expected_columns, indexes, ...).
*/
protected function register_custom_table( TMDO_Custom_Table_Registry $r, array $table_def ): void {
$r->register( $this->plugin_slug(), $table_def );
}
/**
* Register an entity field group via TMDO_Entity_Registry.
*
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
* @param string $group_name Logical group name (e.g. 'tmos_vendor', 'tmos_audience').
* @param array<int,array<string,mixed>> $fields Field definitions.
*/
protected function register_entity_fields( string $entity_type, string $group_name, array $fields ): bool {
if ( ! class_exists( 'TMDO_Entity_Registry' ) ) {
return false;
/**
* Plugin slug used as provider identifier when registering fields/tables.
*
* Partner plugins SHOULD override this with their canonical slug
* (e.g. 'tmos-core', 'tmos-events'). Default returns lowercased class name
* for backward compatibility with older partner plugins that didn't define
* a slug.
*/
protected function plugin_slug(): string {
return strtolower( static::class );
}
/**
* Attach the three `wpdo_register_*` hooks to the corresponding
* `on_register_*` methods. Call once during plugin boot.
*
* Idempotent — safe to call multiple times because WP de-dupes
* identical (action, callback) pairs.
*/
protected function bind_anti_eav_hooks(): void {
add_action( 'wpdo_register_fields', array( $this, 'on_register_fields' ), 10, 1 );
add_action( 'wpdo_register_custom_tables', array( $this, 'on_register_custom_tables' ), 10, 1 );
add_action( 'wpdo_register_entity_fields', array( $this, 'on_register_entity_fields' ), 10, 0 );
}
// ── Hook handlers (override in subclass) ─────────────────────────────────
/**
* Register hot/warm/cold/archive zone field mappings.
*
* Override in subclass and call `$this->register_field( $registry, [...] )`
* for each post-meta key the plugin manages.
*
* @param TMDO_Schema_Registry $registry The shared field registry.
*/
public function on_register_fields( TMDO_Schema_Registry $registry ): void {
// Default no-op. Override in subclass.
}
/**
* Register custom tables owned by this plugin.
*
* Override in subclass and call `$this->register_custom_table( $r, [...] )`
* for each table.
*
* @param TMDO_Custom_Table_Registry $r The shared custom-table registry.
*/
public function on_register_custom_tables( TMDO_Custom_Table_Registry $r ): void {
// Default no-op. Override in subclass.
}
/**
* Register entity field groups (user / term / comment / post metadata).
*
* Override in subclass and call `$this->register_entity_fields( $type, $group, [...] )`
* for each logical field group the plugin contributes.
*/
public function on_register_entity_fields(): void {
// Default no-op. Override in subclass.
}
// ── Sugar wrappers around WPDO public API ────────────────────────────────
/**
* Register a single zone field via TMDO_Schema_Registry.
*
* @param TMDO_Schema_Registry $registry Provided by the `wpdo_register_fields` hook.
* @param array<string,mixed> $field_def Field definition (post_type, meta_key, zone, ...).
*/
protected function register_field( TMDO_Schema_Registry $registry, array $field_def ): void {
$registry->register( $this->plugin_slug(), $field_def );
}
/**
* Register a custom table via TMDO_Custom_Table_Registry.
*
* @param TMDO_Custom_Table_Registry $r Provided by the `wpdo_register_custom_tables` hook.
* @param array<string,mixed> $table_def Table definition (table_name, primary_key, expected_columns, indexes, ...).
*/
protected function register_custom_table( TMDO_Custom_Table_Registry $r, array $table_def ): void {
$r->register( $this->plugin_slug(), $table_def );
}
/**
* Register an entity field group via TMDO_Entity_Registry.
*
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
* @param string $group_name Logical group name (e.g. 'tmos_vendor', 'tmos_audience').
* @param array<int,array<string,mixed>> $fields Field definitions.
*/
protected function register_entity_fields( string $entity_type, string $group_name, array $fields ): bool {
if ( ! class_exists( 'TMDO_Entity_Registry' ) ) {
return false;
}
return TMDO_Entity_Registry::register_group( $entity_type, $group_name, $fields );
}
// ── Read/write convenience wrappers ──────────────────────────────────────
/**
* Read an entity field via the TMDO_API facade.
*
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
* @param int $entity_id Entity primary id.
* @param string $key Meta key.
* @param bool $single Return single value (default true).
*/
protected function get_field( string $entity_type, int $entity_id, string $key, bool $single = true ): mixed {
return TMDO_API::get_entity( $entity_type, $entity_id, $key, $single );
}
/**
* Write an entity field via the TMDO_API facade.
*
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
* @param int $entity_id Entity primary id.
* @param string $key Meta key.
* @param mixed $value Meta value.
*
* @return bool|int False on failure, otherwise the meta id (add) or true (update).
*/
protected function set_field( string $entity_type, int $entity_id, string $key, mixed $value ): bool|int {
return TMDO_API::set_entity( $entity_type, $entity_id, $key, $value );
}
/**
* Subscribe to write events on a specific meta key.
*
* Convenience wrapper around `add_action('wpdo_after_write', ...)` that
* filters callbacks to the plugin's own keys via prefix match.
*
* @param string $key_prefix Meta-key prefix to react on (e.g. 'tmos_vendor_').
* @param callable $callback `function(string $entity_type, int $entity_id, string $key, mixed $value, bool $ok, string $op, mixed $before)`.
* @param int $priority WordPress action priority (default 10).
*/
protected function on_after_write( string $key_prefix, callable $callback, int $priority = 10 ): void {
add_action(
'wpdo_after_write',
static function ( $entity_type, $entity_id, $meta_key, $meta_value, $ok, $op, $before ) use ( $key_prefix, $callback ): void {
if ( is_string( $meta_key ) && str_starts_with( $meta_key, $key_prefix ) ) {
$callback( $entity_type, $entity_id, $meta_key, $meta_value, $ok, $op, $before );
}
},
$priority,
7
);
}
// ── Backward-compat (legacy 2meet-* mu-plugin trait surface) ─────────────
// The pre-v2.17.0 mu-plugin trait stub exposed two abstract static methods
// (`register_wpdo_fields`, `register_custom_tables`). Older partner plugins
// (e.g. 2meet-inquiries) implemented those static methods. The promoted
// trait keeps the names with non-abstract no-op defaults so existing
// classes continue to work without modification.
/**
* Legacy entry point for plugins that registered fields via a static method
* before v2.17.0. New partner plugins should override `on_register_fields()`
* (instance method) instead.
*
* @deprecated 2.17.0 Use instance method `on_register_fields()` + `bind_anti_eav_hooks()` instead.
*/
public static function register_wpdo_fields(): void {
// No-op default. Legacy classes overrode this and called the registry directly.
}
/**
* Legacy entry point for plugins that registered custom tables via a static
* method before v2.17.0.
*
* @deprecated 2.17.0 Use instance method `on_register_custom_tables()` + `bind_anti_eav_hooks()` instead.
*/
public static function register_custom_tables(): void {
// No-op default.
}
return TMDO_Entity_Registry::register_group( $entity_type, $group_name, $fields );
}
// ── Read/write convenience wrappers ──────────────────────────────────────
/**
* Read an entity field via the TMDO_API facade.
*
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
* @param int $entity_id Entity primary id.
* @param string $key Meta key.
* @param bool $single Return single value (default true).
*/
protected function get_field( string $entity_type, int $entity_id, string $key, bool $single = true ): mixed {
return TMDO_API::get_entity( $entity_type, $entity_id, $key, $single );
}
/**
* Write an entity field via the TMDO_API facade.
*
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
* @param int $entity_id Entity primary id.
* @param string $key Meta key.
* @param mixed $value Meta value.
*
* @return bool|int False on failure, otherwise the meta id (add) or true (update).
*/
protected function set_field( string $entity_type, int $entity_id, string $key, mixed $value ): bool|int {
return TMDO_API::set_entity( $entity_type, $entity_id, $key, $value );
}
/**
* Subscribe to write events on a specific meta key.
*
* Convenience wrapper around `add_action('wpdo_after_write', ...)` that
* filters callbacks to the plugin's own keys via prefix match.
*
* @param string $key_prefix Meta-key prefix to react on (e.g. 'tmos_vendor_').
* @param callable $callback `function(string $entity_type, int $entity_id, string $key, mixed $value, bool $ok, string $op, mixed $before)`.
* @param int $priority WordPress action priority (default 10).
*/
protected function on_after_write( string $key_prefix, callable $callback, int $priority = 10 ): void {
add_action(
'wpdo_after_write',
static function ( $entity_type, $entity_id, $meta_key, $meta_value, $ok, $op, $before ) use ( $key_prefix, $callback ): void {
if ( is_string( $meta_key ) && str_starts_with( $meta_key, $key_prefix ) ) {
$callback( $entity_type, $entity_id, $meta_key, $meta_value, $ok, $op, $before );
}
},
$priority,
7
);
}
// ── Backward-compat (legacy 2meet-* mu-plugin trait surface) ─────────────
// The pre-v2.17.0 mu-plugin trait stub exposed two abstract static methods
// (`register_wpdo_fields`, `register_custom_tables`). Older partner plugins
// (e.g. 2meet-inquiries) implemented those static methods. The promoted
// trait keeps the names with non-abstract no-op defaults so existing
// classes continue to work without modification.
/**
* Legacy entry point for plugins that registered fields via a static method
* before v2.17.0. New partner plugins should override `on_register_fields()`
* (instance method) instead.
*
* @deprecated 2.17.0 Use instance method `on_register_fields()` + `bind_anti_eav_hooks()` instead.
*/
public static function register_wpdo_fields(): void {
// No-op default. Legacy classes overrode this and called the registry directly.
}
/**
* Legacy entry point for plugins that registered custom tables via a static
* method before v2.17.0.
*
* @deprecated 2.17.0 Use instance method `on_register_custom_tables()` + `bind_anti_eav_hooks()` instead.
*/
public static function register_custom_tables(): void {
// No-op default.
}
}
} // end if ( ! trait_exists )