From 08d2c7638527c271a8e1a5f715e39a35c5d64fea Mon Sep 17 00:00:00 2001 From: David Stone Date: Mon, 10 Aug 2026 14:35:54 -0600 Subject: [PATCH 1/2] fix: skip global table switch hooks --- inc/database/engine/class-table.php | 4 + .../WP_Ultimo/Database/Engine/Table_Test.php | 108 ++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 tests/WP_Ultimo/Database/Engine/Table_Test.php diff --git a/inc/database/engine/class-table.php b/inc/database/engine/class-table.php index 50298e0b7..fab594dfa 100644 --- a/inc/database/engine/class-table.php +++ b/inc/database/engine/class-table.php @@ -77,5 +77,9 @@ public function exists(): bool { public function __construct() { $this->update_prefix_with_network_id(); parent::__construct(); + + if ($this->global) { + remove_action('switch_blog', [$this, 'switch_blog']); + } } } diff --git a/tests/WP_Ultimo/Database/Engine/Table_Test.php b/tests/WP_Ultimo/Database/Engine/Table_Test.php new file mode 100644 index 000000000..cd843b72a --- /dev/null +++ b/tests/WP_Ultimo/Database/Engine/Table_Test.php @@ -0,0 +1,108 @@ +assertFalse(has_action('switch_blog', [$table, 'switch_blog'])); + } + + /** + * Tests global table state remains unchanged while switching sites. + */ + public function test_global_table_state_remains_unchanged_while_switching_sites(): void { + $table = new Products_Table(); + $site_id = self::factory()->blog->create(); + $before = $this->get_table_state($table); + + switch_to_blog($site_id); + $switched = $this->get_table_state($table); + restore_current_blog(); + $restored = $this->get_table_state($table); + + $this->assertSame($before, $switched); + $this->assertSame($before, $restored); + } + + /** + * Tests per-site tables retain their callback and switch table state. + */ + public function test_per_site_tables_retain_switch_blog_callback_and_restore_state(): void { + $table = new class() extends Table { + + protected $name = 'table_test_local'; + + protected $version = '1.0.0'; + + protected function set_schema(): void { + $this->schema = 'id bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)'; + } + }; + + $table->switch_blog(get_current_blog_id()); + + $this->assertSame(10, has_action('switch_blog', [$table, 'switch_blog'])); + + $site_id = self::factory()->blog->create(); + $before = $this->get_table_state($table); + + switch_to_blog($site_id); + $switched = $this->get_table_state($table); + restore_current_blog(); + $restored = $this->get_table_state($table); + + $this->assertSame($site_id, $switched['site_id']); + $this->assertNotSame($before['table_name'], $switched['table_name']); + $this->assertNotSame($before['table_prefix'], $switched['table_prefix']); + $this->assertNotSame($before['database_interface'], $switched['database_interface']); + $this->assertSame($before, $restored); + } + + /** + * Returns the state affected by BerlinDB's switch_blog callback. + * + * @param Table $table Table instance. + * @return array + */ + private function get_table_state(Table $table): array { + $prefixed_name = $this->get_table_property($table, 'prefixed_name'); + + return [ + 'table_name' => $this->get_table_property($table, 'table_name'), + 'table_prefix' => $this->get_table_property($table, 'table_prefix'), + 'database_interface' => $GLOBALS['wpdb']->{$prefixed_name}, + 'version' => $this->get_table_property($table, 'version'), + 'site_id' => $this->get_table_property($table, 'site_id'), + ]; + } + + /** + * Gets an inherited protected property. + * + * @param Table $table Table instance. + * @param string $property Property name. + * @return mixed + */ + private function get_table_property(Table $table, string $property) { + $reflection = new \ReflectionProperty($table, $property); + + return $reflection->getValue($table); + } +} From 103de740ff60f6ce9a3f8b4630d963783b974600 Mon Sep 17 00:00:00 2001 From: David Stone Date: Mon, 10 Aug 2026 14:43:34 -0600 Subject: [PATCH 2/2] style: use Yoda condition for global table hook --- inc/database/engine/class-table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/database/engine/class-table.php b/inc/database/engine/class-table.php index fab594dfa..5199f95d6 100644 --- a/inc/database/engine/class-table.php +++ b/inc/database/engine/class-table.php @@ -78,7 +78,7 @@ public function __construct() { $this->update_prefix_with_network_id(); parent::__construct(); - if ($this->global) { + if (true === $this->global) { remove_action('switch_blog', [$this, 'switch_blog']); } }