recurse_dirsize

The timeline below displays how wordpress function recurse_dirsize has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.4

/**
 * Gets the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory size when it contains other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 The `$exclude` parameter was added.
 * @since 5.2.0 The `$max_execution_time` parameter was added.
 * @since 5.6.0 The `$directory_cache` parameter was added.
 *
 * @param string          $directory          Full path of a directory.
 * @param string|string[] $exclude            Optional. Full path of a subdirectory to exclude from the total,
 *                                            or array of paths. Expected without trailing slash(es).
 *                                            Default null.
 * @param int             $max_execution_time Optional. Maximum time to run before giving up. In seconds.
 *                                            The timeout is global and is measured from the moment
 *                                            WordPress started to load. Defaults to the value of
 *                                            `max_execution_time` PHP setting.
 * @param array           $directory_cache    Optional. Array of cached directory paths.
 *                                            Defaults to the value of `dirsize_cache` transient.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null, &$directory_cache = null)
{
    $directory = untrailingslashit($directory);
    $save_cache = false;
    if (!isset($directory_cache)) {
        $directory_cache = get_transient('dirsize_cache');
        $save_cache = true;
    }
    if (isset($directory_cache[$directory]) && is_int($directory_cache[$directory])) {
        return $directory_cache[$directory];
    }
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    /**
     * Filters the amount of storage space used by one directory and all its children, in megabytes.
     *
     * 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.
     *
     * @since 5.6.0
     *
     * @param int|false            $space_used         The amount of used space, in bytes. Default 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);
    if (false === $size) {
        $size = 0;
        $handle = opendir($directory);
        if ($handle) {
            while (($file = readdir($handle)) !== false) {
                $path = $directory . '/' . $file;
                if ('.' !== $file && '..' !== $file) {
                    if (is_file($path)) {
                        $size += filesize($path);
                    } elseif (is_dir($path)) {
                        $handlesize = recurse_dirsize($path, $exclude, $max_execution_time, $directory_cache);
                        if ($handlesize > 0) {
                            $size += $handlesize;
                        }
                    }
                    if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                        // Time exceeded. Give up instead of risking a fatal timeout.
                        $size = null;
                        break;
                    }
                }
            }
            closedir($handle);
        }
    }
    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.
    if ($save_cache) {
        $expiration = wp_using_ext_object_cache() ? 0 : (10 * YEAR_IN_SECONDS);
        set_transient('dirsize_cache', $directory_cache, $expiration);
    }
    return $size;
}

WordPress Version: 6.2

/**
 * Gets the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory size when it contains other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 The `$exclude` parameter was added.
 * @since 5.2.0 The `$max_execution_time` parameter was added.
 * @since 5.6.0 The `$directory_cache` parameter was added.
 *
 * @param string          $directory          Full path of a directory.
 * @param string|string[] $exclude            Optional. Full path of a subdirectory to exclude from the total,
 *                                            or array of paths. Expected without trailing slash(es).
 *                                            Default null.
 * @param int             $max_execution_time Optional. Maximum time to run before giving up. In seconds.
 *                                            The timeout is global and is measured from the moment
 *                                            WordPress started to load. Defaults to the value of
 *                                            `max_execution_time` PHP setting.
 * @param array           $directory_cache    Optional. Array of cached directory paths.
 *                                            Defaults to the value of `dirsize_cache` transient.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null, &$directory_cache = null)
{
    $directory = untrailingslashit($directory);
    $save_cache = false;
    if (!isset($directory_cache)) {
        $directory_cache = get_transient('dirsize_cache');
        $save_cache = true;
    }
    if (isset($directory_cache[$directory]) && is_int($directory_cache[$directory])) {
        return $directory_cache[$directory];
    }
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    /**
     * Filters the amount of storage space used by one directory and all its children, in megabytes.
     *
     * 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.
     *
     * @since 5.6.0
     *
     * @param int|false            $space_used         The amount of used space, in bytes. Default 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);
    if (false === $size) {
        $size = 0;
        $handle = opendir($directory);
        if ($handle) {
            while (($file = readdir($handle)) !== false) {
                $path = $directory . '/' . $file;
                if ('.' !== $file && '..' !== $file) {
                    if (is_file($path)) {
                        $size += filesize($path);
                    } elseif (is_dir($path)) {
                        $handlesize = recurse_dirsize($path, $exclude, $max_execution_time, $directory_cache);
                        if ($handlesize > 0) {
                            $size += $handlesize;
                        }
                    }
                    if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                        // Time exceeded. Give up instead of risking a fatal timeout.
                        $size = null;
                        break;
                    }
                }
            }
            closedir($handle);
        }
    }
    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.
    if ($save_cache) {
        set_transient('dirsize_cache', $directory_cache);
    }
    return $size;
}

WordPress Version: 6.1

/**
 * Gets the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory size when it contains other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 The `$exclude` parameter was added.
 * @since 5.2.0 The `$max_execution_time` parameter was added.
 * @since 5.6.0 The `$directory_cache` parameter was added.
 *
 * @param string          $directory          Full path of a directory.
 * @param string|string[] $exclude            Optional. Full path of a subdirectory to exclude from the total,
 *                                            or array of paths. Expected without trailing slash(es).
 * @param int             $max_execution_time Optional. Maximum time to run before giving up. In seconds.
 *                                            The timeout is global and is measured from the moment
 *                                            WordPress started to load.
 * @param array           $directory_cache    Optional. Array of cached directory paths.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null, &$directory_cache = null)
{
    $directory = untrailingslashit($directory);
    $save_cache = false;
    if (!isset($directory_cache)) {
        $directory_cache = get_transient('dirsize_cache');
        $save_cache = true;
    }
    if (isset($directory_cache[$directory]) && is_int($directory_cache[$directory])) {
        return $directory_cache[$directory];
    }
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    /**
     * Filters the amount of storage space used by one directory and all its children, in megabytes.
     *
     * 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.
     *
     * @since 5.6.0
     *
     * @param int|false            $space_used         The amount of used space, in bytes. Default 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);
    if (false === $size) {
        $size = 0;
        $handle = opendir($directory);
        if ($handle) {
            while (($file = readdir($handle)) !== false) {
                $path = $directory . '/' . $file;
                if ('.' !== $file && '..' !== $file) {
                    if (is_file($path)) {
                        $size += filesize($path);
                    } elseif (is_dir($path)) {
                        $handlesize = recurse_dirsize($path, $exclude, $max_execution_time, $directory_cache);
                        if ($handlesize > 0) {
                            $size += $handlesize;
                        }
                    }
                    if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                        // Time exceeded. Give up instead of risking a fatal timeout.
                        $size = null;
                        break;
                    }
                }
            }
            closedir($handle);
        }
    }
    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.
    if ($save_cache) {
        set_transient('dirsize_cache', $directory_cache);
    }
    return $size;
}

WordPress Version: 5.9

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory size when it contains other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 The `$exclude` parameter was added.
 * @since 5.2.0 The `$max_execution_time` parameter was added.
 * @since 5.6.0 The `$directory_cache` parameter was added.
 *
 * @param string          $directory          Full path of a directory.
 * @param string|string[] $exclude            Optional. Full path of a subdirectory to exclude from the total,
 *                                            or array of paths. Expected without trailing slash(es).
 * @param int             $max_execution_time Optional. Maximum time to run before giving up. In seconds.
 *                                            The timeout is global and is measured from the moment
 *                                            WordPress started to load.
 * @param array           $directory_cache    Optional. Array of cached directory paths.
 *
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null, &$directory_cache = null)
{
    $directory = untrailingslashit($directory);
    $save_cache = false;
    if (!isset($directory_cache)) {
        $directory_cache = get_transient('dirsize_cache');
        $save_cache = true;
    }
    if (isset($directory_cache[$directory]) && is_int($directory_cache[$directory])) {
        return $directory_cache[$directory];
    }
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    /**
     * Filters the amount of storage space used by one directory and all its children, in megabytes.
     *
     * 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.
     *
     * @since 5.6.0
     *
     * @param int|false            $space_used         The amount of used space, in bytes. Default 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);
    if (false === $size) {
        $size = 0;
        $handle = opendir($directory);
        if ($handle) {
            while (($file = readdir($handle)) !== false) {
                $path = $directory . '/' . $file;
                if ('.' !== $file && '..' !== $file) {
                    if (is_file($path)) {
                        $size += filesize($path);
                    } elseif (is_dir($path)) {
                        $handlesize = recurse_dirsize($path, $exclude, $max_execution_time, $directory_cache);
                        if ($handlesize > 0) {
                            $size += $handlesize;
                        }
                    }
                    if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                        // Time exceeded. Give up instead of risking a fatal timeout.
                        $size = null;
                        break;
                    }
                }
            }
            closedir($handle);
        }
    }
    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.
    if ($save_cache) {
        set_transient('dirsize_cache', $directory_cache);
    }
    return $size;
}

WordPress Version: 5.6

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory size when it contains other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 The `$exclude` parameter was added.
 * @since 5.2.0 The `$max_execution_time` parameter was added.
 * @since 5.6.0 The `$directory_cache` parameter was added.
 *
 * @param string       $directory          Full path of a directory.
 * @param string|array $exclude            Optional. Full path of a subdirectory to exclude from the total,
 *                                         or array of paths. Expected without trailing slash(es).
 * @param int          $max_execution_time Maximum time to run before giving up. In seconds. The timeout is global
 *                                         and is measured from the moment WordPress started to load.
 * @param array        $directory_cache    Optional. Array of cached directory paths.
 *
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null, &$directory_cache = null)
{
    $directory = untrailingslashit($directory);
    $save_cache = false;
    if (!isset($directory_cache)) {
        $directory_cache = get_transient('dirsize_cache');
        $save_cache = true;
    }
    if (isset($directory_cache[$directory]) && is_int($directory_cache[$directory])) {
        return $directory_cache[$directory];
    }
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    /**
     * Filters the amount of storage space used by one directory and all its children, in megabytes.
     *
     * 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.
     *
     * @since 5.6.0
     *
     * @param int|false $space_used The amount of used space, in bytes. Default false.
     */
    $size = apply_filters('pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache);
    if (false === $size) {
        $size = 0;
        $handle = opendir($directory);
        if ($handle) {
            while (($file = readdir($handle)) !== false) {
                $path = $directory . '/' . $file;
                if ('.' !== $file && '..' !== $file) {
                    if (is_file($path)) {
                        $size += filesize($path);
                    } elseif (is_dir($path)) {
                        $handlesize = recurse_dirsize($path, $exclude, $max_execution_time, $directory_cache);
                        if ($handlesize > 0) {
                            $size += $handlesize;
                        }
                    }
                    if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                        // Time exceeded. Give up instead of risking a fatal timeout.
                        $size = null;
                        break;
                    }
                }
            }
            closedir($handle);
        }
    }
    $directory_cache[$directory] = $size;
    // Only write the transient on the top level call and not on recursive calls.
    if ($save_cache) {
        set_transient('dirsize_cache', $directory_cache);
    }
    return $size;
}

