diff options
Diffstat (limited to 'plugins/jetpack/_inc/lib/core-api')
12 files changed, 752 insertions, 78 deletions
diff --git a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php index 45d10d14..368b381a 100644 --- a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php +++ b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php @@ -67,7 +67,7 @@ class Jetpack_Core_API_Module_Toggle_Endpoint ); } - if ( ! Jetpack::active_plan_supports( $module_slug ) ) { + if ( ! Jetpack_Plan::supports( $module_slug ) ) { return new WP_Error( 'not_supported', esc_html__( 'The requested Jetpack module is not supported by your plan.', 'jetpack' ), @@ -1503,7 +1503,7 @@ class Jetpack_Core_API_Module_Data_Endpoint { * @type string $date Date range to restrict results to. * } * - * @return int|string Number of spam blocked by Akismet. Otherwise, an error message. + * @return WP_Error|WP_HTTP_Response|WP_REST_Response Stats information relayed from WordPress.com. */ public function get_stats_data( WP_REST_Request $request ) { // Get parameters to fetch Stats data. diff --git a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php index c8fba69c..68327f51 100644 --- a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php +++ b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php @@ -48,69 +48,6 @@ class Jetpack_Core_API_Site_Endpoint { } /** - * Returns the result of `/sites/%s/posts/%d/related` endpoint call. - * Results are not cached and are retrieved in real time. - * - * @since 6.7.0 - * - * @param int ID of the post to get related posts of - * - * @return array - */ - public static function get_related_posts( $api_request ) { - $params = $api_request->get_params(); - $post_id = ! empty( $params['post_id'] ) ? absint( $params['post_id'] ) : 0; - - if ( ! $post_id ) { - return new WP_Error( - 'incorrect_post_id', - esc_html__( 'You need to specify a correct ID of a post to return related posts for.', 'jetpack' ), - array( 'status' => 400 ) - ); - } - - // Make the API request - $request = sprintf( '/sites/%d/posts/%d/related', Jetpack_Options::get_option( 'id' ), $post_id ); - $request_args = array( - 'headers' => array( - 'Content-Type' => 'application/json', - ), - 'timeout' => 10, - 'method' => 'POST', - ); - $response = Jetpack_Client::wpcom_json_api_request_as_blog( $request, '1.1', $request_args ); - - // Bail if there was an error or malformed response - if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) { - return new WP_Error( - 'failed_to_fetch_data', - esc_html__( 'Unable to fetch the requested data.', 'jetpack' ), - array( 'status' => 400 ) - ); - } - - // Decode the results - $results = json_decode( wp_remote_retrieve_body( $response ), true ); - - $related_posts = array(); - if ( isset( $results['hits'] ) && is_array( $results['hits'] ) ) { - $related_posts_ids = array_map( array( 'Jetpack_Core_API_Site_Endpoint', 'get_related_post_id' ), $results['hits'] ); - - $related_posts_instance = Jetpack_RelatedPosts::init(); - foreach ( $related_posts_ids as $related_post_id ) { - $related_posts[] = $related_posts_instance->get_related_post_data_for_post( $related_post_id, 0, 0 ); - } - } - - return rest_ensure_response( array( - 'code' => 'success', - 'message' => esc_html__( 'Related posts retrieved successfully.', 'jetpack' ), - 'posts' => $related_posts, - ) - ); - } - - /** * Check that the current user has permissions to request information about this site. * * @since 5.1.0 @@ -120,16 +57,4 @@ class Jetpack_Core_API_Site_Endpoint { public static function can_request() { return current_user_can( 'jetpack_manage_modules' ); } - - /** - * Returns the post ID out of a related post entry from the - * `/sites/%s/posts/%d/related` WP.com endpoint. - * - * @since 6.7.0 - * - * @return int - */ - public static function get_related_post_id( $item ) { - return $item['fields']['post_id']; - } } diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php new file mode 100644 index 00000000..2bf80939 --- /dev/null +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php @@ -0,0 +1,49 @@ +<?php + +/** + * Business Hours: Localized week + * + * @since 7.1 + */ +class WPCOM_REST_API_V2_Endpoint_Business_Hours extends WP_REST_Controller { + function __construct() { + $this->namespace = 'wpcom/v2'; + $this->rest_base = 'business-hours'; + // This endpoint *does not* need to connect directly to Jetpack sites. + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + public function register_routes() { + // GET /sites/<blog_id>/business-hours/localized-week - Return the localized + register_rest_route( $this->namespace, '/' . $this->rest_base . '/localized-week', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_localized_week' ), + ) + ) ); + } + + /** + * Retreives localized business hours + * + * @return array data object containing information about business hours + */ + public function get_localized_week() { + global $wp_locale; + + return array( + 'days' => array( + 'Sun' => $wp_locale->get_weekday( 0 ), + 'Mon' => $wp_locale->get_weekday( 1 ), + 'Tue' => $wp_locale->get_weekday( 2 ), + 'Wed' => $wp_locale->get_weekday( 3 ), + 'Thu' => $wp_locale->get_weekday( 4 ), + 'Fri' => $wp_locale->get_weekday( 5 ), + 'Sat' => $wp_locale->get_weekday( 6 ), + ), + 'startOfWeek' => (int) get_option( 'start_of_week', 0 ), + ); + } +} + +wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Business_Hours' ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php new file mode 100644 index 00000000..09ef9499 --- /dev/null +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php @@ -0,0 +1,79 @@ +<?php + +/** + * Mailchimp: Get Mailchimp Status. + * API to determine if current site has linked Mailchimp account and mailing list selected. + * This API is meant to be used in Jetpack and on WPCOM. + * + * @since 7.1 + */ +class WPCOM_REST_API_V2_Endpoint_Mailchimp extends WP_REST_Controller { + public function __construct() { + $this->namespace = 'wpcom/v2'; + $this->rest_base = 'mailchimp'; + $this->wpcom_is_wpcom_only_endpoint = true; + + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + /** + * Called automatically on `rest_api_init()`. + */ + public function register_routes() { + register_rest_route( + $this->namespace, + $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_mailchimp_status' ), + ), + ) + ); + } + + /** + * Check if MailChimp is set up properly. + * + * @return bool + */ + private function is_connected() { + $option = get_option( 'jetpack_mailchimp' ); + if ( ! $option ) { + return false; + } + $data = json_decode( $option, true ); + if ( ! $data ) { + return false; + } + return isset( $data['follower_list_id'], $data['keyring_id'] ); + } + + /** + * Get the status of current blog's Mailchimp connection + * + * @return mixed + * code:string (connected|unconnected), + * connect_url:string + * site_id:int + */ + public function get_mailchimp_status() { + $is_wpcom = ( defined( 'IS_WPCOM' ) && IS_WPCOM ); + $site_id = $is_wpcom ? get_current_blog_id() : Jetpack_Options::get_option( 'id' ); + if ( ! $site_id ) { + return new WP_Error( + 'unavailable_site_id', + __( 'Sorry, something is wrong with your Jetpack connection.', 'jetpack' ), + 403 + ); + } + $connect_url = sprintf( 'https://wordpress.com/sharing/%s', rawurlencode( $site_id ) ); + return array( + 'code' => $this->is_connected() ? 'connected' : 'not_connected', + 'connect_url' => $connect_url, + 'site_id' => $site_id, + ); + } +} + +wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Mailchimp' ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php new file mode 100644 index 00000000..a10a4056 --- /dev/null +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php @@ -0,0 +1,71 @@ +<?php + +/* + * Gutenberg: List Available Gutenberg Extensions (Blocks and Plugins) + * + * [ + * { # Availabilty Object. See schema for more detail. + * available: (boolean) Whether the extension is available + * unavailable_reason: (string) Reason for the extension not being available + * }, + * ... + * ] + * + * @since 6.9 + */ +class WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions extends WP_REST_Controller { + function __construct() { + $this->namespace = 'wpcom/v2'; + $this->rest_base = 'gutenberg'; + $this->wpcom_is_site_specific_endpoint = true; + + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + public function register_routes() { + register_rest_route( $this->namespace, $this->rest_base . '/available-extensions', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( 'Jetpack_Gutenberg', 'get_availability' ), + 'permission_callback' => array( $this, 'get_items_permission_check' ), + ), + 'schema' => array( $this, 'get_item_schema' ), + ) ); + } + + /** + * Return the available Gutenberg extensions schema + * + * @return array Available Gutenberg extensions schema + */ + public function get_public_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'gutenberg-available-extensions', + 'type' => 'object', + 'properties' => array( + 'available' => array( + 'description' => __( 'Whether the extension is available', 'jetpack' ), + 'type' => 'boolean', + ), + 'unavailable_reason' => array( + 'description' => __( 'Reason for the extension not being available', 'jetpack' ), + 'type' => 'string', + ), + ), + ); + + return $this->add_additional_fields_schema( $schema ); + } + + /** + * Ensure the user has proper permissions + * + * @return boolean + */ + public function get_items_permission_check() { + return current_user_can( 'edit_posts' ); + } +} + +wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions' ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php index 86019880..6e04a289 100644 --- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php @@ -105,6 +105,10 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connection_Test_Results extends } } + if ( 'linkedin' === $item['id'] && 'must_reauth' === $test_result['connectionTestPassed'] ) { + $item['test_success'] = 'must_reauth'; + } + $response = rest_ensure_response( $items ); $response->header( 'X-WP-Total', count( $items ) ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php index f7e9b351..34d6b2a6 100644 --- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php @@ -171,6 +171,14 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont public function get_items_permission_check() { global $publicize; + if ( ! $publicize ) { + return new WP_Error( + 'publicize_not_available', + __( 'Sorry, Publicize is not available on your site right now.', 'jetpack' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + if ( $publicize->current_user_can_access_publicize_data() ) { return true; } diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php index fb418263..4641b218 100644 --- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php @@ -144,6 +144,14 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Services extends WP_REST_Control public function get_items_permission_check() { global $publicize; + if ( ! $publicize ) { + return new WP_Error( + 'publicize_not_available', + __( 'Sorry, Publicize is not available on your site right now.', 'jetpack' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + if ( $publicize->current_user_can_access_publicize_data() ) { return true; } 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 new file mode 100644 index 00000000..05d0ddd3 --- /dev/null +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php @@ -0,0 +1,281 @@ +<?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 + * }, + * ... + * ] + * + * @since 6.9 + */ +class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller { + + function __construct() { + $this->namespace = 'wpcom/v2'; + $this->rest_base = 'service-api-keys'; + + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + public function register_routes() { + register_rest_route( + 'wpcom/v2', + '/service-api-keys/(?P<service>[a-z\-_]+)', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( __CLASS__, 'get_service_api_key' ), + ), + array( + 'methods' => WP_REST_Server::EDITABLE, + 'callback' => array( __CLASS__, 'update_service_api_key' ), + 'permission_callback' => array( __CLASS__, 'edit_others_posts_check' ), + 'args' => array( + 'service_api_key' => array( + 'required' => true, + 'type' => 'text', + ), + ), + ), + array( + 'methods' => WP_REST_Server::DELETABLE, + 'callback' => array( __CLASS__, 'delete_service_api_key' ), + 'permission_callback' => array( __CLASS__, 'edit_others_posts_check' ), + ), + ) + ); + } + + public static function edit_others_posts_check() { + if ( current_user_can( 'edit_others_posts' ) ) { + return true; + } + + $user_permissions_error_msg = esc_html__( + 'You do not have the correct user permissions to perform this action. + Please contact your site admin if you think this is a mistake.', + 'jetpack' + ); + + return new WP_Error( 'invalid_user_permission_edit_others_posts', $user_permissions_error_msg, rest_authorization_required_code() ); + } + + /** + * Return the available Gutenberg extensions schema + * + * @return array Service API Key schema + */ + public function get_public_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'service-api-keys', + 'type' => 'object', + 'properties' => 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( + 'description' => __( 'The name of the service in question', 'jetpack' ), + 'type' => 'string', + ), + 'service_api_key' => array( + 'description' => __( 'The API key used by the service. Empty if none has been set yet', 'jetpack' ), + 'type' => 'string', + ), + 'message' => array( + 'description' => __( 'User friendly message', 'jetpack' ), + 'type' => 'string', + ), + ), + ); + + return $this->add_additional_fields_schema( $schema ); + } + + /** + * Get third party plugin API keys. + * + * @param WP_REST_Request $request { + * Array of parameters received by request. + * + * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. + * } + */ + 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 ); + $message = esc_html__( 'API key retrieved successfully.', 'jetpack' ); + return array( + 'code' => 'success', + 'service' => $service, + 'service_api_key' => Jetpack_Options::get_option( $option, '' ), + 'message' => $message, + ); + } + + /** + * Update third party plugin API keys. + * + * @param WP_REST_Request $request { + * Array of parameters received by request. + * + * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. + * } + */ + public static function update_service_api_key( $request ) { + $service = self::validate_service_api_service( $request['service'] ); + if ( ! $service ) { + return self::service_api_invalid_service_response(); + } + $json_params = $request->get_json_params(); + $params = ! empty( $json_params ) ? $json_params : $request->get_body_params(); + $service_api_key = trim( $params['service_api_key'] ); + $option = self::key_for_api_service( $service ); + + $validation = self::validate_service_api_key( $service_api_key, $service, $params ); + if ( ! $validation['status'] ) { + return new WP_Error( 'invalid_key', esc_html__( 'Invalid API Key', 'jetpack' ), array( 'status' => 404 ) ); + } + $message = esc_html__( 'API key updated successfully.', 'jetpack' ); + Jetpack_Options::update_option( $option, $service_api_key ); + return array( + 'code' => 'success', + 'service' => $service, + 'service_api_key' => Jetpack_Options::get_option( $option, '' ), + 'message' => $message, + ); + } + + /** + * Delete a third party plugin API key. + * + * @param WP_REST_Request $request { + * Array of parameters received by request. + * + * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. + * } + */ + public static function delete_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 ); + Jetpack_Options::delete_option( $option ); + $message = esc_html__( 'API key deleted successfully.', 'jetpack' ); + return array( + 'code' => 'success', + 'service' => $service, + 'service_api_key' => Jetpack_Options::get_option( $option, '' ), + 'message' => $message, + ); + } + + /** + * Validate the service provided in /service-api-keys/ endpoints. + * To add a service to these endpoints, add the service name to $valid_services + * and add '{service name}_api_key' to the non-compact return array in get_option_names(), + * in class-jetpack-options.php + * + * @param string $service The service the API key is for. + * @return string Returns the service name if valid, null if invalid. + */ + public static function validate_service_api_service( $service = null ) { + $valid_services = array( + 'mapbox', + ); + return in_array( $service, $valid_services, true ) ? $service : null; + } + + /** + * Error response for invalid service API key requests with an invalid service. + */ + public static function service_api_invalid_service_response() { + return new WP_Error( + 'invalid_service', + esc_html__( 'Invalid Service', 'jetpack' ), + array( 'status' => 404 ) + ); + } + + /** + * Validate API Key + * + * @param string $key The API key to be validated. + * @param string $service The service the API key is for. + */ + public static function validate_service_api_key( $key = null, $service = null ) { + $validation = false; + switch ( $service ) { + case 'mapbox': + $validation = self::validate_service_api_key_mapbox( $key ); + break; + } + return $validation; + } + + /** + * Validate Mapbox API key + * Based loosely on https://github.com/mapbox/geocoding-example/blob/master/php/MapboxTest.php + * + * @param string $key The API key to be validated. + */ + public static function validate_service_api_key_mapbox( $key ) { + $status = true; + $msg = null; + $mapbox_url = sprintf( + 'https://api.mapbox.com?%s', + $key + ); + $mapbox_response = wp_safe_remote_get( esc_url_raw( $mapbox_url ) ); + $mapbox_body = wp_remote_retrieve_body( $mapbox_response ); + if ( '{"api":"mapbox"}' !== $mapbox_body ) { + $status = false; + $msg = esc_html__( 'Can\'t connect to Mapbox', 'jetpack' ); + return array( + 'status' => $status, + 'error_message' => $msg, + ); + } + $mapbox_geocode_url = esc_url_raw( + sprintf( + 'https://api.mapbox.com/geocoding/v5/mapbox.places/%s.json?access_token=%s', + '1+broadway+new+york+ny+usa', + $key + ) + ); + $mapbox_geocode_response = wp_safe_remote_get( esc_url_raw( $mapbox_geocode_url ) ); + $mapbox_geocode_body = wp_remote_retrieve_body( $mapbox_geocode_response ); + $mapbox_geocode_json = json_decode( $mapbox_geocode_body ); + if ( isset( $mapbox_geocode_json->message ) && ! isset( $mapbox_geocode_json->query ) ) { + $status = false; + $msg = $mapbox_geocode_json->message; + } + return array( + 'status' => $status, + 'error_message' => $msg, + ); + } + + /** + * Create site option key for service + * + * @param string $service The service to create key for. + */ + private static function key_for_api_service( $service ) { + return $service . '_api_key'; + } +} + +wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys' ); diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php new file mode 100644 index 00000000..c1a712bd --- /dev/null +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php @@ -0,0 +1,62 @@ +<?php + +/** + * Subscribers: Get subscriber count + * + * @since 6.9 + */ +class WPCOM_REST_API_V2_Endpoint_Subscribers extends WP_REST_Controller { + function __construct() { + $this->namespace = 'wpcom/v2'; + $this->rest_base = 'subscribers'; + // This endpoint *does not* need to connect directly to Jetpack sites. + $this->wpcom_is_wpcom_only_endpoint = true; + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + public function register_routes() { + // GET /sites/<blog_id>/subscribers/count - Return number of subscribers for this site. + register_rest_route( $this->namespace, '/' . $this->rest_base . '/count', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_subscriber_count' ), + 'permission_callback' => array( $this, 'readable_permission_check' ), + ) + ) ); + } + + public function readable_permission_check() { + if ( ! current_user_can_for_blog( get_current_blog_id(), 'edit_posts' ) ) { + return new WP_Error( 'authorization_required', 'Only users with the permission to edit posts can see the subscriber count.', array( 'status' => 401 ) ); + } + + return true; + } + + /** + * Retrieves subscriber count + * + * @param WP_REST_Request $request incoming API request info + * @return array data object containing subscriber count + */ + public function get_subscriber_count( $request ) { + // Get the most up to date subscriber count when request is not a test + if ( ! Jetpack_Constants::is_defined( 'TESTING_IN_JETPACK' ) ) { + delete_transient( 'wpcom_subscribers_total' ); + } + + $subscriber_info = Jetpack_Subscriptions_Widget::fetch_subscriber_count(); + $subscriber_count = $subscriber_info['value']; + + return array( + 'count' => $subscriber_count + ); + } +} + +if ( + Jetpack::is_module_active( 'subscriptions' ) || + ( Jetpack_Constants::is_defined( 'TESTING_IN_JETPACK' ) && Jetpack_Constants::get_constant( 'TESTING_IN_JETPACK' ) ) +) { + wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Subscribers' ); +} diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php new file mode 100644 index 00000000..b615c4e6 --- /dev/null +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php @@ -0,0 +1,171 @@ +<?php +/** + * Extend the REST API functionality for VideoPress users. + * + * @package Jetpack + */ + +/** + * Add per-attachment VideoPress data. + * + * { # Attachment Object + * ... + * jetpack_videopress_guid: (string) VideoPress identifier + * ... + * } + * + * @since 7.1.0 + */ +class WPCOM_REST_API_V2_Attachment_VideoPress_Field extends WPCOM_REST_API_V2_Field_Controller { + /** + * The REST Object Type to which the jetpack_videopress_guid field will be added. + * + * @var string + */ + protected $object_type = 'attachment'; + + /** + * The name of the REST API field to add. + * + * @var string $field_name + */ + protected $field_name = 'jetpack_videopress_guid'; + + /** + * Registers the jetpack_videopress field and adds a filter to remove it for attachments that are not videos. + */ + public function register_fields() { + parent::register_fields(); + + add_filter( 'rest_prepare_attachment', array( $this, 'remove_field_for_non_videos' ), 10, 2 ); + } + + /** + * Defines data structure and what elements are visible in which contexts + */ + public function get_schema() { + return array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => $this->field_name, + 'type' => 'string', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + 'description' => __( 'Unique VideoPress ID', 'jetpack' ), + ); + } + + /** + * Getter: Retrieve current VideoPress data for a given attachment. + * + * @param array $attachment Response from the attachment endpoint. + * @param WP_REST_Request $request Request to the attachment endpoint. + * + * @return string + */ + public function get( $attachment, $request ) { + if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { + $blog_id = get_current_blog_id(); + } else { + $blog_id = Jetpack_Options::get_option( 'id' ); + } + + $post_id = absint( $attachment['id'] ); + + $videopress_guid = $this->get_videopress_guid( $post_id, $blog_id ); + + if ( ! $videopress_guid ) { + return ''; + } + + return $videopress_guid; + } + + /** + * Gets the VideoPress GUID for a given attachment. + * + * This is pulled out into a separate method to support unit test mocking. + * + * @param int $attachment_id Attachment ID. + * @param int $blog_id Blog ID. + * + * @return string + */ + public function get_videopress_guid( $attachment_id, $blog_id ) { + return video_get_info_by_blogpostid( $blog_id, $attachment_id )->guid; + } + + /** + * Checks if the given attachment is a video. + * + * @param object $attachment The attachment object. + * + * @return false|int + */ + public function is_video( $attachment ) { + return wp_startswith( $attachment->post_mime_type, 'video/' ); + } + + /** + * Removes the jetpack_videopress_guid field from the response if the + * given attachment is not a video. + * + * @param WP_REST_Response $response Response from the attachment endpoint. + * @param WP_Post $attachment The original attachment object. + * + * @return mixed + */ + public function remove_field_for_non_videos( $response, $attachment ) { + if ( ! $this->is_video( $attachment ) ) { + unset( $response->data[ $this->field_name ] ); + } + + return $response; + } + + /** + * Setter: It does nothing since `jetpack_videopress` is a read-only field. + * + * @param mixed $value The new value for the field. + * @param WP_Post $object The attachment object. + * @param WP_REST_Request $request The request object. + * + * @return null + */ + public function update( $value, $object, $request ) { + return null; + } + + /** + * Permission Check for the field's getter. Delegate the responsibility to the + * attachment endpoint, so it always returns true. + * + * @param mixed $object Response from the attachment endpoint. + * @param WP_REST_Request $request Request to the attachment endpoint. + * + * @return true + */ + public function get_permission_check( $object, $request ) { + return true; + } + + /** + * Permission Check for the field's setter. Delegate the responsibility to the + * attachment endpoint, so it always returns true. + * + * @param mixed $value The new value for the field. + * @param WP_Post $object The attachment object. + * @param WP_REST_Request $request Request to the attachment endpoint. + * + * @return true + */ + public function update_permission_check( $value, $object, $request ) { + return true; + } +} + +if ( + ( method_exists( 'Jetpack', 'is_active' ) && Jetpack::is_active() ) || + ( defined( 'IS_WPCOM' ) && IS_WPCOM ) +) { + wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Attachment_VideoPress_Field' ); +} diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php index 1aa8ec86..c4254a9d 100644 --- a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php +++ b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php @@ -115,6 +115,14 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_ function permission_check( $post_id ) { global $publicize; + if ( ! $publicize ) { + return new WP_Error( + 'publicize_not_available', + __( 'Sorry, Publicize is not available on your site right now.', 'jetpack' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + if ( $publicize->current_user_can_access_publicize_data( $post_id ) ) { return true; } @@ -160,6 +168,10 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_ public function get( $post_array, $request ) { global $publicize; + if ( ! $publicize ) { + return array(); + } + $schema = $this->post_connection_schema(); $properties = array_keys( $schema['properties'] ); @@ -238,6 +250,10 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_ protected function get_meta_to_update( $requested_connections, $post_id = 0 ) { global $publicize; + if ( ! $publicize ) { + return array(); + } + if ( isset( $this->memoized_updates[$post_id] ) ) { return $this->memoized_updates[$post_id]; } @@ -334,4 +350,4 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_ if ( Jetpack::is_module_active( 'publicize' ) ) { wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Post_Publicize_Connections_Field' ); -}
\ No newline at end of file +} |