From 6df13376450a61492a19459f13d51a8494fa0def Mon Sep 17 00:00:00 2001 From: Jeremy Felt Date: Mon, 13 Jul 2015 00:06:39 +0000 Subject: [PATCH] Exclude individual site directories when calculating space used for the main site. * Add an `$exclude` parameter to `recurse_dirsize()`. * Use this parameter in `get_dirsize()` to exclude `/sites` when on the main site. * Add tests for main site and switched site. Props @earnjam, @jeremyfelt. Fixes #30202. git-svn-id: https://develop.svn.wordpress.org/trunk@33184 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/ms-functions.php | 25 +++-- .../phpunit/tests/multisite/getSpaceUsed.php | 94 +++++++++++++++++++ 2 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 tests/phpunit/tests/multisite/getSpaceUsed.php diff --git a/src/wp-includes/ms-functions.php b/src/wp-includes/ms-functions.php index 487d8401e5..edbb984255 100644 --- a/src/wp-includes/ms-functions.php +++ b/src/wp-includes/ms-functions.php @@ -1686,8 +1686,8 @@ function get_most_recent_post_of_user( $user_id ) { * * @since MU * - * @param string $directory - * @return int + * @param string $directory Full path of a directory. + * @return int Size of the directory in MB. */ function get_dirsize( $directory ) { $dirsize = get_transient( 'dirsize_cache' ); @@ -1697,7 +1697,13 @@ function get_dirsize( $directory ) { if ( ! is_array( $dirsize ) ) $dirsize = array(); - $dirsize[ $directory ][ 'size' ] = recurse_dirsize( $directory ); + // Exclude individual site directories from the total when checking the main site, + // as they are subdirectories and should not be counted. + if ( is_main_site() ) { + $dirsize[ $directory ][ 'size' ] = recurse_dirsize( $directory, $directory . '/sites' ); + } else { + $dirsize[ $directory ][ 'size' ] = recurse_dirsize( $directory ); + } set_transient( 'dirsize_cache', $dirsize, HOUR_IN_SECONDS ); return $dirsize[ $directory ][ 'size' ]; @@ -1710,17 +1716,20 @@ function get_dirsize( $directory ) { * other directories. * * @since MU + * @since 4.3.0 $exclude parameter added. * - * @param string $directory - * @return int|false + * @param string $directory Full path of a directory. + * @param string $exclude Optional. Full path of a subdirectory to exclude from the total. + * @return int|false Size in MB if a valid directory. False if not. */ -function recurse_dirsize( $directory ) { +function recurse_dirsize( $directory, $exclude = null ) { $size = 0; $directory = untrailingslashit( $directory ); - if ( !file_exists($directory) || !is_dir( $directory ) || !is_readable( $directory ) ) + if ( ! file_exists( $directory ) || ! is_dir( $directory ) || ! is_readable( $directory ) || $directory === $exclude ) { return false; + } if ($handle = opendir($directory)) { while(($file = readdir($handle)) !== false) { @@ -1729,7 +1738,7 @@ function recurse_dirsize( $directory ) { if (is_file($path)) { $size += filesize($path); } elseif (is_dir($path)) { - $handlesize = recurse_dirsize($path); + $handlesize = recurse_dirsize( $path, $exclude ); if ($handlesize > 0) $size += $handlesize; } diff --git a/tests/phpunit/tests/multisite/getSpaceUsed.php b/tests/phpunit/tests/multisite/getSpaceUsed.php new file mode 100644 index 0000000000..e9f6bdc0a1 --- /dev/null +++ b/tests/phpunit/tests/multisite/getSpaceUsed.php @@ -0,0 +1,94 @@ +suppress = $wpdb->suppress_errors(); + + $_SERVER['REMOTE_ADDR'] = ''; + } + + function tearDown() { + global $wpdb; + $wpdb->suppress_errors( $this->suppress ); + parent::tearDown(); + } + + function test_get_space_used_switched_site() { + $blog_id = $this->factory->blog->create(); + switch_to_blog( $blog_id ); + + // Our comparison of space relies on an initial value of 0. If a previous test has failed or if the + // src directory already contains a content directory with site content, then the initial expectation + // will be polluted. We create sites until an empty one is available. + while ( 0 != get_space_used() ) { + restore_current_blog(); + $blog_id = $this->factory->blog->create(); + switch_to_blog( $blog_id ); + } + + // Upload a file to the new site. + $filename = rand_str().'.jpg'; + $contents = rand_str(); + $file = wp_upload_bits( $filename, null, $contents ); + + // get_space_used() is measures in MB, get the size of the new file in MB. + $size = filesize( $file['file'] ) / 1024 / 1024; + + delete_transient( 'dirsize_cache' ); + + $this->assertEquals( $size, get_space_used() ); + $upload_dir = wp_upload_dir(); + $this->remove_added_uploads(); + $this->delete_folders( $upload_dir['basedir'] ); + restore_current_blog(); + } + + /** + * Directories of sub sites on a network should not count against the same spaced used total for + * the main site. + */ + function test_get_space_used_main_site() { + $space_used = get_space_used(); + + $blog_id = $this->factory->blog->create(); + switch_to_blog( $blog_id ); + + // We don't rely on an initial value of 0 for space used, but should have a clean space available + // so that we can remove any uploaded files and directories without concern of a conflict with + // existing content directories in src. + while ( 0 != get_space_used() ) { + restore_current_blog(); + $blog_id = $this->factory->blog->create(); + switch_to_blog( $blog_id ); + } + + // Upload a file to the new site. + $filename = rand_str().'.jpg'; + $contents = rand_str(); + wp_upload_bits( $filename, null, $contents ); + + restore_current_blog(); + + delete_transient( 'dirsize_cache' ); + + $this->assertEquals( $space_used, get_space_used() ); + + // Switch back to the new site to remove the uploaded file. + switch_to_blog( $blog_id ); + $upload_dir = wp_upload_dir(); + $this->remove_added_uploads(); + $this->delete_folders( $upload_dir['basedir'] ); + restore_current_blog(); + } +} +endif; \ No newline at end of file