WordPress Version: 5.5

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 $exclude parameter added.
 * @since 5.2.0 $max_execution_time parameter added.
 *
 * @param string       $directory          Full path of a directory.
 * @param string|array $exclude            Optional. Full path of a subdirectory to exclude from the total,
 *                                         or array of paths. Expected without trailing slash(es).
 * @param int          $max_execution_time Maximum time to run before giving up. In seconds. The timeout is global
 *                                         and is measured from the moment WordPress started to load.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    $handle = opendir($directory);
    if ($handle) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ('.' !== $file && '..' !== $file) {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path, $exclude, $max_execution_time);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
                if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                    // Time exceeded. Give up instead of risking a fatal timeout.
                    $size = null;
                    break;
                }
            }
        }
        closedir($handle);
    }
    return $size;
}

WordPress Version: 5.4

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 $exclude parameter added.
 * @since 5.2.0 $max_execution_time parameter added.
 *
 * @param string $directory       Full path of a directory.
 * @param string|array $exclude   Optional. Full path of a subdirectory to exclude from the total, or array of paths.
 *                                Expected without trailing slash(es).
 * @param int $max_execution_time Maximum time to run before giving up. In seconds.
 *                                The timeout is global and is measured from the moment WordPress started to load.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if (null === $max_execution_time) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    $handle = opendir($directory);
    if ($handle) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ('.' !== $file && '..' !== $file) {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path, $exclude, $max_execution_time);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
                if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                    // Time exceeded. Give up instead of risking a fatal timeout.
                    $size = null;
                    break;
                }
            }
        }
        closedir($handle);
    }
    return $size;
}

