Files
2meet-data-optimizer/PLAN.md
T
wpdev d8e7a7190a docs(plan): 記錄 dev30 實機驗證結果
A 33 OK + 15 WC MISSING → B 49 OK / All checks passed。
alias / CLI 雙命名空間 / anti-EAV 寫入 / audit 欄位 / REST allowlist
逐項實測通過;brandcards 的 doctor_callback 在新 ABI 下仍正常。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
2026-07-31 08:30:52 +08:00

18 KiB
Raw Blame History

PLAN — 2meet Data Optimizer (核心)

完整四階段拆分計畫見 ~/.claude/plans/wp-data-optimizer-2meet-data-optimizer-zesty-liskov.md


Current state

  • Version: 0.1.0 (scaffold + 4 phase 完成 2026-05-15)
  • Phase: 全 4 phase 已完成
  • Source: 從 wp-data-optimizer v2.16.0 提煉

Phase 0 — 骨架建立 (2026-05-15)

  • 12 plugin 目錄結構(核心 + 11 AddOn
  • 主檔 2meet-data-optimizer.php + Plugin Header
  • includes/class-tmdo-bootstrap.php stub
  • uninstall.php stub
  • composer.json
  • .gitignore
  • 7 件 MDREADME / PLAN / CHANGELOG / DEPLOY / SECURITY / DESIGN / CLAUDE

Phase 1 — Core v0.1.0 (2026-05-15)

  • rsync 從 wp-data-optimizer 複製 ~110 個核心檔案,排除 HP/WC/LP/2meet 整合
  • 檔名 class-wpdo-*class-tmdo-*(含 abstract / interface / trait
  • sed 內容批次 renameWPDO_TMDO_class + 常數,hook/table/option 前綴 wpdo_ 保留共用)
  • 常數 TMDO_PLUGIN_DIRTMDO_PATH 等對齊
  • Text-domain 'wp-data-optimizer''2meet-data-optimizer'
  • 主檔重寫成完整 loaderrequire chain ~150 行)
  • tmdo_run() boot 函式 + plugins_loaded:4 action
  • late-bind safety net (priority 30) 確保 AddOn listener 收到 hook
  • includes/class-tmdo-back-compat.php — 80+ class_alias + 8 常數 alias + 9 hook dual-fire
  • 移除 register_hivepress_defaults() (193 行) → 搬到 HP AddOn
  • 把 core 內所有 HP/WC/LP 整合 class 引用加 class_exists 守門
  • PHP lint111 files PASS
  • Live testwp tmdo doctor 全 PASS、wp wpdo (alias) 通

