Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCom_Themes_Api
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 7
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 fetch_themes
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 handle_request
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 fetch_all_non_delisted_themes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 fetch_theme
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 fetch_recommended_themes
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 search_themes
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Class WPCom_Themes_Api.
4 * Retrieves themes from the WordPress.com themes API.
5 *
6 * @package wpcom-themes
7 */
8
9/**
10 * Fetches themes from the WordPress.com themes API.
11 */
12class WPCom_Themes_Api {
13
14    /**
15     * The URL of the WordPress.com themes API.
16     */
17    const WP_COM_THEMES_API_URL = 'https://public-api.wordpress.com/wpcom/v2/themes?_envelope=1&page=1&number=1000';
18
19    /**
20     * The URL of the WordPress.com theme API.
21     */
22    const WP_COM_THEME_API_URL = 'https://public-api.wordpress.com/rest/v1.2/themes/%s?http_envelope=1';
23
24    /**
25     * Cache handler.
26     *
27     * @var WPCom_Themes_Cache $cache
28     */
29    private WPCom_Themes_Cache $cache;
30
31    /**
32     * Class constructor.
33     *
34     * @param WPCom_Themes_Cache $cache Cache handler.
35     */
36    public function __construct( WPCom_Themes_Cache $cache ) {
37        $this->cache = $cache;
38    }
39
40    /**
41     * Returns an array of themes fetched from the WordPress.com themes API.
42     * Caching is used to avoid fetching the themes on every request.
43     *
44     * @param string $cache_key Key of the cache where the API response will be cached.
45     * @param array  $params    Query params to pass to the API URL.
46     *
47     * @return array<stdClass> An array with all the WPCom themes.
48     */
49    protected function fetch_themes( string $cache_key, array $params = array() ): array {
50        $url = add_query_arg( $params, self::WP_COM_THEMES_API_URL );
51
52        return $this->cache->run_cached(
53            $cache_key,
54            fn() => $this->handle_request( $url )->themes ?? array()
55        );
56    }
57
58    /**
59     * Fetches the response from the given URL.
60     *
61     * @param string $url URL to fetch.
62     *
63     * @return ?stdClass Response body.
64     */
65    protected function handle_request( string $url ): ?stdClass {
66        $response = wp_remote_get( esc_url_raw( $url ) );
67        if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
68            $body_json = json_decode( wp_remote_retrieve_body( $response ) );
69
70            if ( isset( $body_json->body ) ) {
71                return $body_json->body;
72            }
73        }
74
75        return null;
76    }
77
78    /**
79     * Returns all the WP.com themes.
80     *
81     * @return array<stdClass> An array with all the WPCom themes.
82     */
83    public function fetch_all_non_delisted_themes(): array {
84        return $this->fetch_themes( 'wpcom-themes-all' );
85    }
86
87    /**
88     * Returns the WP.com theme with the given slug.
89     *
90     * @param string $slug Theme slug.
91     *
92     * @return stdClass|null A WPCom theme object or null if not found.
93     */
94    public function fetch_theme( string $slug ): ?stdClass {
95        $url = sprintf( self::WP_COM_THEME_API_URL, $slug );
96
97        $theme = $this->cache->run_cached(
98            'wpcom-themes-' . $slug,
99            fn() => $this->handle_request( $url )
100        );
101
102        if ( ! $theme || isset( $theme->error ) ) {
103            return null;
104        }
105
106        return $theme;
107    }
108
109    /**
110     * Returns the collection of the recommended WP.com themes.
111     *
112     * @return array<stdClass> An array with all the recommended WPCom themes.
113     */
114    public function fetch_recommended_themes(): array {
115        return $this->fetch_themes(
116            'wpcom-themes-recommended',
117            array( 'collection' => 'recommended' )
118        );
119    }
120
121    /**
122     * Returns the WP.com themes that match the given search term.
123     *
124     * @param string $search Search term.
125     *
126     * @return array<stdClass> An array with all the matching WPCom themes.
127     */
128    public function search_themes( string $search ): array {
129        return $this->fetch_themes(
130            'wpcom-themes-search-' . md5( $search ),
131            array(
132                'search' => $search,
133                'sort'   => 'date',
134            )
135        );
136    }
137}