diff --git a/connectors/class-connector-blogs.php b/connectors/class-connector-blogs.php index a94b9161c..03e9ed5e7 100644 --- a/connectors/class-connector-blogs.php +++ b/connectors/class-connector-blogs.php @@ -24,7 +24,8 @@ class Connector_Blogs extends Connector { * @var array */ public $actions = array( - 'wpmu_new_blog', + 'wp_initialize_site', + 'wp_delete_site', 'wpmu_activate_blog', 'wpmu_new_user', 'add_user_to_blog', @@ -127,14 +128,16 @@ public function action_links( $links, $record ) { } /** - * Blog created + * Blog created. * - * @action wpmu_new_blog + * @action wp_initialize_site * - * @param int $blog_id Blog ID. + * @param WP_Site $new_site New site object. + * @param array $args Arguments for the initialization. */ - public function callback_wpmu_new_blog( $blog_id ) { - $blog = get_blog_details( $blog_id ); + public function callback_wp_initialize_site( $new_site, $args ) { + $blogname = ! empty( $args['title'] ) ? $args['title'] : $new_site->blogname; + $blog_id = $new_site->blog_id; $this->log( /* translators: %s: site name (e.g. "FooBar Blog") */ @@ -144,14 +147,42 @@ public function callback_wpmu_new_blog( $blog_id ) { 'stream' ), array( - 'site_name' => $blog->blogname, + 'site_name' => ! empty( $blogname ) ? $blogname : 'Site %d', + 'siteurl' => $new_site->siteurl, + 'id' => $new_site->blog_id, ), $blog_id, - sanitize_key( $blog->blogname ), + sanitize_key( $blogname ), 'created' ); } + /** + * A site has been deleted from the database. + * + * @action wp_deleted_site + * + * @param WP_Site $old_site Deleted site object. + */ + public function callback_wp_delete_site( $old_site ) { + $this->log( + /* translators: %s: site name (e.g. "FooBar Blog") */ + _x( + '"%s" site was deleted', + '1. Site name', + 'stream' + ), + array( + 'site_name' => $old_site->blogname, + 'siteurl' => $old_site->siteurl, + 'id' => $old_site->blog_id, + ), + $old_site->blog_id, + sanitize_key( $old_site->blogname ), + 'deleted' + ); + } + /** * Blog registered * @@ -161,7 +192,7 @@ public function callback_wpmu_new_blog( $blog_id ) { * @param int $user_id User ID. */ public function callback_wpmu_activate_blog( $blog_id, $user_id ) { - $blog = get_blog_details( $blog_id ); + $blog = get_site( $blog_id ); $this->log( /* translators: %s: site name (e.g. "FooBar Blog") */ @@ -172,6 +203,8 @@ public function callback_wpmu_activate_blog( $blog_id, $user_id ) { ), array( 'site_name' => $blog->blogname, + 'siteurl' => $blog->siteurl, + 'id' => $blog->blog_id, ), $blog_id, sanitize_key( $blog->blogname ), @@ -190,7 +223,7 @@ public function callback_wpmu_activate_blog( $blog_id, $user_id ) { * @param int $blog_id Blog ID. */ public function callback_add_user_to_blog( $user_id, $role, $blog_id ) { - $blog = get_blog_details( $blog_id ); + $blog = get_site( $blog_id ); $user = get_user_by( 'id', $user_id ); if ( ! is_a( $user, 'WP_User' ) ) { @@ -207,6 +240,8 @@ public function callback_add_user_to_blog( $user_id, $role, $blog_id ) { array( 'user_name' => $user->display_name, 'site_name' => $blog->blogname, + 'siteurl' => $blog->siteurl, + 'id' => $blog->blog_id, 'role_name' => $role, ), $blog_id, @@ -224,7 +259,7 @@ public function callback_add_user_to_blog( $user_id, $role, $blog_id ) { * @param int $blog_id Blog ID. */ public function callback_remove_user_from_blog( $user_id, $blog_id ) { - $blog = get_blog_details( $blog_id ); + $blog = get_site( $blog_id ); $user = get_user_by( 'id', $user_id ); if ( ! is_a( $user, 'WP_User' ) ) { @@ -241,6 +276,8 @@ public function callback_remove_user_from_blog( $user_id, $blog_id ) { array( 'user_name' => $user->display_name, 'site_name' => $blog->blogname, + 'siteurl' => $blog->siteurl, + 'id' => $blog->blog_id, ), $blog_id, sanitize_key( $blog->blogname ), @@ -322,7 +359,7 @@ public function callback_unarchive_blog( $blog_id ) { * @param int $blog_id Blog ID. */ public function callback_make_delete_blog( $blog_id ) { - $this->callback_update_blog_status( $blog_id, esc_html__( 'deleted', 'stream' ), 'deleted' ); + $this->callback_update_blog_status( $blog_id, esc_html__( 'trashed', 'stream' ), 'trashed' ); } /** @@ -333,7 +370,7 @@ public function callback_make_delete_blog( $blog_id ) { * @param int $blog_id Blog ID. */ public function callback_make_undelete_blog( $blog_id ) { - $this->callback_update_blog_status( $blog_id, esc_html__( 'restored', 'stream' ), 'updated' ); + $this->callback_update_blog_status( $blog_id, esc_html__( 'restored', 'stream' ), 'restored' ); } /** @@ -345,7 +382,7 @@ public function callback_make_undelete_blog( $blog_id ) { * @param string $value Status flag. */ public function callback_update_blog_public( $blog_id, $value ) { - if ( $value ) { + if ( absint( $value ) ) { $status = esc_html__( 'marked as public', 'stream' ); } else { $status = esc_html__( 'marked as private', 'stream' ); @@ -364,8 +401,7 @@ public function callback_update_blog_public( $blog_id, $value ) { * @param string $action Action. */ public function callback_update_blog_status( $blog_id, $status, $action ) { - $blog = get_blog_details( $blog_id ); - + $blog = get_site( $blog_id ); $this->log( /* translators: %1$s: a site name, %2$s: a blog status (e.g. "FooBar Blog", "archived") */ _x( @@ -375,6 +411,8 @@ public function callback_update_blog_status( $blog_id, $status, $action ) { ), array( 'site_name' => $blog->blogname, + 'siteurl' => $blog->siteurl, + 'id' => $blog->blog_id, 'status' => $status, ), $blog_id, diff --git a/tests/tests/connectors/test-class-connector-blogs.php b/tests/tests/connectors/test-class-connector-blogs.php index aeac6eda6..690c229b4 100644 --- a/tests/tests/connectors/test-class-connector-blogs.php +++ b/tests/tests/connectors/test-class-connector-blogs.php @@ -1,6 +1,6 @@ connector_blogs = new Connector_Blogs; - $this->assertNotEmpty( $this->connector_blogs ); + if ( ! is_multisite() ) { + $this->markTestSkipped( 'This test requires multisite.' ); + } + + $this->plugin->connectors->unload_connector( 'blogs' ); + + // Add hook to provide mock blog details because sub-sites aren't + // created with an options table to use. + add_filter( 'site_details', array( $this, 'get_testsite_details' ) ); + + // Make partial of Connector_Blogs class, with mocked "log" function. + $this->mock = $this->getMockBuilder( Connector_Blogs::class ) + ->setMethods( array( 'log' ) ) + ->getMock(); + + // Register connector. + $this->mock->register(); + } + + public function get_testsite_details( $details ) { + global $base; + + $details->blogname = 'testsite'; + $details->siteurl = $base . '/testsite'; + $details->post_count = 0; + $details->home = $base . '/testsite'; + + return $details; } /** @@ -28,13 +57,434 @@ public function setUp() { * @group ms-required */ public function test_get_context_labels() { - if ( ! is_multisite() ) { - $this->markTestSkipped( 'This test requires multisite.' ); - } // Validate this works for foreign characters as well. - $id = $this->factory->blog->create( array( 'title' => 'ובזכויותיהם' ) ); - $labels = $this->connector_blogs->get_context_labels(); + $id = self::factory()->blog->create( array( 'title' => 'ובזכויותיהם' ) ); + $labels = $this->mock->get_context_labels(); $this->assertArrayHasKey( 'blog-1', $labels ); $this->assertArrayHasKey( 'blog-' . $id, $labels ); } + + public function test_callback_wp_initialize_site() { + // Expected log calls. + $this->mock->expects( $this->once() ) + ->method( 'log' ) + ->with( + $this->equalTo( + _x( + '"%s" site was created', + '1. Site name', + 'stream' + ) + ), + $this->callback( + function( $meta ) { + $expected_meta = array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + ); + + return $expected_meta === array_intersect_key( $expected_meta, $meta ); + } + ), + $this->greaterThan( 0 ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'created' ) + ); + + // Create new blog to trigger callback. + self::factory()->blog->create( array( 'title' => 'testsite' ) ); + + // Check callback test action. + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_wp_initialize_site' ) ); + } + + public function test_callback_wp_delete_site() { + global $wpdb; + + // Create site for later use. + $blog_id = self::factory()->blog->create( array( 'title' => 'testsite' ) ); + + // Temporary tables will trigger DB errors when we attempt to reference them as new temporary tables. + $suppress = $wpdb->suppress_errors(); + + // Expected log calls. + $this->mock->expects( $this->once() ) + ->method( 'log' ) + ->with( + $this->equalTo( + _x( + '"%s" site was deleted', + '1. Site name', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + ) + ), + $this->greaterThan( 0 ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'deleted' ) + ); + + // Delete blog to trigger callback. + \wp_delete_site( $blog_id ); + $wpdb->suppress_errors( $suppress ); + + // Check callback test action. + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_wp_delete_site' ) ); + } + + public function test_callback_wpmu_activate_blog() { + // Create site for later use. + $blog_id = self::factory()->blog->create( array( 'title' => 'testsite' ) ); + + // Expected log calls. + $this->mock->expects( $this->once() ) + ->method( 'log' ) + ->with( + $this->equalTo( + _x( + '"%s" site was registered', + '1. Site name', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'created' ), + 1 + ); + + // Activate blog to trigger callback. + do_action( 'wpmu_activate_blog', $blog_id, 1, 'password', 'testsite', array() ); + + // Check callback test action. + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_wpmu_activate_blog' ) ); + } + + public function test_callback_add_user_to_blog() { + // Create site and user for later use. + $blog_id = self::factory()->blog->create( array( 'title' => 'testsite' ) ); + $user_id = self::factory()->user->create( array( 'display_name' => 'testuser' ) ); + + // Expected log calls. + $this->mock->expects( $this->once() ) + ->method( 'log' ) + ->with( + $this->equalTo( + _x( + '%1$s was added to the "%2$s" site with %3$s capabilities', + '1. User\'s name, 2. Site name, 3. Role', + 'stream' + ) + ), + $this->equalTo( + array( + 'user_name' => 'testuser', + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'role_name' => 'subscriber', + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ); + + // Add user to site to trigger callback. + add_user_to_blog( $blog_id, $user_id, 'subscriber' ); + + // Check callback test action. + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_add_user_to_blog' ) ); + } + + public function test_callback_remove_user_from_blog() { + // Create site and add user to site for later use. + $blog_id = self::factory()->blog->create( array( 'title' => 'testsite' ) ); + $user_id = self::factory()->user->create( array( 'display_name' => 'testuser' ) ); + add_user_to_blog( $blog_id, $user_id, 'subscriber' ); + + // Expected log calls. + $this->mock->expects( $this->once() ) + ->method( 'log' ) + ->with( + $this->equalTo( + _x( + '%1$s was removed from the "%2$s" site', + '1. User\'s name, 2. Site name', + 'stream' + ) + ), + $this->equalTo( + array( + 'user_name' => 'testuser', + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ); + + // Remove user from site to trigger callback. + remove_user_from_blog( $user_id, $blog_id ); + + // Check callback test action. + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_remove_user_from_blog' ) ); + } + + public function test_callback_update_blog_status() { + // Create site and add user to site for later use. + $blog_id = self::factory()->blog->create( + array( + 'title' => 'testsite', + 'meta' => array( 'public' => '0' ), + ) + ); + $site = get_site( $blog_id ); + + // Expected log calls. + $this->mock->expects( $this->exactly( 10 ) ) + ->method( 'log' ) + ->withConsecutive( + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'marked as spam', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'marked as not spam', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'marked as mature', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'marked as not mature', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'archived', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'archive_blog' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'restored from archive', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'trashed', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'trashed' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'restored', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'restored' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'marked as public', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ), + array( + $this->equalTo( + _x( + '"%1$s" site was %2$s', + '1. Site name, 2. Status', + 'stream' + ) + ), + $this->equalTo( + array( + 'site_name' => 'testsite', + 'siteurl' => '//testsite', + 'id' => $blog_id, + 'status' => esc_html__( 'marked as private', 'stream' ), + ) + ), + $this->equalTo( $blog_id ), + $this->equalTo( 'testsite' ), + $this->equalTo( 'updated' ) + ) + ); + + // Update blog status blog to trigger callback. + $fields = array( + 'spam' => '1', + 'mature' => '1', + 'archived' => '1', + 'deleted' => '1', + 'public' => '1', + ); + foreach( $fields as $field => $value ) { + wp_update_site( $blog_id, array( $field => $value ) ); + wp_update_site( $blog_id, array( $field => absint( $value ) ? '0' : '1' ) ); + } + + // Check callback test action. + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_make_spam_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_make_ham_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_mature_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_unmature_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_archive_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_unarchive_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_make_delete_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_make_undelete_blog' ) ); + $this->assertGreaterThan( 0, did_action( $this->action_prefix . 'callback_update_blog_public' ) ); + } }