wp_get_themes

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

WordPress Version: 6.3

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 *
 * @param array $args {
 *     Optional. The search arguments.
 *
 *     @type mixed $errors  True to return themes with errors, false to return
 *                          themes without errors, null to return all themes.
 *                          Default false.
 *     @type mixed $allowed (Multisite) True to return only allowed themes for a site.
 *                          False to return only disallowed themes for a site.
 *                          'site' to return only site-allowed themes.
 *                          'network' to return only network-allowed themes.
 *                          Null to return all themes. Default null.
 *     @type int   $blog_id (Multisite) The blog ID used to calculate which themes
 *                          are allowed. Default 0, synonymous for the current blog.
 * }
 * @return WP_Theme[] Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (is_array($wp_theme_directories) && count($wp_theme_directories) > 1) {
        /*
         * Make sure the active theme wins out, in case search_theme_directories() picks the wrong
         * one in the case of a conflict. (Normally, last registered theme root wins.)
         */
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories, true)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = new WP_Theme($theme, $theme_root['theme_root']);
            $_themes[$theme_root['theme_root'] . '/' . $theme] = $themes[$theme];
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 6.1

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 *
 * @param array $args {
 *     Optional. The search arguments.
 *
 *     @type mixed $errors  True to return themes with errors, false to return
 *                          themes without errors, null to return all themes.
 *                          Default false.
 *     @type mixed $allowed (Multisite) True to return only allowed themes for a site.
 *                          False to return only disallowed themes for a site.
 *                          'site' to return only site-allowed themes.
 *                          'network' to return only network-allowed themes.
 *                          Null to return all themes. Default null.
 *     @type int   $blog_id (Multisite) The blog ID used to calculate which themes
 *                          are allowed. Default 0, synonymous for the current blog.
 * }
 * @return WP_Theme[] Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (is_array($wp_theme_directories) && count($wp_theme_directories) > 1) {
        // Make sure the active theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories, true)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = new WP_Theme($theme, $theme_root['theme_root']);
            $_themes[$theme_root['theme_root'] . '/' . $theme] = $themes[$theme];
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 5.5

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 *
 * @param array $args {
 *     Optional. The search arguments.
 *
 *     @type mixed $errors  True to return themes with errors, false to return
 *                          themes without errors, null to return all themes.
 *                          Default false.
 *     @type mixed $allowed (Multisite) True to return only allowed themes for a site.
 *                          False to return only disallowed themes for a site.
 *                          'site' to return only site-allowed themes.
 *                          'network' to return only network-allowed themes.
 *                          Null to return all themes. Default null.
 *     @type int   $blog_id (Multisite) The blog ID used to calculate which themes
 *                          are allowed. Default 0, synonymous for the current blog.
 * }
 * @return WP_Theme[] Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (is_array($wp_theme_directories) && count($wp_theme_directories) > 1) {
        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories, true)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = new WP_Theme($theme, $theme_root['theme_root']);
            $_themes[$theme_root['theme_root'] . '/' . $theme] = $themes[$theme];
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 5.3

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $_themes
 *
 * @param array $args {
 *     Optional. The search arguments.
 *
 *     @type mixed $errors  True to return themes with errors, false to return themes without errors, null to return all themes.
 *                          Defaults to false.
 *     @type mixed $allowed (Multisite) True to return only allowed themes for a site. False to return only disallowed themes for a site.
 *                          'site' to return only site-allowed themes. 'network' to return only network-allowed themes.
 *                          Null to return all themes. Defaults to null.
 *     @type int   $blog_id (Multisite) The blog ID used to calculate which themes are allowed.
 *                          Defaults to 0, synonymous for the current blog.
 * }
 * @return WP_Theme[] Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (is_array($wp_theme_directories) && count($wp_theme_directories) > 1) {
        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = new WP_Theme($theme, $theme_root['theme_root']);
            $_themes[$theme_root['theme_root'] . '/' . $theme] = $themes[$theme];
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 5.1

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $_themes
 *
 * @param array $args {
 *     Optional. The search arguments.
 *
 *     @type mixed $errors  True to return themes with errors, false to return themes without errors, null to return all themes.
 *                          Defaults to false.
 *     @type mixed $allowed (Multisite) True to return only allowed themes for a site. False to return only disallowed themes for a site.
 *                          'site' to return only site-allowed themes. 'network' to return only network-allowed themes.
 *                          Null to return all themes. Defaults to null.
 *     @type int   $blog_id (Multisite) The blog ID used to calculate which themes are allowed.
 *                          Defaults to 0, synonymous for the current blog.
 * }
 * @return WP_Theme[] Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (is_array($wp_theme_directories) && count($wp_theme_directories) > 1) {
        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme] = new WP_Theme($theme, $theme_root['theme_root']);
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 4.9

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $_themes
 *
 * @param array $args The search arguments. Optional.
 * - errors      mixed  True to return themes with errors, false to return themes without errors, null
 *                      to return all themes. Defaults to false.
 * - allowed     mixed  (Multisite) True to return only allowed themes for a site. False to return only
 *                      disallowed themes for a site. 'site' to return only site-allowed themes. 'network'
 *                      to return only network-allowed themes. Null to return all themes. Defaults to null.
 * - blog_id     int    (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0,
 *                      synonymous for the current blog.
 * @return array Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (is_array($wp_theme_directories) && count($wp_theme_directories) > 1) {
        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme] = new WP_Theme($theme, $theme_root['theme_root']);
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 4.3

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @global array $wp_theme_directories
 * @staticvar array $_themes
 *
 * @param array $args The search arguments. Optional.
 * - errors      mixed  True to return themes with errors, false to return themes without errors, null
 *                      to return all themes. Defaults to false.
 * - allowed     mixed  (Multisite) True to return only allowed themes for a site. False to return only
 *                      disallowed themes for a site. 'site' to return only site-allowed themes. 'network'
 *                      to return only network-allowed themes. Null to return all themes. Defaults to null.
 * - blog_id     int    (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0,
 *                      synonymous for the current blog.
 * @return array Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (count($wp_theme_directories) > 1) {
        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme] = new WP_Theme($theme, $theme_root['theme_root']);
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}

WordPress Version: 3.7

/**
 * Theme, template, and stylesheet functions.
 *
 * @package WordPress
 * @subpackage Theme
 */
/**
 * Returns an array of WP_Theme objects based on the arguments.
 *
 * Despite advances over get_themes(), this function is quite expensive, and grows
 * linearly with additional themes. Stick to wp_get_theme() if possible.
 *
 * @since 3.4.0
 *
 * @param array $args The search arguments. Optional.
 * - errors      mixed  True to return themes with errors, false to return themes without errors, null
 *                      to return all themes. Defaults to false.
 * - allowed     mixed  (Multisite) True to return only allowed themes for a site. False to return only
 *                      disallowed themes for a site. 'site' to return only site-allowed themes. 'network'
 *                      to return only network-allowed themes. Null to return all themes. Defaults to null.
 * - blog_id     int    (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0,
 *                      synonymous for the current blog.
 * @return Array of WP_Theme objects.
 */
function wp_get_themes($args = array())
{
    global $wp_theme_directories;
    $defaults = array('errors' => false, 'allowed' => null, 'blog_id' => 0);
    $args = wp_parse_args($args, $defaults);
    $theme_directories = search_theme_directories();
    if (count($wp_theme_directories) > 1) {
        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
        // one in the case of a conflict. (Normally, last registered theme root wins.)
        $current_theme = get_stylesheet();
        if (isset($theme_directories[$current_theme])) {
            $root_of_current_theme = get_raw_theme_root($current_theme);
            if (!in_array($root_of_current_theme, $wp_theme_directories)) {
                $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
            }
            $theme_directories[$current_theme]['theme_root'] = $root_of_current_theme;
        }
    }
    if (empty($theme_directories)) {
        return array();
    }
    if (is_multisite() && null !== $args['allowed']) {
        $allowed = $args['allowed'];
        if ('network' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_network());
        } elseif ('site' === $allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed_on_site($args['blog_id']));
        } elseif ($allowed) {
            $theme_directories = array_intersect_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        } else {
            $theme_directories = array_diff_key($theme_directories, WP_Theme::get_allowed($args['blog_id']));
        }
    }
    $themes = array();
    static $_themes = array();
    foreach ($theme_directories as $theme => $theme_root) {
        if (isset($_themes[$theme_root['theme_root'] . '/' . $theme])) {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme];
        } else {
            $themes[$theme] = $_themes[$theme_root['theme_root'] . '/' . $theme] = new WP_Theme($theme, $theme_root['theme_root']);
        }
    }
    if (null !== $args['errors']) {
        foreach ($themes as $theme => $wp_theme) {
            if ($wp_theme->errors() != $args['errors']) {
                unset($themes[$theme]);
            }
        }
    }
    return $themes;
}