Phase 1 DoD 全達標(除舊 unit/integration test 套件需後續 phase 1 follow-up


Phase 2 — Hub + Spoke AddOn v0.1.0 (2026-05-15)

Hub AddOn (2meet-data-optimizer-hub-addon)

  • TMDO_Hub_Bootstrap 主啟動類別
  • TMDO_Hub_Vendor_Field — 註冊 _2meet_global_vendor_id (hp_vendor / cold zone / indexed)
  • TMDO_Hub_Custom_Tables — 註冊 12 張 2mhc_* 自訂表(fallback 列表 + delegate to hub-core helper if available
  • dual-emit 支援 (tmdo_* + wpdo_* 兩個 hook 路徑)
  • PHP lint PASS

Spoke AddOn (2meet-data-optimizer-spoke-addon)

  • TMDO_Spoke_Bootstrap 主啟動類別
  • TMDO_Spoke_SSO_Group — 註冊 user entity sso group7 欄位 → wp_wpdo_user_sso
  • TMDO_Spoke_Custom_Tables — 註冊 2mso_sso_config / 2mso_user_mapping
  • TMDO_Spoke_CLI::sync() — 從舊 _tmso_* usermeta 遷移
  • TMDO_Spoke_CLI::force_logout() — 設置 token_expires_at = 過去
  • CLI 雙命名空間:wp tmdo spoke-* + wp wpdo spoke-*
  • PHP lint PASS

Phase 2 Live test 結果:

  • Hub: 12 hub tables 全部 OK
  • Spoke: SSO group 7 fields registered, 2 tables registered
  • CLI: wp tmdo spoke-sync --dry-run 跑通,spoke-force-logout --user-id=1 --dry-run 跑通

Phase 3 — HP + WC + LP AddOn v0.1.0 (2026-05-15)

HivePress AddOn (2meet-data-optimizer-hivepress-addon, ~7,400 行)

  • 複製 13 adaptercore / reviews / bookings / messages / memberships / requests / favorites / statistics / tags / seo / social-links / blocks / marketplace
  • 複製 7 HPCT interceptorreviews / messages / favorites / memberships / statistics / requests / listing-meta
  • 複製 5 query interceptorreviews / messages / memberships / requests / listing-meta
  • 複製 補助組件(bootstrap framework / detector / conflict-guard / comment-router / cron-optimizer / attribute-bridge / suitability-scorer / benchmark / rest
  • 複製 admin tab + CLI namespace
  • 複製 HP transient filter / HPCT import / Listing Stats / term-comment-fields
  • TMDO_HP_Bootstrap outer bootstrap(避免與 inner family bootstrap class 衝突)
  • PHP lint46 files PASS

WooCommerce AddOn (2meet-data-optimizer-woocommerce-addon, ~1,316 行)

  • 複製 4 個 WC 整合檔
  • TMDO_Woocommerce_Bootstrap 載入 + register
  • PHP lint PASS

LatePoint AddOn (2meet-data-optimizer-latepoint-addon, ~151 行)

  • 複製 LatePoint interceptor
  • TMDO_Latepoint_Bootstrap 載入 + register_hooks
  • PHP lint PASS

Phase 3 Live test 結果:

  • Plugin 全 active
  • Hot zone 20 fields registeredmostly WC product/order
  • Cold zone 3 fields
  • Total 23 fields
  • HP no-op when HivePress not installeddetector check

Phase 4 — 6 個 2meet 家族 AddOn v0.1.0 (2026-05-15)

AddOn Source Status
infocards class-tmdo-infocards.php
bookings class-tmdo-bookings.php
quotation class-tmdo-quotation.php
mobile-bridge class-tmdo-mobile-bridge.php
collab class-tmdo-collab.php
playlist class-tmdo-playlist.php

每個 AddOn 都有:

  • TMDO_{Module}_Bootstrap 啟動類別
  • 核心整合 class(從 wp-data-optimizer 搬入)
  • partner detection (early return if target plugin not installed)
  • register()wpdo_register_fields / wpdo_register_custom_tables

Phase 4 Live test 結果:

  • 6 AddOn 全 active
  • Target plugin 未安裝時正確 no-op (designed behavior)
  • 0 fatal、0 lint error

整體驗收(2026-05-15 末)

指標 結果
12 plugin active
PHP lint 全 files 203 files PASS
wp tmdo CLI 18 個 subcommand 全 listed
wp wpdo alias CLI
wp tmdo doctor system tables 全綠 + 14 partner tables 註冊
wp tmdo status 23 fields registered
SSO group 7 欄位 全 7 欄位(含 hub_global_user_id searchable
Hub-addon 12 表 全 12 表存在 + doctor PASS
Spoke-addon 2 表 註冊 OKDB 表 missing 是 spoke-sso 從未啟用之故)
WC 20 表 註冊 OKDB 表 missing 是 WC 未安裝)
6 family AddOn no-op target 未安裝時正確 early return

Lessons learned

Phase 1

  • rsync 的 --excludetests/tools/ top-level 不生效(因為 source 路徑沒這個前綴),需後續 rm -rf 清理
  • sed 全檔大寫 WPDO_TMDO_ 不影響 hook/table/option 小寫前綴 wpdo_,確保資料相容
  • 主檔的 require chain 無法以 sed 自動產出(需手動寫,因為 require 路徑與檔名變動)
  • TMDO_Core::run() 內有 8 處對「整合層 class」的硬引用,需逐個加 class_exists 守門
  • class_alias() 對 trait 與 interface 不適用(需 wrapping wrapper,留 Phase 1 follow-up
  • WP 6.5+ Requires Plugins: 強制檢查 Plugin Name 而非 slughub-core / spoke-sso 仍寫死 Requires Plugins: wp-data-optimizer 故無法直接啟用 → Phase 5 計畫請求 hub-core / spoke-sso 端更新或加 or 2meet-data-optimizer 邏輯

Phase 2

  • inner Hub class TMDO_Hub_Bootstrap 需與 outer AddOn bootstrap 區分名稱(衝突避免)
  • TMDO_Entity_Registry::register_group() 是公開 API;其他 read methods (get_group_fields not get_fields) 命名不直觀

Phase 3

  • HP family 內部已有 TMDO_HivePress_Bootstrap classv3.0.0 family bootstrap),故 outer AddOn bootstrap 改名 TMDO_HP_Bootstrap 避免衝突

Phase 4

  • 所有 family integration class 皆有 partner detection (e.g. class_exists('TMEETIC_Plugin')) → AddOn 無需自己重複偵測

Phase 5 follow-up 執行狀態(2026-05-15

# 項目 狀態
1 Tests 套件搬遷tests/unit/tests/integration/ 重命名 + path 修正 完成
2 PHPCS 套件:補 phpcs.xml.dist + WordPress coding standards 待執行
3 PHPUnit bootstrap:完整重建 unit/integration test 環境 完成
4 DB version migrationTMDO_DB_VERSION 對齊 SCHEMA_VERSION = '2.0.0' 完成
5 Requires Plugins: 2meet-data-optimizer — 12 個 AddOn + brandcards header 全部更新 完成
6 Trait/interface alias wrappersTrait_TMDO_Anti_EAV_Aware 完成
7 Doctor callback signature 修正 完成
8 打包驗收:scripts/package-plugin.sh 12 次 10 終檢 PASS 待執行

#1 + #3 完成摘要(2026-05-15

Unit tests373/373 GREEN771 assertions

  • phpunit.xml 已建立,bootstrap tests/bootstrap.php 完整重建
  • 32 個 unit test 檔從 wp-data-optimizer 搬遷,全部 class-wpdo-class-tmdo- 修正
  • bootstrap 新增:minimal filter registry$GLOBALS['_wp_filter_callbacks'])、全域 FSM bypass filter、TMDO_Listing_Stats stub、esc_sqladdslashes()
  • 跳過 HP/WC/LP 專屬 testHivePress/*、WooCommerceIntegrationTest、ListingStatsTest

Integration tests398/398 GREEN1139 assertions

  • phpunit-integration.xml 已建立,bootstrap tests/integration/bootstrap.php 完整重建
  • 35 個 integration test 檔搬遷(跳過 HivepressIntegrationTest × 3、WCTermCountFilterTest、ListingMetaInterceptorTest、TermCommentBackfillTest
  • bootstrap 新增:wp_upload_dir()wp_mkdir_p()TMDO_Listing_Stats stub
  • 移除 WarmArchiveIntegrationTest 的 listing_stats 2 個方法(需真實 HP AddOn
  • 移除 RestApiIntegrationTest 的 post_view increment + rate-limit 2 個方法(同上)

Backport wp-data-optimizer v3.0.1v3.4.62026-07-31 起)

完整計畫:~/.claude/plans/a-data-www-studio-wp-local-dev-wp-conten-imperative-wind.md

背景:B 分叉自 A v3.0.02026-05-15 11:40),A 其後又走了 92 個 commit 到 v3.4.6,無一回流。目標是全量對齊後讓 wp-data-optimizer 退休。

階段 內容 狀態
0 回歸網:composer dev 依賴、test bootstrap FSM guard、failOnWarning=true、12 個 repo git init 2026-07-31unit 379 / integration 398 全綠)
1 安全與正確性 A1A1413 個 admin GET→POST、REST allowlist、DDL 白名單、Logger 3-arity fatal…) 2026-07-31
2 DDL 與並發 B1B4warm UNIQUE KEY → Zone_Cold save_patch → Zone_Warm increment 2026-07-31
3 架構回填(Zone_Router + Routing_Predicate13 個 Migration Phase 類別) 2026-07-31
4 相容層 E1E7(雙向 hook 橋、57 個 AddOn alias、38 個 CLI 子指令、選單 slug 2026-07-31
5 AddOn 同步 F1F5Standard_Post_Interceptor、HP detector v3.4.5、WC 2026-07-31
6 功能與診斷 PR-Gcrypto 健檢、doctor_callback ABI、15 個 usermeta 欄位…) 2026-07-31Settings 分區 AJAX 未做,見下)
7 全域清理與 CIstrict_types、phpcs.xml、phpstan + baseline、gitea workflows 🔶 部分(strict_types / PHPCS / PHPStan CI workflow、ci-package.sh、39 個測試檔補齊、文件移植未做
退休 兩站台切到 B、移除 A、B 升 1.0.0 🔶 dev30 已切換並驗證通過;dev 未切、A 未移除、版本未升

dev30 實機驗證結果(2026-07-31

環境:2meet-brandcards 1.8.3 / 2meet-hub-core 1.16.0 / 2meet-spoke-sso 1.15.0 同時啟用;HivePress / WooCommerce 未安裝,故只啟用核心 + hub-addon + spoke-addon。

項目 A v3.0.0(切換前) B v0.1.0(切換後)
doctor 33 個 [OK] + 15 個 WC 表 MISSING 警告 49 個 [OK]、All checks passed
姊妹外掛自訂表 36 張 OK 36 張 OK(含 brandcards 的 doctor_callback 回傳訊息)
新健檢 Backup dir blocked (HTTP 404)Crypto key derivable 皆 OK

逐項確認:

  • alias15 個核心類別 + trait + interface + wpdo_run() + WPDO_VERSION 全部可用
  • CLIwp tmdo bridge-status / crypto-status / mode-auditwp wpdo * 兩條路徑都通(38 個子指令)
  • anti-EAV 寫入WPDO_API::set_entity()wp_wpdo_user_sso.known_login_ips 寫入成功(A14 生效)
  • auditwp_wpdo_auditgroup_name / action / trace_idUUIDv4)皆有值(A11/A12 生效)
  • REST allowlist:註冊 show_in_rest => false 的欄位不出現在 get_rest_visible_hot_columns()A5/A6 生效)
  • doctor_callback ABI 變更brandcards 既有 callback 在 1 參數簽章下仍正常
  • 前台 HTTP 200_load_textdomain_just_in_time notice 僅出現在 wp plugin activate 當下(啟用鉤子早於 init),一般請求與前台皆無

實機才抓到的 fatalTMDO_Logger::trace_id() 在 B 提煉時遺漏,而 Audit_Logger::write_row() 會呼叫它。A12 把 Audit_Logger 掛上後,任何一次受管 meta 寫入都會 fatal。PHPUnit 沒有覆蓋 audit 寫入路徑 → 這類「跨模組才會踩到」的缺口只有實機能發現。

尚未完成(follow-up

  1. Settings 分區 AJAX 儲存A v3.0.2):ajax_save_settings_section() + 7 個 save_section_*() + admin/assets/wpdo-settings.js。B 目前是一次存全部的 inline update_option 巨塊,功能可用,屬 UX 改善。其中 save_section_hp_transient / save_section_wc_term_count 對應 AddOn 已移除的設定,移植時要拆掉或加 class_exists 守衛。
  2. CI workflow.gitea/workflows/{test,release,anti-eav-lint}.ymlenv 改 TMDO_TEST_DB_*WPDO_HOST 指向 dev30、slug 改 2meet-data-optimizer、順手加 phpstan job、11 個 AddOn 的 matrix)。
  3. scripts/ci-package.shdist/ 產出流程。
  4. 補 39 個測試檔:核心優先 HookBusIntegrationTestTermCommentBackfillTest32 個 HivePress/WC 測試需先為兩個 AddOn 建 phpunit.xml + bootstrap。
  5. 文件移植readme.txtCONTEXT.mddocs/ENTITY_ADAPTER_COOKBOOK、INTEGRATION_PATTERN_DECISION、2 篇 ADR)。
  6. 實機驗證與退休切換:兩站台目前仍跑 Adev = v3.4.6、dev30 = v3.0.0),B 家族 12 個外掛全 inactive,尚未做過 wp tmdo doctor 實機驗證。

ABI / 行為變更(升級須知)

  • doctor_callback 由 3 參數改為 1 參數(表名)——AddOn 若註冊過該 callback 需同步。
  • wpdo_capture_before_value 預設 truefalse,每次受管寫入省一次 DB read;需要 value_before 的消費者(audit log)要 add_filter( 'wpdo_capture_before_value', '__return_true' )
  • wpdo_allow_mass_column_clear 現為 opt-indelete_all=true 的整欄清空預設被拒。
  • 選單 slug 由 2meet-data-optimizer 改回 wp-data-optimizer

Lessons learnedbackport

  • 階段 0 的初始 git 快照已包含階段 0 的修復composer.json / 兩個 bootstrap / phpunit.xml / HealthCronTest),不是純粹的 pre-change 現況。要看純現況請比對 A 或 dist/ 內的 v0.1.0 ZIP。
  • composer update 後 autoload 出現 WPDO_Entity_Adapter_Interface 三重宣告警告(includes/adapters/interface-entity-adapter.phpback-compat/interface-wpdo-entity-adapter-alias.phpback-compat/trait-wpdo-anti-eav-aware-alias.php)→ 階段 4 E2 要刪掉重複的那一份。
  • TMDO_FSM_GUARD_DISABLED 兩個 test bootstrap 原本都沒 define,但 class-tmdo-feature-flags.php:128 會檢查它 → 強制 FSM 轉換的測試會被 guard 擋掉(A 在 v3.4.6 踩過同一個坑)。
  • integration 測試需要 TMDO_TEST_DB_PASS(或 WPDO_TEST_DB_PASS)環境變數,DB 為本機 wp_wpdo_test
  • A 不是照抄對象,有兩處自身缺陷不可照搬
    1. A/includes/engine/class-wpdo-hook-bus.php:511,522 傳 3 個 string 給 Logger::warning( string $event, array $context ) → A 有 strict_typesmass-clear 路徑必炸。B 用正確簽章。
    2. A/admin/class-wpdo-dashboard-widget.php:191wpdo_postmeta_cleanup 仍是 wp_nonce_url GET 連結,但其 handler 已只收 POST → 該按鈕在 A 是壞的。B 改成 form。
  • B 有 7 處 Logger::error( 'event', array(...) ) 兩參數呼叫(4 個 stress tester、auto-promoter、conflict-detector、hook-bus),全部是 array→string 的 TypeError。用 token 掃描器(scan_logger.php)找出來的,肉眼與 grep 都容易漏。
  • Zone_Warm::set() 改 upsert 後,測試表也要有 UNIQUE KEY ui_post_meta,否則 integration 會出現「set 沒覆蓋舊值」的假失敗。
  • B 的 unit bootstrap 會載入 Member_Fields / Post_FieldsA 的不會。這使 Entity_Registry 在測試啟動時就有註冊 group,從 A 移植過來、假設「registry 為空」的測試(MigrationPhaseRemainingTest)會真的走進 dbDelta 而爆掉。修法是在該測試 setUp 以 reflection 清空 registry 並移除 wpdo_register_entity_fields listenerphase 內部會再 fire 一次)。
  • 快取類重構必定連帶測試隔離工作Routing_Predicate::flush_cache()SyncBridgeEntityGuardTest)與 Schema_Manager::flush_table_exists_cache()PostMigrationTest / PostEntityLifecycleTest)兩處都是 A 事後才補的,移植時要一起帶,否則出現「表被 drop 但快取說還在」的假錯誤。
  • B 自身的 slug 不一致MENU_SLUG2meet-data-optimizer,但 help-tabs / setup-wizard / conflict-monitor / 3 個 template 共 10+ 處硬編碼 page=wp-data-optimizer → 這些連結原本全部 404。已統一回 wp-data-optimizer(與 wpdo_ 表/option/cron/hook/CLI 命名空間一致)。
  • 雙向 hook 橋會暴露 test bootstrap 的 stub 缺口:單向時 do_action_ref_array() 從未被走到,改雙向後兩個 bootstrap 都要補這個 stub。
  • AddOn 的 alias 必須各自做:核心 back-compat 在 plugins_loaded:4 執行,AddOn 在 :6 才載入類別,核心的 alias 表涵蓋不到它們(57 個整合層類別先前完全沒有 WPDO_ 名稱)。
  • PHP 無法 class_alias() 介面WPDO_Migration_Phase_Interface 沒有雙向 alias 的乾淨解法(單向 extends wrapper 無法讓 instanceof 成立),該契約是核心內部擴充點,測試改用 TMDO_ 正式名稱即可。

Git tag plan

  • v0.1.0 — 本 releasePhase 0-4 完成)
  • v0.1.1 — Phase 5 follow-uptests / PHPCS / packaging
  • v0.2.0 — WPDO_ deprecation notice + wpdo → tmdo migration CLI