PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 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 1 week ago class.wpcom-json-api-add-widget-endpoint.php 8 months ago class.wpcom-json-api-autosave-post-v1-1-endpoint.php 8 months ago class.wpcom-json-api-bulk-delete-post-endpoint.php 8 months ago class.wpcom-json-api-bulk-restore-post-endpoint.php 8 months ago class.wpcom-json-api-bulk-update-comments-endpoint.php 2 months ago class.wpcom-json-api-comment-endpoint.php 8 months ago class.wpcom-json-api-delete-media-endpoint.php 8 months ago class.wpcom-json-api-delete-media-v1-1-endpoint.php 8 months ago class.wpcom-json-api-edit-media-v1-2-endpoint.php 1 week ago class.wpcom-json-api-get-autosave-v1-1-endpoint.php 8 months ago class.wpcom-json-api-get-comment-counts-endpoint.php 8 months ago class.wpcom-json-api-get-comment-endpoint.php 8 months ago class.wpcom-json-api-get-comment-history-endpoint.php 8 months ago class.wpcom-json-api-get-comments-tree-endpoint.php 8 months ago class.wpcom-json-api-get-comments-tree-v1-1-endpoint.php 8 months ago class.wpcom-json-api-get-comments-tree-v1-2-endpoint.php 8 months ago class.wpcom-json-api-get-customcss.php 8 months ago class.wpcom-json-api-get-media-endpoint.php 8 months ago class.wpcom-json-api-get-media-v1-1-endpoint.php 8 months ago class.wpcom-json-api-get-media-v1-2-endpoint.php 8 months ago class.wpcom-json-api-get-post-counts-v1-1-endpoint.php 1 month ago class.wpcom-json-api-get-post-endpoint.php 8 months ago class.wpcom-json-api-get-post-v1-1-endpoint.php 1 month ago class.wpcom-json-api-get-site-endpoint.php 2 days ago class.wpcom-json-api-get-site-v1-2-endpoint.php 1 month ago class.wpcom-json-api-get-taxonomies-endpoint.php 4 months ago class.wpcom-json-api-get-taxonomy-endpoint.php 8 months ago class.wpcom-json-api-get-term-endpoint.php 8 months ago class.wpcom-json-api-list-comments-endpoint.php 1 month ago class.wpcom-json-api-list-dropdown-pages-endpoint.php 8 months ago class.wpcom-json-api-list-embeds-endpoint.php 8 months ago class.wpcom-json-api-list-media-endpoint.php 8 months ago class.wpcom-json-api-list-media-v1-1-endpoint.php 2 months ago class.wpcom-json-api-list-media-v1-2-endpoint.php 8 months ago class.wpcom-json-api-list-post-type-taxonomies-endpoint.php 8 months ago class.wpcom-json-api-list-post-types-endpoint.php 8 months ago class.wpcom-json-api-list-posts-endpoint.php 1 month ago class.wpcom-json-api-list-posts-v1-1-endpoint.php 1 month ago class.wpcom-json-api-list-posts-v1-2-endpoint.php 1 month ago class.wpcom-json-api-list-roles-endpoint.php 8 months ago class.wpcom-json-api-list-shortcodes-endpoint.php 8 months ago class.wpcom-json-api-list-terms-endpoint.php 8 months ago class.wpcom-json-api-list-users-endpoint.php 1 month ago class.wpcom-json-api-menus-v1-1-endpoint.php 2 months ago class.wpcom-json-api-post-endpoint.php 8 months ago class.wpcom-json-api-post-v1-1-endpoint.php 3 months ago class.wpcom-json-api-render-embed-endpoint.php 8 months ago class.wpcom-json-api-render-embed-reversal-endpoint.php 8 months ago class.wpcom-json-api-render-endpoint.php 3 months ago class.wpcom-json-api-render-shortcode-endpoint.php 8 months ago class.wpcom-json-api-sharing-buttons-endpoint.php 2 months ago class.wpcom-json-api-site-settings-endpoint.php 2 weeks ago class.wpcom-json-api-site-settings-v1-2-endpoint.php 8 months ago class.wpcom-json-api-site-settings-v1-3-endpoint.php 8 months ago class.wpcom-json-api-site-settings-v1-4-endpoint.php 1 month ago class.wpcom-json-api-site-user-endpoint.php 8 months ago class.wpcom-json-api-taxonomy-endpoint.php 8 months ago class.wpcom-json-api-update-comment-endpoint.php 7 months ago class.wpcom-json-api-update-customcss.php 8 months ago class.wpcom-json-api-update-media-endpoint.php 2 days ago class.wpcom-json-api-update-media-v1-1-endpoint.php 2 days ago class.wpcom-json-api-update-post-endpoint.php 2 months ago class.wpcom-json-api-update-post-v1-1-endpoint.php 2 months ago class.wpcom-json-api-update-post-v1-2-endpoint.php 2 months ago class.wpcom-json-api-update-site-homepage-endpoint.php 8 months ago class.wpcom-json-api-update-site-logo-endpoint.php 8 months ago class.wpcom-json-api-update-taxonomy-endpoint.php 8 months ago class.wpcom-json-api-update-term-endpoint.php 8 months ago class.wpcom-json-api-update-user-endpoint.php 8 months ago class.wpcom-json-api-upload-media-endpoint.php 8 months ago class.wpcom-json-api-upload-media-v1-1-endpoint.php 8 months ago
class.wpcom-json-api-get-site-endpoint.php
1313 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 'atomic_email_block' => '(object) State of the block on the site\'s outgoing email, with `status` (`blocked` while a block is active, `at_risk` once it has expired), `reason` and `expires_on` keys, or null when the site has no block history. WordPress.com platform only.',
105 'hosting_provider_guess' => '(string) Guess of the hosting provider. WordPress.com platform only; only returned when explicitly requested via the fields parameter.',
106 '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.',
107 );
108
109 /**
110 * No member fields.
111 *
112 * @var array $no_member_fields
113 */
114 protected static $no_member_fields = array(
115 'ID',
116 'name',
117 'description',
118 'URL',
119 'jetpack',
120 'jetpack_connection',
121 'post_count',
122 'subscribers_count',
123 'lang',
124 'locale',
125 'icon',
126 'logo',
127 'visible',
128 'is_private',
129 'is_coming_soon',
130 'is_following',
131 'organization_id',
132 'meta',
133 'launch_status',
134 'site_migration',
135 'is_fse_active',
136 'is_fse_eligible',
137 'is_core_site_editor_enabled',
138 'is_wpcom_atomic',
139 'is_wpcom_staging_site',
140 'is_deleted',
141 'is_wpcom_flex',
142 'is_a4a_client',
143 'is_a4a_dev_site',
144 'is_garden',
145 'big_sky_enabled',
146 'garden_name',
147 );
148
149 /**
150 * Site options.
151 *
152 * @var array $site_options_format
153 */
154 protected static $site_options_format = array(
155 'timezone',
156 'gmt_offset',
157 'blog_public',
158 'videopress_enabled',
159 'upgraded_filetypes_enabled',
160 'login_url',
161 'admin_url',
162 'is_mapped_domain',
163 'is_redirect',
164 'unmapped_url',
165 'featured_images_enabled',
166 'theme_slug',
167 'theme_errors',
168 'header_image',
169 'background_color',
170 'image_default_link_type',
171 'image_thumbnail_width',
172 'image_thumbnail_height',
173 'image_thumbnail_crop',
174 'image_medium_width',
175 'image_medium_height',
176 'image_large_width',
177 'image_large_height',
178 'permalink_structure',
179 'post_formats',
180 'default_post_format',
181 'default_category',
182 'allowed_file_types',
183 'show_on_front',
184 /** This filter is documented in modules/likes.php */
185 'default_likes_enabled',
186 'default_sharing_status',
187 'default_comment_status',
188 'default_ping_status',
189 'software_version',
190 'created_at',
191 'updated_at',
192 'wordads',
193 'publicize_permanently_disabled',
194 'frame_nonce',
195 'jetpack_frame_nonce',
196 'page_on_front',
197 'page_for_posts',
198 'headstart',
199 'headstart_is_fresh',
200 'ak_vp_bundle_enabled',
201 Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION,
202 Jetpack_SEO_Titles::TITLE_FORMATS_OPTION,
203 'verification_services_codes',
204 'podcasting_archive',
205 'is_domain_only',
206 'is_automated_transfer',
207 'is_wpcom_atomic',
208 'is_wpcom_store',
209 'signup_is_store',
210 'has_pending_automated_transfer',
211 'woocommerce_is_active',
212 'editing_toolkit_is_active',
213 'design_type',
214 'site_goals',
215 'site_segment',
216 'site_source_slug',
217 'import_engine',
218 'is_pending_plan',
219 'is_wpforteams_site',
220 'p2_hub_blog_id',
221 'site_creation_flow',
222 'is_cloud_eligible',
223 'selected_features',
224 'anchor_podcast',
225 'was_created_with_blank_canvas_design',
226 'videopress_storage_used',
227 'is_difm_lite_in_progress',
228 'difm_lite_site_options',
229 'is_gating_business_q1',
230 'site_intent',
231 'site_partner_bundle',
232 'onboarding_segment',
233 'site_vertical_id',
234 'blogging_prompts_settings',
235 'launchpad_screen',
236 'launchpad_checklist_tasks_statuses',
237 'migration_source_site_domain',
238 'wpcom_production_blog_id',
239 'wpcom_staging_blog_ids',
240 'can_blaze',
241 'wpcom_site_setup',
242 'is_commercial',
243 'is_commercial_reasons',
244 'wpcom_admin_interface',
245 'wpcom_classic_early_release',
246 'jetpack_recovery_mode_status',
247 'apm_enabled',
248 'wpcom_ai_launchpad_enabled',
249 'wpcom_ai_launchpad_dismissed',
250 'wpcom_ai_launchpad_completed',
251 );
252
253 /**
254 * Jetpack response fields.
255 *
256 * @var array $jetpack_response_field_additions
257 */
258 protected static $jetpack_response_field_additions = array(
259 'slug',
260 'subscribers_count',
261 'site_migration',
262 'site_owner',
263 'is_wpcom_staging_site',
264 'was_ecommerce_trial',
265 'was_migration_trial',
266 'was_hosting_trial',
267 'was_upgraded_from_trial',
268 'is_a4a_dev_site',
269 'is_garden',
270 'garden_name',
271 'garden_partner',
272 'garden_is_provisioned',
273 'is_wpcom_flex',
274 'big_sky_enabled',
275 'atomic_email_block',
276 );
277
278 /**
279 * Jetpack response field member additions.
280 *
281 * @var array $jetpack_response_field_member_additions
282 */
283 protected static $jetpack_response_field_member_additions = array(
284 'capabilities',
285 'plan',
286 'products',
287 'zendesk_site_meta',
288 );
289
290 /**
291 * Jetpack response option additions.
292 *
293 * @var array $jetpack_response_option_additions
294 */
295 protected static $jetpack_response_option_additions = array(
296 'publicize_permanently_disabled',
297 'ak_vp_bundle_enabled',
298 'is_automated_transfer',
299 'is_wpcom_atomic',
300 'is_wpcom_store',
301 'woocommerce_is_active',
302 'editing_toolkit_is_active',
303 'frame_nonce',
304 'jetpack_frame_nonce',
305 'design_type',
306 'wordads',
307 // Use the site registered date from wpcom, since it is only available in a multisite context
308 // and defaults to `0000-00-00T00:00:00+00:00` from the Jetpack site.
309 // See https://github.com/Automattic/jetpack/blob/58638f46094b36f5df9cbc4570006544f0ad300c/sal/class.json-api-site-base.php#L387.
310 'created_at',
311 'updated_at',
312 'is_pending_plan',
313 'is_cloud_eligible',
314 'videopress_storage_used',
315 'blogging_prompts_settings',
316 'wpcom_production_blog_id',
317 'wpcom_staging_blog_ids',
318 'is_commercial',
319 'is_commercial_reasons',
320 'wpcom_admin_interface',
321 'wpcom_classic_early_release',
322 'jetpack_recovery_mode_status',
323 'apm_enabled',
324 );
325
326 /**
327 * Current enabled trials.
328 *
329 * @var array $jetpack_enabled_trials
330 */
331 public static $jetpack_enabled_trials = array(
332 'was_ecommerce_trial' => 'ecommerce',
333 'was_migration_trial' => 'migration',
334 'was_hosting_trial' => 'hosting',
335 );
336
337 /**
338 * Site.
339 *
340 * @var SAL_Site $site.
341 */
342 private $site;
343
344 /**
345 * Fields to include.
346 *
347 * @var $fields_to_include
348 */
349 protected $fields_to_include = '_all';
350
351 /**
352 * Options to include.
353 *
354 * @var $options_to_include
355 */
356 protected $options_to_include = '_all';
357
358 /**
359 *
360 * API callback.
361 *
362 * /sites/mine
363 * /sites/%s -> $blog_id\
364 *
365 * @param string $path - the path.
366 * @param int|string $blog_id - the blog ID or the string 'mine'.
367 *
368 * @return array|\WP_Error Site response array on success, or WP_Error on failure.
369 */
370 public function callback( $path = '', $blog_id = 0 ) {
371 if ( 'mine' === $blog_id ) {
372 $api = WPCOM_JSON_API::init();
373 if ( ! $api->token_details || empty( $api->token_details['blog_id'] ) ) {
374 return new WP_Error( 'authorization_required', 'An active access token must be used to query information about the current blog.', 403 );
375 }
376 $blog_id = $api->token_details['blog_id'];
377 }
378
379 add_filter( 'wpcom_allow_jetpack_blog_token', '__return_true' );
380 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
381 if ( is_wp_error( $blog_id ) ) {
382 return $blog_id;
383 }
384
385 $this->filter_fields_and_options();
386
387 $response = $this->build_current_site_response();
388
389 /** This action is documented in json-endpoints/class.wpcom-json-api-site-settings-endpoint.php */
390 do_action( 'wpcom_json_api_objects', 'sites' );
391
392 return $response;
393 }
394
395 /**
396 * Filter fields and options.
397 */
398 public function filter_fields_and_options() {
399 $query_args = $this->query_args();
400
401 $this->fields_to_include = empty( $query_args['fields'] ) ? '_all' : array_map( 'trim', explode( ',', $query_args['fields'] ) );
402 $this->options_to_include = empty( $query_args['options'] ) ? '_all' : array_map( 'trim', explode( ',', $query_args['options'] ) );
403 }
404
405 /**
406 * Collects the necessary information to return for a site's response.
407 *
408 * @return array
409 */
410 public function build_current_site_response() {
411
412 $blog_id = (int) $this->api->get_blog_id_for_output();
413
414 $this->site = $this->get_platform()->get_site( $blog_id );
415
416 /**
417 * Filter the structure of information about the site to return.
418 *
419 * @module json-api
420 *
421 * @since 3.9.3
422 *
423 * @param array $site_format Data structure.
424 */
425 $default_fields = array_keys( apply_filters( 'sites_site_format', self::$site_format ) );
426
427 $response_keys = is_array( $this->fields_to_include ) ?
428 array_intersect( $default_fields, $this->fields_to_include ) :
429 $default_fields;
430
431 $has_blog_access = $this->has_blog_access( $this->api->token_details );
432 $has_user_access = $this->has_user_access();
433
434 if ( ! $has_user_access && ! $has_blog_access ) {
435 // Public access without user or blog auth, only return `$no_member_fields`.
436 $response_keys = array_intersect( $response_keys, self::$no_member_fields );
437 } elseif ( $has_user_access && ! current_user_can( 'edit_posts' ) ) {
438 // Subscriber level user, don't return site options.
439 $response_keys = array_diff( $response_keys, array( 'options' ) );
440 }
441
442 return $this->render_response_keys( $response_keys );
443 }
444
445 /**
446 * Checks that the current user has access to the current blog.
447 *
448 * @return bool Whether or not the current user can access the current blog.
449 */
450 private function has_user_access() {
451 return is_user_member_of_blog( get_current_user_id(), get_current_blog_id() );
452 }
453
454 /**
455 * Checks if the request has a valid blog token for the current blog.
456 *
457 * @param array $token_details Access token for the api request.
458 * @return bool
459 */
460 private function has_blog_access( $token_details ) {
461 $token_details = (array) $token_details;
462 if ( ! isset( $token_details['access'] ) || ! isset( $token_details['auth'] ) || ! isset( $token_details['blog_id'] ) ) {
463 return false;
464 }
465
466 return 'jetpack' === $token_details['auth'] &&
467 'blog' === $token_details['access'] &&
468 get_current_blog_id() === $token_details['blog_id'];
469 }
470
471 /**
472 * Render response keys.
473 *
474 * @param array $response_keys - the response keys.
475 */
476 private function render_response_keys( &$response_keys ) {
477 $response = array();
478
479 $is_user_logged_in = is_user_logged_in();
480
481 $this->site->before_render();
482
483 foreach ( $response_keys as $key ) {
484 $this->render_response_key( $key, $response, $is_user_logged_in );
485 }
486
487 $this->site->after_render( $response );
488
489 return $response;
490 }
491
492 /**
493 * Render response key.
494 *
495 * @param string $key - the key.
496 * @param array $response - the response.
497 * @param boolean $is_user_logged_in - if the user is logged in.
498 */
499 protected function render_response_key( $key, &$response, $is_user_logged_in ) {
500 do_action( 'pre_render_site_response_key', $key );
501
502 switch ( $key ) {
503 case 'ID':
504 $response[ $key ] = $this->site->blog_id;
505 break;
506 case 'slug':
507 $response[ $key ] = $this->site->get_slug();
508 break;
509 case 'name':
510 $response[ $key ] = $this->site->get_name();
511 break;
512 case 'description':
513 $response[ $key ] = $this->site->get_description();
514 break;
515 case 'URL':
516 $response[ $key ] = $this->site->get_url();
517 break;
518 case 'user_can_manage':
519 $response[ $key ] = $this->site->user_can_manage();
520 // fall through is intentional.
521 case 'is_private':
522 $response[ $key ] = $this->site->is_private();
523 break;
524 case 'is_coming_soon':
525 // This option is stored on wp.com for both simple and atomic sites. @see mu-plugins/private-blog.php.
526 $response[ $key ] = $this->site->is_coming_soon();
527
528 break;
529 case 'launch_status':
530 $response[ $key ] = $this->site->get_launch_status();
531 break;
532 case 'visible':
533 $response[ $key ] = $this->site->is_visible();
534 break;
535 case 'subscribers_count':
536 $response[ $key ] = $this->site->get_subscribers_count();
537 break;
538 case 'post_count':
539 if ( $is_user_logged_in ) {
540 $response[ $key ] = $this->site->get_post_count();
541 }
542 break;
543 case 'icon':
544 $icon = $this->site->get_icon();
545
546 if ( $icon !== null ) {
547 $response[ $key ] = $icon;
548 }
549 break;
550 case 'logo':
551 $response[ $key ] = $this->site->get_logo();
552 break;
553 case 'is_following':
554 $response[ $key ] = $this->site->is_following();
555 break;
556 case 'options':
557 // small optimisation - don't recalculate.
558 $all_options = apply_filters( 'sites_site_options_format', self::$site_options_format );
559
560 $options_response_keys = is_array( $this->options_to_include ) ?
561 array_intersect( $all_options, $this->options_to_include ) :
562 $all_options;
563
564 $options = $this->render_option_keys( $options_response_keys );
565
566 $this->site->after_render_options( $options );
567
568 $response[ $key ] = (object) $options;
569 break;
570 case 'meta':
571 $this->build_meta_response( $response );
572 break;
573 case 'lang':
574 $response[ $key ] = $is_user_logged_in ? $this->site->get_locale() : false;
575 break;
576 case 'locale':
577 $response[ $key ] = $is_user_logged_in ? $this->site->get_locale() : false;
578 break;
579 case 'jetpack':
580 $response[ $key ] = $this->site->is_jetpack();
581 break;
582 case 'jetpack_connection':
583 $response[ $key ] = $this->site->is_jetpack_connection();
584 break;
585 case 'single_user_site':
586 $response[ $key ] = $this->site->is_single_user_site();
587 break;
588 case 'is_vip':
589 $response[ $key ] = $this->site->is_vip();
590 break;
591 case 'is_multisite':
592 $response[ $key ] = $this->site->is_multisite();
593 break;
594 case 'site_owner':
595 $response[ $key ] = $this->site->get_site_owner();
596 break;
597 case 'organization_id':
598 $response[ $key ] = $this->site->get_p2_organization_id();
599 break;
600
601 case 'capabilities':
602 $response[ $key ] = $this->site->get_capabilities();
603 break;
604 case 'jetpack_modules':
605 if ( is_user_member_of_blog() ) {
606 $response[ $key ] = $this->site->get_jetpack_modules();
607 }
608 break;
609 case 'plan':
610 $response[ $key ] = $this->site->get_plan();
611 break;
612 case 'products':
613 $response[ $key ] = $this->site->get_products();
614 break;
615 case 'zendesk_site_meta':
616 $response[ $key ] = $this->site->get_zendesk_site_meta();
617 break;
618 case 'quota':
619 $response[ $key ] = $this->site->get_quota();
620 break;
621 case 'site_migration':
622 $response[ $key ] = $this->site->get_migration_meta();
623 break;
624 case 'is_fse_active':
625 $response[ $key ] = $this->site->is_fse_active();
626 break;
627 case 'is_fse_eligible':
628 $response[ $key ] = $this->site->is_fse_eligible();
629 break;
630 case 'is_core_site_editor_enabled':
631 $response[ $key ] = $this->site->is_core_site_editor_enabled();
632 break;
633 case 'is_wpcom_atomic':
634 $response[ $key ] = $this->site->is_wpcom_atomic();
635 break;
636 case 'is_wpcom_staging_site':
637 $response[ $key ] = $this->site->is_wpcom_staging_site();
638 break;
639 case 'user_interactions':
640 $response[ $key ] = $this->site->get_user_interactions();
641 break;
642 case 'p2_thumbnail_elements':
643 $response[ $key ] = $this->site->get_p2_thumbnail_elements();
644 break;
645 case 'was_ecommerce_trial':
646 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_ecommerce_trial'] );
647 break;
648 case 'was_migration_trial':
649 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_migration_trial'] );
650 break;
651 case 'was_hosting_trial':
652 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_hosting_trial'] );
653 break;
654 case 'was_upgraded_from_trial':
655 $response[ $key ] = $this->site->was_upgraded_from_trial();
656 break;
657 case 'is_deleted':
658 $response[ $key ] = $this->site->is_deleted();
659 break;
660 case 'is_a4a_client':
661 $response[ $key ] = $this->site->is_a4a_client();
662 break;
663 case 'is_a4a_dev_site':
664 $response[ $key ] = $this->site->is_a4a_dev_site();
665 break;
666 case 'is_garden':
667 $response[ $key ] = $this->site->is_garden();
668 break;
669 case 'garden_name':
670 $response[ $key ] = $this->site->garden_name();
671 break;
672 case 'garden_partner':
673 $response[ $key ] = $this->site->garden_partner();
674 break;
675 case 'garden_is_provisioned':
676 $response[ $key ] = $this->site->garden_is_provisioned();
677 break;
678 case 'is_wpcom_flex':
679 $response[ $key ] = $this->site->is_wpcom_flex();
680 break;
681 case 'big_sky_enabled':
682 $response[ $key ] = $this->site->is_big_sky_enabled();
683 break;
684 case 'atomic_email_block':
685 $response[ $key ] = $this->site->get_atomic_email_block();
686 break;
687 case 'hosting_provider_guess':
688 // WordPress.com platform decoration, computed only when explicitly requested
689 // via `fields` so default `_all` responses are unchanged.
690 if ( $this->is_wpcom()
691 && function_exists( 'get_jetpack_hosting_provider' )
692 && is_array( $this->fields_to_include ) ) {
693 $response[ $key ] = get_jetpack_hosting_provider( get_current_blog_id() );
694 }
695 break;
696 case 'environment_type':
697 // WordPress.com platform decoration, computed only when explicitly requested
698 // via `fields` so default `_all` responses are unchanged.
699 if ( $this->is_wpcom() && is_array( $this->fields_to_include ) ) {
700 $response[ $key ] = $this->get_site_environment_type();
701 }
702 break;
703 }
704
705 do_action( 'post_render_site_response_key', $key );
706 }
707
708 /**
709 * Render option keys.
710 *
711 * @param array $options_response_keys - the response keys.
712 */
713 protected function render_option_keys( &$options_response_keys ) {
714 $options = array();
715 $site = $this->site;
716
717 $custom_front_page = $site->is_custom_front_page();
718
719 foreach ( $options_response_keys as $key ) {
720 switch ( $key ) {
721 case 'timezone':
722 $options[ $key ] = $site->get_timezone();
723 break;
724 case 'gmt_offset':
725 $options[ $key ] = $site->get_gmt_offset();
726 break;
727 case 'videopress_enabled':
728 $options[ $key ] = $site->has_videopress();
729 break;
730 case 'upgraded_filetypes_enabled':
731 $options[ $key ] = $site->upgraded_filetypes_enabled();
732 break;
733 case 'login_url':
734 $options[ $key ] = $site->get_login_url();
735 break;
736 case 'admin_url':
737 $options[ $key ] = $site->get_admin_url();
738 break;
739 case 'is_mapped_domain':
740 $options[ $key ] = $site->is_mapped_domain();
741 break;
742 case 'is_redirect':
743 $options[ $key ] = $site->is_redirect();
744 break;
745 case 'unmapped_url':
746 $options[ $key ] = $site->get_unmapped_url();
747 break;
748 case 'featured_images_enabled':
749 $options[ $key ] = $site->featured_images_enabled();
750 break;
751 case 'theme_slug':
752 $options[ $key ] = $site->get_theme_slug();
753 break;
754 case 'theme_errors':
755 $options[ $key ] = $site->get_theme_errors();
756 break;
757 case 'header_image':
758 $options[ $key ] = $site->get_header_image();
759 break;
760 case 'background_color':
761 $options[ $key ] = $site->get_background_color();
762 break;
763 case 'image_default_link_type':
764 $options[ $key ] = $site->get_image_default_link_type();
765 break;
766 case 'image_thumbnail_width':
767 $options[ $key ] = $site->get_image_thumbnail_width();
768 break;
769 case 'image_thumbnail_height':
770 $options[ $key ] = $site->get_image_thumbnail_height();
771 break;
772 case 'image_thumbnail_crop':
773 $options[ $key ] = $site->get_image_thumbnail_crop();
774 break;
775 case 'image_medium_width':
776 $options[ $key ] = $site->get_image_medium_width();
777 break;
778 case 'image_medium_height':
779 $options[ $key ] = $site->get_image_medium_height();
780 break;
781 case 'image_large_width':
782 $options[ $key ] = $site->get_image_large_width();
783 break;
784 case 'image_large_height':
785 $options[ $key ] = $site->get_image_large_height();
786 break;
787 case 'permalink_structure':
788 $options[ $key ] = $site->get_permalink_structure();
789 break;
790 case 'post_formats':
791 $options[ $key ] = $site->get_post_formats();
792 break;
793 case 'default_post_format':
794 $options[ $key ] = $site->get_default_post_format();
795 break;
796 case 'default_category':
797 $options[ $key ] = $site->get_default_category();
798 break;
799 case 'allowed_file_types':
800 $options[ $key ] = $site->allowed_file_types();
801 break;
802 case 'show_on_front':
803 $options[ $key ] = $site->get_show_on_front();
804 break;
805 /** This filter is documented in modules/likes.php */
806 case 'default_likes_enabled':
807 $options[ $key ] = $site->get_default_likes_enabled();
808 break;
809 case 'default_sharing_status':
810 $options[ $key ] = $site->get_default_sharing_status();
811 break;
812 case 'default_comment_status':
813 $options[ $key ] = $site->get_default_comment_status();
814 break;
815 case 'default_ping_status':
816 $options[ $key ] = $site->default_ping_status();
817 break;
818 case 'software_version':
819 $options[ $key ] = $site->get_wordpress_version();
820 break;
821 case 'created_at':
822 $options[ $key ] = $site->get_registered_date();
823 break;
824 case 'updated_at':
825 $options[ $key ] = $site->get_last_update_date();
826 break;
827 case 'wordads':
828 $options[ $key ] = $site->has_wordads();
829 break;
830 case 'publicize_permanently_disabled':
831 $options[ $key ] = $site->is_publicize_permanently_disabled();
832 break;
833 case 'frame_nonce':
834 $options[ $key ] = $site->get_frame_nonce();
835 break;
836 case 'jetpack_frame_nonce':
837 $options[ $key ] = $site->get_jetpack_frame_nonce();
838 break;
839 case 'page_on_front':
840 if ( $custom_front_page ) {
841 $options[ $key ] = $site->get_page_on_front();
842 }
843 break;
844 case 'page_for_posts':
845 if ( $custom_front_page ) {
846 $options[ $key ] = $site->get_page_for_posts();
847 }
848 break;
849 case 'headstart':
850 $options[ $key ] = $site->is_headstart();
851 break;
852 case 'headstart_is_fresh':
853 $options[ $key ] = $site->is_headstart_fresh();
854 break;
855 case 'ak_vp_bundle_enabled':
856 $options[ $key ] = $site->get_ak_vp_bundle_enabled();
857 break;
858 case Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION:
859 $options[ $key ] = $site->get_jetpack_seo_front_page_description();
860 break;
861 case Jetpack_SEO_Titles::TITLE_FORMATS_OPTION:
862 $options[ $key ] = $site->get_jetpack_seo_title_formats();
863 break;
864 case 'verification_services_codes':
865 $options[ $key ] = $site->get_verification_services_codes();
866 break;
867 case 'podcasting_archive':
868 $options[ $key ] = $site->get_podcasting_archive();
869 break;
870 case 'is_domain_only':
871 $options[ $key ] = $site->is_domain_only();
872 break;
873 case 'is_automated_transfer':
874 $options[ $key ] = $site->is_automated_transfer();
875 break;
876 case 'blog_public':
877 $options[ $key ] = $site->get_blog_public();
878 break;
879 case 'is_wpcom_atomic':
880 $options[ $key ] = $site->is_wpcom_atomic();
881 break;
882 case 'is_wpcom_store':
883 $options[ $key ] = $site->is_wpcom_store();
884 break;
885 case 'signup_is_store':
886 $signup_is_store = $site->signup_is_store();
887
888 if ( $signup_is_store ) {
889 $options[ $key ] = $site->signup_is_store();
890 }
891
892 break;
893 case 'has_pending_automated_transfer':
894 $has_pending_automated_transfer = $site->has_pending_automated_transfer();
895
896 if ( $has_pending_automated_transfer ) {
897 $options[ $key ] = true;
898 }
899
900 break;
901 case 'woocommerce_is_active':
902 $options[ $key ] = $site->woocommerce_is_active();
903 break;
904 case 'editing_toolkit_is_active':
905 $options[ $key ] = $site->editing_toolkit_is_active();
906 break;
907 case 'design_type':
908 $options[ $key ] = $site->get_design_type();
909 break;
910 case 'site_segment':
911 $options[ $key ] = $site->get_site_segment();
912 break;
913 case 'import_engine':
914 $options[ $key ] = $site->get_import_engine();
915 break;
916 case 'is_pending_plan':
917 $options[ $key ] = $site->is_pending_plan();
918 break;
919
920 case 'is_wpforteams_site':
921 $options[ $key ] = $site->is_wpforteams_site();
922 break;
923 case 'p2_hub_blog_id':
924 $options[ $key ] = $site->get_p2_hub_blog_id();
925 break;
926
927 case 'site_creation_flow':
928 $site_creation_flow = $site->get_site_creation_flow();
929 if ( $site_creation_flow ) {
930 $options[ $key ] = $site_creation_flow;
931 }
932 break;
933 case 'site_source_slug':
934 $site_source_slug = $site->get_site_source_slug();
935 if ( $site_source_slug ) {
936 $options[ $key ] = $site_source_slug;
937 }
938 break;
939 case 'is_cloud_eligible':
940 $options[ $key ] = $site->is_cloud_eligible();
941 break;
942 case 'selected_features':
943 $selected_features = $site->get_selected_features();
944 if ( $selected_features ) {
945 $options[ $key ] = $selected_features;
946 }
947 break;
948 case 'anchor_podcast':
949 $options[ $key ] = $site->get_anchor_podcast();
950 break;
951 case 'was_created_with_blank_canvas_design':
952 $options[ $key ] = $site->was_created_with_blank_canvas_design();
953 break;
954 case 'videopress_storage_used':
955 $options[ $key ] = $this->site->get_videopress_storage_used();
956 break;
957 case 'is_difm_lite_in_progress':
958 $options[ $key ] = $site->is_difm_lite_in_progress();
959 break;
960 case 'difm_lite_site_options':
961 $difm_lite_site_options = $site->get_difm_lite_site_options();
962 if ( null !== $difm_lite_site_options ) {
963 $options[ $key ] = (object) $difm_lite_site_options;
964 }
965 break;
966 case 'is_gating_business_q1':
967 $options[ $key ] = $site->is_gating_business_q1();
968 break;
969 case 'site_intent':
970 $options[ $key ] = $site->get_site_intent();
971 break;
972 case 'site_partner_bundle':
973 $options[ $key ] = $site->get_site_partner_bundle();
974 break;
975 case 'site_goals':
976 $options[ $key ] = $site->get_site_goals();
977 break;
978 case 'onboarding_segment':
979 $options[ $key ] = $site->get_onboarding_segment();
980 break;
981 case 'site_vertical_id':
982 $options[ $key ] = $site->get_site_vertical_id();
983 break;
984 case 'blogging_prompts_settings':
985 if ( current_user_can( 'edit_posts' ) ) {
986 $options[ $key ] = $site->get_blogging_prompts_settings( get_current_user_id(), $site->blog_id );
987 }
988 break;
989 case 'launchpad_screen':
990 $options[ $key ] = $site->get_launchpad_screen();
991 break;
992 case 'launchpad_checklist_tasks_statuses':
993 $options[ $key ] = $site->get_launchpad_checklist_tasks_statuses();
994 break;
995 case 'migration_source_site_domain':
996 $options[ $key ] = $site->get_migration_source_site_domain();
997 break;
998 case 'wpcom_production_blog_id':
999 $options[ $key ] = $site->get_wpcom_production_blog_id();
1000 break;
1001 case 'wpcom_staging_blog_ids':
1002 $options[ $key ] = $site->get_wpcom_staging_blog_ids();
1003 break;
1004 case 'can_blaze':
1005 $options[ $key ] = $site->can_blaze();
1006 break;
1007 case 'wpcom_site_setup':
1008 $options[ $key ] = $site->get_wpcom_site_setup();
1009 break;
1010 case 'is_commercial':
1011 $options[ $key ] = $site->is_commercial();
1012 break;
1013 case 'is_commercial_reasons':
1014 $options[ $key ] = $site->get_is_commercial_reasons();
1015 break;
1016 case 'wpcom_admin_interface':
1017 $options[ $key ] = $site->get_wpcom_admin_interface();
1018 break;
1019 case 'wpcom_classic_early_release':
1020 $options[ $key ] = $site->get_wpcom_classic_early_release();
1021 break;
1022 case 'jetpack_recovery_mode_status':
1023 $options[ $key ] = $site->get_jetpack_recovery_mode_status();
1024 break;
1025 case 'apm_enabled':
1026 $options[ $key ] = $site->get_apm_enabled();
1027 break;
1028 case 'wpcom_ai_launchpad_enabled':
1029 $options[ $key ] = $site->is_ai_launchpad_enabled();
1030 break;
1031 case 'wpcom_ai_launchpad_dismissed':
1032 $options[ $key ] = $site->is_ai_launchpad_dismissed();
1033 break;
1034 case 'wpcom_ai_launchpad_completed':
1035 $options[ $key ] = $site->is_ai_launchpad_completed();
1036 break;
1037 }
1038 }
1039
1040 return $options;
1041 }
1042
1043 /**
1044 * Build meta response.
1045 *
1046 * @param array $response - the response.
1047 */
1048 protected function build_meta_response( &$response ) {
1049 $links = array(
1050 'self' => (string) $this->links->get_site_link( $this->site->blog_id ),
1051 'help' => (string) $this->links->get_site_link( $this->site->blog_id, 'help' ),
1052 'posts' => (string) $this->links->get_site_link( $this->site->blog_id, 'posts/' ),
1053 'comments' => (string) $this->links->get_site_link( $this->site->blog_id, 'comments/' ),
1054 'xmlrpc' => (string) $this->site->get_xmlrpc_url(),
1055 );
1056
1057 $icon = $this->site->get_icon();
1058 if ( ! empty( $icon ) && ! empty( $icon['media_id'] ) ) {
1059 $links['site_icon'] = (string) $this->links->get_site_link( $this->site->blog_id, 'media/' . $icon['media_id'] );
1060 }
1061
1062 $response['meta'] = (object) array(
1063 'links' => (object) $links,
1064 );
1065 }
1066
1067 /**
1068 * Apply any WPCOM-only response components to a Jetpack site response.
1069 *
1070 * @param object $response - the response.
1071 */
1072 public function decorate_jetpack_response( &$response ) {
1073 $this->filter_fields_and_options();
1074 $this->site = $this->get_platform()->get_site( $response->ID );
1075 switch_to_blog( $this->site->get_id() );
1076
1077 // Allow the SAL site to apply its own overrides to the proxied response.
1078 if ( method_exists( $this->site, 'decorate_jetpack_response' ) ) {
1079 $this->site->decorate_jetpack_response( $response ); // @phan-suppress-current-line PhanUndeclaredMethod -- checked via method_exists().
1080 }
1081
1082 $wpcom_response = $this->render_response_keys( self::$jetpack_response_field_additions );
1083
1084 foreach ( $wpcom_response as $key => $value ) {
1085 $response->{ $key } = $value;
1086 }
1087
1088 $has_site_access = $this->has_user_access() || $this->has_blog_access( $this->api->token_details );
1089
1090 if ( $has_site_access ) {
1091 $wpcom_member_response = $this->render_response_keys( self::$jetpack_response_field_member_additions );
1092
1093 foreach ( $wpcom_member_response as $key => $value ) {
1094 $response->{ $key } = $value;
1095 }
1096 } else {
1097 // ensure private data is not rendered for non members of the site.
1098 unset( $response->options );
1099 unset( $response->is_vip );
1100 unset( $response->single_user_site );
1101 unset( $response->is_private );
1102 unset( $response->is_coming_soon );
1103 unset( $response->capabilities );
1104 unset( $response->lang );
1105 unset( $response->user_can_manage );
1106 unset( $response->is_multisite );
1107 unset( $response->site_owner );
1108 unset( $response->plan );
1109 unset( $response->products );
1110 unset( $response->zendesk_site_meta );
1111 unset( $response->atomic_email_block );
1112 }
1113
1114 // render additional options.
1115 if ( isset( $response->options ) && $response->options ) {
1116 $wpcom_options_response = $this->render_option_keys( self::$jetpack_response_option_additions );
1117
1118 // Remove heic from jetpack (and atomic) sites so that the iOS app know to convert the file format into a JPEG.
1119 // heic fromat is currently not supported by for uploading.
1120 // See https://jetpackp2.wordpress.com/2020/08/19/image-uploads-in-the-wp-ios-app-broken
1121 if (
1122 $this->site->is_jetpack()
1123 && isset( $response->options['allowed_file_types'] )
1124 && is_array( $response->options['allowed_file_types'] )
1125 ) {
1126 $allowed_file_types = (array) $response->options['allowed_file_types'];
1127 $remove_file_types = array(
1128 'heic',
1129 );
1130 $response->options['allowed_file_types'] = array_values( array_diff( $allowed_file_types, $remove_file_types ) );
1131 }
1132
1133 foreach ( $wpcom_options_response as $key => $value ) {
1134 $response->options[ $key ] = $value;
1135 }
1136 }
1137
1138 // WordPress.com platform fields are not part of proxied Jetpack responses;
1139 // add them only when explicitly requested.
1140 if ( $this->is_wpcom() && $has_site_access && is_array( $this->fields_to_include ) ) {
1141 if ( function_exists( 'get_jetpack_hosting_provider' ) && in_array( 'hosting_provider_guess', $this->fields_to_include, true ) ) {
1142 $response->hosting_provider_guess = get_jetpack_hosting_provider( get_current_blog_id() );
1143 }
1144 if ( in_array( 'environment_type', $this->fields_to_include, true ) ) {
1145 $response->environment_type = $this->get_site_environment_type();
1146 }
1147 }
1148
1149 restore_current_blog();
1150 return $response; // possibly no need since it's modified in place.
1151 }
1152
1153 /**
1154 * Whether this request is running on the WordPress.com platform.
1155 *
1156 * @return bool
1157 */
1158 protected function is_wpcom() {
1159 return ( new \Automattic\Jetpack\Status\Host() )->is_wpcom_platform();
1160 }
1161
1162 /**
1163 * Get the site's synced WP_ENVIRONMENT_TYPE.
1164 *
1165 * @return string|null
1166 */
1167 protected function get_site_environment_type() {
1168 if ( function_exists( 'get_blog_option' ) ) {
1169 return get_blog_option( get_current_blog_id(), 'jetpack_callable_wp_get_environment_type', null );
1170 }
1171
1172 return get_option( 'jetpack_callable_wp_get_environment_type', null );
1173 }
1174 }
1175
1176 new WPCOM_JSON_API_List_Post_Formats_Endpoint(
1177 array(
1178 'description' => 'Get a list of post formats supported by a site.',
1179 'group' => '__do_not_document',
1180 'stat' => 'sites:X:post-formats',
1181
1182 'method' => 'GET',
1183 'path' => '/sites/%s/post-formats',
1184 'path_labels' => array(
1185 '$site' => '(int|string) Site ID or domain',
1186 ),
1187
1188 'query_parameters' => array(
1189 'context' => false,
1190 ),
1191
1192 'allow_fallback_to_jetpack_blog_token' => true,
1193
1194 'response_format' => array(
1195 'formats' => '(object) An object of supported post formats, each key a supported format slug mapped to its display string.',
1196 ),
1197 )
1198 );
1199
1200 /**
1201 * List Post Formats endpoint class.
1202 *
1203 * @phan-constructor-used-for-side-effects
1204 */
1205 class WPCOM_JSON_API_List_Post_Formats_Endpoint extends WPCOM_JSON_API_Endpoint { // phpcs:ignore
1206 /**
1207 *
1208 * API callback.
1209 *
1210 * /sites/%s/post-formats -> $blog_id
1211 *
1212 * @param string $path - the path.
1213 * @param int $blog_id - the blog ID.
1214 *
1215 * @return array|\WP_Error Array with 'formats' on success, or WP_Error on failure.
1216 */
1217 public function callback( $path = '', $blog_id = 0 ) {
1218 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
1219 if ( is_wp_error( $blog_id ) ) {
1220 return $blog_id;
1221 }
1222
1223 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1224 $this->load_theme_functions();
1225 }
1226
1227 // Get a list of supported post formats.
1228 $all_formats = get_post_format_strings();
1229 $supported = get_theme_support( 'post-formats' );
1230
1231 $response = array(
1232 'formats' => array(),
1233 );
1234 $supported_formats = $response['formats'];
1235
1236 if ( isset( $supported[0] ) ) {
1237 foreach ( $supported[0] as $format ) {
1238 $supported_formats[ $format ] = $all_formats[ $format ];
1239 }
1240 }
1241
1242 $response['formats'] = (object) $supported_formats;
1243
1244 return $response;
1245 }
1246 }
1247
1248 new WPCOM_JSON_API_List_Page_Templates_Endpoint(
1249 array(
1250 'description' => 'Get a list of page templates supported by a site.',
1251 'group' => 'sites',
1252 'stat' => 'sites:X:post-templates',
1253
1254 'method' => 'GET',
1255 'path' => '/sites/%s/page-templates',
1256 'path_labels' => array(
1257 '$site' => '(int|string) Site ID or domain',
1258 ),
1259 'query_parameters' => array(
1260 'context' => false,
1261 ),
1262 'response_format' => array(
1263 'templates' => '(array) A list of supported page templates. Contains label and file.',
1264 ),
1265 'example_request' => 'https://public-api.wordpress.com/rest/v1.1/sites/33534099/page-templates',
1266 )
1267 );
1268
1269 /**
1270 * List page templates endpoint class.
1271 *
1272 * @phan-constructor-used-for-side-effects
1273 */
1274 class WPCOM_JSON_API_List_Page_Templates_Endpoint extends WPCOM_JSON_API_Endpoint { // phpcs:ignore
1275 /**
1276 *
1277 * API callback.
1278 * /sites/%s/page-templates -> $blog_id
1279 *
1280 * @param string $path - the path.
1281 * @param int $blog_id - the blog ID.
1282 *
1283 * @return array|\WP_Error Array with 'templates' on success, or WP_Error on failure.
1284 */
1285 public function callback( $path = '', $blog_id = 0 ) {
1286 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
1287 if ( is_wp_error( $blog_id ) ) {
1288 return $blog_id;
1289 }
1290
1291 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1292 $this->load_theme_functions();
1293 }
1294
1295 $response = array();
1296 $page_templates = array();
1297
1298 $templates = get_page_templates();
1299 ksort( $templates );
1300
1301 foreach ( array_keys( $templates ) as $label ) {
1302 $page_templates[] = array(
1303 'label' => $label,
1304 'file' => $templates[ $label ],
1305 );
1306 }
1307
1308 $response['templates'] = $page_templates;
1309
1310 return $response;
1311 }
1312 }
1313