PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 All 507 releases
← All changes | json-endpoints/class.wpcom-json-api-get-site-endpoint.php +232 -44 12.9.5 → 16.3-beta View file →
@@ -1,6 +1,10 @@
1 1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 2
3 +if ( ! defined( 'ABSPATH' ) ) {
4 + exit( 0 );
5 +}
6 +
3 7 new WPCOM_JSON_API_GET_Site_Endpoint(
4 8 array(
5 9 'description' => 'Get information about a site.',
6 10 'group' => 'sites',
@@ -12,8 +16,10 @@
12 16 'path' => '/sites/%s',
13 17 'path_labels' => array(
14 18 '$site' => '(int|string) Site ID or domain',
15 19 ),
20 + 'rest_route' => '/site',
21 + 'rest_min_jp_version' => '15.9',
16 22 'allow_jetpack_site_auth' => true,
17 23
18 24 'allow_fallback_to_jetpack_blog_token' => true,
19 25
@@ -29,8 +35,10 @@
29 35 );
30 36
31 37 /**
32 38 * GET Site endpoint class.
39 + *
40 + * @phan-constructor-used-for-side-effects
33 41 */
34 42 class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
35 43
36 44 /**
@@ -39,8 +47,9 @@
39 47 * @var array $site_format
40 48 */
41 49 public static $site_format = array(
42 50 'ID' => '(int) Site ID',
51 + 'slug' => '(string) Slug of site',
43 52 'name' => '(string) Title of site',
44 53 'description' => '(string) Tagline or description of site',
45 54 'URL' => '(string) Full URL to the site',
46 55 'user_can_manage' => '(bool) The current user can manage this site', // deprecated.
@@ -78,11 +87,24 @@
78 87 'is_wpcom_atomic' => '(bool) If the site is a WP.com Atomic one.',
79 88 'is_wpcom_staging_site' => '(bool) If the site is a WP.com staging site.',
80 89 'user_interactions' => '(array) An array of user interactions with a site.',
81 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.',
82 92 'was_migration_trial' => '(bool) If the site ever used a migration trial.',
83 93 'was_hosting_trial' => '(bool) If the site ever used a hosting trial.',
84 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.',
85 107 );
86 108
87 109 /**
88 110 * No member fields.
@@ -114,8 +136,15 @@
114 136 'is_fse_eligible',
115 137 'is_core_site_editor_enabled',
116 138 'is_wpcom_atomic',
117 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',
118 147 );
119 148
120 149 /**
121 150 * Site options.
@@ -134,8 +163,9 @@
134 163 'is_redirect',
135 164 'unmapped_url',
136 165 'featured_images_enabled',
137 166 'theme_slug',
167 + 'theme_errors',
138 168 'header_image',
139 169 'background_color',
140 170 'image_default_link_type',
141 171 'image_thumbnail_width',
@@ -195,38 +225,42 @@
195 225 'was_created_with_blank_canvas_design',
196 226 'videopress_storage_used',
197 227 'is_difm_lite_in_progress',
198 228 'difm_lite_site_options',
229 + 'is_gating_business_q1',
230 + 'is_legacy_gating_site',
199 231 'site_intent',
232 + 'site_partner_bundle',
233 + 'onboarding_segment',
200 234 'site_vertical_id',
201 235 'blogging_prompts_settings',
202 236 'launchpad_screen',
203 237 'launchpad_checklist_tasks_statuses',
238 + 'migration_source_site_domain',
204 239 'wpcom_production_blog_id',
205 240 'wpcom_staging_blog_ids',
206 241 'can_blaze',
207 242 'wpcom_site_setup',
208 243 'is_commercial',
244 + 'is_commercial_reasons',
209 245 'wpcom_admin_interface',
246 + 'wpcom_classic_early_release',
247 + 'jetpack_recovery_mode_status',
248 + 'jetpack_sso_require_two_step',
249 + 'apm_enabled',
250 + 'wpcom_ai_launchpad_enabled',
251 + 'wpcom_ai_launchpad_dismissed',
252 + 'wpcom_ai_launchpad_completed',
253 + 'wpcom_ai_launchpad_no_guidance',
210 254 );
211 255
212 256 /**
213 - * List of DIFM Lite options to be displayed
214 - *
215 - * @var array $displayed_difm_lite_site_options
216 - */
217 - protected static $displayed_difm_lite_site_options = array(
218 - 'site_category',
219 - 'is_website_content_submitted',
220 - 'selected_page_titles',
221 - );
222 -
223 - /**
224 257 * Jetpack response fields.
225 258 *
226 259 * @var array $jetpack_response_field_additions
227 260 */
228 261 protected static $jetpack_response_field_additions = array(
262 + 'slug',
229 263 'subscribers_count',
230 264 'site_migration',
231 265 'site_owner',
232 266 'is_wpcom_staging_site',
@@ -232,8 +266,17 @@
232 266 'is_wpcom_staging_site',
233 267 'was_ecommerce_trial',
234 268 'was_migration_trial',
235 269 'was_hosting_trial',
270 + 'was_upgraded_from_trial',
271 + 'is_a4a_dev_site',
272 + 'is_garden',
273 + 'garden_name',
274 + 'garden_partner',
275 + 'garden_is_provisioned',
276 + 'is_wpcom_flex',
277 + 'big_sky_enabled',
278 + 'atomic_email_block',
236 279 );
237 280
238 281 /**
239 282 * Jetpack response field member additions.
@@ -249,9 +292,9 @@
249 292
250 293 /**
251 294 * Jetpack response option additions.
252 295 *
253 - * @var array $jetpack_response_field_member_additions
296 + * @var array $jetpack_response_option_additions
254 297 */
255 298 protected static $jetpack_response_option_additions = array(
256 299 'publicize_permanently_disabled',
257 300 'ak_vp_bundle_enabled',
@@ -275,9 +318,14 @@
275 318 'blogging_prompts_settings',
276 319 'wpcom_production_blog_id',
277 320 'wpcom_staging_blog_ids',
278 321 'is_commercial',
322 + 'is_commercial_reasons',
279 323 'wpcom_admin_interface',
324 + 'wpcom_classic_early_release',
325 + 'jetpack_recovery_mode_status',
326 + 'jetpack_sso_require_two_step',
327 + 'apm_enabled',
280 328 );
281 329
282 330 /**
283 331 * Current enabled trials.
@@ -290,11 +338,11 @@
290 338 'was_hosting_trial' => 'hosting',
291 339 );
292 340
293 341 /**
294 - * Site
342 + * Site.
295 343 *
296 - * @var $site.
344 + * @var SAL_Site $site.
297 345 */
298 346 private $site;
299 347
300 348 /**
@@ -317,10 +365,12 @@
317 365 *
318 366 * /sites/mine
319 367 * /sites/%s -> $blog_id\
320 368 *
321 - * @param string $path - the path.
322 - * @param int $blog_id - the blog ID.
369 + * @param string $path - the path.
370 + * @param int|string $blog_id - the blog ID or the string 'mine'.
371 + *
372 + * @return array|\WP_Error Site response array on success, or WP_Error on failure.
323 373 */
324 374 public function callback( $path = '', $blog_id = 0 ) {
325 375 if ( 'mine' === $blog_id ) {
326 376 $api = WPCOM_JSON_API::init();
@@ -456,8 +506,11 @@
456 506 switch ( $key ) {
457 507 case 'ID':
458 508 $response[ $key ] = $this->site->blog_id;
459 509 break;
510 + case 'slug':
511 + $response[ $key ] = $this->site->get_slug();
512 + break;
460 513 case 'name':
461 514 $response[ $key ] = $this->site->get_name();
462 515 break;
463 516 case 'description':
@@ -563,13 +616,9 @@
563 616 case 'products':
564 617 $response[ $key ] = $this->site->get_products();
565 618 break;
566 619 case 'zendesk_site_meta':
567 - // D59613-code only added this function to the wpcom SAL subclasses. Absent any better idea,
568 - // we'll just omit the key entirely in Jetpack.
569 - if ( is_callable( array( $this->site, 'get_zendesk_site_meta' ) ) ) {
570 - $response[ $key ] = $this->site->get_zendesk_site_meta();
571 - }
620 + $response[ $key ] = $this->site->get_zendesk_site_meta();
572 621 break;
573 622 case 'quota':
574 623 $response[ $key ] = $this->site->get_quota();
575 624 break;
@@ -605,8 +654,57 @@
605 654 break;
606 655 case 'was_hosting_trial':
607 656 $response[ $key ] = $this->site->was_trial( self::$jetpack_enabled_trials['was_hosting_trial'] );
608 657 break;
658 + case 'was_upgraded_from_trial':
659 + $response[ $key ] = $this->site->was_upgraded_from_trial();
660 + break;
661 + case 'is_deleted':
662 + $response[ $key ] = $this->site->is_deleted();
663 + break;
664 + case 'is_a4a_client':
665 + $response[ $key ] = $this->site->is_a4a_client();
666 + break;
667 + case 'is_a4a_dev_site':
668 + $response[ $key ] = $this->site->is_a4a_dev_site();
669 + break;
670 + case 'is_garden':
671 + $response[ $key ] = $this->site->is_garden();
672 + break;
673 + case 'garden_name':
674 + $response[ $key ] = $this->site->garden_name();
675 + break;
676 + case 'garden_partner':
677 + $response[ $key ] = $this->site->garden_partner();
678 + break;
679 + case 'garden_is_provisioned':
680 + $response[ $key ] = $this->site->garden_is_provisioned();
681 + break;
682 + case 'is_wpcom_flex':
683 + $response[ $key ] = $this->site->is_wpcom_flex();
684 + break;
685 + case 'big_sky_enabled':
686 + $response[ $key ] = $this->site->is_big_sky_enabled();
687 + break;
688 + case 'atomic_email_block':
689 + $response[ $key ] = $this->site->get_atomic_email_block();
690 + break;
691 + case 'hosting_provider_guess':
692 + // WordPress.com platform decoration, computed only when explicitly requested
693 + // via `fields` so default `_all` responses are unchanged.
694 + if ( $this->is_wpcom()
695 + && function_exists( 'get_jetpack_hosting_provider' )
696 + && is_array( $this->fields_to_include ) ) {
697 + $response[ $key ] = get_jetpack_hosting_provider( get_current_blog_id() );
698 + }
699 + break;
700 + case 'environment_type':
701 + // WordPress.com platform decoration, computed only when explicitly requested
702 + // via `fields` so default `_all` responses are unchanged.
703 + if ( $this->is_wpcom() && is_array( $this->fields_to_include ) ) {
704 + $response[ $key ] = $this->get_site_environment_type();
705 + }
706 + break;
609 707 }
610 708
611 709 do_action( 'post_render_site_response_key', $key );
612 710 }
@@ -656,8 +754,11 @@
656 754 break;
657 755 case 'theme_slug':
658 756 $options[ $key ] = $site->get_theme_slug();
659 757 break;
758 + case 'theme_errors':
759 + $options[ $key ] = $site->get_theme_errors();
760 + break;
660 761 case 'header_image':
661 762 $options[ $key ] = $site->get_header_image();
662 763 break;
663 764 case 'background_color':
@@ -816,13 +917,9 @@
816 917 case 'import_engine':
817 918 $options[ $key ] = $site->get_import_engine();
818 919 break;
819 920 case 'is_pending_plan':
820 - // D40032-code only added this function to the wpcom SAL subclasses. Absent any better idea,
821 - // we'll just omit the key entirely in Jetpack.
822 - if ( is_callable( array( $site, 'is_pending_plan' ) ) ) {
823 - $options[ $key ] = $site->is_pending_plan();
824 - }
921 + $options[ $key ] = $site->is_pending_plan();
825 922 break;
826 923
827 924 case 'is_wpforteams_site':
828 925 $options[ $key ] = $site->is_wpforteams_site();
@@ -864,25 +961,31 @@
864 961 case 'is_difm_lite_in_progress':
865 962 $options[ $key ] = $site->is_difm_lite_in_progress();
866 963 break;
867 964 case 'difm_lite_site_options':
868 - $difm_lite_options = $site->get_difm_lite_site_options();
869 - $visible_options = self::$displayed_difm_lite_site_options;
870 - $filtered_difm_lite_options = new stdClass();
871 - if ( $difm_lite_options ) {
872 - $filtered_difm_lite_options = array_filter(
873 - $difm_lite_options,
874 - function ( $key ) use ( $visible_options ) {
875 - return in_array( $key, $visible_options, true );
876 - },
877 - ARRAY_FILTER_USE_KEY
878 - );
965 + $difm_lite_site_options = $site->get_difm_lite_site_options();
966 + if ( null !== $difm_lite_site_options ) {
967 + $options[ $key ] = (object) $difm_lite_site_options;
879 968 }
880 - $options[ $key ] = $filtered_difm_lite_options;
881 969 break;
970 + case 'is_gating_business_q1':
971 + $options[ $key ] = $site->is_gating_business_q1();
972 + break;
973 + case 'is_legacy_gating_site':
974 + $options[ $key ] = $site->is_legacy_gating_site();
975 + break;
882 976 case 'site_intent':
883 977 $options[ $key ] = $site->get_site_intent();
884 978 break;
979 + case 'site_partner_bundle':
980 + $options[ $key ] = $site->get_site_partner_bundle();
981 + break;
982 + case 'site_goals':
983 + $options[ $key ] = $site->get_site_goals();
984 + break;
985 + case 'onboarding_segment':
986 + $options[ $key ] = $site->get_onboarding_segment();
987 + break;
885 988 case 'site_vertical_id':
886 989 $options[ $key ] = $site->get_site_vertical_id();
887 990 break;
888 991 case 'blogging_prompts_settings':
@@ -895,8 +998,11 @@
895 998 break;
896 999 case 'launchpad_checklist_tasks_statuses':
897 1000 $options[ $key ] = $site->get_launchpad_checklist_tasks_statuses();
898 1001 break;
1002 + case 'migration_source_site_domain':
1003 + $options[ $key ] = $site->get_migration_source_site_domain();
1004 + break;
899 1005 case 'wpcom_production_blog_id':
900 1006 $options[ $key ] = $site->get_wpcom_production_blog_id();
901 1007 break;
902 1008 case 'wpcom_staging_blog_ids':
@@ -910,11 +1016,38 @@
910 1016 break;
911 1017 case 'is_commercial':
912 1018 $options[ $key ] = $site->is_commercial();
913 1019 break;
1020 + case 'is_commercial_reasons':
1021 + $options[ $key ] = $site->get_is_commercial_reasons();
1022 + break;
914 1023 case 'wpcom_admin_interface':
915 1024 $options[ $key ] = $site->get_wpcom_admin_interface();
916 1025 break;
1026 + case 'wpcom_classic_early_release':
1027 + $options[ $key ] = $site->get_wpcom_classic_early_release();
1028 + break;
1029 + case 'jetpack_recovery_mode_status':
1030 + $options[ $key ] = $site->get_jetpack_recovery_mode_status();
1031 + break;
1032 + case 'jetpack_sso_require_two_step':
1033 + $options[ $key ] = $site->get_jetpack_sso_require_two_step();
1034 + break;
1035 + case 'apm_enabled':
1036 + $options[ $key ] = $site->get_apm_enabled();
1037 + break;
1038 + case 'wpcom_ai_launchpad_enabled':
1039 + $options[ $key ] = $site->is_ai_launchpad_enabled();
1040 + break;
1041 + case 'wpcom_ai_launchpad_dismissed':
1042 + $options[ $key ] = $site->is_ai_launchpad_dismissed();
1043 + break;
1044 + case 'wpcom_ai_launchpad_completed':
1045 + $options[ $key ] = $site->is_ai_launchpad_completed();
1046 + break;
1047 + case 'wpcom_ai_launchpad_no_guidance':
1048 + $options[ $key ] = $site->is_ai_launchpad_no_guidance();
1049 + break;
917 1050 }
918 1051 }
919 1052
920 1053 return $options;
@@ -946,14 +1079,20 @@
946 1079
947 1080 /**
948 1081 * Apply any WPCOM-only response components to a Jetpack site response.
949 1082 *
950 - * @param array $response - the response.
1083 + * @param object $response - the response.
951 1084 */
952 1085 public function decorate_jetpack_response( &$response ) {
1086 + $this->filter_fields_and_options();
953 1087 $this->site = $this->get_platform()->get_site( $response->ID );
954 1088 switch_to_blog( $this->site->get_id() );
955 1089
1090 + // Allow the SAL site to apply its own overrides to the proxied response.
1091 + if ( method_exists( $this->site, 'decorate_jetpack_response' ) ) {
1092 + $this->site->decorate_jetpack_response( $response ); // @phan-suppress-current-line PhanUndeclaredMethod -- checked via method_exists().
1093 + }
1094 +
956 1095 $wpcom_response = $this->render_response_keys( self::$jetpack_response_field_additions );
957 1096
958 1097 foreach ( $wpcom_response as $key => $value ) {
959 1098 $response->{ $key } = $value;
@@ -958,9 +1097,11 @@
958 1097 foreach ( $wpcom_response as $key => $value ) {
959 1098 $response->{ $key } = $value;
960 1099 }
961 1100
962 - if ( $this->has_user_access() || $this->has_blog_access( $this->api->token_details ) ) {
1101 + $has_site_access = $this->has_user_access() || $this->has_blog_access( $this->api->token_details );
1102 +
1103 + if ( $has_site_access ) {
963 1104 $wpcom_member_response = $this->render_response_keys( self::$jetpack_response_field_member_additions );
964 1105
965 1106 foreach ( $wpcom_member_response as $key => $value ) {
966 1107 $response->{ $key } = $value;
@@ -979,22 +1120,28 @@
979 1120 unset( $response->site_owner );
980 1121 unset( $response->plan );
981 1122 unset( $response->products );
982 1123 unset( $response->zendesk_site_meta );
1124 + unset( $response->atomic_email_block );
983 1125 }
984 1126
985 1127 // render additional options.
986 - if ( $response->options ) {
1128 + if ( isset( $response->options ) && $response->options ) {
987 1129 $wpcom_options_response = $this->render_option_keys( self::$jetpack_response_option_additions );
988 1130
989 1131 // Remove heic from jetpack (and atomic) sites so that the iOS app know to convert the file format into a JPEG.
990 1132 // heic fromat is currently not supported by for uploading.
991 1133 // See https://jetpackp2.wordpress.com/2020/08/19/image-uploads-in-the-wp-ios-app-broken
992 - if ( $this->site->is_jetpack() && isset( $response->options['allowed_file_types'] ) ) {
1134 + if (
1135 + $this->site->is_jetpack()
1136 + && isset( $response->options['allowed_file_types'] )
1137 + && is_array( $response->options['allowed_file_types'] )
1138 + ) {
1139 + $allowed_file_types = (array) $response->options['allowed_file_types'];
993 1140 $remove_file_types = array(
994 1141 'heic',
995 1142 );
996 - $response->options['allowed_file_types'] = array_values( array_diff( $response->options['allowed_file_types'], $remove_file_types ) );
1143 + $response->options['allowed_file_types'] = array_values( array_diff( $allowed_file_types, $remove_file_types ) );
997 1144 }
998 1145
999 1146 foreach ( $wpcom_options_response as $key => $value ) {
1000 1147 $response->options[ $key ] = $value;
@@ -1000,11 +1147,44 @@
1000 1147 $response->options[ $key ] = $value;
1001 1148 }
1002 1149 }
1003 1150
1151 + // WordPress.com platform fields are not part of proxied Jetpack responses;
1152 + // add them only when explicitly requested.
1153 + if ( $this->is_wpcom() && $has_site_access && is_array( $this->fields_to_include ) ) {
1154 + if ( function_exists( 'get_jetpack_hosting_provider' ) && in_array( 'hosting_provider_guess', $this->fields_to_include, true ) ) {
1155 + $response->hosting_provider_guess = get_jetpack_hosting_provider( get_current_blog_id() );
1156 + }
1157 + if ( in_array( 'environment_type', $this->fields_to_include, true ) ) {
1158 + $response->environment_type = $this->get_site_environment_type();
1159 + }
1160 + }
1161 +
1004 1162 restore_current_blog();
1005 1163 return $response; // possibly no need since it's modified in place.
1006 1164 }
1165 +
1166 + /**
1167 + * Whether this request is running on the WordPress.com platform.
1168 + *
1169 + * @return bool
1170 + */
1171 + protected function is_wpcom() {
1172 + return ( new \Automattic\Jetpack\Status\Host() )->is_wpcom_platform();
1173 + }
1174 +
1175 + /**
1176 + * Get the site's synced WP_ENVIRONMENT_TYPE.
1177 + *
1178 + * @return string|null
1179 + */
1180 + protected function get_site_environment_type() {
1181 + if ( function_exists( 'get_blog_option' ) ) {
1182 + return get_blog_option( get_current_blog_id(), 'jetpack_callable_wp_get_environment_type', null );
1183 + }
1184 +
1185 + return get_option( 'jetpack_callable_wp_get_environment_type', null );
1186 + }
1007 1187 }
1008 1188
1009 1189 new WPCOM_JSON_API_List_Post_Formats_Endpoint(
1010 1190 array(
@@ -1030,9 +1210,11 @@
1030 1210 )
1031 1211 );
1032 1212
1033 1213 /**
1034 - * List Post Formates endpoint class.
1214 + * List Post Formats endpoint class.
1215 + *
1216 + * @phan-constructor-used-for-side-effects
1035 1217 */
1036 1218 class WPCOM_JSON_API_List_Post_Formats_Endpoint extends WPCOM_JSON_API_Endpoint { // phpcs:ignore
1037 1219 /**
1038 1220 *
@@ -1041,8 +1223,10 @@
1041 1223 * /sites/%s/post-formats -> $blog_id
1042 1224 *
1043 1225 * @param string $path - the path.
1044 1226 * @param int $blog_id - the blog ID.
1227 + *
1228 + * @return array|\WP_Error Array with 'formats' on success, or WP_Error on failure.
1045 1229 */
1046 1230 public function callback( $path = '', $blog_id = 0 ) {
1047 1231 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
1048 1232 if ( is_wp_error( $blog_id ) ) {
@@ -1096,8 +1280,10 @@
1096 1280 );
1097 1281
1098 1282 /**
1099 1283 * List page templates endpoint class.
1284 + *
1285 + * @phan-constructor-used-for-side-effects
1100 1286 */
1101 1287 class WPCOM_JSON_API_List_Page_Templates_Endpoint extends WPCOM_JSON_API_Endpoint { // phpcs:ignore
1102 1288 /**
1103 1289 *
@@ -1105,8 +1291,10 @@
1105 1291 * /sites/%s/page-templates -> $blog_id
1106 1292 *
1107 1293 * @param string $path - the path.
1108 1294 * @param int $blog_id - the blog ID.
1295 + *
1296 + * @return array|\WP_Error Array with 'templates' on success, or WP_Error on failure.
1109 1297 */
1110 1298 public function callback( $path = '', $blog_id = 0 ) {
1111 1299 $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
1112 1300 if ( is_wp_error( $blog_id ) ) {