WordPress Version: 5.3

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 $exclude parameter added.
 * @since 5.2.0 $max_execution_time parameter added.
 *
 * @param string $directory       Full path of a directory.
 * @param string|array $exclude   Optional. Full path of a subdirectory to exclude from the total, or array of paths.
 *                                Expected without trailing slash(es).
 * @param int $max_execution_time Maximum time to run before giving up. In seconds.
 *                                The timeout is global and is measured from the moment WordPress started to load.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if ($max_execution_time === null) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    $handle = opendir($directory);
    if ($handle) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ($file != '.' && $file != '..') {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path, $exclude, $max_execution_time);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
                if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                    // Time exceeded. Give up instead of risking a fatal timeout.
                    $size = null;
                    break;
                }
            }
        }
        closedir($handle);
    }
    return $size;
}

WordPress Version: 5.2

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 $exclude parameter added.
 * @since 5.2.0 $max_execution_time parameter added.
 *
 * @param string $directory       Full path of a directory.
 * @param string|array $exclude   Optional. Full path of a subdirectory to exclude from the total, or array of paths.
 *                                Expected without trailing slash(es).
 * @param int $max_execution_time Maximum time to run before giving up. In seconds.
 *                                The timeout is global and is measured from the moment WordPress started to load.
 * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
 */
