diff --git a/includes/core/classes/class-setup.php b/includes/core/classes/class-setup.php index d24d248ce..60234fd51 100644 --- a/includes/core/classes/class-setup.php +++ b/includes/core/classes/class-setup.php @@ -16,6 +16,7 @@ use Exception; use GatherPress\Core\Traits\Singleton; +use WP_Site; /** * Class Setup. @@ -82,8 +83,9 @@ protected function setup_hooks(): void { register_deactivation_hook( GATHERPRESS_CORE_FILE, array( $this, 'deactivate_gatherpress_plugin' ) ); add_action( 'init', array( $this, 'load_textdomain' ), 9 ); - add_action( 'init', array( $this, 'maybe_flush_gatherpress_rewrite_rules' ) ); + add_action( 'init', array( $this, 'maybe_flush_rewrite_rules' ) ); add_action( 'admin_notices', array( $this, 'check_users_can_register' ) ); + add_action( 'wp_initialize_site', array( $this, 'on_site_create' ) ); add_filter( 'block_categories_all', array( $this, 'register_gatherpress_block_category' ) ); add_filter( 'wpmu_drop_tables', array( $this, 'on_site_delete' ) ); @@ -165,21 +167,38 @@ public function filter_plugin_action_links( array $actions ): array { } /** - * Activate the GatherPress plugin. + * Activates the GatherPress plugin. * - * This method performs activation tasks for the GatherPress plugin, such as renaming blocks and tables, - * creating custom tables, and setting a flag to flush rewrite rules if necessary. + * This method handles the activation of the GatherPress plugin. If the plugin + * is being activated network-wide in a multisite installation, it iterates + * through each blog in the network and performs necessary setup actions + * (creating tables). If not network-wide, it only performs the setup actions + * for the current site. * * @since 1.0.0 * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param bool $network_wide Whether the plugin is being activated network-wide. * @return void */ - public function activate_gatherpress_plugin(): void { - $this->maybe_create_custom_table(); - $this->add_online_event_term(); + public function activate_gatherpress_plugin( bool $network_wide ): void { + if ( is_multisite() && $network_wide ) { + // Get all sites in the network and activate plugin on each one. + $site_ids = get_sites( + array( + 'fields' => 'ids', + 'network_id' => get_current_site()->id, + ) + ); - if ( ! get_option( 'gatherpress_flush_rewrite_rules_flag' ) ) { - add_option( 'gatherpress_flush_rewrite_rules_flag', true ); + foreach ( $site_ids as $site_id ) { + switch_to_blog( $site_id ); + $this->create_tables(); + restore_current_blog(); + } + } else { + $this->create_tables(); } } @@ -207,13 +226,30 @@ public function deactivate_gatherpress_plugin(): void { * * @return void */ - public function maybe_flush_gatherpress_rewrite_rules(): void { + public function maybe_flush_rewrite_rules(): void { if ( get_option( 'gatherpress_flush_rewrite_rules_flag' ) ) { flush_rewrite_rules(); delete_option( 'gatherpress_flush_rewrite_rules_flag' ); } } + /** + * Creates a flag option to indicate that rewrite rules need to be flushed. + * + * This method checks if the 'gatherpress_flush_rewrite_rules_flag' option + * exists. If it does not, it adds the option and sets it to true. This flag + * can be used to determine when rewrite rules should be flushed. + * + * @since 1.0.0 + * + * @return void + */ + private function maybe_create_flush_rewrite_rules_flag(): void { + if ( ! get_option( 'gatherpress_flush_rewrite_rules_flag' ) ) { + add_option( 'gatherpress_flush_rewrite_rules_flag', true ); + } + } + /** * Add GatherPress-specific body classes to the existing body classes. * @@ -292,6 +328,27 @@ public function add_online_event_term(): void { } } + /** + * Handles actions to be taken when a new site is created in a multisite network. + * + * This function checks if the 'gatherpress' plugin is active across the network. + * If it is, it switches to the new site, calls the `create_table()` function, + * and then restores the current blog. + * + * @since 1.0.0 + * + * @param WP_Site $new_site the newly created site. + * + * @return void + */ + public function on_site_create( WP_Site $new_site ): void { + if ( is_plugin_active_for_network( 'gatherpress/gatherpress.php' ) ) { + switch_to_blog( $new_site->blog_id ); + $this->create_tables(); + restore_current_blog(); + } + } + /** * Delete custom tables on site deletion. * @@ -314,36 +371,17 @@ public function on_site_delete( array $tables ): array { } /** - * Create a custom table if it doesn't exist for the main site or the current site in a network. + * Creates necessary database tables for the GatherPress plugin. * - * This method checks whether the custom database tables required for the plugin exist - * and creates them if they don't. It handles both the main site and, in a multisite network, - * the current site. - * - * @since 1.0.0 - * - * @return void - */ - public function maybe_create_custom_table(): void { - $this->create_tables(); - - if ( is_multisite() ) { - $blog_id = get_current_blog_id(); - - switch_to_blog( $blog_id ); - $this->create_tables(); - restore_current_blog(); - } - } - - /** - * Create custom database tables for GatherPress events and RSVPs. - * - * This method creates custom database tables for storing GatherPress event data and RSVP information. - * It ensures that the required tables are set up with the appropriate schema. + * This method creates the required database tables for storing event and RSVP data. + * It constructs SQL queries for creating the tables with appropriate charset and + * collation, and then executes these queries using the `dbDelta` function to ensure + * the tables are created or updated as necessary. Additionally, it calls methods to + * add the online event term and to set a flag for flushing rewrite rules. * * @since 1.0.0 * + * @global wpdb $wpdb WordPress database abstraction object. * @return void */ protected function create_tables(): void { @@ -384,6 +422,9 @@ protected function create_tables(): void { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); + + $this->add_online_event_term(); + $this->maybe_create_flush_rewrite_rules_flag(); } /** diff --git a/readme.md b/readme.md index 0c64860ef..ccf56dd78 100644 --- a/readme.md +++ b/readme.md @@ -142,6 +142,11 @@ To get access to [GatherPress.org](htps://gatherpress.org/get-involved) via SSH Find the developer documentation inside the plugins' `docs` folder. +### Is GatherPress WordPress Multisite compatible? +Yes, GatherPress can be run on a network of sites. The additional database tables it needs, will be created automatically for each new site if the plugin is network-activated. + +GatherPress can also be activated per site. + ### What’s about the PRO version? As a Community powered plugin, GatherPress is already the PRO-version. diff --git a/test/unit/php/includes/core/classes/class-test-setup.php b/test/unit/php/includes/core/classes/class-test-setup.php index bcaf1a45e..f353bc1be 100644 --- a/test/unit/php/includes/core/classes/class-test-setup.php +++ b/test/unit/php/includes/core/classes/class-test-setup.php @@ -35,8 +35,26 @@ public function test_setup_hooks(): void { array( 'type' => 'action', 'name' => 'init', + 'priority' => 9, + 'callback' => array( $instance, 'load_textdomain' ), + ), + array( + 'type' => 'action', + 'name' => 'init', + 'priority' => 10, + 'callback' => array( $instance, 'maybe_flush_rewrite_rules' ), + ), + array( + 'type' => 'action', + 'name' => 'admin_notices', 'priority' => 10, - 'callback' => array( $instance, 'maybe_flush_gatherpress_rewrite_rules' ), + 'callback' => array( $instance, 'check_users_can_register' ), + ), + array( + 'type' => 'action', + 'name' => 'wp_initialize_site', + 'priority' => 10, + 'callback' => array( $instance, 'on_site_create' ), ), array( 'type' => 'filter', @@ -68,6 +86,12 @@ public function test_setup_hooks(): void { 'priority' => 10, 'callback' => array( $instance, 'filter_plugin_action_links' ), ), + array( + 'type' => 'filter', + 'name' => 'load_textdomain_mofile', + 'priority' => 10, + 'callback' => array( $instance, 'load_mofile' ), + ), ); $this->assert_hooks( $hooks, $instance ); @@ -269,4 +293,29 @@ static function ( $translation ): string { $this->assertSame( $slug, $term->slug, 'Failed to assert that term slugs match.' ); $this->assertSame( 'Online', $term->name, 'Failed to assert that term names match.' ); } + + /** + * Coverage for maybe_create_flush_rewrite_rules_flag method. + * + * @covers ::maybe_flush_rewrite_rules + * + * @return void + */ + public function test_maybe_create_flush_rewrite_rules_flag(): void { + $instance = Setup::get_instance(); + $this->assertFalse( + get_option( 'gatherpress_flush_rewrite_rules_flag' ), + 'Failed to assert that flush rewrite rules option does not exist.' + ); + + Utility::invoke_hidden_method( $instance, 'maybe_create_flush_rewrite_rules_flag' ); + + $this->assertTrue( + get_option( 'gatherpress_flush_rewrite_rules_flag' ), + 'Failed to assert that flush rewrite rules option exists.' + ); + + // Cleanup. + delete_option( 'gatherpress_flush_rewrite_rules_flag' ); + } }