From fc0f018a948358d5035f020235f0eb8792eed654 Mon Sep 17 00:00:00 2001 From: wpdev Date: Fri, 25 Sep 2026 21:48:23 +0800 Subject: [PATCH] fix(2meet-data-optimizer): stop auto-activating entity bridge on install - install() no longer switches the Hook Bus on or puts user/term/comment into dual_write; the now-unused maybe_autoactivate_entity_bridge() is gone - Hook Bus and Mode_Manager defaults are off/disabled; sites with stored modes (incl. aeav_only) keep them since only unset keys use defaults - Guard run_dbdelta()'s upgrade.php require like install_v2_tables() so install() can run under the integration test stub Verify: InstallerV2Test::test_install_does_not_enable_entity_bridge, ModeManagerDefaultsTest; unit 602 OK, integration 421 OK PR: PR-007 --- includes/class-tmdo-hook-bus-bridge.php | 2 +- includes/class-tmdo-installer.php | 40 ++--------------- includes/engine/class-tmdo-mode-manager.php | 11 +++-- tests/integration/InstallerV2Test.php | 13 ++++++ tests/integration/bootstrap.php | 1 + tests/unit/HookBusBridgeTest.php | 6 +-- tests/unit/ModeManagerDefaultsTest.php | 50 +++++++++++++++++++++ 7 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 tests/unit/ModeManagerDefaultsTest.php diff --git a/includes/class-tmdo-hook-bus-bridge.php b/includes/class-tmdo-hook-bus-bridge.php index 02517bc..6436db4 100644 --- a/includes/class-tmdo-hook-bus-bridge.php +++ b/includes/class-tmdo-hook-bus-bridge.php @@ -54,7 +54,7 @@ final class TMDO_Hook_Bus_Bridge { if ( null !== self::$cache ) { return self::$cache; } - $value = get_option( self::OPTION, '1' ); // Default ON as of v2.5.4. + $value = get_option( self::OPTION, '0' ); self::$cache = ( '1' === (string) $value || true === $value ); return self::$cache; } diff --git a/includes/class-tmdo-installer.php b/includes/class-tmdo-installer.php index 5e90c9c..b003c07 100644 --- a/includes/class-tmdo-installer.php +++ b/includes/class-tmdo-installer.php @@ -224,47 +224,12 @@ class TMDO_Installer { add_option( 'wpdo_features', array(), '', 'no' ); } - // v2.5.4: one-time migration — enable Hook Bus + activate user/term/comment bridge. - self::maybe_autoactivate_entity_bridge(); - // v2.15.0: one-time crypto migration — re-encrypt v1 CBC ciphertext as // v2 GCM. Idempotent best-effort: skipped if no v1 ciphertext present // or if the migration flag is already set. self::maybe_migrate_crypto_v1_to_v2(); } - /** - * One-time migration: enable Hook Bus and set user/term/comment to dual_write. - * - * Runs once per site (guarded by wpdo_entity_bridge_autoactivated_v2 flag). - * Safe: dual_write still writes native EAV — zero data-loss risk. - * - * @return void - */ - private static function maybe_autoactivate_entity_bridge(): void { - if ( get_option( 'wpdo_entity_bridge_autoactivated_v2' ) ) { - return; - } - - // Enable Hook Bus. - update_option( 'wpdo_hook_bus_enabled', '1', false ); - - // Upgrade user/term/comment from disabled → dual_write. - $modes = get_option( 'wpdo_bridge_modes', array() ); - if ( ! is_array( $modes ) ) { - $modes = array(); - } - foreach ( array( 'user', 'term', 'comment' ) as $type ) { - if ( ! isset( $modes[ $type ] ) || 'disabled' === $modes[ $type ] ) { - $modes[ $type ] = 'dual_write'; - } - } - // post entity is intentionally left alone — it uses the legacy Feature_Flags FSM. - update_option( 'wpdo_bridge_modes', $modes, false ); - - update_option( 'wpdo_entity_bridge_autoactivated_v2', '1', false ); - } - /** * One-time best-effort crypto migration v1 (CBC) → v2 (GCM) (v2.15.0). * @@ -1303,7 +1268,10 @@ class TMDO_Installer { */ private static function run_dbdelta(): void { global $wpdb; - require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + // Same guard as install_v2_tables(): integration tests provide a stub dbDelta(). + if ( ! function_exists( 'dbDelta' ) ) { + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + } $charset = $wpdb->get_charset_collate(); $p = $wpdb->prefix; diff --git a/includes/engine/class-tmdo-mode-manager.php b/includes/engine/class-tmdo-mode-manager.php index 4498141..5fed59d 100644 --- a/includes/engine/class-tmdo-mode-manager.php +++ b/includes/engine/class-tmdo-mode-manager.php @@ -65,16 +65,15 @@ final class TMDO_Mode_Manager { private static ?array $cache = null; /** - * 預設模式(v2.5.4 起): - * post → disabled(由 Legacy Feature_Flags FSM 管理,不由 Mode_Manager 控制) - * user / term / comment → dual_write(安全雙寫:寫入 flat table + 原生 EAV,讀取仍走 EAV) + * 預設模式:全部 disabled,由管理者明確選擇後才啟用 entity bridge。 + * 已存在 wpdo_bridge_modes 的站台(包含 aeav_only)以儲存值為準,不受影響。 */ private static function defaults(): array { return array( 'post' => self::MODE_DISABLED, - 'user' => self::MODE_DUAL_WRITE, - 'term' => self::MODE_DUAL_WRITE, - 'comment' => self::MODE_DUAL_WRITE, + 'user' => self::MODE_DISABLED, + 'term' => self::MODE_DISABLED, + 'comment' => self::MODE_DISABLED, ); } diff --git a/tests/integration/InstallerV2Test.php b/tests/integration/InstallerV2Test.php index 689597c..7fc5cfd 100644 --- a/tests/integration/InstallerV2Test.php +++ b/tests/integration/InstallerV2Test.php @@ -111,6 +111,19 @@ class InstallerV2Test extends TestCase { } } + public function test_install_does_not_enable_entity_bridge(): void { + delete_option( 'wpdo_hook_bus_enabled' ); + delete_option( 'wpdo_bridge_modes' ); + delete_option( 'wpdo_entity_bridge_autoactivated_v2' ); + // Skip the crypto step: it queries $wpdb->options, which InstallerCleanupTest leaves pointing at its own prefix. + update_option( 'wpdo_crypto_migrated_v2', '1' ); + + TMDO_Installer::install(); + + $this->assertFalse( get_option( 'wpdo_hook_bus_enabled' ), 'install() must not switch the Hook Bus on' ); + $this->assertFalse( get_option( 'wpdo_bridge_modes' ), 'install() must not write bridge modes' ); + } + public static function tearDownAfterClass(): void { // Leave v2 tables in place for subsequent tests / dev convenience. // Cleanup happens via wp wpdo cleanup-uae-tables --confirm in real upgrades. diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php index 9d6b059..4b3a0a3 100644 --- a/tests/integration/bootstrap.php +++ b/tests/integration/bootstrap.php @@ -302,6 +302,7 @@ if ( ! function_exists( 'wp_strip_all_tags' ) ) { function wp_strip_all_tags( st if ( ! function_exists( 'get_option' ) ) { function get_option( string $key, $default = false ) { return $GLOBALS['_wp_options'][ $key ] ?? $default; } } if ( ! function_exists( 'update_option' ) ) { function update_option( string $key, $value ): bool { $GLOBALS['_wp_options'][ $key ] = $value; return true; } } if ( ! function_exists( 'delete_option' ) ) { function delete_option( string $key ): bool { unset( $GLOBALS['_wp_options'][ $key ] ); return true; } } +if ( ! function_exists( 'add_option' ) ) { function add_option( string $key, $value = '', $deprecated = '', $autoload = null ): bool { if ( array_key_exists( $key, $GLOBALS['_wp_options'] ?? array() ) ) { return false; } $GLOBALS['_wp_options'][ $key ] = $value; return true; } } if ( ! function_exists( 'get_transient' ) ) { function get_transient( string $key ) { return $GLOBALS['_wp_transients'][ $key ] ?? false; } } if ( ! function_exists( 'set_transient' ) ) { function set_transient( string $key, $value, int $exp = 0 ): bool { $GLOBALS['_wp_transients'][ $key ] = $value; return true; } } if ( ! function_exists( 'delete_transient' ) ) { function delete_transient( string $key ): bool { unset( $GLOBALS['_wp_transients'][ $key ] ); return true; } } diff --git a/tests/unit/HookBusBridgeTest.php b/tests/unit/HookBusBridgeTest.php index 129fd05..ebfa8ef 100644 --- a/tests/unit/HookBusBridgeTest.php +++ b/tests/unit/HookBusBridgeTest.php @@ -18,9 +18,9 @@ class HookBusBridgeTest extends TestCase { // ── is_enabled() ──────────────────────────────────────────────────────── - public function test_is_enabled_default_true(): void { - // v2.5.4: Hook Bus is ON by default; option not set → true. - $this->assertTrue( WPDO_Hook_Bus_Bridge::is_enabled() ); + public function test_is_enabled_default_false(): void { + // Hook Bus is opt-in; option not set → false. Existing sites store '1' explicitly. + $this->assertFalse( WPDO_Hook_Bus_Bridge::is_enabled() ); } public function test_is_enabled_when_option_set_to_string_one(): void { diff --git a/tests/unit/ModeManagerDefaultsTest.php b/tests/unit/ModeManagerDefaultsTest.php new file mode 100644 index 0000000..4a441f2 --- /dev/null +++ b/tests/unit/ModeManagerDefaultsTest.php @@ -0,0 +1,50 @@ +assertSame( + array( + 'post' => TMDO_Mode_Manager::MODE_DISABLED, + 'user' => TMDO_Mode_Manager::MODE_DISABLED, + 'term' => TMDO_Mode_Manager::MODE_DISABLED, + 'comment' => TMDO_Mode_Manager::MODE_DISABLED, + ), + TMDO_Mode_Manager::all() + ); + } + + public function test_stored_modes_are_kept(): void { + update_option( + 'wpdo_bridge_modes', + array( + 'post' => 'aeav_only', + 'user' => 'dual_write', + ) + ); + + $modes = TMDO_Mode_Manager::all(); + + $this->assertSame( 'aeav_only', $modes['post'] ); + $this->assertSame( 'dual_write', $modes['user'] ); + $this->assertSame( TMDO_Mode_Manager::MODE_DISABLED, $modes['term'] ); + } +}