search_theme_directories

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

WordPress Version: 6.3

/**
 * Searches all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 *
 * @param bool $force Optional. Whether to force a new directory scan. Default false.
 * @return array|false Valid themes found on success, false on failure.
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    /*
     * Set up maybe-relative, maybe-absolute array of theme directories.
     * We always want to return absolute, but we need to cache relative
     * to use in get_theme_root().
     */
    foreach ($wp_theme_directories as $theme_root) {
        if (str_starts_with($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $context          The class or function name calling the filter.
     */
    $cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories');
    if ($cache_expiration) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 30 * MINUTE_IN_SECONDS;
        }
    } else {
        $cache_expiration = 30 * MINUTE_IN_SECONDS;
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the active theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || '.' === $dir[0] || 'CVS' === $dir) {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                /*
                 * wp-content/themes/a-single-theme
                 * wp-content/themes is $theme_root, a-single-theme is $dir.
                 */
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                /*
                 * wp-content/themes/a-folder-of-themes/*
                 * wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
                 */
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || '.' === $dir[0] || 'CVS' === $dir) {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                /*
                 * Never mind the above, it's just a theme missing a style.css.
                 * Return it; WP_Theme will catch the error.
                 */
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if (get_site_transient('theme_roots') != $theme_roots) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 6.1

/**
 * Searches all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 *
 * @param bool $force Optional. Whether to force a new directory scan. Default false.
 * @return array|false Valid themes found on success, false on failure.
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    /*
     * Set up maybe-relative, maybe-absolute array of theme directories.
     * We always want to return absolute, but we need to cache relative
     * to use in get_theme_root().
     */
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $context          The class or function name calling the filter.
     */
    $cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories');
    if ($cache_expiration) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 30 * MINUTE_IN_SECONDS;
        }
    } else {
        $cache_expiration = 30 * MINUTE_IN_SECONDS;
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the active theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || '.' === $dir[0] || 'CVS' === $dir) {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir.
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || '.' === $dir[0] || 'CVS' === $dir) {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if (get_site_transient('theme_roots') != $theme_roots) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 5.5

/**
 * Searches all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 *
 * @param bool $force Optional. Whether to force a new directory scan. Default false.
 * @return array|false Valid themes found on success, false on failure.
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    /*
     * Set up maybe-relative, maybe-absolute array of theme directories.
     * We always want to return absolute, but we need to cache relative
     * to use in get_theme_root().
     */
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $context          The class or function name calling the filter.
     */
    $cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories');
    if ($cache_expiration) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 30 * MINUTE_IN_SECONDS;
        }
    } else {
        $cache_expiration = 30 * MINUTE_IN_SECONDS;
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || '.' === $dir[0] || 'CVS' === $dir) {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir.
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || '.' === $dir[0] || 'CVS' === $dir) {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if (get_site_transient('theme_roots') != $theme_roots) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 5.4

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $found_themes
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array|false Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    /*
     * Set up maybe-relative, maybe-absolute array of theme directories.
     * We always want to return absolute, but we need to cache relative
     * to use in get_theme_root().
     */
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    $cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories');
    if ($cache_expiration) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 30 * MINUTE_IN_SECONDS;
        }
    } else {
        $cache_expiration = 30 * MINUTE_IN_SECONDS;
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || '.' === $dir[0] || 'CVS' === $dir) {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir.
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || '.' === $dir[0] || 'CVS' === $dir) {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if (get_site_transient('theme_roots') != $theme_roots) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 5.3

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $found_themes
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array|false Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    $cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories');
    if ($cache_expiration) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
            // half hour
        }
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 5.1

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $found_themes
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array|false Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    if ($cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories')) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
            // half hour
        }
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 4.6

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $found_themes
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array|false Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filters whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    if ($cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories')) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
        }
        // half hour
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 4.3

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $found_themes
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array|false Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    static $found_themes = null;
    if (empty($wp_theme_directories)) {
        return false;
    }
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filter whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    if ($cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories')) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
        }
        // half hour
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 4.2

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    if (empty($wp_theme_directories)) {
        return false;
    }
    static $found_themes;
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    $relative_theme_roots = array();
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filter whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    if ($cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories')) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
        }
        // half hour
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 3.8

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    if (empty($wp_theme_directories)) {
        return false;
    }
    static $found_themes;
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    /**
     * Filter whether to get the cache of the registered theme directories.
     *
     * @since 3.4.0
     *
     * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
     * @param string $cache_directory  Directory to be searched for the cache.
     */
    if ($cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories')) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
        }
        // half hour
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}