function recurse_dirsize($directory, $exclude = null, $max_execution_time = null)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if (is_string($exclude) && $directory === $exclude || is_array($exclude) && in_array($directory, $exclude, true)) {
        return false;
    }
    if ($max_execution_time === null) {
        // Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
        if (function_exists('ini_get')) {
            $max_execution_time = ini_get('max_execution_time');
        } else {
            // Disable...
            $max_execution_time = 0;
        }
        // Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
        if ($max_execution_time > 10) {
            $max_execution_time -= 1;
        }
    }
    if ($handle = opendir($directory)) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ($file != '.' && $file != '..') {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path, $exclude, $max_execution_time);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
                if ($max_execution_time > 0 && microtime(true) - WP_START_TIMESTAMP > $max_execution_time) {
                    // Time exceeded. Give up instead of risking a fatal timeout.
                    $size = null;
                    break;
                }
            }
        }
        closedir($handle);
    }
    return $size;
}

WordPress Version: 4.9

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU (3.0.0)
 * @since 4.3.0 $exclude parameter added.
 *
 * @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, $exclude = null)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory) || $directory === $exclude) {
        return false;
    }
    if ($handle = opendir($directory)) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ($file != '.' && $file != '..') {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path, $exclude);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
            }
        }
        closedir($handle);
    }
    return $size;
}

WordPress Version: 4.3

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU
 * @since 4.3.0 $exclude parameter added.
 *
 * @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, $exclude = null)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory) || $directory === $exclude) {
        return false;
    }
    if ($handle = opendir($directory)) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ($file != '.' && $file != '..') {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path, $exclude);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
            }
        }
        closedir($handle);
    }
    return $size;
}

WordPress Version: 3.7

/**
 * Get the size of a directory recursively.
 *
 * Used by get_dirsize() to get a directory's size when it contains
 * other directories.
 *
 * @since MU
 *
 * @param string $directory
 * @return int
 */
function recurse_dirsize($directory)
{
    $size = 0;
    $directory = untrailingslashit($directory);
    if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
        return false;
    }
    if ($handle = opendir($directory)) {
        while (($file = readdir($handle)) !== false) {
            $path = $directory . '/' . $file;
            if ($file != '.' && $file != '..') {
                if (is_file($path)) {
                    $size += filesize($path);
                } elseif (is_dir($path)) {
                    $handlesize = recurse_dirsize($path);
                    if ($handlesize > 0) {
                        $size += $handlesize;
                    }
                }
            }
        }
        closedir($handle);
    }
    return $size;
}