From 55e3e19ee4c2f8332c0f2295b3a0d582ea36bdbe Mon Sep 17 00:00:00 2001 From: wpdev Date: Sun, 9 Aug 2026 00:47:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20partner=20=E5=81=B5=E6=B8=AC=E7=AC=A6?= =?UTF-8?q?=E8=99=9F=E5=B0=8D=E9=BD=8A=E5=AF=A6=E9=9A=9B=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=9A=84=E5=B8=B8=E6=95=B8=20+=20schema=20=E6=9C=9F=E6=9C=9B?= =?UTF-8?q?=E5=80=BC=E8=A3=9C=E9=BD=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TMDO_Collab::register() 舊版偵測 TMCLB_Plugin / TMCLB_Main 兩個類別, 在 partner 外掛中並不存在(或載入太晚),偵測實際完全靠 file_exists() 後備 撐著——程式碼讀起來像在驗證「partner 已載入」,實際只驗證了「目錄存在」。 改用 TMCLB_VERSION / TMCLB_PLUGIN_DIR,兩者在 partner 主檔的檔案解析當下即 define,早於 plugins_loaded,故本 AddOn bootstrap 的 :6 時點確實可用。 file_exists() 後備保留不動,行為不變;但偵測不再是死碼,即使將來移除後備也 不會重演 infocards-addon 那種「整個 AddOn 靜默失效」的事故。 同一版本另含先前未提交的 schema 工作:補齊 expected_columns / indexes, 並將 registry 索引 config key 由 expected_indexes 更正為 indexes (wp_parse_args() 會靜默丟棄未知 key,索引期望值先前等同從未送達)。 實測驗證(mu-plugin 於 plugins_loaded:6 量測真實請求): 新常數 AVAILABLE;wp wpdo doctor 89 OK / 0 FAIL;表註冊欄位與索引 100% 完整。 --- 2meet-data-optimizer-collab-addon.php | 4 +- CHANGELOG.md | 29 ++++ includes/class-tmdo-collab.php | 195 ++++++++++++++++++++++++-- 3 files changed, 213 insertions(+), 15 deletions(-) diff --git a/2meet-data-optimizer-collab-addon.php b/2meet-data-optimizer-collab-addon.php index f7d23f2..342dc80 100644 --- a/2meet-data-optimizer-collab-addon.php +++ b/2meet-data-optimizer-collab-addon.php @@ -3,7 +3,7 @@ * Plugin Name: 2meet Data Optimizer — Collab AddOn * Plugin URI: https://2meet.io/2meet-data-optimizer/collab * Description: 2meet-collab 7 張自訂表 (2mclb_rider_instances/venue_profiles/rider_templates/collaborators/confirmations/comments/rider_history) 註冊 - * Version: 0.1.0 + * Version: 0.1.1 * Requires at least: 6.0 * Tested up to: 6.9.4 * Requires PHP: 8.1 @@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } -define( 'TMDO_COLLAB_VERSION', '0.1.0' ); +define( 'TMDO_COLLAB_VERSION', '0.1.1' ); define( 'TMDO_COLLAB_PATH', plugin_dir_path( __FILE__ ) ); define( 'TMDO_COLLAB_URL', plugin_dir_url( __FILE__ ) ); define( 'TMDO_COLLAB_FILE', __FILE__ ); diff --git a/CHANGELOG.md b/CHANGELOG.md index b656626..141d744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,35 @@ Versioning follows [Semantic Versioning](https://semver.org/). --- +## [0.1.1] — 2026-08-08 — 7 張 `2mclb_*` 表補齊 schema 期望值 + +### Added + +- 為全部 7 張 `2mclb_*` 表補上 `expected_columns` 與 `indexes`: + `2mclb_rider_templates`、`2mclb_rider_instances`、`2mclb_collaborators`、 + `2mclb_confirmations`、`2mclb_comments`、`2mclb_rider_history`、 + `2mclb_venue_profiles`。欄位與索引逐項轉錄自 2meet-collab activator 的 + `CREATE TABLE`。先前只註冊表名,`wp wpdo doctor` 只知道表存在,無從判斷欄位或 + 索引是否漂移。 + +### Fixed + +- `TMDO_Custom_Table_Registry::register()` 的索引期望值 config key 由 + `expected_indexes` 更正為 `indexes`。該 API 以 `wp_parse_args()` 併入預設值, + 未知 key 會被**靜默丟棄**——先前索引期望值等同從未送達 registry, + `wp wpdo doctor` 的 schema drift 只驗欄位、不驗索引。此問題橫跨全部 8 個 AddOn, + 已一併更正。 +- `TMDO_Collab::register()` 的 partner 偵測符號對齊實際存在的常數。舊版偵測 + `TMCLB_Plugin` / `TMCLB_Main` 兩個類別,但這兩者在 2meet-collab 中**根本不存在**, + 偵測實際完全靠 `file_exists()` 後備撐著——程式碼讀起來像在驗證「partner 已載入」, + 實際只驗證了「目錄存在」。改用 `TMCLB_VERSION` / `TMCLB_PLUGIN_DIR`,兩者在 + 2meet-collab 主檔的檔案解析當下即 define,早於 `plugins_loaded`。 + 實測(mu-plugin 於 `plugins_loaded:6` 量測):`TMCLB_VERSION` = AVAILABLE。 + `file_exists()` 後備保留不動,故行為不變;但偵測不再是死碼,即使將來移除後備 + 也不會重演 2meet-data-optimizer-infocards-addon 那種「整個 AddOn 靜默失效」的事故。 + +--- + ## [0.1.0] — TBD ### Added (initial release, scaffold) diff --git a/includes/class-tmdo-collab.php b/includes/class-tmdo-collab.php index 617be46..24473b7 100644 --- a/includes/class-tmdo-collab.php +++ b/includes/class-tmdo-collab.php @@ -19,9 +19,18 @@ if ( ! defined( 'ABSPATH' ) ) { */ final class TMDO_Collab { + /** + * 偵測以常數優先:`TMCLB_VERSION` / `TMCLB_PLUGIN_DIR` 在 2meet-collab 主檔的 + * **檔案解析當下**(第 22/25 行)即 define,早於 `plugins_loaded`;本 AddOn + * bootstrap 掛在 `plugins_loaded:6`,故此時常數已可用。 + * + * 舊版偵測的 `TMCLB_Plugin` / `TMCLB_Main` 兩個類別在 2meet-collab 中**並不存在**, + * 偵測實際完全靠 `file_exists()` 撐著。保留 file_exists 作最終後備,但常數檢查 + * 現在真的有效——即使將來移除後備也不會像 infocards 那樣整個 AddOn 靜默失效。 + */ public static function register(): void { - $detected = class_exists( 'TMCLB_Plugin' ) - || class_exists( 'TMCLB_Main' ) + $detected = defined( 'TMCLB_VERSION' ) + || defined( 'TMCLB_PLUGIN_DIR' ) || file_exists( WP_PLUGIN_DIR . '/2meet-collab/2meet-collab.php' ); if ( ! $detected ) { return; @@ -34,22 +43,182 @@ final class TMDO_Collab { // 之前 v2.0.0~v2.0.3 使用截短名(templates / instances / history / venues)導致 // `wp wpdo doctor` 找不到實際表,誤報 missing。實際表名來自 2meet-collab 自身: // `class-tmclb-activator.php` CREATE TABLE 與 `uninstall.php` 的 7 張表。 + // v2.1.0 修正:補上 expected_columns / expected_indexes,讓 `wp wpdo doctor`/ + // `benchmark` 能做 schema drift 偵測。欄位/索引與 2meet-collab + // `class-tmclb-activator.php::create_tables()` 的 CREATE TABLE 定義完全對齊。 $tables = array( - '2mclb_rider_templates' => array( 'id', null ), - '2mclb_rider_instances' => array( 'id', 'hp_vendor' ), - '2mclb_collaborators' => array( 'id', null ), - '2mclb_confirmations' => array( 'id', null ), - '2mclb_comments' => array( 'id', null ), - '2mclb_rider_history' => array( 'id', null ), - '2mclb_venue_profiles' => array( 'id', null ), + '2mclb_rider_templates' => array( + 'primary_key' => 'id', + 'post_type_link' => null, + 'expected_columns' => array( + 'id' => 'BIGINT', + 'vendor_id' => 'BIGINT', + 'title' => 'VARCHAR', + 'description' => 'TEXT', + 'default_sections' => 'LONGTEXT', + 'is_public' => 'TINYINT', + 'status' => 'VARCHAR', + 'created_at' => 'DATETIME', + 'updated_at' => 'DATETIME', + ), + 'indexes' => array( + 'vendor_id' => array( 'vendor_id' ), + 'status' => array( 'status' ), + ), + ), + '2mclb_rider_instances' => array( + 'primary_key' => 'id', + 'post_type_link' => 'hp_vendor', + 'expected_columns' => array( + 'id' => 'BIGINT', + 'template_id' => 'BIGINT', + 'vendor_id' => 'BIGINT', + 'title' => 'VARCHAR', + 'event_date' => 'DATE', + 'event_name' => 'VARCHAR', + 'venue_profile_id' => 'BIGINT', + 'status' => 'VARCHAR', + 'stage_plot_data' => 'LONGTEXT', + 'channel_list_data' => 'LONGTEXT', + 'equipment_data' => 'LONGTEXT', + 'timeline_data' => 'LONGTEXT', + 'checklist_data' => 'LONGTEXT', + 'access_token' => 'VARCHAR', + 'token_expires_at' => 'DATETIME', + 'locked_at' => 'DATETIME', + 'locked_by' => 'BIGINT', + 'created_at' => 'DATETIME', + 'updated_at' => 'DATETIME', + ), + 'indexes' => array( + 'vendor_id' => array( 'vendor_id' ), + 'template_id' => array( 'template_id' ), + 'status' => array( 'status' ), + 'access_token' => array( 'access_token' ), + ), + ), + '2mclb_collaborators' => array( + 'primary_key' => 'id', + 'post_type_link' => null, + 'expected_columns' => array( + 'id' => 'BIGINT', + 'instance_id' => 'BIGINT', + 'user_id' => 'BIGINT', + 'email' => 'VARCHAR', + 'display_name' => 'VARCHAR', + 'role' => 'VARCHAR', + 'permissions' => 'LONGTEXT', + 'invite_token' => 'VARCHAR', + 'token_expires_at' => 'DATETIME', + 'status' => 'VARCHAR', + 'last_seen_at' => 'DATETIME', + 'created_at' => 'DATETIME', + ), + 'indexes' => array( + 'instance_id' => array( 'instance_id' ), + 'user_id' => array( 'user_id' ), + 'invite_token' => array( 'invite_token' ), + 'email' => array( 'email' ), + ), + ), + '2mclb_confirmations' => array( + 'primary_key' => 'id', + 'post_type_link' => null, + 'expected_columns' => array( + 'id' => 'BIGINT', + 'instance_id' => 'BIGINT', + 'section' => 'VARCHAR', + 'confirmed_by' => 'BIGINT', + 'confirmed_role' => 'VARCHAR', + 'status' => 'VARCHAR', + 'note' => 'TEXT', + 'confirmed_at' => 'DATETIME', + ), + 'indexes' => array( + 'instance_section' => array( 'instance_id', 'section' ), + 'confirmed_by' => array( 'confirmed_by' ), + ), + ), + '2mclb_comments' => array( + 'primary_key' => 'id', + 'post_type_link' => null, + 'expected_columns' => array( + 'id' => 'BIGINT', + 'instance_id' => 'BIGINT', + 'section' => 'VARCHAR', + 'parent_id' => 'BIGINT', + 'author_id' => 'BIGINT', + 'author_name' => 'VARCHAR', + 'author_role' => 'VARCHAR', + 'content' => 'TEXT', + 'is_resolved' => 'TINYINT', + 'created_at' => 'DATETIME', + ), + 'indexes' => array( + 'instance_section' => array( 'instance_id', 'section' ), + 'parent_id' => array( 'parent_id' ), + ), + ), + '2mclb_rider_history' => array( + 'primary_key' => 'id', + 'post_type_link' => null, + 'expected_columns' => array( + 'id' => 'BIGINT', + 'instance_id' => 'BIGINT', + 'action' => 'VARCHAR', + 'section' => 'VARCHAR', + 'actor_id' => 'BIGINT', + 'actor_name' => 'VARCHAR', + 'actor_role' => 'VARCHAR', + 'snapshot' => 'LONGTEXT', + 'note' => 'TEXT', + 'created_at' => 'DATETIME', + ), + 'indexes' => array( + 'instance_id' => array( 'instance_id' ), + 'instance_section' => array( 'instance_id', 'section' ), + ), + ), + '2mclb_venue_profiles' => array( + 'primary_key' => 'id', + 'post_type_link' => null, + 'expected_columns' => array( + 'id' => 'BIGINT', + 'vendor_id' => 'BIGINT', + 'buyer_id' => 'BIGINT', + 'name' => 'VARCHAR', + 'address' => 'VARCHAR', + 'stage_width' => 'DECIMAL', + 'stage_depth' => 'DECIMAL', + 'ceiling_height' => 'DECIMAL', + 'power_capacity_amps' => 'INT', + 'power_outlets_count' => 'INT', + 'has_pa_system' => 'TINYINT', + 'has_monitors' => 'TINYINT', + 'has_lighting' => 'TINYINT', + 'has_backline' => 'TINYINT', + 'load_in_info' => 'TEXT', + 'parking_info' => 'TEXT', + 'contact_name' => 'VARCHAR', + 'contact_phone' => 'VARCHAR', + 'contact_email' => 'VARCHAR', + 'notes' => 'TEXT', + 'extra_specs' => 'LONGTEXT', + 'created_at' => 'DATETIME', + 'updated_at' => 'DATETIME', + ), + 'indexes' => array( + 'vendor_id' => array( 'vendor_id' ), + 'buyer_id' => array( 'buyer_id' ), + ), + ), ); foreach ( $tables as $table_name => $meta ) { $registry->register( '2meet-collab', - array( - 'table_name' => $table_name, - 'primary_key' => $meta[0], - 'post_type_link' => $meta[1], + array_merge( + array( 'table_name' => $table_name ), + $meta ) ); } -- 2.43.0