WordPress Version: 3.7

/**
 * Search all registered theme directories for complete and valid themes.
 *
 * @since 2.9.0
 *
 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
 * @return array Valid themes found
 */
function search_theme_directories($force = false)
{
    global $wp_theme_directories;
    if (empty($wp_theme_directories)) {
        return false;
    }
    static $found_themes;
    if (!$force && isset($found_themes)) {
        return $found_themes;
    }
    $found_themes = array();
    $wp_theme_directories = (array) $wp_theme_directories;
    // Set up maybe-relative, maybe-absolute array of theme directories.
    // We always want to return absolute, but we need to cache relative
    // to use in get_theme_root().
    foreach ($wp_theme_directories as $theme_root) {
        if (0 === strpos($theme_root, WP_CONTENT_DIR)) {
            $relative_theme_roots[str_replace(WP_CONTENT_DIR, '', $theme_root)] = $theme_root;
        } else {
            $relative_theme_roots[$theme_root] = $theme_root;
        }
    }
    if ($cache_expiration = apply_filters('wp_cache_themes_persistently', false, 'search_theme_directories')) {
        $cached_roots = get_site_transient('theme_roots');
        if (is_array($cached_roots)) {
            foreach ($cached_roots as $theme_dir => $theme_root) {
                // A cached theme root is no longer around, so skip it.
                if (!isset($relative_theme_roots[$theme_root])) {
                    continue;
                }
                $found_themes[$theme_dir] = array('theme_file' => $theme_dir . '/style.css', 'theme_root' => $relative_theme_roots[$theme_root]);
            }
            return $found_themes;
        }
        if (!is_int($cache_expiration)) {
            $cache_expiration = 1800;
        }
        // half hour
    } else {
        $cache_expiration = 1800;
        // half hour
    }
    /* Loop the registered theme directories and extract all themes */
    foreach ($wp_theme_directories as $theme_root) {
        // Start with directories in the root of the current theme directory.
        $dirs = @scandir($theme_root);
        if (!$dirs) {
            trigger_error("{$theme_root} is not readable", E_USER_NOTICE);
            continue;
        }
        foreach ($dirs as $dir) {
            if (!is_dir($theme_root . '/' . $dir) || $dir[0] == '.' || $dir == 'CVS') {
                continue;
            }
            if (file_exists($theme_root . '/' . $dir . '/style.css')) {
                // wp-content/themes/a-single-theme
                // wp-content/themes is $theme_root, a-single-theme is $dir
                $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
            } else {
                $found_theme = false;
                // wp-content/themes/a-folder-of-themes/*
                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
                $sub_dirs = @scandir($theme_root . '/' . $dir);
                if (!$sub_dirs) {
                    trigger_error("{$theme_root}/{$dir} is not readable", E_USER_NOTICE);
                    continue;
                }
                foreach ($sub_dirs as $sub_dir) {
                    if (!is_dir($theme_root . '/' . $dir . '/' . $sub_dir) || $dir[0] == '.' || $dir == 'CVS') {
                        continue;
                    }
                    if (!file_exists($theme_root . '/' . $dir . '/' . $sub_dir . '/style.css')) {
                        continue;
                    }
                    $found_themes[$dir . '/' . $sub_dir] = array('theme_file' => $dir . '/' . $sub_dir . '/style.css', 'theme_root' => $theme_root);
                    $found_theme = true;
                }
                // Never mind the above, it's just a theme missing a style.css.
                // Return it; WP_Theme will catch the error.
                if (!$found_theme) {
                    $found_themes[$dir] = array('theme_file' => $dir . '/style.css', 'theme_root' => $theme_root);
                }
            }
        }
    }
    asort($found_themes);
    $theme_roots = array();
    $relative_theme_roots = array_flip($relative_theme_roots);
    foreach ($found_themes as $theme_dir => $theme_data) {
        $theme_roots[$theme_dir] = $relative_theme_roots[$theme_data['theme_root']];
        // Convert absolute to relative.
    }
    if ($theme_roots != get_site_transient('theme_roots')) {
        set_site_transient('theme_roots', $theme_roots, $cache_expiration);
    }
    return $found_themes;
}