From 3326f3a9efe4b4623bf5ff42327eaf4fb0fd113a Mon Sep 17 00:00:00 2001 From: Sukhendu Sekhar Guria Date: Wed, 29 Jul 2026 11:40:02 +0530 Subject: [PATCH 1/2] Networks and Sites: Add directory size cache filter --- src/wp-includes/functions.php | 45 ++++++++++++++++--- .../tests/multisite/cleanDirsizeCache.php | 39 ++++++++++++++++ 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 9a688b9866ce0..df250c2cbf083 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -8973,6 +8973,40 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul } } + if ( ! is_array( $directory_cache ) ) { + $directory_cache = array(); + } + + /** + * Filters the directory size cache before a directory's size is calculated. + * + * Returning an array containing the current directory's path with an integer size + * can short-circuit the recursive PHP file size calculation. + * + * @since x.x.x + * + * @param array $directory_cache Array of cached directory paths and sizes. + * @param string $directory Full path of a directory. + * @param string|string[]|null $exclude Full path of a subdirectory to exclude from the total, + * or array of paths. + * @param int $max_execution_time Maximum time to run before giving up. In seconds. + */ + $filtered_directory_cache = apply_filters( + 'pre_recurse_dirsize_cache', + $directory_cache, + $directory, + $exclude, + $max_execution_time + ); + + if ( is_array( $filtered_directory_cache ) ) { + $directory_cache = $filtered_directory_cache; + } + + $size = isset( $directory_cache[ $directory ] ) && is_int( $directory_cache[ $directory ] ) + ? $directory_cache[ $directory ] + : false; + /** * Filters the amount of storage space used by one directory and all its children, in megabytes. * @@ -8980,15 +9014,18 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul * and use something else, like a CDN API or native operating system tools for better performance. * * @since 5.6.0 + * @since x.x.x The default `$space_used` value may be provided by the + * `pre_recurse_dirsize_cache` filter. * - * @param int|false $space_used The amount of used space, in bytes. Default false. + * @param int|false $space_used The amount of used space, in bytes. Default cached size + * for the current directory, or false. * @param string $directory Full path of a directory. * @param string|string[]|null $exclude Full path of a subdirectory to exclude from the total, * or array of paths. * @param int $max_execution_time Maximum time to run before giving up. In seconds. * @param array $directory_cache Array of cached directory paths. */ - $size = apply_filters( 'pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache ); + $size = apply_filters( 'pre_recurse_dirsize', $size, $directory, $exclude, $max_execution_time, $directory_cache ); if ( false === $size ) { $size = 0; @@ -9020,10 +9057,6 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul } } - if ( ! is_array( $directory_cache ) ) { - $directory_cache = array(); - } - $directory_cache[ $directory ] = $size; // Only write the transient on the top level call and not on recursive calls. diff --git a/tests/phpunit/tests/multisite/cleanDirsizeCache.php b/tests/phpunit/tests/multisite/cleanDirsizeCache.php index 2271c3b6bcfe9..dc627d86329f7 100644 --- a/tests/phpunit/tests/multisite/cleanDirsizeCache.php +++ b/tests/phpunit/tests/multisite/cleanDirsizeCache.php @@ -218,6 +218,45 @@ public function filter_pre_recurse_dirsize() { return 1042; } + /** + * @ticket 56909 + */ + public function test_pre_recurse_dirsize_cache_filter() { + delete_transient( 'dirsize_cache' ); + add_filter( 'pre_recurse_dirsize_cache', array( $this, 'filter_pre_recurse_dirsize_cache' ), 10, 2 ); + + $directory = untrailingslashit( wp_upload_dir()['path'] ); + $this->assertSame( 1042, recurse_dirsize( $directory ) ); + $this->assertSame( 42, get_transient( 'dirsize_cache' )[ $directory . '/subdirectory' ] ); + + remove_filter( 'pre_recurse_dirsize_cache', array( $this, 'filter_pre_recurse_dirsize_cache' ) ); + } + + public function filter_pre_recurse_dirsize_cache( $directory_cache, $directory ) { + $directory_cache[ $directory ] = 1042; + $directory_cache[ $directory . '/subdirectory' ] = 42; + + return $directory_cache; + } + + /** + * @ticket 56909 + */ + public function test_pre_recurse_dirsize_cache_filter_with_invalid_value() { + $directory = untrailingslashit( wp_upload_dir()['path'] ); + $cached_directory = $directory . '/cached'; + set_transient( 'dirsize_cache', array( $cached_directory => 42 ) ); + add_filter( 'pre_recurse_dirsize_cache', '__return_false' ); + + $this->assertIsInt( recurse_dirsize( $directory ) ); + + $directory_cache = get_transient( 'dirsize_cache' ); + $this->assertIsArray( $directory_cache ); + $this->assertSame( 42, $directory_cache[ $cached_directory ] ); + + remove_filter( 'pre_recurse_dirsize_cache', '__return_false' ); + } + private function get_mock_dirsize_cache_for_site( $site_id ) { $prefix = wp_upload_dir()['basedir']; From a1212f66adf64696c0488e2909833fd4a8e09206 Mon Sep 17 00:00:00 2001 From: Sukhendu Sekhar Guria Date: Wed, 29 Jul 2026 12:05:54 +0530 Subject: [PATCH 2/2] Networks and Sites: Correct dirsize docs and tests --- src/wp-includes/functions.php | 2 +- tests/phpunit/tests/multisite/cleanDirsizeCache.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index df250c2cbf083..290a7ee4a647a 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -9008,7 +9008,7 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul : false; /** - * Filters the amount of storage space used by one directory and all its children, in megabytes. + * Filters the amount of storage space used by one directory and all its children, in bytes. * * Return the actual used space to short-circuit the recursive PHP file size calculation * and use something else, like a CDN API or native operating system tools for better performance. diff --git a/tests/phpunit/tests/multisite/cleanDirsizeCache.php b/tests/phpunit/tests/multisite/cleanDirsizeCache.php index dc627d86329f7..406919318676e 100644 --- a/tests/phpunit/tests/multisite/cleanDirsizeCache.php +++ b/tests/phpunit/tests/multisite/cleanDirsizeCache.php @@ -230,6 +230,7 @@ public function test_pre_recurse_dirsize_cache_filter() { $this->assertSame( 42, get_transient( 'dirsize_cache' )[ $directory . '/subdirectory' ] ); remove_filter( 'pre_recurse_dirsize_cache', array( $this, 'filter_pre_recurse_dirsize_cache' ) ); + delete_transient( 'dirsize_cache' ); } public function filter_pre_recurse_dirsize_cache( $directory_cache, $directory ) { @@ -255,6 +256,7 @@ public function test_pre_recurse_dirsize_cache_filter_with_invalid_value() { $this->assertSame( 42, $directory_cache[ $cached_directory ] ); remove_filter( 'pre_recurse_dirsize_cache', '__return_false' ); + delete_transient( 'dirsize_cache' ); } private function get_mock_dirsize_cache_for_site( $site_id ) {