diff options
Diffstat (limited to 'plugins/jetpack/json-endpoints')
24 files changed, 501 insertions, 112 deletions
diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-autosave-post-v1-1-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-autosave-post-v1-1-endpoint.php index 7747c214..452a7c25 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-autosave-post-v1-1-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-autosave-post-v1-1-endpoint.php @@ -58,6 +58,11 @@ class WPCOM_JSON_API_Autosave_Post_v1_1_Endpoint extends WPCOM_JSON_API_Post_v1_ return new WP_Error( 'invalid_input', 'Invalid request input', 400 ); } + if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { + // Make sure Custom Post Types, etc. get registered. + $this->load_theme_functions(); + } + $post = get_post( $post_id ); if ( ! $post || is_wp_error( $post ) ) { diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-delete-post-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-delete-post-endpoint.php index 34c0a23b..31ab8d95 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-delete-post-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-delete-post-endpoint.php @@ -35,8 +35,7 @@ new WPCOM_JSON_API_Bulk_Delete_Post_Endpoint( array( class WPCOM_JSON_API_Bulk_Delete_Post_Endpoint extends WPCOM_JSON_API_Update_Post_v1_1_Endpoint { // /sites/%s/posts/delete - // The unused $object parameter is for making the method signature compatible with its parent class method. - function callback( $path = '', $blog_id = 0, $object = null ) { + function callback( $path = '', $blog_id = 0, $post_id = 0 ) { $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) ); if ( is_wp_error( $blog_id ) ) { return $blog_id; diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-edit-media-v1-2-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-edit-media-v1-2-endpoint.php index 368e4541..2366653d 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-edit-media-v1-2-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-edit-media-v1-2-endpoint.php @@ -2,6 +2,9 @@ jetpack_require_lib( 'class.media' ); +const REVISION_HISTORY_MAXIMUM_AMOUNT = 0; +const WP_ATTACHMENT_IMAGE_ALT = '_wp_attachment_image_alt'; + new WPCOM_JSON_API_Edit_Media_v1_2_Endpoint( array( 'description' => 'Edit a media item.', 'group' => 'media', @@ -24,15 +27,15 @@ new WPCOM_JSON_API_Edit_Media_v1_2_Endpoint( array( 'artist' => "(string) Audio Only. Artist metadata for the audio track.", 'album' => "(string) Audio Only. Album metadata for the audio track.", 'media' => "(object) An object file to attach to the post. To upload media, " . - "the entire request should be multipart/form-data encoded. " . - "Multiple media items will be displayed in a gallery. Accepts " . - "jpg, jpeg, png, gif, pdf, doc, ppt, odt, pptx, docx, pps, ppsx, xls, xlsx, key. " . - "Audio and Video may also be available. See <code>allowed_file_types</code> " . - "in the options response of the site endpoint. " . - "<br /><br /><strong>Example</strong>:<br />" . + "the entire request should be multipart/form-data encoded. " . + "Multiple media items will be displayed in a gallery. Accepts " . + "jpg, jpeg, png, gif, pdf, doc, ppt, odt, pptx, docx, pps, ppsx, xls, xlsx, key. " . + "Audio and Video may also be available. See <code>allowed_file_types</code> " . + "in the options response of the site endpoint. " . + "<br /><br /><strong>Example</strong>:<br />" . "<code>curl \<br />--form 'title=Image' \<br />--form 'media=@/path/to/file.jpg' \<br />-H 'Authorization: BEARER your-token' \<br />'https://public-api.wordpress.com/rest/v1/sites/123/posts/new'</code>", 'attrs' => "(object) An Object of attributes (`title`, `description` and `caption`) " . - "are supported to assign to the media uploaded via the `media` or `media_url`", + "are supported to assign to the media uploaded via the `media` or `media_url`", 'media_url' => "(string) An URL of the image to attach to a post.", ), @@ -58,9 +61,9 @@ new WPCOM_JSON_API_Edit_Media_v1_2_Endpoint( array( 'videopress_guid' => '(string) (Video only) VideoPress GUID of the video when uploaded on a blog with VideoPress', 'videopress_processing_done' => '(bool) (Video only) If the video is uploaded on a blog with VideoPress, this will return the status of processing on the video.', 'revision_history' => '(object) An object with `items` and `original` keys. ' . - '`original` is an object with data about the original image. ' . - '`items` is an array of snapshots of the previous images of this Media. ' . - 'Each item has the `URL`, `file, `extension`, `date`, and `mime_type` fields.' + '`original` is an object with data about the original image. ' . + '`items` is an array of snapshots of the previous images of this Media. ' . + 'Each item has the `URL`, `file, `extension`, `date`, and `mime_type` fields.' ), 'example_request' => 'https://public-api.wordpress.com/rest/v1.2/sites/82974409/media/446', @@ -76,12 +79,31 @@ new WPCOM_JSON_API_Edit_Media_v1_2_Endpoint( array( class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Media_v1_1_Endpoint { /** + * Return an array of mime_type items allowed when the media file is uploaded. + * + * @return {Array} mime_type array + */ + static function get_allowed_mime_types( $default_mime_types ) { + return array_unique( array_merge( $default_mime_types, array( + 'application/msword', // .doc + 'application/vnd.ms-powerpoint', // .ppt, .pps + 'application/vnd.ms-excel', // .xls + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', // .ppsx + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx + 'application/vnd.oasis.opendocument.text', // .odt + 'application/pdf', // .pdf + ) ) ); + } + + /** * Update the media post grabbing the post values from * the `attrs` parameter * * @param {Number} $media_id - post media ID * @param {Object} $attrs - `attrs` parameter sent from the client in the request body - * @return bool|WP_Error `WP_Error` on failure. `true` on success. + * @return */ private function update_by_attrs_parameter( $media_id, $attrs ) { $insert = array(); @@ -103,14 +125,18 @@ class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Medi $insert['ID'] = $media_id; $update_action = wp_update_post( (object) $insert ); if ( is_wp_error( $update_action ) ) { - $update_action; + return $update_action; } } // Attributes: Alt if ( isset( $attrs['alt'] ) ) { $alt = wp_strip_all_tags( $attrs['alt'], true ); - update_post_meta( $media_id, Jetpack_Media::$WP_ATTACHMENT_IMAGE_ALT, $alt ); + $post_update_action = update_post_meta( $media_id, WP_ATTACHMENT_IMAGE_ALT, $alt ); + + if ( is_wp_error( $post_update_action ) ) { + return $post_update_action; + } } // Attributes: Artist, Album @@ -126,11 +152,126 @@ class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Medi // Before updating metadata, ensure that the item is audio $item = $this->get_media_item_v1_1( $media_id ); if ( 0 === strpos( $item->mime_type, 'audio/' ) ) { - wp_update_attachment_metadata( $media_id, $id3_meta ); + $update_action = wp_update_attachment_metadata( $media_id, $id3_meta ); + if ( is_wp_error( $update_action ) ) { + return $update_action; + } } } - return $update_action; + return $post_update_action; + } + + /** + * Return an object to be used to store into the revision_history + * + * @param {Object} $media_item - media post object + * @return {Object} the snapshot object + */ + private function get_snapshot( $media_item ) { + $current_file = get_attached_file( $media_item->ID ); + $file_paths = pathinfo( $current_file ); + + $snapshot = array( + 'date' => (string) $this->format_date( $media_item->post_modified_gmt, $media_item->post_modified ), + 'URL' => (string) wp_get_attachment_url( $media_item->ID ), + 'file' => (string) $file_paths['basename'], + 'extension' => (string) $file_paths['extension'], + 'mime_type' => (string) $media_item->post_mime_type, + 'size' => (int) filesize( $current_file ) + ); + + return (object) $snapshot; + } + + /** + * Try to remove the temporal file from the given file array. + * + * @param {Array} $file_array - Array with data about the temporal file + * @return {Boolean} `true` if the file has been removed. + * `false` either the file doesn't exist or it couldn't be removed. + */ + private function remove_tmp_file( $file_array ) { + if ( ! file_exists ( $file_array['tmp_name'] ) ) { + return false; + } + return @unlink( $file_array['tmp_name'] ); + } + + /** + * Save the given temporal file in a local folder. + * + * @param {Array} $file_array + * @param {Number} $media_id + * @return {Array|WP_Error} An array with information about the new file saved or a WP_Error is something went wrong. + */ + private function save_temporary_file( $file_array, $media_id ) { + $tmp_filename = $file_array['tmp_name']; + + if ( ! file_exists( $tmp_filename ) ) { + return new WP_Error( 'invalid_input', 'No media provided in input.' ); + } + + // add additional mime_types through of the `jetpack_supported_media_sideload_types` filter + $mime_type_static_filter = array( + 'WPCOM_JSON_API_Edit_Media_v1_2_Endpoint', + 'get_allowed_mime_types' + ); + + add_filter( 'jetpack_supported_media_sideload_types', $mime_type_static_filter ); + if ( + ! $this->is_file_supported_for_sideloading( $tmp_filename ) && + ! file_is_displayable_image( $tmp_filename ) + ) { + @unlink( $tmp_filename ); + return new WP_Error( 'invalid_input', 'Invalid file type.', 403 ); + } + remove_filter( 'jetpack_supported_media_sideload_types', $mime_type_static_filter ); + + // generate a new file name + $tmp_new_filename = Jetpack_Media::generate_new_filename( $media_id, $file_array[ 'name' ] ); + + // start to create the parameters to move the temporal file + $overrides = array( 'test_form' => false ); + + $time = $this->get_time_string_from_guid( $media_id ); + + $file_array['name'] = $tmp_new_filename; + $file = wp_handle_sideload( $file_array, $overrides, $time ); + + $this->remove_tmp_file( $file_array ); + + if ( isset( $file['error'] ) ) { + return new WP_Error( 'upload_error', $file['error'] ); + } + + return $file; + } + + /** + * File urls use the post date to generate a folder path. + * Post dates can change, so we use the original date used in the guid + * url so edits can remain in the same folder. In the following function + * we capture a string in the format of `YYYY/MM` from the guid. + * + * For example with a guid of + * "http://test.files.wordpress.com/2016/10/test.png" the resulting string + * would be: "2016/10" + * + * @param $media_id + * + * @return string + */ + private function get_time_string_from_guid( $media_id ) { + $time = date( "Y/m", strtotime( current_time( 'mysql' ) ) ); + if ( $media = get_post( $media_id ) ) { + $pattern = '/\/(\d{4}\/\d{2})\//'; + preg_match( $pattern, $media->guid, $matches ); + if ( count( $matches ) > 1 ) { + $time = $matches[1]; + } + } + return $time; } /** @@ -152,7 +293,7 @@ class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Medi } // save the remote image into a tmp file - $tmp = download_url( $url ); + $tmp = download_url( wpcom_get_private_file( $url ) ); if ( is_wp_error( $tmp ) ) { return $tmp; } @@ -163,6 +304,25 @@ class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Medi ); } + /** + * Add a new item into revision_history array. + * + * @param {Object} $media_item - media post + * @param {file} $file - file recentrly added + * @param {Boolean} $has_original_media - condition is the original media has been already added + * @return {Boolean} `true` if the item has been added. Otherwise `false`. + */ + private function register_revision( $media_item, $file, $has_original_media ) { + if ( + is_wp_error( $file ) || + ! $has_original_media + ) { + return false; + } + + add_post_meta( $media_item->ID, Jetpack_Media::$WP_REVISION_HISTORY, $this->get_snapshot( $media_item ) ); + } + function callback( $path = '', $blog_id = 0, $media_id = 0 ) { $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) ); if ( is_wp_error( $blog_id ) ) { @@ -171,7 +331,7 @@ class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Medi $media_item = get_post( $media_id ); - if ( ! $media_item ) { + if ( ! $media_item || is_wp_error( $media_item ) ) { return new WP_Error( 'unknown_media', 'Unknown Media', 404 ); } @@ -186,36 +346,70 @@ class WPCOM_JSON_API_Edit_Media_v1_2_Endpoint extends WPCOM_JSON_API_Update_Medi $input = $this->input( true ); // images + $media_file = $input['media'] ? (array) $input['media'] : null; $media_url = $input['media_url']; $media_attrs = $input['attrs'] ? (array) $input['attrs'] : null; - if ( isset( $media_url ) ) { + if ( isset( $media_url ) || $media_file ) { $user_can_upload_files = current_user_can( 'upload_files' ) || $this->api->is_authorized_with_upload_token(); if ( ! $user_can_upload_files ) { return new WP_Error( 'unauthorized', 'User cannot upload media.', 403 ); } - // save the temporal file locally - $temporal_file = $this->build_file_array_from_url( $media_id, $media_url ); + $has_original_media = Jetpack_Media::get_original_media( $media_id ); + + if ( ! $has_original_media ) { + // The first time that the media is updated + // the original media is stored into the revision_history + $snapshot = $this->get_snapshot( $media_item ); + add_post_meta( $media_id, Jetpack_Media::$WP_ORIGINAL_MEDIA, $snapshot, true ); + } + + // save the temporal file locally + $temporal_file = $media_file ? $media_file : $this->build_file_array_from_url( $media_id, $media_url ); + + if ( is_wp_error( $temporal_file ) ) { + return $temporal_file; + } - $edited_media_item = Jetpack_Media::edit_media_file( $media_id, $temporal_file ); + $uploaded_file = $this->save_temporary_file( $temporal_file, $media_id ); - if ( is_wp_error( $edited_media_item ) ) { - return $edited_media_item; + if ( is_wp_error( $uploaded_file ) ) { + return $uploaded_file; + } + + // revision_history control + $this->register_revision( $media_item, $uploaded_file, $has_original_media ); + + $uploaded_path = $uploaded_file['file']; + $udpated_mime_type = $uploaded_file['type']; + $was_updated = update_attached_file( $media_id, $uploaded_path ); + + if ( $was_updated ) { + $new_metadata = wp_generate_attachment_metadata( $media_id, $uploaded_path ); + wp_update_attachment_metadata( $media_id, $new_metadata ); + + // check maximum amount of revision_history + Jetpack_Media::limit_revision_history( $media_id, REVISION_HISTORY_MAXIMUM_AMOUNT ); + + wp_update_post( (object) array( + 'ID' => $media_id, + 'post_mime_type' => $udpated_mime_type + ) ); } unset( $input['media'] ); unset( $input['media_url'] ); unset( $input['attrs'] ); + } - // update media through of `attrs` value it it's defined - if ( $media_attrs ) { - $updated_by_attrs = $this->update_by_attrs_parameter( $media_id, $media_attrs ); + // update media through of `attrs` value it it's defined + if ( ( $media_file || isset( $media_url ) ) && $media_attrs ) { + $was_updated = $this->update_by_attrs_parameter( $media_id, $media_attrs ); - if ( is_wp_error( $updated_by_attrs ) ) { - return $updated_by_attrs; - } + if ( is_wp_error( $was_updated ) ) { + return $was_updated; } } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-comment-counts-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-comment-counts-endpoint.php index a86f2e8d..88688e42 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-comment-counts-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-comment-counts-endpoint.php @@ -17,15 +17,13 @@ new WPCOM_JSON_API_GET_Comment_Counts_Endpoint( array( 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/comment-counts', 'response_format' => array( - 'comment_counts' => array( - 'all' => '(int) Combined number of approved and unapproved comments', - 'approved' => '(int) Number of approved comments', - 'pending' => '(int) Number of unapproved comments', - 'trash' => '(int) Number of trash comments', - 'spam' => '(int) Number of spam comments', - 'post_trashed' => '(int) Number of comments whose parent post has been trashed', - 'total_comments' => '(int) Combined number of comments in each category', - ) + 'all' => '(int) Combined number of approved and unapproved comments', + 'approved' => '(int) Number of approved comments', + 'pending' => '(int) Number of unapproved comments', + 'trash' => '(int) Number of trash comments', + 'spam' => '(int) Number of spam comments', + 'post_trashed' => '(int) Number of comments whose parent post has been trashed', + 'total_comments' => '(int) Combined number of comments in each category', ) ) ); diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-media-v1-2-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-media-v1-2-endpoint.php index 06c0b2d3..413e3b94 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-media-v1-2-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-media-v1-2-endpoint.php @@ -1,6 +1,6 @@ <?php -require_once( JETPACK__PLUGIN_DIR . 'sal/class.json-api-date.php' ); +jetpack_require_lib( 'class.media' ); new WPCOM_JSON_API_Get_Media_v1_2_Endpoint( array( 'description' => 'Get a single media item (by ID).', @@ -36,9 +36,9 @@ new WPCOM_JSON_API_Get_Media_v1_2_Endpoint( array( 'videopress_guid' => '(string) (Video only) VideoPress GUID of the video when uploaded on a blog with VideoPress', 'videopress_processing_done' => '(bool) (Video only) If the video is uploaded on a blog with VideoPress, this will return the status of processing on the video.', 'revision_history' => '(object) An object with `items` and `original` keys. ' . - '`original` is an object with data about the original image. ' . - '`items` is an array of snapshots of the previous images of this Media. ' . - 'Each item has the `URL`, `file, `extension`, `date`, and `mime_type` fields.' + '`original` is an object with data about the original image. ' . + '`items` is an array of snapshots of the previous images of this Media. ' . + 'Each item has the `URL`, `file, `extension`, `date`, and `mime_type` fields.' ), 'example_request' => 'https://public-api.wordpress.com/rest/v1.2/sites/82974409/media/934', @@ -58,7 +58,7 @@ class WPCOM_JSON_API_Get_Media_v1_2_Endpoint extends WPCOM_JSON_API_Get_Media_v1 } $media_item = get_post( $media_id ); - $response->modified = WPCOM_JSON_API_Date::format_date( $media_item->post_modified_gmt, $media_item->post_modified ); + $response->modified = (string) $this->format_date( $media_item->post_modified_gmt, $media_item->post_modified ); // expose `revision_history` object $response->revision_history = (object) array( @@ -69,3 +69,4 @@ class WPCOM_JSON_API_Get_Media_v1_2_Endpoint extends WPCOM_JSON_API_Get_Media_v1 return $response; } } + diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php index 4cb99d0d..c7dbcb24 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php @@ -120,6 +120,12 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { 'podcasting_archive', 'is_domain_only', 'is_automated_transfer', + 'is_wpcom_store', + 'signup_is_store', + 'has_pending_automated_transfer', + 'woocommerce_is_active', + 'design_type', + 'site_goals' ); protected static $jetpack_response_field_additions = array( @@ -135,7 +141,11 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { 'publicize_permanently_disabled', 'ak_vp_bundle_enabled', 'is_automated_transfer', - 'frame_nonce' + 'is_wpcom_store', + 'woocommerce_is_active', + 'frame_nonce', + 'design_type', + 'wordads' ); private $site; @@ -210,8 +220,21 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { return $this->render_response_keys( $response_keys ); } - private function has_blog_access( $token_details, $wpcom_blog_id ) { - if ( is_user_member_of_blog( get_current_user_id(), get_current_blog_id() ) ) { + /** + * Checks that the current user has access to the current blog, + * and failing that checks that we have a valid blog token. + * + * @param $token_details array Details obtained from the authorization token + * @param $blog_id int The server-side blog id on wordpress.com + * + * @return bool + */ + private function has_blog_access( $token_details, $blog_id ) { + $current_blog_id = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ? + $blog_id : + get_current_blog_id(); + + if ( is_user_member_of_blog( get_current_user_id(), $current_blog_id ) ) { return true; } @@ -223,7 +246,7 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { if ( 'jetpack' === $token_details['auth'] && 'blog' === $token_details['access'] && - $wpcom_blog_id === $token_details['blog_id'] + $current_blog_id === $token_details['blog_id'] ) { return true; } @@ -507,6 +530,34 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { case 'blog_public': $options[ $key ] = $site->get_blog_public(); break; + case 'is_wpcom_store': + $options[ $key ] = $site->is_wpcom_store(); + break; + case 'signup_is_store': + $signup_is_store = $site->signup_is_store(); + + if ( $signup_is_store ) { + $options[ $key ] = $site->signup_is_store(); + } + + break; + case 'has_pending_automated_transfer': + $has_pending_automated_transfer = $site->has_pending_automated_transfer(); + + if ( $has_pending_automated_transfer ) { + $options[ $key ] = true; + } + + break; + case 'woocommerce_is_active': + $options[ $key ] = $site->woocommerce_is_active(); + break; + case 'design_type': + $options[ $key ] = $site->get_design_type(); + break; + case 'site_goals': + $options[ $key ] = $site->get_site_goals(); + break; } } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-endpoint.php index 9ef1e64f..95d11c58 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-endpoint.php @@ -60,8 +60,7 @@ class WPCOM_JSON_API_List_Media_Endpoint extends WPCOM_JSON_API_Endpoint { 'post_parent' => $args['parent_id'], 'offset' => $args['offset'], 'numberposts' => $args['number'], - 'post_mime_type' => $args['mime_type'], - 'suppress_filters' => false, + 'post_mime_type' => $args['mime_type'] ) ); $response = array(); diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-v1-2-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-v1-2-endpoint.php index 3b20fa08..0ffd971b 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-v1-2-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-media-v1-2-endpoint.php @@ -66,8 +66,8 @@ class WPCOM_JSON_API_List_Media_v1_2_Endpoint extends WPCOM_JSON_API_List_Media_ foreach ( $media_list as $index => $media_item ) { // expose `revision_history` object for each image $media_item->revision_history = (object) array( - 'items' => (array) Media::get_revision_history( $media_item->ID ), - 'original' => (object) Media::get_original_media( $media_item->ID ) + 'items' => (array) Jetpack_Media::get_revision_history( $media_item->ID ), + 'original' => (object) Jetpack_Media::get_original_media( $media_item->ID ) ); } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-type-taxonomies-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-type-taxonomies-endpoint.php index 69d5bf47..27b1cf0e 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-type-taxonomies-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-type-taxonomies-endpoint.php @@ -39,12 +39,7 @@ class WPCOM_JSON_API_List_Post_Type_Taxonomies_Endpoint extends WPCOM_JSON_API_E $this->load_theme_functions(); } - /** This filter is documented in jetpack/json-endpoints/class.wpcom-json-api-list-post-types-endpoint.php */ - if ( apply_filters( 'rest_api_localize_response', false ) ) { - // API localization occurs after the initial taxonomies have been - // registered, so re-register if localizing response - create_initial_taxonomies(); - } + $this->localize_initial_taxonomies( $post_type ); $args = $this->query_args(); @@ -79,4 +74,25 @@ class WPCOM_JSON_API_List_Post_Type_Taxonomies_Endpoint extends WPCOM_JSON_API_E 'taxonomies' => $formatted_taxonomy_objects, ); } + + protected function localize_initial_taxonomies( $post_type ) { + /** This filter is documented in jetpack/json-endpoints/class.wpcom-json-api-list-post-types-endpoint.php */ + if ( ! apply_filters( 'rest_api_localize_response', false ) ) { + return; + } + + // Since recreating initial taxonomies will restore the default post + // types to which they are associated, save post type's taxonomies in + // case it was customized via `register_taxonomy_for_object_type` + $post_type_taxonomies = get_object_taxonomies( $post_type ); + + // API localization occurs after the initial taxonomies have been + // registered, so re-register if localizing response + create_initial_taxonomies(); + + // Restore registered taxonomies for post type + foreach ( $post_type_taxonomies as $taxonomy ) { + register_taxonomy_for_object_type( $taxonomy, $post_type ); + } + } } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-types-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-types-endpoint.php index d6cbefa8..06ac5747 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-types-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-post-types-endpoint.php @@ -108,6 +108,9 @@ class WPCOM_JSON_API_List_Post_Types_Endpoint extends WPCOM_JSON_API_Endpoint { return false; } - return in_array( $post_type, $featured_content[0]['post_types'] ); + if ( is_array( $featured_content[0]['post_types'] ) ) { + return in_array( $post_type, $featured_content[0]['post_types'] ); + } + return $post_type === $featured_content[0]['post_types']; } } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-roles-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-roles-endpoint.php index 028aabd7..733f26f7 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-roles-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-roles-endpoint.php @@ -4,7 +4,7 @@ new WPCOM_JSON_API_List_Roles_Endpoint( array( 'description' => 'List the user roles of a site.', 'group' => '__do_not_document', 'stat' => 'roles:list', - + 'max_version' => '1.1', 'method' => 'GET', 'path' => '/sites/%s/roles', 'path_labels' => array( @@ -26,6 +26,32 @@ new WPCOM_JSON_API_List_Roles_Endpoint( array( ) ) ); +new WPCOM_JSON_API_List_Roles_Endpoint( array( + 'description' => 'List the user roles of a site.', + 'group' => '__do_not_document', + 'stat' => 'roles:list', + 'min_version' => '1.2', + 'force' => 'wpcom', + 'method' => 'GET', + 'path' => '/sites/%s/roles', + 'path_labels' => array( + '$site' => '(int|string) Site ID or domain', + ), + + 'query_parameters' => array(), + + 'response_format' => array( + 'roles' => '(array:role) Array of role objects.', + ), + + 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/82974409/roles', + 'example_request_data' => array( + 'headers' => array( + 'authorization' => 'Bearer YOUR_API_TOKEN', + ), + ), +) ); + class WPCOM_JSON_API_List_Roles_Endpoint extends WPCOM_JSON_API_Endpoint { var $response_format = array( @@ -60,26 +86,45 @@ class WPCOM_JSON_API_List_Roles_Endpoint extends WPCOM_JSON_API_Endpoint { // /sites/%s/roles/ -> $blog_id function callback( $path = '', $blog_id = 0 ) { - $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) ); if ( is_wp_error( $blog_id ) ) { return $blog_id; } - if ( ! current_user_can( 'list_users' ) ) { - return new WP_Error( 'unauthorized', 'User cannot view roles for specified site', 403 ); - } - $roles = array(); - $wp_roles= new WP_Roles(); - $role_names = $wp_roles->get_names(); - $role_keys = array_keys( $role_names ); + $sal_site = $this->get_platform()->get_site( $blog_id ); + $wp_roles = $sal_site->get_roles(); + + // Check if the site is connected and talks to us on a regular basis + $is_connected = $sal_site->is_connected_site(); + if ( is_wp_error( $is_connected ) ) { + return $is_connected; + } + + if ( ! $sal_site->current_user_can( 'list_users' ) ) { + return new WP_Error( 'unauthorized', 'User cannot view roles for specified site', 403 ); + } - foreach ( (array) $role_keys as $role_key ) { - $role_details = get_role( $role_key ); - $role_details->display_name = translate_user_role( $role_names[$role_key] ); - $roles[] = $role_details; + if ( method_exists( $wp_roles, 'get_names' ) ) { + $role_names = $wp_roles->get_names(); + + $role_keys = array_keys( $role_names ); + + foreach ( (array) $role_keys as $role_key ) { + $role_details = get_role( $role_key ); + $role_details->display_name = translate_user_role( $role_names[$role_key] ); + $roles[] = $role_details; + } + } else { + // Jetpack Shadow Site side of things. + foreach ( $wp_roles as $role_key => $role ) { + $roles[] = (object) array( + 'name' => $role_key, + 'display_name' => $role['name'], + 'capabilities' => (object) $role['capabilities'] + ); + } } // Sort the array so roles with the most number of capabilities comes first, then the next role, and so on diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-endpoint.php index e5ae428c..09d3f50c 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-endpoint.php @@ -556,16 +556,16 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint { if ( !empty( $include ) ) { $include = preg_replace( '/[^0-9,]+/', '', $include ); - $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby, 'suppress_filters' => false ) ); + $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) ); $attachments = array(); foreach ( $_attachments as $key => $val ) { $attachments[$val->ID] = $_attachments[$key]; } } elseif ( !empty( $exclude ) ) { $exclude = preg_replace( '/[^0-9,]+/', '', $exclude ); - $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby, 'suppress_filters' => false ) ); + $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) ); } else { - $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby, 'suppress_filters' => false ) ); + $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) ); } if ( ! empty( $attachments ) ) { diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-v1-1-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-v1-1-endpoint.php index 2668a259..418cfb16 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-v1-1-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-post-v1-1-endpoint.php @@ -324,16 +324,16 @@ abstract class WPCOM_JSON_API_Post_v1_1_Endpoint extends WPCOM_JSON_API_Endpoint if ( !empty( $include ) ) { $include = preg_replace( '/[^0-9,]+/', '', $include ); - $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby, 'suppress_filters' => false ) ); + $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) ); $attachments = array(); foreach ( $_attachments as $key => $val ) { $attachments[$val->ID] = $_attachments[$key]; } } elseif ( !empty( $exclude ) ) { $exclude = preg_replace( '/[^0-9,]+/', '', $exclude ); - $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby, 'suppress_filters' => false ) ); + $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) ); } else { - $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby, 'suppress_filters' => false ) ); + $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) ); } if ( ! empty( $attachments ) ) { diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-render-embed-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-render-embed-endpoint.php index 5320978c..1c08060b 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-render-embed-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-render-embed-endpoint.php @@ -33,7 +33,7 @@ class WPCOM_JSON_API_Render_Embed_Endpoint extends WPCOM_JSON_API_Render_Endpoin } if ( ! current_user_can( 'edit_posts' ) ) { - return new WP_Error( 'unauthorized', 'Your token must have permission to post on this blog.', 403 ); + return new WP_Error( 'unauthorized', __( 'Your token must have permission to post on this blog.', 'jetpack' ), 403 ); } $args = $this->query_args(); @@ -41,17 +41,17 @@ class WPCOM_JSON_API_Render_Embed_Endpoint extends WPCOM_JSON_API_Render_Endpoin // quick validation if ( ! preg_match_all( '|^\s*(https?://[^\s"]+)\s*$|im', $embed_url, $matches ) ) { - return new WP_Error( 'invalid_embed_url', 'The embed_url parameter must be a valid URL.', 400 ); + return new WP_Error( 'invalid_embed_url', __( 'The embed_url parameter must be a valid URL.', 'jetpack' ), 400 ); } if ( count( $matches[1] ) > 1 ) { - return new WP_Error( 'invalid_embed', 'Only one embed can be rendered at a time.', 400 ); + return new WP_Error( 'invalid_embed', __( 'Only one embed can be rendered at a time.', 'jetpack' ), 400 ); } $embed_url = array_shift( $matches[1] ); $parts = parse_url( $embed_url ); if ( ! $parts ) { - return new WP_Error( 'invalid_embed_url', 'The embed_url parameter must be a valid URL.', 400 ); + return new WP_Error( 'invalid_embed_url', __( 'The embed_url parameter must be a valid URL.', 'jetpack' ), 400 ); } global $wp_embed; @@ -60,7 +60,7 @@ class WPCOM_JSON_API_Render_Embed_Endpoint extends WPCOM_JSON_API_Render_Endpoin // if nothing happened, then the shortcode does not exist. $is_an_embed = ( $embed_url != $render['result'] && $wp_embed->maybe_make_link( $embed_url ) != $render['result'] ); if ( ! $is_an_embed ) { - return new WP_Error( 'invalid_embed', 'The requested URL is not an embed.', 400 ); + return new WP_Error( 'invalid_embed', __( 'The requested URL is not an embed.', 'jetpack' ), 400 ); } // our output for this endpoint.. @@ -72,4 +72,4 @@ class WPCOM_JSON_API_Render_Embed_Endpoint extends WPCOM_JSON_API_Render_Endpoin return $return; } -}
\ No newline at end of file +} diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php index b450c3ea..ecc9eaf8 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php @@ -99,6 +99,7 @@ new WPCOM_JSON_API_Site_Settings_Endpoint( array( 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', 'posts_per_page' => '(int) Number of posts to show on blog pages', + 'net_neutrality' => '(bool) Whether to show the net neutrality modal for a site', 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', ), @@ -131,6 +132,8 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { } if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { + // Source & include the infinite scroll compatibility files prior to loading theme functions + add_filter( 'restapi_theme_action_copy_dirs', array( 'WPCOM_JSON_API_Site_Settings_Endpoint', 'wpcom_restapi_copy_theme_plugin_actions' ) ); $this->load_theme_functions(); } @@ -161,6 +164,37 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { } /** + * Includes additional theme-specific files to be included in REST API theme + * context loading action copying. + * + * @see WPCOM_JSON_API_Endpoint#load_theme_functions + * @see the_neverending_home_page_theme_support + */ + function wpcom_restapi_copy_theme_plugin_actions( $copy_dirs ) { + $theme_name = get_stylesheet(); + $default_file_name = WP_CONTENT_DIR . "/mu-plugins/infinity/themes/{$theme_name}.php"; + + /** + * Filter the path to the Infinite Scroll compatibility file. + * + * @module infinite-scroll + * + * @since 2.0.0 + * + * @param string $str IS compatibility file path. + * @param string $theme_name Theme name. + */ + $customization_file = apply_filters( 'infinite_scroll_customization_file', $default_file_name, $theme_name ); + + if ( is_readable( $customization_file ) ) { + require_once $customization_file; + $copy_dirs[] = $customization_file; + } + + return $copy_dirs; + } + + /** * Determines whether jetpack_relatedposts is supported * * @return bool @@ -278,6 +312,11 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { $api_cache = $is_jetpack ? (bool) get_option( 'jetpack_api_cache_enabled' ) : true; + $net_neutrality_options = get_option( 'net_neutrality_options_2017' ); + $net_neutrality = ( $net_neutrality_options && ! empty( $net_neutrality_options['enabled'] ) ) + ? true + : false; + $response[ $key ] = array( // also exists as "options" @@ -343,6 +382,7 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { 'amp_is_enabled' => (bool) function_exists( 'wpcom_is_amp_enabled' ) && wpcom_is_amp_enabled( $blog_id ), 'api_cache' => $api_cache, 'posts_per_page' => (int) get_option( 'posts_per_page' ), + 'net_neutrality' => $net_neutrality, 'posts_per_rss' => (int) get_option( 'posts_per_rss' ), 'rss_use_excerpt' => (bool) get_option( 'rss_use_excerpt' ), ); @@ -350,6 +390,25 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { $response[ $key ]['wpcom_publish_posts_with_markdown'] = (bool) WPCom_Markdown::is_posting_enabled(); $response[ $key ]['wpcom_publish_comments_with_markdown'] = (bool) WPCom_Markdown::is_commenting_enabled(); + + // WPCOM-specific Infinite Scroll Settings + if ( is_callable( array( 'The_Neverending_Home_Page', 'get_settings' ) ) ) { + /** + * Clear the cached copy of widget info so it's pulled fresh from blog options. + * It was primed during the initial load under the __REST API site__'s context. + * @see wp_get_sidebars_widgets https://core.trac.wordpress.org/browser/trunk/src/wp-includes/widgets.php?rev=42374#L931 + */ + $GLOBALS['_wp_sidebars_widgets'] = array(); + + $infinite_scroll_settings = The_Neverending_Home_Page::get_settings(); + $response[ $key ]['infinite_scroll'] = get_option( 'infinite_scroll', true ) && $infinite_scroll_settings->type === 'scroll'; + if ( $infinite_scroll_settings->footer_widgets || 'click' == $infinite_scroll_settings->requested_type ) { + // The blog has footer widgets -- infinite scroll is blocked + $response[ $key ]['infinite_scroll_blocked'] = 'footer'; + } else { + $response[ $key ]['infinite_scroll_blocked'] = false; + } + } } //allow future versions of this endpoint to support additional settings keys @@ -412,16 +471,22 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { public function update_settings() { // $this->input() retrieves posted arguments whitelisted and casted to the $request_format // specs that get passed in when this class is instantiated + $input = $this->input(); + $unfiltered_input = $this->input( false, false ); /** * Filters the settings to be updated on the site. * * @module json-api * * @since 3.6.0 + * @since 6.1.1 Added $unfiltered_input parameter. * - * @param array $input Associative array of site settings to be updated. + * @param array $input Associative array of site settings to be updated. + * Cast and filtered based on documentation. + * @param array $unfiltered_input Associative array of site settings to be updated. + * Neither cast nor filtered. Contains raw input. */ - $input = apply_filters( 'rest_api_update_site_settings', $this->input() ); + $input = apply_filters( 'rest_api_update_site_settings', $input, $unfiltered_input ); $blog_id = get_current_blog_id(); @@ -695,6 +760,15 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { } break; + case 'net_neutrality': + $original_value = $value; + $value = array( 'enabled' => (bool) $value ); + if ( update_option( 'net_neutrality_options_2017', $value ) ) { + $updated[ $key ] = $original_value; + } + + break; + default: //allow future versions of this endpoint to support additional settings keys if ( has_filter( 'site_settings_endpoint_update_' . $key ) ) { diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-2-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-2-endpoint.php index 388eac66..e494a1bb 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-2-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-2-endpoint.php @@ -96,6 +96,7 @@ new WPCOM_JSON_API_Site_Settings_V1_2_Endpoint( array( 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', 'posts_per_page' => '(int) Number of posts to show on blog pages', + 'net_neutrality' => '(bool) Whether the net neutrality modal is enabled for this site', 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', ), diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-3-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-3-endpoint.php index 680d70b5..316c64a4 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-3-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-3-endpoint.php @@ -1,11 +1,4 @@ <?php -/** - * WARNING: This file is distributed verbatim in Jetpack. - * There should be nothing WordPress.com specific in this file. - * - * @hide-in-jetpack - * @autounit api-v1 site-settings - */ new WPCOM_JSON_API_Site_Settings_V1_3_Endpoint( array( 'description' => 'Get detailed settings information about a site.', @@ -96,13 +89,14 @@ new WPCOM_JSON_API_Site_Settings_V1_3_Endpoint( array( 'jetpack_portfolio' => '(bool) Whether portfolio custom post type is enabled for the site', 'jetpack_portfolio_posts_per_page' => '(int) Number of portfolio projects to show per page', Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION => '(string) The SEO meta description for the site.', - Jetpack_SEO_Titles::TITLE_FORMATS_OPTION => '(array) SEO meta title formats. Allowed keys: front_page, posts, pages, groups, archives', + Jetpack_SEO_Titles::TITLE_FORMATS_OPTION => '(array) SEO meta title formats. Allowed keys: front_page, posts, pages, groups, archives', 'verification_services_codes' => '(array) Website verification codes. Allowed keys: google, pinterest, bing, yandex', 'amp_is_enabled' => '(bool) Whether AMP is enabled for this site', 'podcasting_archive' => '(string) The post category, if any, used for publishing podcasts', 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', 'posts_per_page' => '(int) Number of posts to show on blog pages', + 'net_neutrality' => '(bool) Whether the net neutrality modal is enabled for this site', 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', ), @@ -115,12 +109,14 @@ new WPCOM_JSON_API_Site_Settings_V1_3_Endpoint( array( ) ); class WPCOM_JSON_API_Site_Settings_V1_3_Endpoint extends WPCOM_JSON_API_Site_Settings_V1_2_Endpoint { - public static $wga_defaults = array( - 'code' => '', - 'anonymize_ip' => false, - 'ec_track_purchases' => false, - 'ec_track_add_to_cart' => false - ); + protected function get_defaults() { + return array( + 'code' => '', + 'anonymize_ip' => false, + 'ec_track_purchases' => false, + 'ec_track_add_to_cart' => false + ); + } function callback( $path = '', $blog_id = 0 ) { add_filter( 'site_settings_endpoint_get', array( $this, 'filter_site_settings_endpoint_get' ) ); diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php index de3cd5a9..929acde3 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php @@ -1,11 +1,4 @@ <?php -/** - * WARNING: This file is distributed verbatim in Jetpack. - * There should be nothing WordPress.com specific in this file. - * - * @hide-in-jetpack - * @autounit api-v1 site-settings - */ new WPCOM_JSON_API_Site_Settings_V1_4_Endpoint( array( 'description' => 'Get detailed settings information about a site.', @@ -103,6 +96,7 @@ new WPCOM_JSON_API_Site_Settings_V1_4_Endpoint( array( 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', 'posts_per_page' => '(int) Number of posts to show on blog pages', + 'net_neutrality' => '(bool) Whether the net neutrality modal is enabled for this site', 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', ), diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-1-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-1-endpoint.php index 72c04a8e..1e1a1f1b 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-1-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-1-endpoint.php @@ -321,8 +321,12 @@ class WPCOM_JSON_API_Update_Post_v1_1_Endpoint extends WPCOM_JSON_API_Post_v1_1_ $new_status = isset( $input['status'] ) ? $input['status'] : $last_status; // Make sure that drafts get the current date when transitioning to publish if not supplied in the post. + // Similarly, scheduled posts that are manually published before their scheduled date should have the date reset. $date_in_past = ( strtotime($post->post_date_gmt) < time() ); - if ( 'publish' === $new_status && 'draft' === $last_status && ! isset( $input['date_gmt'] ) && $date_in_past ) { + $reset_draft_date = 'publish' === $new_status && 'draft' === $last_status && ! isset( $input['date_gmt'] ) && $date_in_past; + $reset_scheduled_date = 'publish' === $new_status && 'future' === $last_status && ! isset( $input['date_gmt'] ) && ! $date_in_past; + + if ( $reset_draft_date || $reset_scheduled_date ) { $input['date_gmt'] = gmdate( 'Y-m-d H:i:s' ); } } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-2-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-2-endpoint.php index 98186ca3..6deae172 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-2-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-2-endpoint.php @@ -265,8 +265,12 @@ class WPCOM_JSON_API_Update_Post_v1_2_Endpoint extends WPCOM_JSON_API_Update_Pos $new_status = isset( $input['status'] ) ? $input['status'] : $last_status; // Make sure that drafts get the current date when transitioning to publish if not supplied in the post. + // Similarly, scheduled posts that are manually published before their scheduled date should have the date reset. $date_in_past = ( strtotime($post->post_date_gmt) < time() ); - if ( 'publish' === $new_status && 'draft' === $last_status && ! isset( $input['date_gmt'] ) && $date_in_past ) { + $reset_draft_date = 'publish' === $new_status && 'draft' === $last_status && ! isset( $input['date_gmt'] ) && $date_in_past; + $reset_scheduled_date = 'publish' === $new_status && 'future' === $last_status && ! isset( $input['date_gmt'] ) && ! $date_in_past; + + if ( $reset_draft_date || $reset_scheduled_date ) { $input['date_gmt'] = gmdate( 'Y-m-d H:i:s' ); } } diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php index 7aea6949..a46d0afd 100644 --- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php +++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php @@ -159,6 +159,10 @@ class WPCOM_JSON_API_Upload_Media_v1_1_Endpoint extends WPCOM_JSON_API_Endpoint $input = $this->input( true ); $media_files = ! empty( $input['media'] ) ? $input['media'] : array(); + if ( empty( $media_files ) ) { + return false; + } + foreach ( $media_files as $media_item ) { if ( ! preg_match( '@^video/@', $media_item['type'] ) ) { return false; diff --git a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-sync-endpoint.php b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-sync-endpoint.php index ef5831e8..cba22c24 100644 --- a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-sync-endpoint.php +++ b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-sync-endpoint.php @@ -148,6 +148,7 @@ class Jetpack_JSON_API_Sync_Object extends Jetpack_JSON_API_Sync_Endpoint { return array( 'objects' => $objects, + 'codec' => $codec->name(), ); } } diff --git a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-user-connect-endpoint.php b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-user-connect-endpoint.php index 8b758559..b30597de 100644 --- a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-user-connect-endpoint.php +++ b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-user-connect-endpoint.php @@ -27,5 +27,4 @@ class Jetpack_JSON_API_User_Connect_Endpoint extends Jetpack_JSON_API_Endpoint { $this->user_token = sanitize_text_field( $input[ 'user_token'] ); return parent::validate_input( $user_id ); } - } diff --git a/plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php b/plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php index ee138cf1..919c9ee6 100644 --- a/plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php +++ b/plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php @@ -592,7 +592,8 @@ new Jetpack_JSON_API_Sync_Object( array( 'object_ids' => '(array) The IDs of the objects', ), 'response_format' => array( - 'objects' => '(string) The encoded objects' + 'objects' => '(string) The encoded objects', + 'codec' => '(string) The codec used to encode the objects, deflate-json-array or simple' ), 'example_request' => 'https://public-api.wordpress.com/rest/v1.1/sites/example.wordpress.org/sync/object?module_name=posts&object_type=post&object_ids[]=1&object_ids[]=2&object_ids[]=3' ) ); |