wp_prepare_themes_for_js

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

WordPress Version: 6.3

/**
 * Prepares themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The active theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the active theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    $no_updates = array();
    if (!is_multisite() && current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
        if (isset($updates_transient->no_update)) {
            $no_updates = $updates_transient->no_update;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    $auto_updates = (array) get_site_option('auto_update_themes', array());
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        $can_edit_theme_options = current_user_can('edit_theme_options');
        $can_customize = current_user_can('customize');
        $is_block_theme = $theme->is_block_theme();
        if ($is_block_theme && $can_edit_theme_options) {
            $customize_action = admin_url('site-editor.php');
            if ($current_theme !== $slug) {
                $customize_action = add_query_arg('wp_theme_preview', $slug, $customize_action);
            }
        } elseif (!$is_block_theme && $can_customize && $can_edit_theme_options) {
            $customize_action = wp_customize_url($slug);
        }
        if (null !== $customize_action) {
            $customize_action = add_query_arg(array('return' => urlencode(sanitize_url(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), $customize_action);
            $customize_action = esc_url($customize_action);
        }
        $update_requires_wp = isset($updates[$slug]['requires']) ? $updates[$slug]['requires'] : null;
        $update_requires_php = isset($updates[$slug]['requires_php']) ? $updates[$slug]['requires_php'] : null;
        $auto_update = in_array($slug, $auto_updates, true);
        $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
        if (isset($updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $updates[$slug];
        } elseif (isset($no_updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $no_updates[$slug];
        } else {
            $auto_update_supported = false;
            /*
             * Create the expected payload for the auto_update_theme filter, this is the same data
             * as contained within $updates or $no_updates but used when the Theme is not known.
             */
            $auto_update_filter_payload = (object) array('theme' => $slug, 'new_version' => $theme->get('Version'), 'url' => '', 'package' => '', 'requires' => $theme->get('RequiresWP'), 'requires_php' => $theme->get('RequiresPHP'));
        }
        $auto_update_forced = wp_is_auto_update_forced_for_item('theme', null, $auto_update_filter_payload);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo Multiple screenshots.
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'tags' => $theme->display('Tags'),
            'version' => $theme->get('Version'),
            'compatibleWP' => is_wp_version_compatible($theme->get('RequiresWP')),
            'compatiblePHP' => is_php_version_compatible($theme->get('RequiresPHP')),
            'updateResponse' => array('compatibleWP' => is_wp_version_compatible($update_requires_wp), 'compatiblePHP' => is_php_version_compatible($update_requires_php)),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'autoupdate' => array('enabled' => $auto_update || $auto_update_forced, 'supported' => $auto_update_supported, 'forced' => $auto_update_forced),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => (!is_multisite() && current_user_can('delete_themes')) ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null, 'autoupdate' => (wp_is_auto_update_enabled_for_type('theme') && !is_multisite() && current_user_can('update_themes')) ? wp_nonce_url(admin_url('themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug), 'updates') : null),
            'blockTheme' => $theme->is_block_theme(),
        );
    }
    // Remove 'delete' action if theme has an active child.
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 6.1

