diff options
Diffstat (limited to 'plugins/jetpack/_inc/lib/core-api')
3 files changed, 177 insertions, 38 deletions
diff --git a/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php b/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php index 2b26f78c..f9e1fb44 100644 --- a/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php +++ b/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php @@ -35,6 +35,11 @@ function wpcom_rest_api_v2_load_plugin( $class_name ) { require dirname( __FILE__ ) . '/class-wpcom-rest-field-controller.php'; -// Now load the endpoint files. -wpcom_rest_api_v2_load_plugin_files( 'wpcom-endpoints/*.php' ); -wpcom_rest_api_v2_load_plugin_files( 'wpcom-fields/*.php' ); +/** + * Load the REST API v2 plugin files during the plugins_loaded action. + */ +function load_wpcom_rest_api_v2_plugin_files() { + wpcom_rest_api_v2_load_plugin_files( 'wpcom-endpoints/*.php' ); + wpcom_rest_api_v2_load_plugin_files( 'wpcom-fields/*.php' ); +} +add_action( 'plugins_loaded', 'load_wpcom_rest_api_v2_plugin_files' ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-resolve-redirect.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-resolve-redirect.php index 442a2efa..c3777f6d 100644 --- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-resolve-redirect.php +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-resolve-redirect.php @@ -36,7 +36,9 @@ class WPCOM_REST_API_V2_Endpoint_Resolve_Redirect extends WP_REST_Controller { 'description' => __( 'The URL to check for redirects.', 'jetpack' ), 'type' => 'string', 'required' => 'true', - 'validate_callback' => 'wp_http_validate_url', + 'validate_callback' => function ( $param ) { + return wp_http_validate_url( $param ); + }, ), ), array( @@ -50,45 +52,83 @@ class WPCOM_REST_API_V2_Endpoint_Resolve_Redirect extends WP_REST_Controller { } /** - * Follows 301/302 redirect for the passed URL, and returns the final destination. + * Follows 301/302 redirect for the passed URL, and returns the final destination and status code. * * @param WP_REST_Request $request The REST API request data. * @return WP_REST_Response The REST API response. */ public function follow_redirect( $request ) { - $response = wp_safe_remote_get( $request['url'] ); - if ( is_wp_error( $response ) ) { - return rest_ensure_response( '' ); - } - - $history = $response['http_response']->get_response_object()->history; - if ( ! $history ) { - return response_ensure_response( $request['url'] ); - } + // Add a User-Agent header since the request is sometimes blocked without it. + $response = wp_safe_remote_get( + $request['url'], + array( + 'headers' => array( + 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:71.0) Gecko/20100101 Firefox/71.0', + ), + ) + ); - $location = $history[0]->headers->getValues( 'location' ); - if ( ! $location ) { - return response_ensure_response( $request['url'] ); + if ( is_wp_error( $response ) ) { + return rest_ensure_response( + array( + 'url' => '', + 'status' => $response->get_error_code(), + ) + ); } - return rest_ensure_response( $location[0] ); + return rest_ensure_response( + array( + 'url' => $this->get_response_url( $response['http_response']->get_response_object() ), + 'status' => wp_remote_retrieve_response_code( $response ), + ) + ); } /** - * Retrieves the comment's schema, conforming to JSON Schema. + * Retrieves the response schema, conforming to JSON Schema. * * @return array */ public function get_item_schema() { $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'resolve-redirect', - 'type' => 'string', - 'description' => __( 'The final destination of the URL being checked for redirects.', 'jetpack' ), + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'resolve-redirect', + 'type' => 'object', + 'properties' => array( + 'url' => array( + 'description' => __( 'The final destination of the URL being checked for redirects.', 'jetpack' ), + 'type' => 'string', + ), + 'status' => array( + 'description' => __( 'The status code of the URL\'s response.', 'jetpack' ), + 'type' => 'integer', + ), + ), ); return $schema; } + + /** + * Finds the destination url from an http response. + * + * @param Requests_Response $response Response object. + * @return string Final url of the response. + */ + protected function get_response_url( Requests_Response $response ) { + $history = $response->history; + if ( ! $history ) { + return $response->url; + } + + $location = $history[0]->headers->getValues( 'location' ); + if ( ! $location ) { + return $response->url; + } + + return $location[0]; + } } wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Resolve_Redirect' ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php index 05d0ddd3..edf174cf 100644 --- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php @@ -1,13 +1,14 @@ <?php -/* +/** * Service API Keys: Exposes 3rd party api keys that are used on a site. * * [ * { # Availabilty Object. See schema for more detail. - * code: (string) Displays success if the operation was successfully executed and an error code if it was not - * service: (string) The name of the service in question - * service_api_key: (string) The API key used by the service empty if one is not set yet - * message: (string) User friendly message + * code: (string) Displays success if the operation was successfully executed and an error code if it was not + * service: (string) The name of the service in question + * service_api_key: (string) The API key used by the service empty if one is not set yet + * service_api_key_source: (string) The source of the API key, defaults to "site" + * message: (string) User friendly message * }, * ... * ] @@ -77,19 +78,23 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller { 'title' => 'service-api-keys', 'type' => 'object', 'properties' => array( - 'code' => array( + 'code' => array( 'description' => __( 'Displays success if the operation was successfully executed and an error code if it was not', 'jetpack' ), 'type' => 'string', ), - 'service' => array( + 'service' => array( 'description' => __( 'The name of the service in question', 'jetpack' ), 'type' => 'string', ), - 'service_api_key' => array( + 'service_api_key' => array( 'description' => __( 'The API key used by the service. Empty if none has been set yet', 'jetpack' ), 'type' => 'string', ), - 'message' => array( + 'service_api_key_source' => array( + 'description' => __( 'The source of the API key. Defaults to "site"', 'jetpack' ), + 'type' => 'string', + ), + 'message' => array( 'description' => __( 'User friendly message', 'jetpack' ), 'type' => 'string', ), @@ -109,18 +114,31 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller { * } */ public static function get_service_api_key( $request ) { - $service = self::validate_service_api_service( $request['service'] ); if ( ! $service ) { return self::service_api_invalid_service_response(); } - $option = self::key_for_api_service( $service ); + + switch ( $service ) { + case 'mapbox': + $mapbox = self::get_service_api_key_mapbox(); + $service_api_key = $mapbox['key']; + $service_api_key_source = $mapbox['source']; + break; + default: + $option = self::key_for_api_service( $service ); + $service_api_key = Jetpack_Options::get_option( $option, '' ); + $service_api_key_source = 'site'; + }; + $message = esc_html__( 'API key retrieved successfully.', 'jetpack' ); + return array( - 'code' => 'success', - 'service' => $service, - 'service_api_key' => Jetpack_Options::get_option( $option, '' ), - 'message' => $message, + 'code' => 'success', + 'service' => $service, + 'service_api_key' => $service_api_key, + 'service_api_key_source' => $service_api_key_source, + 'message' => $message, ); } @@ -269,6 +287,82 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller { } /** + * Get the site's own Mapbox API key if set, or the WordPress.com's one otherwise. + * + * @return array An array containing the key (if any) and its source ("site" or "wpcom"). + */ + public static function get_service_api_key_mapbox() { + // If the site provides its own Mapbox API key, return it. + $service_api_key = Jetpack_Options::get_option( self::key_for_api_service( 'mapbox' ) ); + if ( $service_api_key ) { + return self::format_api_key( $service_api_key ); + } + + // If the site is not WordPress.com, return an empty API key. + $site_id = self::get_wpcom_site_id(); + if ( ( ! self::is_wpcom() && ! jetpack_is_atomic_site() ) || ! $site_id ) { + return self::format_api_key(); + } + + // If there is a cached token, return it. + $transient_key = 'wpcom_mapbox_access_token'; + $cached_token = get_transient( $transient_key ); + if ( $cached_token ) { + return self::format_api_key( $cached_token, 'wpcom' ); + } + + // Otherwise retrieve a WordPress.com token. + $request_url = 'https://public-api.wordpress.com/wpcom/v2/sites/' . $site_id . '/mapbox'; + $response = wp_remote_get( esc_url_raw( $request_url ) ); + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { + return self::format_api_key(); + } + + $response_body = json_decode( wp_remote_retrieve_body( $response ) ); + $wpcom_mapbox_access_token = $response_body->wpcom_mapbox_access_token; + + set_transient( $transient_key, $wpcom_mapbox_access_token, HOUR_IN_SECONDS ); + return self::format_api_key( $wpcom_mapbox_access_token, 'wpcom' ); + } + + /** + * Format an API key and its source into an array. + * + * @param string $key The API key. + * @param string $source The key's source ("site" or "wpcom"). + * @return array + */ + private static function format_api_key( $key = '', $source = 'site' ) { + return array( + 'key' => $key, + 'source' => $source, + ); + } + + /** + * Check if we're in WordPress.com. + * + * @return bool + */ + private static function is_wpcom() { + return defined( 'IS_WPCOM' ) && IS_WPCOM; + } + + /** + * Get the current site's WordPress.com ID. + * + * @return mixed The site's WordPress.com ID or an empty string. + */ + private static function get_wpcom_site_id() { + if ( self::is_wpcom() ) { + return get_current_blog_id(); + } elseif ( method_exists( 'Jetpack', 'is_active' ) && Jetpack::is_active() ) { + return Jetpack_Options::get_option( 'id' ); + } + return false; + } + + /** * Create site option key for service * * @param string $service The service to create key for. |