themes_api

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

WordPress Version: 6.5

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: Accepts 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API. Default empty array.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // Include an unmodified $wp_version.
    require ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' === $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // x.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Returning a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        $ssl = wp_http_supports(array('ssl'));
        if ($ssl) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('timeout' => 15, 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: Support forums URL. */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/forums/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        if (!is_wp_error($res)) {
            // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
            if ('query_themes' === $action) {
                foreach ($res->themes as $i => $theme) {
                    $res->themes[$i] = (object) $theme;
                }
            }
            // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
            if ('feature_list' === $action) {
                $res = (array) $res;
            }
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|stdClass|WP_Error $res    WordPress.org Themes API response.
     * @param string                  $action Requested action. Likely values are 'theme_information',
     *                                        'feature_list', or 'query_themes'.
     * @param stdClass                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 6.2

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API. Default empty array.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // Include an unmodified $wp_version.
    require ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' === $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // x.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Returning a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        $ssl = wp_http_supports(array('ssl'));
        if ($ssl) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('timeout' => 15, 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: Support forums URL. */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/forums/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        if (!is_wp_error($res)) {
            // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
            if ('query_themes' === $action) {
                foreach ($res->themes as $i => $theme) {
                    $res->themes[$i] = (object) $theme;
                }
            }
            // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
            if ('feature_list' === $action) {
                $res = (array) $res;
            }
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|stdClass|WP_Error $res    WordPress.org Themes API response.
     * @param string                  $action Requested action. Likely values are 'theme_information',
     *                                        'feature_list', or 'query_themes'.
     * @param stdClass                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 5.9

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // Include an unmodified $wp_version.
    require ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' === $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // x.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Returning a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        $ssl = wp_http_supports(array('ssl'));
        if ($ssl) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: Support forums URL. */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/forums/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        if (!is_wp_error($res)) {
            // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
            if ('query_themes' === $action) {
                foreach ($res->themes as $i => $theme) {
                    $res->themes[$i] = (object) $theme;
                }
            }
            // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
            if ('feature_list' === $action) {
                $res = (array) $res;
            }
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|stdClass|WP_Error $res    WordPress.org Themes API response.
     * @param string                  $action Requested action. Likely values are 'theme_information',
     *                                        'feature_list', or 'query_themes'.
     * @param stdClass                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 5.5

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // Include an unmodified $wp_version.
    require ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' === $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // x.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        $ssl = wp_http_supports(array('ssl'));
        if ($ssl) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: Support forums URL. */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/forums/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
        if ('query_themes' === $action) {
            foreach ($res->themes as $i => $theme) {
                $res->themes[$i] = (object) $theme;
            }
        }
        // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
        if ('feature_list' === $action) {
            $res = (array) $res;
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 5.4

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // Include an unmodified $wp_version.
    require ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' == $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // x.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        $ssl = wp_http_supports(array('ssl'));
        if ($ssl) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: Support forums URL. */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/forums/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
        if ('query_themes' == $action) {
            foreach ($res->themes as $i => $theme) {
                $res->themes[$i] = (object) $theme;
            }
        }
        // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
        if ('feature_list' == $action) {
            $res = (array) $res;
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 5.3

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // include an unmodified $wp_version
    include ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' == $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // X.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        $ssl = wp_http_supports(array('ssl'));
        if ($ssl) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: Support forums URL. */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/forums/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: Support forums URL. */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/forums/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
        if ('query_themes' == $action) {
            foreach ($res->themes as $i => $theme) {
                $res->themes[$i] = (object) $theme;
            }
        }
        // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
        if ('feature_list' == $action) {
            $res = (array) $res;
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 5.1

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    // include an unmodified $wp_version
    include ABSPATH . WPINC . '/version.php';
    if (is_array($args)) {
        $args = (object) $args;
    }
    if ('query_themes' == $action) {
        if (!isset($args->per_page)) {
            $args->per_page = 24;
        }
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    if (!isset($args->wp_version)) {
        $args->wp_version = substr($wp_version, 0, 3);
        // X.y
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.2/';
        $url = add_query_arg(array('action' => $action, 'request' => $args), $url);
        $http_url = $url;
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'));
        $request = wp_remote_get($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: support forums URL */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_get($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: support forums URL */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/')
            ), $request->get_error_message());
        } else {
            $res = json_decode(wp_remote_retrieve_body($request), true);
            if (is_array($res)) {
                // Object casting is required in order to match the info/1.0 format.
                $res = (object) $res;
            } elseif (null === $res) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: support forums URL */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/')
                ), wp_remote_retrieve_body($request));
            }
            if (isset($res->error)) {
                $res = new WP_Error('themes_api_failed', $res->error);
            }
        }
        // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
        if ('query_themes' == $action) {
            foreach ($res->themes as $i => $theme) {
                $res->themes[$i] = (object) $theme;
            }
        }
        // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
        if ('feature_list' == $action) {
            $res = (array) $res;
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.9

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        // include an unmodified $wp_version
        include ABSPATH . WPINC . '/version.php';
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('user-agent' => 'WordPress/' . $wp_version . '; ' . home_url('/'), 'body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: support forums URL */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: support forums URL */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/')
            ), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: support forums URL */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/')
                ), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.7

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    if (!isset($args->locale)) {
        $args->locale = get_user_locale();
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!wp_doing_ajax()) {
                trigger_error(sprintf(
                    /* translators: %s: support forums URL */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/')
                ) . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', sprintf(
                /* translators: %s: support forums URL */
                __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                __('https://wordpress.org/support/')
            ), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', sprintf(
                    /* translators: %s: support forums URL */
                    __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.'),
                    __('https://wordpress.org/support/')
                ), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.6

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Plugin Info API.
 *
 *     @type string  $slug     The plugin slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    if (!isset($args->locale)) {
        $args->locale = get_locale();
    }
    /**
     * Filters arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filters whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags', an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!defined('DOING_AJAX') || !DOING_AJAX) {
                trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.') . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filters the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object|WP_Error $res    WordPress.org Themes API response.
     * @param string                $action Requested action. Likely values are 'theme_information',
     *                                      'feature_list', or 'query_themes'.
     * @param object                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.4

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags`, an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Plugin Info API.
 *
 *     @type string  $slug     The plugin slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api($action, $args = array())
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    if (!isset($args->locale)) {
        $args->locale = get_locale();
    }
    /**
     * Filter arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filter whether to override the WordPress.org Themes API.
     *
     * Passing a non-false value will effectively short-circuit the WordPress.org API request.
     *
     * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
     * be passed. If `$action` is 'hot_tags`, an array should be passed.
     *
     * @since 2.8.0
     *
     * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
     * @param string             $action   Requested action. Likely values are 'theme_information',
     *                                    'feature_list', or 'query_themes'.
     * @param object             $args     Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!defined('DOING_AJAX') || !DOING_AJAX) {
                trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.') . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filter the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object $res    WordPress.org Themes API response.
     * @param string       $action Requested action. Likely values are 'theme_information',
     *                             'feature_list', or 'query_themes'.
     * @param object       $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.2

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string       $action The requested action. Likely values are 'theme_information',
 *                             'feature_list', or 'query_themes'.
 * @param array|object $args   Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    if (!isset($args->locale)) {
        $args->locale = get_locale();
    }
    /**
     * Filter arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filter whether to override the WordPress.org Themes API.
     *
     * Returning a value of true to this filter allows a theme to completely
     * override the built-in WordPress.org API.
     *
     * @since 2.8.0
     *
     * @param bool   $bool   Whether to override the WordPress.org Themes API. Default false.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     * @param object $args   Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $http_args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $http_args);
        if ($ssl && is_wp_error($request)) {
            if (!defined('DOING_AJAX') || !DOING_AJAX) {
                trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.') . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $http_args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filter the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object $res    WordPress.org Themes API response.
     * @param string       $action Requested action. Likely values are 'theme_information',
     *                             'feature_list', or 'query_themes'.
     * @param object       $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.1

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string       $action The requested action. Likely values are 'theme_information',
 *                             'feature_list', or 'query_themes'.
 * @param array|object $args   Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    if (!isset($args->locale)) {
        $args->locale = get_locale();
    }
    /**
     * Filter arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filter whether to override the WordPress.org Themes API.
     *
     * Returning a value of true to this filter allows a theme to completely
     * override the built-in WordPress.org API.
     *
     * @since 2.8.0
     *
     * @param bool   $bool   Whether to override the WordPress.org Themes API. Default false.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     * @param object $args   Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $args);
        if ($ssl && is_wp_error($request)) {
            if (!defined('DOING_AJAX') || !DOING_AJAX) {
                trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.') . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filter the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object $res    WordPress.org Themes API response.
     * @param string       $action Requested action. Likely values are 'theme_information',
     *                             'feature_list', or 'query_themes'.
     * @param object       $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 4.0

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string       $action The requested action. Likely values are 'theme_information',
 *                             'feature_list', or 'query_themes'.
 * @param array|object $args   Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    /**
     * Filter arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filter whether to override the WordPress.org Themes API.
     *
     * Returning a value of true to this filter allows a theme to completely
     * override the built-in WordPress.org API.
     *
     * @since 2.8.0
     *
     * @param bool   $bool   Whether to override the WordPress.org Themes API. Default false.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     * @param object $args   Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $args);
        if ($ssl && is_wp_error($request)) {
            if (!defined('DOING_AJAX') || !DOING_AJAX) {
                trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.') . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filter the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object $res    WordPress.org Themes API response.
     * @param string       $action Requested action. Likely values are 'theme_information',
     *                             'feature_list', or 'query_themes'.
     * @param object       $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 3.9

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overridding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string       $action The requested action. Likely values are 'theme_information',
 *                             'feature_list', or 'query_themes'.
 * @param array|object $args   Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    /**
     * Filter arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filter whether to override the WordPress.org Themes API.
     *
     * Returning a value of true to this filter allows a theme to completely
     * override the built-in WordPress.org API.
     *
     * @since 2.8.0
     *
     * @param bool   $bool   Whether to override the WordPress.org Themes API. Default false.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     * @param object $args   Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $args);
        if ($ssl && is_wp_error($request)) {
            if (!defined('DOING_AJAX') || !DOING_AJAX) {
                trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.') . ' ' . __('(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)'), (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            }
            $request = wp_remote_post($http_url, $args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filter the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object $res    WordPress.org Themes API response.
     * @param string       $action Requested action. Likely values are 'theme_information',
     *                             'feature_list', or 'query_themes'.
     * @param object       $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 3.8

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overridding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string       $action The requested action. Likely values are 'theme_information',
 *                             'feature_list', or 'query_themes'.
 * @param array|object $args   Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    /**
     * Filter arguments used to query for installer pages from the WordPress.org Themes API.
     *
     * Important: An object MUST be returned to this filter.
     *
     * @since 2.8.0
     *
     * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     */
    $args = apply_filters('themes_api_args', $args, $action);
    /**
     * Filter whether to override the WordPress.org Themes API.
     *
     * Returning a value of true to this filter allows a theme to completely
     * override the built-in WordPress.org API.
     *
     * @since 2.8.0
     *
     * @param bool   $bool   Whether to override the WordPress.org Themes API. Default false.
     * @param string $action Requested action. Likely values are 'theme_information',
     *                       'feature_list', or 'query_themes'.
     * @param object $args   Arguments used to query for installer pages from the Themes API.
     */
    $res = apply_filters('themes_api', false, $action, $args);
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $args);
        if ($ssl && is_wp_error($request)) {
            trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.') . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            $request = wp_remote_post($http_url, $args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    /**
     * Filter the returned WordPress.org Themes API response.
     *
     * @since 2.8.0
     *
     * @param array|object $res    WordPress.org Themes API response.
     * @param string       $action Requested action. Likely values are 'theme_information',
     *                             'feature_list', or 'query_themes'.
     * @param object       $args   Arguments used to query for installer pages from the WordPress.org Themes API.
     */
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 7.1

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overridding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string $action
 * @param array|object $args Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    $args = apply_filters('themes_api_args', $args, $action);
    //NOTE: Ensure that an object is returned via this filter.
    $res = apply_filters('themes_api', false, $action, $args);
    //NOTE: Allows a theme to completely override the builtin WordPress.org API.
    if (!$res) {
        $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
        if ($ssl = wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $args = array('body' => array('action' => $action, 'request' => serialize($args)));
        $request = wp_remote_post($url, $args);
        if ($ssl && is_wp_error($request)) {
            trigger_error(__('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.') . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', (headers_sent() || WP_DEBUG) ? E_USER_WARNING : E_USER_NOTICE);
            $request = wp_remote_post($http_url, $args);
        }
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    return apply_filters('themes_api_result', $res, $action, $args);
}

WordPress Version: 3.7

/**
 * Retrieve theme installer pages from WordPress Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overridding the filters.
 *
 * The first filter, 'themes_api_args', is for the args and gives the action as
 * the second parameter. The hook for 'themes_api_args' must ensure that an
 * object is returned.
 *
 * The second filter, 'themes_api', is the result that would be returned.
 *
 * @since 2.8.0
 *
 * @param string $action
 * @param array|object $args Optional. Arguments to serialize for the Theme Info API.
 * @return mixed
 */
function themes_api($action, $args = null)
{
    if (is_array($args)) {
        $args = (object) $args;
    }
    if (!isset($args->per_page)) {
        $args->per_page = 24;
    }
    $args = apply_filters('themes_api_args', $args, $action);
    //NOTE: Ensure that an object is returned via this filter.
    $res = apply_filters('themes_api', false, $action, $args);
    //NOTE: Allows a theme to completely override the builtin WordPress.org API.
    if (!$res) {
        $url = 'http://api.wordpress.org/themes/info/1.0/';
        if (wp_http_supports(array('ssl'))) {
            $url = set_url_scheme($url, 'https');
        }
        $request = wp_remote_post($url, array('body' => array('action' => $action, 'request' => serialize($args))));
        if (is_wp_error($request)) {
            $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.'), $request->get_error_message());
        } else {
            $res = maybe_unserialize(wp_remote_retrieve_body($request));
            if (!is_object($res) && !is_array($res)) {
                $res = new WP_Error('themes_api_failed', __('An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.'), wp_remote_retrieve_body($request));
            }
        }
    }
    return apply_filters('themes_api_result', $res, $action, $args);
}