diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-sites-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-sites-controller.php index 09903dc2b96cb..9665f05309c22 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-sites-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-sites-controller.php @@ -100,7 +100,7 @@ public function register_routes() { 'force' => array( 'type' => 'boolean', 'default' => false, - 'description' => __( 'Required to be true, as sites do not support trashing.' ), + 'description' => __( 'Whether to set site to deleted and force deletion.' ), ), ), ), @@ -694,24 +694,15 @@ public function delete_item_permissions_check( $request ) { * @return WP_Error|WP_REST_Response Response object on success, or error object on failure. */ public function delete_item( $request ) { - $site = $this->get_site( $request['id'] ); + $blog_id = (int) $request['id']; + $site = $this->get_site( $blog_id ); if ( is_wp_error( $site ) ) { return $site; } - if ( ! (bool) $request['force'] ) { - return new WP_Error( - 'rest_trash_not_supported', - /* translators: %s: force=true */ - sprintf( __( "Sites do not support trashing. Set '%s' to delete." ), 'force=true' ), - array( 'status' => 501 ) - ); - } - $request->set_param( 'context', 'edit' ); $previous = $this->prepare_item_for_response( $site, $request ); - $result = wp_delete_site( $request['id'] ); $response = new WP_REST_Response(); $response->set_data( @@ -721,10 +712,36 @@ public function delete_item( $request ) { ) ); - if ( is_wp_error( $result ) ) { - $result->add_data( array( 'status' => 500 ) ); + if ( ! (bool) $request['force'] ) { + /** This action is documented in wp-includes/ms-site.php */ + do_action_deprecated( 'delete_blog', array( $blog_id, false ), '5.1.0' ); - return $result; + $users = get_users( + array( + 'blog_id' => $blog_id, + 'fields' => 'ids', + ) + ); + + // Remove users from this blog. + if ( ! empty( $users ) ) { + foreach ( $users as $user_id ) { + remove_user_from_blog( $user_id, $blog_id ); + } + } + + update_blog_status( $blog_id, 'deleted', 1 ); + + /** This action is documented in wp-includes/ms-site.php */ + do_action_deprecated( 'deleted_blog', array( $blog_id, false ), '5.1.0' ); + } else { + + $result = wp_delete_site( $request['id'] ); + if ( is_wp_error( $result ) ) { + $result->add_data( array( 'status' => 500 ) ); + + return $result; + } } /** diff --git a/tests/phpunit/tests/rest-api/wpRestSitesController.php b/tests/phpunit/tests/rest-api/wpRestSitesController.php index 789eb40852f2c..3291c3e9803ce 100644 --- a/tests/phpunit/tests/rest-api/wpRestSitesController.php +++ b/tests/phpunit/tests/rest-api/wpRestSitesController.php @@ -306,7 +306,8 @@ public function test_delete_item_uninitializes_the_site() { } /** - * Sites have no trash, so deleting has to be explicit. + * Deleting without force marks the site as deleted and removes its users, + * but does not drop the site. * * @ticket 40365 * @covers ::delete_item @@ -316,12 +317,26 @@ public function test_delete_item_requires_force() { wp_set_current_user( self::$superadmin_id ); $blog_id = self::factory()->blog->create( array( 'path' => '/consectetur/' ) ); + $user_id = self::factory()->user->create(); + add_user_to_blog( $blog_id, $user_id, 'author' ); + + $this->assertTrue( is_user_member_of_blog( $user_id, $blog_id ) ); $request = new WP_REST_Request( 'DELETE', '/wp/v2/sites/' . $blog_id ); $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_trash_not_supported', $response, 501 ); - $this->assertNotNull( get_site( $blog_id ) ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $this->assertTrue( $data['deleted'] ); + + // The site still exists but is flagged as deleted. + $site = get_site( $blog_id ); + $this->assertNotNull( $site ); + $this->assertEquals( '1', $site->deleted ); + + // Its users have been removed from the blog. + $this->assertFalse( is_user_member_of_blog( $user_id, $blog_id ) ); } /**