diff --git a/src/Schema/Builder.php b/src/Schema/Builder.php index 09f6d03..9f33691 100644 --- a/src/Schema/Builder.php +++ b/src/Schema/Builder.php @@ -263,11 +263,23 @@ public function register_custom_tables_names() { * @return array A list of each creation or update result. */ public function up( $force = false ) { - /* - * The value will be `false` if the value has not been set yet or the blog is not installed. - * In either case we should not try to create the tables. - */ - $is_blog_installed = wp_cache_get( 'is_blog_installed' ); + if ( doing_action( 'switch_blog' ) ) { + /* + * The `switch_blog` action can be called by the `wp_initialize_site` function, before the blog exists. + * Running `is_blog_installed()` in this case will kill the site with a dead db message since the + * `users` table will be found (it's common for all blogs), but the `options` table will not be found for + * the blog. + * If the blog does not exist, the value will not be cached yet and the value will be `false`. + * Else we can just use the value; this will be the case for a normal `switch_blog` action that does not + * fire while creating the site. + * + * When is the next chance to create the tables? Likely in the `activate_blog` action that will be fired + * in the same request following the blog creation or in the next `switch_blog` action. + */ + $is_blog_installed = wp_cache_get( 'is_blog_installed' ); + } else { + $is_blog_installed = is_blog_installed(); + } if ( ! $is_blog_installed || wp_installing() ) { return []; diff --git a/tests/wpunit/BuilderTest.php b/tests/wpunit/BuilderTest.php index d38ed6d..8946369 100644 --- a/tests/wpunit/BuilderTest.php +++ b/tests/wpunit/BuilderTest.php @@ -365,4 +365,76 @@ public function update() { Register::remove_table( $klutz_table ); Register::remove_table( $zorps_table ); } + + /** + * @test + */ + public function should_not_create_tables_during_switch_blog_if_blog_not_installed(): void { + // Register the table. + $table = $this->get_simple_table(); + Register::table( $table ); + $table->drop(); + // Sanity check. + $this->assertFalse( $table->exists() ); + // Set up as if switching to a blog before it's installed, during its creeation. + wp_cache_delete( 'is_blog_installed' ); + // Remove all other filters to avoid side-effects. + remove_all_filters( 'switch_blog' ); + + $builder = Schema::builder(); + + add_action( 'switch_blog', [ $builder, 'update_blog_tables' ] ); + + do_action( 'switch_blog', 66 ); + + $this->assertFalse( $table->exists() ); + } + + /** + * @test + */ + public function should_create_tables_during_switch_blog_if_blog_installed(): void { + // Register the table. + $table = $this->get_simple_table(); + Register::table( $table ); + $table->drop(); + // Sanity check. + $this->assertFalse( $table->exists() ); + // Set up as if switching to a blog after it's installed. + wp_cache_set( 'is_blog_installed', true ); + // Remove all other filters to avoid side-effects. + remove_all_filters( 'switch_blog' ); + + $builder = Schema::builder(); + + add_action( 'switch_blog', [ $builder, 'update_blog_tables' ] ); + + do_action( 'switch_blog', 66 ); + + $this->assertTrue( $table->exists() ); + } + + /** + * @test + */ + public function should_create_tables_during_activate_blog(): void { + // Register the table. + $table = $this->get_simple_table(); + Register::table( $table ); + $table->drop(); + // Sanity check. + $this->assertFalse( $table->exists() ); + // Set up as if switching to a blog after it's installed. + wp_cache_set( 'is_blog_installed', true ); + // Remove all other filters to avoid side-effects. + remove_all_filters( 'activate_blog' ); + + $builder = Schema::builder(); + + add_action( 'activate_blog', [ $builder, 'update_blog_tables' ] ); + + do_action( 'activate_blog', 66 ); + + $this->assertTrue( $table->exists() ); + } }