/**
 * Prepares themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The active theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the active theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    $no_updates = array();
    if (!is_multisite() && current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
        if (isset($updates_transient->no_update)) {
            $no_updates = $updates_transient->no_update;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    $auto_updates = (array) get_site_option('auto_update_themes', array());
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        $can_edit_theme_options = current_user_can('edit_theme_options');
        $can_customize = current_user_can('customize');
        $is_block_theme = $theme->is_block_theme();
        if ($is_block_theme && $can_edit_theme_options) {
            $customize_action = esc_url(admin_url('site-editor.php'));
        } elseif (!$is_block_theme && $can_customize && $can_edit_theme_options) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(sanitize_url(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $update_requires_wp = isset($updates[$slug]['requires']) ? $updates[$slug]['requires'] : null;
        $update_requires_php = isset($updates[$slug]['requires_php']) ? $updates[$slug]['requires_php'] : null;
        $auto_update = in_array($slug, $auto_updates, true);
        $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
        if (isset($updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $updates[$slug];
        } elseif (isset($no_updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $no_updates[$slug];
        } else {
            $auto_update_supported = false;
            /*
             * Create the expected payload for the auto_update_theme filter, this is the same data
             * as contained within $updates or $no_updates but used when the Theme is not known.
             */
            $auto_update_filter_payload = (object) array('theme' => $slug, 'new_version' => $theme->get('Version'), 'url' => '', 'package' => '', 'requires' => $theme->get('RequiresWP'), 'requires_php' => $theme->get('RequiresPHP'));
        }
        $auto_update_forced = wp_is_auto_update_forced_for_item('theme', null, $auto_update_filter_payload);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo Multiple screenshots.
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'tags' => $theme->display('Tags'),
            'version' => $theme->get('Version'),
            'compatibleWP' => is_wp_version_compatible($theme->get('RequiresWP')),
            'compatiblePHP' => is_php_version_compatible($theme->get('RequiresPHP')),
            'updateResponse' => array('compatibleWP' => is_wp_version_compatible($update_requires_wp), 'compatiblePHP' => is_php_version_compatible($update_requires_php)),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'autoupdate' => array('enabled' => $auto_update || $auto_update_forced, 'supported' => $auto_update_supported, 'forced' => $auto_update_forced),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => (!is_multisite() && current_user_can('delete_themes')) ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null, 'autoupdate' => (wp_is_auto_update_enabled_for_type('theme') && !is_multisite() && current_user_can('update_themes')) ? wp_nonce_url(admin_url('themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug), 'updates') : null),
            'blockTheme' => $theme->is_block_theme(),
        );
    }
    // Remove 'delete' action if theme has an active child.
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 5.9

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    $no_updates = array();
    if (!is_multisite() && current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
        if (isset($updates_transient->no_update)) {
            $no_updates = $updates_transient->no_update;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    $auto_updates = (array) get_site_option('auto_update_themes', array());
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        $can_edit_theme_options = current_user_can('edit_theme_options');
        $can_customize = current_user_can('customize');
        $is_block_theme = $theme->is_block_theme();
        if ($is_block_theme && $can_edit_theme_options) {
            $customize_action = esc_url(admin_url('site-editor.php'));
        } elseif (!$is_block_theme && $can_customize && $can_edit_theme_options) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $update_requires_wp = isset($updates[$slug]['requires']) ? $updates[$slug]['requires'] : null;
        $update_requires_php = isset($updates[$slug]['requires_php']) ? $updates[$slug]['requires_php'] : null;
        $auto_update = in_array($slug, $auto_updates, true);
        $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
        if (isset($updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $updates[$slug];
        } elseif (isset($no_updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $no_updates[$slug];
        } else {
            $auto_update_supported = false;
            /*
             * Create the expected payload for the auto_update_theme filter, this is the same data
             * as contained within $updates or $no_updates but used when the Theme is not known.
             */
            $auto_update_filter_payload = (object) array('theme' => $slug, 'new_version' => $theme->get('Version'), 'url' => '', 'package' => '', 'requires' => $theme->get('RequiresWP'), 'requires_php' => $theme->get('RequiresPHP'));
        }
        $auto_update_forced = wp_is_auto_update_forced_for_item('theme', null, $auto_update_filter_payload);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo Multiple screenshots.
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'tags' => $theme->display('Tags'),
            'version' => $theme->get('Version'),
            'compatibleWP' => is_wp_version_compatible($theme->get('RequiresWP')),
            'compatiblePHP' => is_php_version_compatible($theme->get('RequiresPHP')),
            'updateResponse' => array('compatibleWP' => is_wp_version_compatible($update_requires_wp), 'compatiblePHP' => is_php_version_compatible($update_requires_php)),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'autoupdate' => array('enabled' => $auto_update || $auto_update_forced, 'supported' => $auto_update_supported, 'forced' => $auto_update_forced),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => (!is_multisite() && current_user_can('delete_themes')) ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null, 'autoupdate' => (wp_is_auto_update_enabled_for_type('theme') && !is_multisite() && current_user_can('update_themes')) ? wp_nonce_url(admin_url('themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug), 'updates') : null),
            'blockTheme' => $theme->is_block_theme(),
        );
    }
    // Remove 'delete' action if theme has an active child.
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 5.6

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    $no_updates = array();
    if (!is_multisite() && current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
        if (isset($updates_transient->no_update)) {
            $no_updates = $updates_transient->no_update;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    $auto_updates = (array) get_site_option('auto_update_themes', array());
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $update_requires_wp = isset($updates[$slug]['requires']) ? $updates[$slug]['requires'] : null;
        $update_requires_php = isset($updates[$slug]['requires_php']) ? $updates[$slug]['requires_php'] : null;
        $auto_update = in_array($slug, $auto_updates, true);
        $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
        if (isset($updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $updates[$slug];
        } elseif (isset($no_updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $no_updates[$slug];
        } else {
            $auto_update_supported = false;
            /*
             * Create the expected payload for the auto_update_theme filter, this is the same data
             * as contained within $updates or $no_updates but used when the Theme is not known.
             */
            $auto_update_filter_payload = (object) array('theme' => $slug, 'new_version' => $theme->get('Version'), 'url' => '', 'package' => '', 'requires' => $theme->get('RequiresWP'), 'requires_php' => $theme->get('RequiresPHP'));
        }
        $auto_update_forced = wp_is_auto_update_forced_for_item('theme', null, $auto_update_filter_payload);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo Multiple screenshots.
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'tags' => $theme->display('Tags'),
            'version' => $theme->get('Version'),
            'compatibleWP' => is_wp_version_compatible($theme->get('RequiresWP')),
            'compatiblePHP' => is_php_version_compatible($theme->get('RequiresPHP')),
            'updateResponse' => array('compatibleWP' => is_wp_version_compatible($update_requires_wp), 'compatiblePHP' => is_php_version_compatible($update_requires_php)),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'autoupdate' => array('enabled' => $auto_update || $auto_update_forced, 'supported' => $auto_update_supported, 'forced' => $auto_update_forced),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => (!is_multisite() && current_user_can('delete_themes')) ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null, 'autoupdate' => (wp_is_auto_update_enabled_for_type('theme') && !is_multisite() && current_user_can('update_themes')) ? wp_nonce_url(admin_url('themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug), 'updates') : null),
        );
    }
    // Remove 'delete' action if theme has an active child.
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 5.5

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    $no_updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
        if (isset($updates_transient->no_update)) {
            $no_updates = $updates_transient->no_update;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    $auto_updates = (array) get_site_option('auto_update_themes', array());
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $update_requires_wp = isset($updates[$slug]['requires']) ? $updates[$slug]['requires'] : null;
        $update_requires_php = isset($updates[$slug]['requires_php']) ? $updates[$slug]['requires_php'] : null;
        $auto_update = in_array($slug, $auto_updates, true);
        $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
        if (isset($updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $updates[$slug];
        } elseif (isset($no_updates[$slug])) {
            $auto_update_supported = true;
            $auto_update_filter_payload = (object) $no_updates[$slug];
        } else {
            $auto_update_supported = false;
            /*
             * Create the expected payload for the auto_update_theme filter, this is the same data
             * as contained within $updates or $no_updates but used when the Theme is not known.
             */
            $auto_update_filter_payload = (object) array('theme' => $slug, 'new_version' => $theme->get('Version'), 'url' => '', 'package' => '', 'requires' => $theme->get('RequiresWP'), 'requires_php' => $theme->get('RequiresPHP'));
        }
        $type = 'theme';
        /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
        $auto_update_forced = apply_filters("auto_update_{$type}", null, $auto_update_filter_payload);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo Multiple screenshots.
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'tags' => $theme->display('Tags'),
            'version' => $theme->get('Version'),
            'compatibleWP' => is_wp_version_compatible($theme->get('RequiresWP')),
            'compatiblePHP' => is_php_version_compatible($theme->get('RequiresPHP')),
            'updateResponse' => array('compatibleWP' => is_wp_version_compatible($update_requires_wp), 'compatiblePHP' => is_php_version_compatible($update_requires_php)),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'autoupdate' => array('enabled' => $auto_update || $auto_update_forced, 'supported' => $auto_update_supported, 'forced' => $auto_update_forced),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null, 'autoupdate' => (wp_is_auto_update_enabled_for_type('theme') && !is_multisite() && current_user_can('update_themes')) ? wp_nonce_url(admin_url('themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug), 'updates') : null),
        );
    }
    // Remove 'delete' action if theme has an active child.
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 5.4

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo Multiple screenshots.
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child.
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 5.3

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of theme data.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 5.1

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array           $prepared_themes An associative array of theme data. Default empty array.
     * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
     * @param string          $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.9

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent();
            $parents[$slug] = $parent->get_stylesheet();
            $parent = $parent->display('Name');
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.8

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(remove_query_arg(wp_removable_query_args(), wp_unslash($_SERVER['REQUEST_URI']))))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.7

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'hasPackage' => isset($updates[$slug]) && !empty($updates[$slug]['package']),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.6

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filters theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filters the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.4

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filter theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $customize_action = null;
        if (current_user_can('edit_theme_options') && current_user_can('customize')) {
            $customize_action = esc_url(add_query_arg(array('return' => urlencode(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])))), wp_customize_url($slug)));
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => $customize_action, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filter the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.3

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filter theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => (current_user_can('edit_theme_options') && current_user_can('customize')) ? wp_customize_url($slug) : null, 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filter the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.2

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    /**
     * Filter theme data before it is prepared for JavaScript.
     *
     * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
     * early with that value instead.
     *
     * @since 4.2.0
     *
     * @param array      $prepared_themes An associative array of theme data. Default empty array.
     * @param null|array $themes          An array of WP_Theme objects to prepare, if any.
     * @param string     $current_theme   The current theme slug.
     */
    $prepared_themes = (array) apply_filters('pre_prepare_themes_for_js', array(), $themes, $current_theme);
    if (!empty($prepared_themes)) {
        return $prepared_themes;
    }
    // Make sure the current theme is listed first.
    $prepared_themes[$current_theme] = array();
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    $parents = array();
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => (current_user_can('edit_theme_options') && current_user_can('customize')) ? wp_customize_url($slug) : null, 'preview' => add_query_arg(array('preview' => 1, 'template' => urlencode($theme->get_template()), 'stylesheet' => urlencode($slug), 'preview_iframe' => true, 'TB_iframe' => true), home_url('/')), 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (!empty($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filter the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    $prepared_themes = array_values($prepared_themes);
    return array_filter($prepared_themes);
}

WordPress Version: 4.1

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    // Make sure the current theme is listed first.
    $prepared_themes = array($current_theme => array());
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    foreach ($themes as $theme) {
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
            $parents[$slug] = $theme->parent()->get_stylesheet();
        }
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => (current_user_can('edit_theme_options') && current_user_can('customize')) ? wp_customize_url($slug) : null, 'preview' => add_query_arg(array('preview' => 1, 'template' => urlencode($theme->get_template()), 'stylesheet' => urlencode($slug), 'preview_iframe' => true, 'TB_iframe' => true), home_url('/')), 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    // Remove 'delete' action if theme has an active child
    if (isset($parents) && array_key_exists($current_theme, $parents)) {
        unset($prepared_themes[$parents[$current_theme]]['actions']['delete']);
    }
    /**
     * Filter the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    return array_values($prepared_themes);
}

WordPress Version: 4.0

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    // Make sure the current theme is listed first.
    $prepared_themes = array($current_theme => array());
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    foreach ($themes as $theme) {
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
        }
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => (current_user_can('edit_theme_options') && current_user_can('customize')) ? wp_customize_url($slug) : null, 'preview' => add_query_arg(array('preview' => 1, 'template' => urlencode($theme->get_template()), 'stylesheet' => urlencode($slug), 'preview_iframe' => true, 'TB_iframe' => true), home_url('/')), 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    /**
     * Filter the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    return array_values($prepared_themes);
}

WordPress Version: 3.8

/**
 * Prepare themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param array $themes Optional. Array of WP_Theme objects to prepare.
 *                      Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js($themes = null)
{
    $current_theme = get_stylesheet();
    // Make sure the current theme is listed first.
    $prepared_themes = array($current_theme => array());
    if (null === $themes) {
        $themes = wp_get_themes(array('allowed' => true));
        if (!isset($themes[$current_theme])) {
            $themes[$current_theme] = wp_get_theme();
        }
    }
    $updates = array();
    if (current_user_can('update_themes')) {
        $updates_transient = get_site_transient('update_themes');
        if (isset($updates_transient->response)) {
            $updates = $updates_transient->response;
        }
    }
    WP_Theme::sort_by_name($themes);
    foreach ($themes as $theme) {
        $parent = false;
        if ($theme->parent()) {
            $parent = $theme->parent()->display('Name');
        }
        $slug = $theme->get_stylesheet();
        $encoded_slug = urlencode($slug);
        $prepared_themes[$slug] = array(
            'id' => $slug,
            'name' => $theme->display('Name'),
            'screenshot' => array($theme->get_screenshot()),
            // @todo multiple
            'description' => $theme->display('Description'),
            'author' => $theme->display('Author', false, true),
            'authorAndUri' => $theme->display('Author'),
            'version' => $theme->display('Version'),
            'tags' => $theme->display('Tags'),
            'parent' => $parent,
            'active' => $slug === $current_theme,
            'hasUpdate' => isset($updates[$slug]),
            'update' => get_theme_update_available($theme),
            'actions' => array('activate' => current_user_can('switch_themes') ? wp_nonce_url(admin_url('themes.php?action=activate&stylesheet=' . $encoded_slug), 'switch-theme_' . $slug) : null, 'customize' => current_user_can('edit_theme_options') ? wp_customize_url($slug) : null, 'preview' => add_query_arg(array('preview' => 1, 'template' => urlencode($theme->get_template()), 'stylesheet' => urlencode($slug), 'preview_iframe' => true, 'TB_iframe' => true), home_url('/')), 'delete' => current_user_can('delete_themes') ? wp_nonce_url(admin_url('themes.php?action=delete&stylesheet=' . $encoded_slug), 'delete-theme_' . $slug) : null),
        );
    }
    /**
     * Filter the themes prepared for JavaScript, for themes.php.
     *
     * Could be useful for changing the order, which is by name by default.
     *
     * @since 3.8.0
     *
     * @param array $prepared_themes Array of themes.
     */
    $prepared_themes = apply_filters('wp_prepare_themes_for_js', $prepared_themes);
    return array_values($prepared_themes);
}