PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.1-a.1
16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / json-endpoints / class.wpcom-json-api-get-site-endpoint.php
jetpack / json-endpoints Last commit date
jetpack 3 weeks ago class.wpcom-json-api-add-widget-endpoint.php 7 months ago class.wpcom-json-api-autosave-post-v1-1-endpoint.php 7 months ago class.wpcom-json-api-bulk-delete-post-endpoint.php 7 months ago class.wpcom-json-api-bulk-restore-post-endpoint.php 7 months ago class.wpcom-json-api-bulk-update-comments-endpoint.php 1 month ago class.wpcom-json-api-comment-endpoint.php 7 months ago class.wpcom-json-api-delete-media-endpoint.php 7 months ago class.wpcom-json-api-delete-media-v1-1-endpoint.php 7 months ago class.wpcom-json-api-edit-media-v1-2-endpoint.php 1 month ago class.wpcom-json-api-get-autosave-v1-1-endpoint.php 7 months ago class.wpcom-json-api-get-comment-counts-endpoint.php 7 months ago class.wpcom-json-api-get-comment-endpoint.php 7 months ago class.wpcom-json-api-get-comment-history-endpoint.php 7 months ago class.wpcom-json-api-get-comments-tree-endpoint.php 7 months ago class.wpcom-json-api-get-comments-tree-v1-1-endpoint.php 7 months ago class.wpcom-json-api-get-comments-tree-v1-2-endpoint.php 7 months ago class.wpcom-json-api-get-customcss.php 7 months ago class.wpcom-json-api-get-media-endpoint.php 7 months ago class.wpcom-json-api-get-media-v1-1-endpoint.php 7 months ago class.wpcom-json-api-get-media-v1-2-endpoint.php 7 months ago class.wpcom-json-api-get-post-counts-v1-1-endpoint.php 3 weeks ago class.wpcom-json-api-get-post-endpoint.php 7 months ago class.wpcom-json-api-get-post-v1-1-endpoint.php 7 months ago class.wpcom-json-api-get-site-endpoint.php 2 days ago class.wpcom-json-api-get-site-v1-2-endpoint.php 2 days ago class.wpcom-json-api-get-taxonomies-endpoint.php 2 months ago class.wpcom-json-api-get-taxonomy-endpoint.php 7 months ago class.wpcom-json-api-get-term-endpoint.php 7 months ago class.wpcom-json-api-list-comments-endpoint.php 3 weeks ago class.wpcom-json-api-list-dropdown-pages-endpoint.php 7 months ago class.wpcom-json-api-list-embeds-endpoint.php 7 months ago class.wpcom-json-api-list-media-endpoint.php 7 months ago class.wpcom-json-api-list-media-v1-1-endpoint.php 1 month ago class.wpcom-json-api-list-media-v1-2-endpoint.php 7 months ago class.wpcom-json-api-list-post-type-taxonomies-endpoint.php 7 months ago class.wpcom-json-api-list-post-types-endpoint.php 7 months ago class.wpcom-json-api-list-posts-endpoint.php 3 weeks ago class.wpcom-json-api-list-posts-v1-1-endpoint.php 3 weeks ago class.wpcom-json-api-list-posts-v1-2-endpoint.php 3 weeks ago class.wpcom-json-api-list-roles-endpoint.php 7 months ago class.wpcom-json-api-list-shortcodes-endpoint.php 7 months ago class.wpcom-json-api-list-terms-endpoint.php 7 months ago class.wpcom-json-api-list-users-endpoint.php 3 weeks ago class.wpcom-json-api-menus-v1-1-endpoint.php 1 month ago class.wpcom-json-api-post-endpoint.php 7 months ago class.wpcom-json-api-post-v1-1-endpoint.php 2 months ago class.wpcom-json-api-render-embed-endpoint.php 7 months ago class.wpcom-json-api-render-embed-reversal-endpoint.php 7 months ago class.wpcom-json-api-render-endpoint.php 1 month ago class.wpcom-json-api-render-shortcode-endpoint.php 7 months ago class.wpcom-json-api-sharing-buttons-endpoint.php 1 month ago class.wpcom-json-api-site-settings-endpoint.php 3 weeks ago class.wpcom-json-api-site-settings-v1-2-endpoint.php 7 months ago class.wpcom-json-api-site-settings-v1-3-endpoint.php 7 months ago class.wpcom-json-api-site-settings-v1-4-endpoint.php 3 weeks ago class.wpcom-json-api-site-user-endpoint.php 7 months ago class.wpcom-json-api-taxonomy-endpoint.php 7 months ago class.wpcom-json-api-update-comment-endpoint.php 6 months ago class.wpcom-json-api-update-customcss.php 7 months ago class.wpcom-json-api-update-media-endpoint.php 7 months ago class.wpcom-json-api-update-media-v1-1-endpoint.php 1 month ago class.wpcom-json-api-update-post-endpoint.php 1 month ago class.wpcom-json-api-update-post-v1-1-endpoint.php 1 month ago class.wpcom-json-api-update-post-v1-2-endpoint.php 1 month ago class.wpcom-json-api-update-site-homepage-endpoint.php 7 months ago class.wpcom-json-api-update-site-logo-endpoint.php 7 months ago class.wpcom-json-api-update-taxonomy-endpoint.php 6 months ago class.wpcom-json-api-update-term-endpoint.php 7 months ago class.wpcom-json-api-update-user-endpoint.php 7 months ago class.wpcom-json-api-upload-media-endpoint.php 7 months ago class.wpcom-json-api-upload-media-v1-1-endpoint.php 7 months ago
class.wpcom-json-api-get-site-endpoint.php
1300 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit( 0 );
5 }
6
7 new WPCOM_JSON_API_GET_Site_Endpoint(
8 array(
9 'description' => 'Get information about a site.',
10 'group' => 'sites',
11 'stat' => 'sites:X',
12 'allowed_if_flagged' => true,
13 'method' => 'GET',
14 'max_version' => '1.1',
15 'new_version' => '1.2',
16 'path' => '/sites/%s',
17 'path_labels' => array(
18 '$site' => '(int|string) Site ID or domain',
19 ),
20 'rest_route' => '/site',
21 'rest_min_jp_version' => '15.9',
22 'allow_jetpack_site_auth' => true,
23
24 'allow_fallback_to_jetpack_blog_token' => true,
25
26 'query_parameters' => array(
27 'context' => false,
28 'options' => '(string) Optional. Returns specified options only. Comma-separated list. Example: options=login_url,timezone',
29 ),
30
31 'response_format' => WPCOM_JSON_API_GET_Site_Endpoint::$site_format,
32
33 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/',
34 )
35 );
36
37 /**
38 * GET Site endpoint class.
39 *
40 * @phan-constructor-used-for-side-effects
41 */
42 class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
43
44 /**
45 * Site meta data.
46 *
47 * @var array $site_format
48 */
49 public static $site_format = array(
50 'ID' => '(int) Site ID',
51 'slug' => '(string) Slug of site',
52 'name' => '(string) Title of site',
53 'description' => '(string) Tagline or description of site',
54 'URL' => '(string) Full URL to the site',
55 'user_can_manage' => '(bool) The current user can manage this site', // deprecated.
56 'capabilities' => '(array) Array of capabilities for the current user on this site.',
57 'jetpack' => '(bool) Whether the site is a Jetpack site or not',
58 'jetpack_connection' => '(bool) Whether the site is connected to WP.com via `jetpack-connection`',
59 'is_multisite' => '(bool) Whether the site is a Multisite site or not. Always true for WP.com sites.',
60 'site_owner' => '(int) User ID of the site owner',
61 'post_count' => '(int) The number of posts the site has',
62 'subscribers_count' => '(int) The number of subscribers the site has',
63 'lang' => '(string) Primary language code of the site',
64 'icon' => '(array) An array of icon formats for the site',
65 'logo' => '(array) The site logo, set in the Customizer',
66 'visible' => '(bool) If this site is visible in the user\'s site list',
67 'is_private' => '(bool) If the site is a private site or not',
68 'is_coming_soon' => '(bool) If the site is marked as "coming soon" or not',
69 'single_user_site' => '(bool) Whether the site is single user. Only returned for WP.com sites and for Jetpack sites with version 3.4 or higher.',
70 'is_vip' => '(bool) If the site is a VIP site or not.',
71 'is_following' => '(bool) If the current user is subscribed to this site in the reader',
72 'organization_id' => '(int) P2 Organization identifier.',
73 'options' => '(array) An array of options/settings for the blog. Only viewable by users with post editing rights to the site. Note: Post formats is deprecated, please see /sites/$id/post-formats/',
74 'p2_thumbnail_elements' => '(array) Details used to render a thumbnail of the site. P2020 themed sites only.',
75 'plan' => '(array) Details of the current plan for this site.',
76 'products' => '(array) Details of the current products for this site.',
77 'zendesk_site_meta' => '(array) Site meta data for Zendesk.',
78 'updates' => '(array) An array of available updates for plugins, themes, wordpress, and languages.',
79 'jetpack_modules' => '(array) A list of active Jetpack modules.',
80 'meta' => '(object) Meta data',
81 'quota' => '(array) An array describing how much space a user has left for uploads',
82 'launch_status' => '(string) A string describing the launch status of a site',
83 'site_migration' => '(array) Data about any migration into the site.',
84 'is_fse_active' => '(bool) If the site has Full Site Editing active or not.',
85 'is_fse_eligible' => '(bool) If the site is capable of Full Site Editing or not',
86 'is_core_site_editor_enabled' => '(bool) If the site has the core site editor enabled.',
87 'is_wpcom_atomic' => '(bool) If the site is a WP.com Atomic one.',
88 'is_wpcom_staging_site' => '(bool) If the site is a WP.com staging site.',
89 'user_interactions' => '(array) An array of user interactions with a site.',
90 'was_ecommerce_trial' => '(bool) If the site ever used an eCommerce trial.',
91 'was_upgraded_from_trial' => '(bool) If the site ever upgraded to a paid plan from a trial.',
92 'was_migration_trial' => '(bool) If the site ever used a migration trial.',
93 'was_hosting_trial' => '(bool) If the site ever used a hosting trial.',
94 'wpcom_site_setup' => '(string) The WP.com site setup identifier.',
95 'is_deleted' => '(bool) If the site flagged as deleted.',
96 'is_a4a_client' => '(bool) If the site is an A4A client site.',
97 'is_a4a_dev_site' => '(bool) If the site is an A4A dev site.',
98 'is_garden' => '(bool) If the site is a Garden site.',
99 'garden_name' => '(string) The name of the Garden site.',
100 'garden_partner' => '(string) The partner of the Garden site.',
101 'garden_is_provisioned' => '(bool) If the Garden site is provisioned.',
102 'is_wpcom_flex' => '(bool) If the site is a Flex site',
103 'big_sky_enabled' => '(bool) Whether the Big Sky AI assistant is enabled for this site.',
104 'hosting_provider_guess' => '(string) Guess of the hosting provider. WordPress.com platform only; only returned when explicitly requested via the fields parameter.',
105 'environment_type' => '(string) The WP_ENVIRONMENT_TYPE of the site as synced by Jetpack. WordPress.com platform only; only returned when explicitly requested via the fields parameter.',
106 );
107
108 /**
109 * No member fields.
110 *
111 * @var array $no_member_fields
112 */
113 protected static $no_member_fields = array(
114 'ID',
115 'name',
116 'description',
117 'URL',
118 'jetpack',
119 'jetpack_connection',
120 'post_count',
121 'subscribers_count',
122 'lang',
123 'locale',
124 'icon',
125 'logo',
126 'visible',
127 'is_private',
128 'is_coming_soon',
129 'is_following',
130 'organization_id',
131 'meta',
132 'launch_status',
133 'site_migration',
134 'is_fse_active',
135 'is_fse_eligible',
136 'is_core_site_editor_enabled',
137 'is_wpcom_atomic',
138 'is_wpcom_staging_site',
139 'is_deleted',
140 'is_wpcom_flex',
141 'is_a4a_client',
142 'is_a4a_dev_site',
143 'is_garden',
144 'big_sky_enabled',
145 'garden_name',
146 );
147
148 /**
149 * Site options.
150 *
151 * @var array $site_options_format
152 */
153 protected static $site_options_format = array(
154 'timezone',
155 'gmt_offset',
156 'blog_public',
157 'videopress_enabled',
158 'upgraded_filetypes_enabled',
159 'login_url',
160 'admin_url',
161 'is_mapped_domain',
162 'is_redirect',
163 'unmapped_url',
164 'featured_images_enabled',
165 'theme_slug',
166 'theme_errors',
167 'header_image',
168 'background_color',
169 'image_default_link_type',
170 'image_thumbnail_width',
171 'image_thumbnail_height',
172 'image_thumbnail_crop',
173 'image_medium_width',
174 'image_medium_height',
175 'image_large_width',
176 'image_large_height',
177 'permalink_structure',
178 'post_formats',
179 'default_post_format',
180 'default_category',
181 'allowed_file_types',
182 'show_on_front',
183 /** This filter is documented in modules/likes.php */
184 'default_likes_enabled',
185 'default_sharing_status',
186 'default_comment_status',
187 'default_ping_status',
188 'software_version',
189 'created_at',
190 'updated_at',
191 'wordads',
192 'publicize_permanently_disabled',
193 'frame_nonce',
194 'jetpack_frame_nonce',
195 'page_on_front',
196 'page_for_posts',
197 'headstart',
198 'headstart_is_fresh',
199 'ak_vp_bundle_enabled',
200 Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION,
201 Jetpack_SEO_Titles::TITLE_FORMATS_OPTION,
202 'verification_services_codes',
203 'podcasting_archive',
204 'is_domain_only',
205 'is_automated_transfer',
206 'is_wpcom_atomic',
207 'is_wpcom_store',
208 'signup_is_store',
209 'has_pending_automated_transfer',
210 'woocommerce_is_active',
211 'editing_toolkit_is_active',
212 'design_type',
213 'site_goals',
214 'site_segment',
215 'site_source_slug',
216 'import_engine',
217 'is_pending_plan',
218 'is_wpforteams_site',
219 'p2_hub_blog_id',
220 'site_creation_flow',
221 'is_cloud_eligible',
222 'selected_features',
223 'anchor_podcast',
224 'was_created_with_blank_canvas_design',
225 'videopress_storage_used',
226 'is_difm_lite_in_progress',
227 'is_gating_business_q1',
228 'site_intent',
229 'site_partner_bundle',
230 'onboarding_segment',
231 'site_vertical_id',
232 'blogging_prompts_settings',
233 'launchpad_screen',
234 'launchpad_checklist_tasks_statuses',
235 'migration_source_site_domain',
236 'wpcom_production_blog_id',
237 'wpcom_staging_blog_ids',
238 'can_blaze',
239 'wpcom_site_setup',
240 'is_commercial',
241 'is_commercial_reasons',
242 'wpcom_admin_interface',
243 'wpcom_classic_early_release',
244 'jetpack_recovery_mode_status',
245 'apm_enabled',
246 'wpcom_ai_launchpad_enabled',
247 'wpcom_ai_launchpad_dismissed',
248 'wpcom_ai_launchpad_completed',
249 );
250
251 /**
252 * Jetpack response fields.
253 *
254 * @var array $jetpack_response_field_additions
255 */
256 protected static $jetpack_response_field_additions = array(
257 'slug',
258 'subscribers_count',
259 'site_migration',
260 'site_owner',
261 'is_wpcom_staging_site',
262 'was_ecommerce_trial',
263 'was_migration_trial',
264 'was_hosting_trial',
265 'was_upgraded_from_trial',
266 'is_a4a_dev_site',
267 'is_garden',
268 'garden_name',
269 'garden_partner',
270 'garden_is_provisioned',
271 'is_wpcom_flex',
272 'big_sky_enabled',
273 );
274
275 /**
276 * Jetpack response field member additions.
277 *
278 * @var array $jetpack_response_field_member_additions
279 */
280 protected static $jetpack_response_field_member_additions = array(
281 'capabilities',
282 'plan',
283 'products',
284 'zendesk_site_meta',
285 );
286
287 /**
288 * Jetpack response option additions.
289 *
290 * @var array $jetpack_response_option_additions
291 */
292 protected static $jetpack_response_option_additions = array(
293 'publicize_permanently_disabled',
294 'ak_vp_bundle_enabled',
295 'is_automated_transfer',
296 'is_wpcom_atomic',
297 'is_wpcom_store',
298 'woocommerce_is_active',
299 'editing_toolkit_is_active',
300 'frame_nonce',
301 'jetpack_frame_nonce',
302 'design_type',
303 'wordads',
304 // Use the site registered date from wpcom, since it is only available in a multisite context
305 // and defaults to `0000-00-00T00:00:00+00:00` from the Jetpack site.
306 // See https://github.com/Automattic/jetpack/blob/58638f46094b36f5df9cbc4570006544f0ad300c/sal/class.json-api-site-base.php#L387.
307 'created_at',
308 'updated_at',
309 'is_pending_plan',
310 'is_cloud_eligible',
311 'videopress_storage_used',
312 'blogging_prompts_settings',
313 'wpcom_production_blog_id',
314 'wpcom_staging_blog_ids',
315 'is_commercial',
316 'is_commercial_reasons',
317 'wpcom_admin_interface',
318 'wpcom_classic_early_release',
319 'jetpack_recovery_mode_status',
320 'apm_enabled',
321 );
322
323 /**
324 * Current enabled trials.
325 *
326 * @var array $jetpack_enabled_trials
327 */
328 public static $jetpack_enabled_trials = array(
329 'was_ecommerce_trial' => 'ecommerce',
330 'was_migration_trial' => 'migration',
331 'was_hosting_trial' => 'hosting',
332 );
333
334 /**
335 * Site.
336 *
337 * @var SAL_Site $site.
338 */
339 private $site;
340
341 /**
342 * Fields to include.
343 *
344 * @var $fields_to_include
345 */
346 protected $fields_to_include = '_all';
347
348 /**
349 * Options to include.
350 *
351 * @var $options_to_include
352 */
353 protected $options_to_include = '_all';
354
355 /**
356 *
357 * API callback.
358 *
359 * /sites/mine
360 * /sites/%s -> $blog_id\
361 *
362 * @param string $path - the path.
363 * @param int|string $blog_id - the blog ID or the string 'mine'.
364 *
365 * @return array|\WP_Error Site response array on success, or WP_Error on failure.
366 */
367 public function callback( $path = '', $blog_id = 0 ) {
368 if ( 'mine' === $blog_id ) {
369 $api = WPCOM_JSON_API::init();
370 if ( ! $api->token_details || empty( $api->token_details['blog_id'] ) ) {
371 return new WP_Error( 'authorization_required', 'An active access token must be used to query information about the current blog.', 403 );
372 }
373 $blog_id = $api->token_details['blog_id'];
374 }
375
376 add_filter( 'wpcom_allow_jetpack_blog_token', '__return_true' );
377 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
378 if ( is_wp_error( $blog_id ) ) {
379 return $blog_id;
380 }
381
382 $this->filter_fields_and_options();
383
384 $response = $this->build_current_site_response();
385
386 /** This action is documented in json-endpoints/class.wpcom-json-api-site-settings-endpoint.php */
387 do_action( 'wpcom_json_api_objects', 'sites' );
388
389 return $response;
390 }
391
392 /**
393 * Filter fields and options.
394 */
395 public function filter_fields_and_options() {
396 $query_args = $this->query_args();
397
398 $this->fields_to_include = empty( $query_args['fields'] ) ? '_all' : array_map( 'trim', explode( ',', $query_args['fields'] ) );
399 $this->options_to_include = empty( $query_args['options'] ) ? '_all' : array_map( 'trim', explode( ',', $query_args['options'] ) );
400 }
401
402 /**
403 * Collects the necessary information to return for a site's response.
404 *
405 * @return array
406 */
407 public function build_current_site_response() {
408
409 $blog_id = (int) $this->api->get_blog_id_for_output();
410
411 $this->site = $this->get_platform()->get_site( $blog_id );
412
413 /**
414 * Filter the structure of information about the site to return.
415 *
416 * @module json-api
417 *
418 * @since 3.9.3
419 *
420 * @param array $site_format Data structure.
421 */
422 $default_fields = array_keys( apply_filters( 'sites_site_format', self::$site_format ) );
423
424 $response_keys = is_array( $this->fields_to_include ) ?
425 array_intersect( $default_fields, $this->fields_to_include ) :
426 $default_fields;
427
428 $has_blog_access = $this->has_blog_access( $this->api->token_details );
429 $has_user_access = $this->has_user_access();
430
431 if ( ! $has_user_access && ! $has_blog_access ) {
432 // Public access without user or blog auth, only return `$no_member_fields`.
433 $response_keys = array_intersect( $response_keys, self::$no_member_fields );
434 } elseif ( $has_user_access && ! current_user_can( 'edit_posts' ) ) {
435 // Subscriber level user, don't return site options.
436 $response_keys = array_diff( $response_keys, array( 'options' ) );
437 }
438
439 return $this->render_response_keys( $response_keys );
440 }
441
442 /**
443 * Checks that the current user has access to the current blog.
444 *
445 * @return bool Whether or not the current user can access the current blog.
446 */
447 private function has_user_access() {
448 return is_user_member_of_blog( get_current_user_id(), get_current_blog_id() );
449 }
450
451 /**
452 * Checks if the request has a valid blog token for the current blog.
453 *
454 * @param array $token_details Access token for the api request.
455 * @return bool
456 */
457 private function has_blog_access( $token_details ) {
458 $token_details = (array) $token_details;
459 if ( ! isset( $token_details['access'] ) || ! isset( $token_details['auth'] ) || ! isset( $token_details['blog_id'] ) ) {
460 return false;
461 }
462
463 return 'jetpack' === $token_details['auth'] &&
464 'blog' === $token_details['access'] &&
465 get_current_blog_id() === $token_details['blog_id'];
466 }
467
468 /**
469 * Render response keys.
470 *
471 * @param array $response_keys - the response keys.
472 */
473 private function render_response_keys( &$response_keys ) {
474 $response = array();
475
476 $is_user_logged_in = is_user_logged_in();
477
478 $this->site->before_render();
479
480 foreach ( $response_keys as $key ) {
481 $this->render_response_key( $key, $response, $is_user_logged_in );
482 }
483
484 $this->site->after_render( $response );
485
486 return $response;
487 }
488
489 /**
490 * Render response key.
491 *
492 * @param string $key - the key.
493 * @param array $response - the response.
494 * @param boolean $is_user_logged_in - if the user is logged in.
495 */
496 protected function render_response_key( $key, &$response, $is_user_logged_in ) {
497 do_action( 'pre_render_site_response_key', $key );
498
499 switch ( $key ) {
500 case 'ID':
501 $response[ $key ] = $this->site->blog_id;
502 break;
503 case 'slug':
504 $response[ $key ] = $this->site->get_slug();
505 break;
506 case 'name':
507 $response[ $key ] = $this->site->get_name();
508 break;
509 case 'description':
510 $response[ $key ] = $this->site->get_description();
511 break;
512 case 'URL':
513 $response[ $key ] = $this->site->get_url();
514 break;
515 case 'user_can_manage':
516 $response[ $key ] = $this->site->user_can_manage();
517 // fall through is intentional.
518 case 'is_private':
519 $response[ $key ] = $this->site->is_private();
520 break;
521 case 'is_coming_soon':
522 // This option is stored on wp.com for both simple and atomic sites. @see mu-plugins/private-blog.php.
523 $response[ $key ] = $this->site->is_coming_soon();
524
525 break;
526 case 'launch_status':
527 $response[ $key ] = $this->site->get_launch_status();
528 break;
529 case 'visible':
530 $response[ $key ] = $this->site->is_visible();
531 break;
532 case 'subscribers_count':
533 $response[ $key ] = $this->site->get_subscribers_count();
534 break;
535 case 'post_count':
536 if ( $is_user_logged_in ) {
537 $response[ $key ] = $this->site->get_post_count();
538 }
539 break;
540 case 'icon':
541 $icon = $this->site->get_icon();
542
543 if ( $icon !== null ) {
544 $response[ $key ] = $icon;
545 }
546 break;
547 case 'logo':
548 $response[ $key ] = $this->site->get_logo();
549 break;
550 case 'is_following':
551 $response[ $key ] = $this->site->is_following();
552 break;
553 case 'options':
554 // small optimisation - don't recalculate.
555 $all_options = apply_filters( 'sites_site_options_format', self::$site_options_format );
556
557 $options_response_keys = is_array( $this->options_to_include ) ?
558 array_intersect( $all_options, $this->options_to_include ) :
559 $all_options;
560
561 $options = $this->render_option_keys( $options_response_keys );
562
563 $this->site->after_render_options( $options );
564
565 $response[ $key ] = (object) $options;
566 break;
567 case 'meta':
568 $this->build_meta_response( $response );
569 break;
570 case 'lang':
571 $response[ $key ] = $is_user_logged_in ? $this->site->get_locale() : false;
572 break;
573 case 'locale':
574 $response[ $key ] = $is_user_logged_in ? $this->site->get_locale() : false;
575 break;
576 case 'jetpack':
577 $response[ $key ] = $this->site->is_jetpack();
578 break;
579 case 'jetpack_connection':
580 $response[ $key ] = $this->site->is_jetpack_connection();
581 break;
582 case 'single_user_site':
583 $response[ $key ] = $this->site->is_single_user_site();
584 break;
585 case 'is_vip':
586 $response[ $key ] = $this->site->is_vip();
587 break;
588 case 'is_multisite':
589 $response[ $key ] = $this->site->is_multisite();
590 break;
591 case 'site_owner':
592 $response[ $key ] = $this->site->get_site_owner();
593 break;
594 case 'organization_id':
595 $response[ $key ] = $this->site->get_p2_organization_id();
596 break;
597
598 case 'capabilities':
599 $response[ $key ] = $this->site->get_capabilities();
600 break;
601 case 'jetpack_modules':
602 if ( is_user_member_of_blog() ) {
603 $response[ $key ] = $this->site->get_jetpack_modules();
604 }
605 break;
606 case 'plan':
607 $response[ $key ] = $this->site->get_plan();
608 break;
609 case 'products':
610 $response[ $key ] = $this->site->get_products();
611 break;
612 case 'zendesk_site_meta':
613 $response[ $key ] = $this->site->get_zendesk_site_meta();
614 break;
615 case 'quota':
616 $response[ $key ] = $this->site->get_quota();
617 break;
618 case 'site_migration':
619 $response[ $key ] = $this->site->get_migration_meta();
620 break;
621 case 'is_fse_active':
622 $response[ $key ] = $this->site->is_fse_active();
623 break;
624 case 'is_fse_eligible':
625 $response[ $key ] = $this->site->is_fse_eligible();
626 break;
627 case 'is_core_site_editor_enabled':
628 $response[ $key ] = $this->site->is_core_site_editor_enabled();
629 break;
630 case 'is_wpcom_atomic':
631 $response[ $key ] = $this->site->is_wpcom_atomic();
632 break;
633 case 'is_wpcom_staging_site':
634 $response[ $key ] = $this->site->is_wpcom_staging_site();
635 break;
636 case 'user_interactions':
637 $response[ $key ] = $this->site->get_user_interactions();
638 break;
639 case 'p2_thumbnail_elements':
640 $response[ $key ] = $this->site->get_p2_thumbnail_elements();
641 break;
642 case 'was_ecommerce_trial':
643 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_ecommerce_trial'] );
644 break;
645 case 'was_migration_trial':
646 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_migration_trial'] );
647 break;
648 case 'was_hosting_trial':
649 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_hosting_trial'] );
650 break;
651 case 'was_upgraded_from_trial':
652 $response[ $key ] = $this->site->was_upgraded_from_trial();
653 break;
654 case 'is_deleted':
655 $response[ $key ] = $this->site->is_deleted();
656 break;
657 case 'is_a4a_client':
658 $response[ $key ] = $this->site->is_a4a_client();
659 break;
660 case 'is_a4a_dev_site':
661 $response[ $key ] = $this->site->is_a4a_dev_site();
662 break;
663 case 'is_garden':
664 $response[ $key ] = $this->site->is_garden();
665 break;
666 case 'garden_name':
667 $response[ $key ] = $this->site->garden_name();
668 break;
669 case 'garden_partner':
670 $response[ $key ] = $this->site->garden_partner();
671 break;
672 case 'garden_is_provisioned':
673 $response[ $key ] = $this->site->garden_is_provisioned();
674 break;
675 case 'is_wpcom_flex':
676 $response[ $key ] = $this->site->is_wpcom_flex();
677 break;
678 case 'big_sky_enabled':
679 $response[ $key ] = $this->site->is_big_sky_enabled();
680 break;
681 case 'hosting_provider_guess':
682 // WordPress.com platform decoration, computed only when explicitly requested
683 // via `fields` so default `_all` responses are unchanged.
684 if ( $this->is_wpcom()
685 && function_exists( 'get_jetpack_hosting_provider' )
686 && is_array( $this->fields_to_include ) ) {
687 $response[ $key ] = get_jetpack_hosting_provider( get_current_blog_id() );
688 }
689 break;
690 case 'environment_type':
691 // WordPress.com platform decoration, computed only when explicitly requested
692 // via `fields` so default `_all` responses are unchanged.
693 if ( $this->is_wpcom() && is_array( $this->fields_to_include ) ) {
694 $response[ $key ] = $this->get_site_environment_type();
695 }
696 break;
697 }
698
699 do_action( 'post_render_site_response_key', $key );
700 }
701
702 /**
703 * Render option keys.
704 *
705 * @param array $options_response_keys - the response keys.
706 */
707 protected function render_option_keys( &$options_response_keys ) {
708 $options = array();
709 $site = $this->site;
710
711 $custom_front_page = $site->is_custom_front_page();
712
713 foreach ( $options_response_keys as $key ) {
714 switch ( $key ) {
715 case 'timezone':
716 $options[ $key ] = $site->get_timezone();
717 break;
718 case 'gmt_offset':
719 $options[ $key ] = $site->get_gmt_offset();
720 break;
721 case 'videopress_enabled':
722 $options[ $key ] = $site->has_videopress();
723 break;
724 case 'upgraded_filetypes_enabled':
725 $options[ $key ] = $site->upgraded_filetypes_enabled();
726 break;
727 case 'login_url':
728 $options[ $key ] = $site->get_login_url();
729 break;
730 case 'admin_url':
731 $options[ $key ] = $site->get_admin_url();
732 break;
733 case 'is_mapped_domain':
734 $options[ $key ] = $site->is_mapped_domain();
735 break;
736 case 'is_redirect':
737 $options[ $key ] = $site->is_redirect();
738 break;
739 case 'unmapped_url':
740 $options[ $key ] = $site->get_unmapped_url();
741 break;
742 case 'featured_images_enabled':
743 $options[ $key ] = $site->featured_images_enabled();
744 break;
745 case 'theme_slug':
746 $options[ $key ] = $site->get_theme_slug();
747 break;
748 case 'theme_errors':
749 $options[ $key ] = $site->get_theme_errors();
750 break;
751 case 'header_image':
752 $options[ $key ] = $site->get_header_image();
753 break;
754 case 'background_color':
755 $options[ $key ] = $site->get_background_color();
756 break;
757 case 'image_default_link_type':
758 $options[ $key ] = $site->get_image_default_link_type();
759 break;
760 case 'image_thumbnail_width':
761 $options[ $key ] = $site->get_image_thumbnail_width();
762 break;
763 case 'image_thumbnail_height':
764 $options[ $key ] = $site->get_image_thumbnail_height();
765 break;
766 case 'image_thumbnail_crop':
767 $options[ $key ] = $site->get_image_thumbnail_crop();
768 break;
769 case 'image_medium_width':
770 $options[ $key ] = $site->get_image_medium_width();
771 break;
772 case 'image_medium_height':
773 $options[ $key ] = $site->get_image_medium_height();
774 break;
775 case 'image_large_width':
776 $options[ $key ] = $site->get_image_large_width();
777 break;
778 case 'image_large_height':
779 $options[ $key ] = $site->get_image_large_height();
780 break;
781 case 'permalink_structure':
782 $options[ $key ] = $site->get_permalink_structure();
783 break;
784 case 'post_formats':
785 $options[ $key ] = $site->get_post_formats();
786 break;
787 case 'default_post_format':
788 $options[ $key ] = $site->get_default_post_format();
789 break;
790 case 'default_category':
791 $options[ $key ] = $site->get_default_category();
792 break;
793 case 'allowed_file_types':
794 $options[ $key ] = $site->allowed_file_types();
795 break;
796 case 'show_on_front':
797 $options[ $key ] = $site->get_show_on_front();
798 break;
799 /** This filter is documented in modules/likes.php */
800 case 'default_likes_enabled':
801 $options[ $key ] = $site->get_default_likes_enabled();
802 break;
803 case 'default_sharing_status':
804 $options[ $key ] = $site->get_default_sharing_status();
805 break;
806 case 'default_comment_status':
807 $options[ $key ] = $site->get_default_comment_status();
808 break;
809 case 'default_ping_status':
810 $options[ $key ] = $site->default_ping_status();
811 break;
812 case 'software_version':
813 $options[ $key ] = $site->get_wordpress_version();
814 break;
815 case 'created_at':
816 $options[ $key ] = $site->get_registered_date();
817 break;
818 case 'updated_at':
819 $options[ $key ] = $site->get_last_update_date();
820 break;
821 case 'wordads':
822 $options[ $key ] = $site->has_wordads();
823 break;
824 case 'publicize_permanently_disabled':
825 $options[ $key ] = $site->is_publicize_permanently_disabled();
826 break;
827 case 'frame_nonce':
828 $options[ $key ] = $site->get_frame_nonce();
829 break;
830 case 'jetpack_frame_nonce':
831 $options[ $key ] = $site->get_jetpack_frame_nonce();
832 break;
833 case 'page_on_front':
834 if ( $custom_front_page ) {
835 $options[ $key ] = $site->get_page_on_front();
836 }
837 break;
838 case 'page_for_posts':
839 if ( $custom_front_page ) {
840 $options[ $key ] = $site->get_page_for_posts();
841 }
842 break;
843 case 'headstart':
844 $options[ $key ] = $site->is_headstart();
845 break;
846 case 'headstart_is_fresh':
847 $options[ $key ] = $site->is_headstart_fresh();
848 break;
849 case 'ak_vp_bundle_enabled':
850 $options[ $key ] = $site->get_ak_vp_bundle_enabled();
851 break;
852 case Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION:
853 $options[ $key ] = $site->get_jetpack_seo_front_page_description();
854 break;
855 case Jetpack_SEO_Titles::TITLE_FORMATS_OPTION:
856 $options[ $key ] = $site->get_jetpack_seo_title_formats();
857 break;
858 case 'verification_services_codes':
859 $options[ $key ] = $site->get_verification_services_codes();
860 break;
861 case 'podcasting_archive':
862 $options[ $key ] = $site->get_podcasting_archive();
863 break;
864 case 'is_domain_only':
865 $options[ $key ] = $site->is_domain_only();
866 break;
867 case 'is_automated_transfer':
868 $options[ $key ] = $site->is_automated_transfer();
869 break;
870 case 'blog_public':
871 $options[ $key ] = $site->get_blog_public();
872 break;
873 case 'is_wpcom_atomic':
874 $options[ $key ] = $site->is_wpcom_atomic();
875 break;
876 case 'is_wpcom_store':
877 $options[ $key ] = $site->is_wpcom_store();
878 break;
879 case 'signup_is_store':
880 $signup_is_store = $site->signup_is_store();
881
882 if ( $signup_is_store ) {
883 $options[ $key ] = $site->signup_is_store();
884 }
885
886 break;
887 case 'has_pending_automated_transfer':
888 $has_pending_automated_transfer = $site->has_pending_automated_transfer();
889
890 if ( $has_pending_automated_transfer ) {
891 $options[ $key ] = true;
892 }
893
894 break;
895 case 'woocommerce_is_active':
896 $options[ $key ] = $site->woocommerce_is_active();
897 break;
898 case 'editing_toolkit_is_active':
899 $options[ $key ] = $site->editing_toolkit_is_active();
900 break;
901 case 'design_type':
902 $options[ $key ] = $site->get_design_type();
903 break;
904 case 'site_segment':
905 $options[ $key ] = $site->get_site_segment();
906 break;
907 case 'import_engine':
908 $options[ $key ] = $site->get_import_engine();
909 break;
910 case 'is_pending_plan':
911 $options[ $key ] = $site->is_pending_plan();
912 break;
913
914 case 'is_wpforteams_site':
915 $options[ $key ] = $site->is_wpforteams_site();
916 break;
917 case 'p2_hub_blog_id':
918 $options[ $key ] = $site->get_p2_hub_blog_id();
919 break;
920
921 case 'site_creation_flow':
922 $site_creation_flow = $site->get_site_creation_flow();
923 if ( $site_creation_flow ) {
924 $options[ $key ] = $site_creation_flow;
925 }
926 break;
927 case 'site_source_slug':
928 $site_source_slug = $site->get_site_source_slug();
929 if ( $site_source_slug ) {
930 $options[ $key ] = $site_source_slug;
931 }
932 break;
933 case 'is_cloud_eligible':
934 $options[ $key ] = $site->is_cloud_eligible();
935 break;
936 case 'selected_features':
937 $selected_features = $site->get_selected_features();
938 if ( $selected_features ) {
939 $options[ $key ] = $selected_features;
940 }
941 break;
942 case 'anchor_podcast':
943 $options[ $key ] = $site->get_anchor_podcast();
944 break;
945 case 'was_created_with_blank_canvas_design':
946 $options[ $key ] = $site->was_created_with_blank_canvas_design();
947 break;
948 case 'videopress_storage_used':
949 $options[ $key ] = $this->site->get_videopress_storage_used();
950 break;
951 case 'is_difm_lite_in_progress':
952 $options[ $key ] = $site->is_difm_lite_in_progress();
953 break;
954 case 'is_gating_business_q1':
955 $options[ $key ] = $site->is_gating_business_q1();
956 break;
957 case 'site_intent':
958 $options[ $key ] = $site->get_site_intent();
959 break;
960 case 'site_partner_bundle':
961 $options[ $key ] = $site->get_site_partner_bundle();
962 break;
963 case 'site_goals':
964 $options[ $key ] = $site->get_site_goals();
965 break;
966 case 'onboarding_segment':
967 $options[ $key ] = $site->get_onboarding_segment();
968 break;
969 case 'site_vertical_id':
970 $options[ $key ] = $site->get_site_vertical_id();
971 break;
972 case 'blogging_prompts_settings':
973 if ( current_user_can( 'edit_posts' ) ) {
974 $options[ $key ] = $site->get_blogging_prompts_settings( get_current_user_id(), $site->blog_id );
975 }
976 break;
977 case 'launchpad_screen':
978 $options[ $key ] = $site->get_launchpad_screen();
979 break;
980 case 'launchpad_checklist_tasks_statuses':
981 $options[ $key ] = $site->get_launchpad_checklist_tasks_statuses();
982 break;
983 case 'migration_source_site_domain':
984 $options[ $key ] = $site->get_migration_source_site_domain();
985 break;
986 case 'wpcom_production_blog_id':
987 $options[ $key ] = $site->get_wpcom_production_blog_id();
988 break;
989 case 'wpcom_staging_blog_ids':
990 $options[ $key ] = $site->get_wpcom_staging_blog_ids();
991 break;
992 case 'can_blaze':
993 $options[ $key ] = $site->can_blaze();
994 break;
995 case 'wpcom_site_setup':
996 $options[ $key ] = $site->get_wpcom_site_setup();
997 break;
998 case 'is_commercial':
999 $options[ $key ] = $site->is_commercial();
1000 break;
1001 case 'is_commercial_reasons':
1002 $options[ $key ] = $site->get_is_commercial_reasons();
1003 break;
1004 case 'wpcom_admin_interface':
1005 $options[ $key ] = $site->get_wpcom_admin_interface();
1006 break;
1007 case 'wpcom_classic_early_release':
1008 $options[ $key ] = $site->get_wpcom_classic_early_release();
1009 break;
1010 case 'jetpack_recovery_mode_status':
1011 $options[ $key ] = $site->get_jetpack_recovery_mode_status();
1012 break;
1013 case 'apm_enabled':
1014 $options[ $key ] = $site->get_apm_enabled();
1015 break;
1016 case 'wpcom_ai_launchpad_enabled':
1017 $options[ $key ] = $site->is_ai_launchpad_enabled();
1018 break;
1019 case 'wpcom_ai_launchpad_dismissed':
1020 $options[ $key ] = $site->is_ai_launchpad_dismissed();
1021 break;
1022 case 'wpcom_ai_launchpad_completed':
1023 $options[ $key ] = $site->is_ai_launchpad_completed();
1024 break;
1025 }
1026 }
1027
1028 return $options;
1029 }
1030
1031 /**
1032 * Build meta response.
1033 *
1034 * @param array $response - the response.
1035 */
1036 protected function build_meta_response( &$response ) {
1037 $links = array(
1038 'self' => (string) $this->links->get_site_link( $this->site->blog_id ),
1039 'help' => (string) $this->links->get_site_link( $this->site->blog_id, 'help' ),
1040 'posts' => (string) $this->links->get_site_link( $this->site->blog_id, 'posts/' ),
1041 'comments' => (string) $this->links->get_site_link( $this->site->blog_id, 'comments/' ),
1042 'xmlrpc' => (string) $this->site->get_xmlrpc_url(),
1043 );
1044
1045 $icon = $this->site->get_icon();
1046 if ( ! empty( $icon ) && ! empty( $icon['media_id'] ) ) {
1047 $links['site_icon'] = (string) $this->links->get_site_link( $this->site->blog_id, 'media/' . $icon['media_id'] );
1048 }
1049
1050 $response['meta'] = (object) array(
1051 'links' => (object) $links,
1052 );
1053 }
1054
1055 /**
1056 * Apply any WPCOM-only response components to a Jetpack site response.
1057 *
1058 * @param object $response - the response.
1059 */
1060 public function decorate_jetpack_response( &$response ) {
1061 $this->filter_fields_and_options();
1062 $this->site = $this->get_platform()->get_site( $response->ID );
1063 switch_to_blog( $this->site->get_id() );
1064
1065 // Allow the SAL site to apply its own overrides to the proxied response.
1066 if ( method_exists( $this->site, 'decorate_jetpack_response' ) ) {
1067 $this->site->decorate_jetpack_response( $response ); // @phan-suppress-current-line PhanUndeclaredMethod -- checked via method_exists().
1068 }
1069
1070 $wpcom_response = $this->render_response_keys( self::$jetpack_response_field_additions );
1071
1072 foreach ( $wpcom_response as $key => $value ) {
1073 $response->{ $key } = $value;
1074 }
1075
1076 $has_site_access = $this->has_user_access() || $this->has_blog_access( $this->api->token_details );
1077
1078 if ( $has_site_access ) {
1079 $wpcom_member_response = $this->render_response_keys( self::$jetpack_response_field_member_additions );
1080
1081 foreach ( $wpcom_member_response as $key => $value ) {
1082 $response->{ $key } = $value;
1083 }
1084 } else {
1085 // ensure private data is not rendered for non members of the site.
1086 unset( $response->options );
1087 unset( $response->is_vip );
1088 unset( $response->single_user_site );
1089 unset( $response->is_private );
1090 unset( $response->is_coming_soon );
1091 unset( $response->capabilities );
1092 unset( $response->lang );
1093 unset( $response->user_can_manage );
1094 unset( $response->is_multisite );
1095 unset( $response->site_owner );
1096 unset( $response->plan );
1097 unset( $response->products );
1098 unset( $response->zendesk_site_meta );
1099 }
1100
1101 // render additional options.
1102 if ( isset( $response->options ) && $response->options ) {
1103 $wpcom_options_response = $this->render_option_keys( self::$jetpack_response_option_additions );
1104
1105 // Remove heic from jetpack (and atomic) sites so that the iOS app know to convert the file format into a JPEG.
1106 // heic fromat is currently not supported by for uploading.
1107 // See https://jetpackp2.wordpress.com/2020/08/19/image-uploads-in-the-wp-ios-app-broken
1108 if (
1109 $this->site->is_jetpack()
1110 && isset( $response->options['allowed_file_types'] )
1111 && is_array( $response->options['allowed_file_types'] )
1112 ) {
1113 $allowed_file_types = (array) $response->options['allowed_file_types'];
1114 $remove_file_types = array(
1115 'heic',
1116 );
1117 $response->options['allowed_file_types'] = array_values( array_diff( $allowed_file_types, $remove_file_types ) );
1118 }
1119
1120 foreach ( $wpcom_options_response as $key => $value ) {
1121 $response->options[ $key ] = $value;
1122 }
1123 }
1124
1125 // WordPress.com platform fields are not part of proxied Jetpack responses;
1126 // add them only when explicitly requested.
1127 if ( $this->is_wpcom() && $has_site_access && is_array( $this->fields_to_include ) ) {
1128 if ( function_exists( 'get_jetpack_hosting_provider' ) && in_array( 'hosting_provider_guess', $this->fields_to_include, true ) ) {
1129 $response->hosting_provider_guess = get_jetpack_hosting_provider( get_current_blog_id() );
1130 }
1131 if ( in_array( 'environment_type', $this->fields_to_include, true ) ) {
1132 $response->environment_type = $this->get_site_environment_type();
1133 }
1134 }
1135
1136 restore_current_blog();
1137 return $response; // possibly no need since it's modified in place.
1138 }
1139
1140 /**
1141 * Whether this request is running on the WordPress.com platform.
1142 *
1143 * @return bool
1144 */
1145 protected function is_wpcom() {
1146 return ( new \Automattic\Jetpack\Status\Host() )->is_wpcom_platform();
1147 }
1148
1149 /**
1150 * Get the site's synced WP_ENVIRONMENT_TYPE.
1151 *
1152 * @return string|null
1153 */
1154 protected function get_site_environment_type() {
1155 if ( function_exists( 'get_blog_option' ) ) {
1156 return get_blog_option( get_current_blog_id(), 'jetpack_callable_wp_get_environment_type', null );
1157 }
1158
1159 return get_option( 'jetpack_callable_wp_get_environment_type', null );
1160 }
1161 }
1162
1163 new WPCOM_JSON_API_List_Post_Formats_Endpoint(
1164 array(
1165 'description' => 'Get a list of post formats supported by a site.',
1166 'group' => '__do_not_document',
1167 'stat' => 'sites:X:post-formats',
1168
1169 'method' => 'GET',
1170 'path' => '/sites/%s/post-formats',
1171 'path_labels' => array(
1172 '$site' => '(int|string) Site ID or domain',
1173 ),
1174
1175 'query_parameters' => array(
1176 'context' => false,
1177 ),
1178
1179 'allow_fallback_to_jetpack_blog_token' => true,
1180
1181 'response_format' => array(
1182 'formats' => '(object) An object of supported post formats, each key a supported format slug mapped to its display string.',
1183 ),
1184 )
1185 );
1186
1187 /**
1188 * List Post Formats endpoint class.
1189 *
1190 * @phan-constructor-used-for-side-effects
1191 */
1192 class WPCOM_JSON_API_List_Post_Formats_Endpoint extends WPCOM_JSON_API_Endpoint { // phpcs:ignore
1193 /**
1194 *
1195 * API callback.
1196 *
1197 * /sites/%s/post-formats -> $blog_id
1198 *
1199 * @param string $path - the path.
1200 * @param int $blog_id - the blog ID.
1201 *
1202 * @return array|\WP_Error Array with 'formats' on success, or WP_Error on failure.
1203 */
1204 public function callback( $path = '', $blog_id = 0 ) {
1205 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
1206 if ( is_wp_error( $blog_id ) ) {
1207 return $blog_id;
1208 }
1209
1210 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1211 $this->load_theme_functions();
1212 }
1213
1214 // Get a list of supported post formats.
1215 $all_formats = get_post_format_strings();
1216 $supported = get_theme_support( 'post-formats' );
1217
1218 $response = array(
1219 'formats' => array(),
1220 );
1221 $supported_formats = $response['formats'];
1222
1223 if ( isset( $supported[0] ) ) {
1224 foreach ( $supported[0] as $format ) {
1225 $supported_formats[ $format ] = $all_formats[ $format ];
1226 }
1227 }
1228
1229 $response['formats'] = (object) $supported_formats;
1230
1231 return $response;
1232 }
1233 }
1234
1235 new WPCOM_JSON_API_List_Page_Templates_Endpoint(
1236 array(
1237 'description' => 'Get a list of page templates supported by a site.',
1238 'group' => 'sites',
1239 'stat' => 'sites:X:post-templates',
1240
1241 'method' => 'GET',
1242 'path' => '/sites/%s/page-templates',
1243 'path_labels' => array(
1244 '$site' => '(int|string) Site ID or domain',
1245 ),
1246 'query_parameters' => array(
1247 'context' => false,
1248 ),
1249 'response_format' => array(
1250 'templates' => '(array) A list of supported page templates. Contains label and file.',
1251 ),
1252 'example_request' => 'https://public-api.wordpress.com/rest/v1.1/sites/33534099/page-templates',
1253 )
1254 );
1255
1256 /**
1257 * List page templates endpoint class.
1258 *
1259 * @phan-constructor-used-for-side-effects
1260 */
1261 class WPCOM_JSON_API_List_Page_Templates_Endpoint extends WPCOM_JSON_API_Endpoint { // phpcs:ignore
1262 /**
1263 *
1264 * API callback.
1265 * /sites/%s/page-templates -> $blog_id
1266 *
1267 * @param string $path - the path.
1268 * @param int $blog_id - the blog ID.
1269 *
1270 * @return array|\WP_Error Array with 'templates' on success, or WP_Error on failure.
1271 */
1272 public function callback( $path = '', $blog_id = 0 ) {
1273 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
1274 if ( is_wp_error( $blog_id ) ) {
1275 return $blog_id;
1276 }
1277
1278 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1279 $this->load_theme_functions();
1280 }
1281
1282 $response = array();
1283 $page_templates = array();
1284
1285 $templates = get_page_templates();
1286 ksort( $templates );
1287
1288 foreach ( array_keys( $templates ) as $label ) {
1289 $page_templates[] = array(
1290 'label' => $label,
1291 'file' => $templates[ $label ],
1292 );
1293 }
1294
1295 $response['templates'] = $page_templates;
1296
1297 return $response;
1298 }
1299 }
1300