summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/json-endpoints')
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-update-comments-endpoint.php219
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-comment-endpoint.php3
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-edit-media-v1-2-endpoint.php4
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-list-comments-endpoint.php7
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php33
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-2-endpoint.php2
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-3-endpoint.php2
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php2
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-update-post-v1-2-endpoint.php2
-rw-r--r--plugins/jetpack/json-endpoints/class.wpcom-json-api-update-user-endpoint.php33
-rw-r--r--plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-get-database-object-backup-endpoint.php97
-rw-r--r--plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-plugins-modify-endpoint.php2
-rw-r--r--plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-themes-modify-endpoint.php2
-rw-r--r--plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php29
14 files changed, 427 insertions, 10 deletions
diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-update-comments-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-update-comments-endpoint.php
new file mode 100644
index 00000000..3468b81e
--- /dev/null
+++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-bulk-update-comments-endpoint.php
@@ -0,0 +1,219 @@
+<?php
+
+new WPCOM_JSON_API_Bulk_Update_Comments_Endpoint( array(
+ 'description' => 'Update multiple comment\'s status.',
+ 'group' => 'comments',
+ 'stat' => 'comments:1:bulk-update-status',
+ 'min_version' => '1',
+ 'max_version' => '1',
+ 'method' => 'POST',
+ 'path' => '/sites/%s/comments/status',
+ 'path_labels' => array(
+ '$site' => '(int|string) Site ID or domain',
+ ),
+ 'request_format' => array(
+ 'comment_ids' => '(array|string) An array, or comma-separated list, of Comment IDs to update.',
+ 'status' => '(string) The new status value. Allowed values: approved, unapproved, spam, trash',
+ ),
+ 'response_format' => array(
+ 'results' => '(array) An array of updated Comment IDs.'
+ ),
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/82974409/comments/status',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'comment_ids' => array( 881, 882 ),
+ 'status' => 'approved',
+ ),
+ )
+) );
+
+new WPCOM_JSON_API_Bulk_Update_Comments_Endpoint( array(
+ 'description' => 'Permanently delete multiple comments. Note: this request will send non-trashed comments to the trash. Trashed comments will be permanently deleted.',
+ 'group' => 'comments',
+ 'stat' => 'comments:1:bulk-delete',
+ 'min_version' => '1',
+ 'max_version' => '1',
+ 'method' => 'POST',
+ 'path' => '/sites/%s/comments/delete',
+ 'path_labels' => array(
+ '$site' => '(int|string) Site ID or domain',
+ ),
+ 'request_format' => array(
+ 'comment_ids' => '(array|string) An array, or comma-separated list, of Comment IDs to delete or trash. (optional)',
+ 'empty_status' => '(string) Force to permanently delete all spam or trash comments. (optional). Allowed values: spam, trash',
+ ),
+ 'response_format' => array(
+ 'results' => '(array) An array of deleted or trashed Comment IDs.'
+ ),
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/82974409/comments/delete',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'comment_ids' => array( 881, 882 ),
+ ),
+ )
+) );
+
+class WPCOM_JSON_API_Bulk_Update_Comments_Endpoint extends WPCOM_JSON_API_Endpoint {
+ // /sites/%s/comments/status
+ // /sites/%s/comments/delete
+ 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;
+ }
+
+ $input = $this->input();
+
+ if ( isset( $input['comment_ids'] ) && is_array( $input['comment_ids'] ) ) {
+ $comment_ids = $input['comment_ids'];
+ } else if ( isset( $input['comment_ids'] ) && ! empty( $input['comment_ids'] ) ) {
+ $comment_ids = explode( ',', $input['comment_ids'] );
+ } else {
+ $comment_ids = array();
+ }
+
+ $result = array(
+ 'results' => array(),
+ );
+
+ wp_defer_comment_counting( true );
+
+ if ( $this->api->ends_with( $path, '/delete' ) ) {
+ if ( isset( $input['empty_status'] ) && $this->validate_empty_status_param( $input['empty_status'] ) ) {
+ $result['results'] = $this->delete_all( $input['empty_status'] );
+ } else {
+ $result['results'] = $this->bulk_delete_comments( $comment_ids );
+ }
+ } else {
+ $status = isset( $input['status'] ) ? $input['status'] : '';
+ $result['results'] = $this->bulk_update_comments_status( $comment_ids, $status );
+ }
+
+ wp_defer_comment_counting( false );
+
+ return $result;
+ }
+
+ /**
+ * Determine if the passed comment status is valid or not.
+ *
+ * @param string $status
+ *
+ * @return boolean
+ */
+ function validate_status_param( $status ) {
+ return in_array( $status, array( 'approved', 'unapproved', 'pending', 'spam', 'trash' ), true );
+ }
+
+ /**
+ * Determine if the passed empty status is valid or not.
+ *
+ * @param string $empty_status
+ *
+ * @return boolean
+ */
+ function validate_empty_status_param( $empty_status ) {
+ return in_array( $empty_status, array( 'spam', 'trash' ), true );
+ }
+
+ /**
+ * Update the status of multiple comments.
+ *
+ * @param array $comment_ids Comments to update.
+ * @param string $status New status value.
+ *
+ * @return array Updated comments IDs.
+ */
+ function bulk_update_comments_status( $comment_ids, $status ) {
+ if ( count( $comment_ids ) < 1 ) {
+ return new WP_Error( 'empty_comment_ids', 'The request must include comment_ids', 400 );
+ }
+ if ( ! $this->validate_status_param( $status ) ) {
+ return new WP_Error( 'invalid_status', "Invalid comment status value provided: '$status'.", 400 );
+ }
+ $results = array();
+ foreach( $comment_ids as $comment_id ) {
+ if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
+ continue;
+ }
+ $result = false;
+ switch( $status ) {
+ case 'approved':
+ $result = wp_set_comment_status( $comment_id, 'approve' );
+ break;
+ case 'unapproved':
+ case 'pending':
+ $result = wp_set_comment_status( $comment_id, 'hold' );
+ break;
+ case 'spam':
+ $result = wp_spam_comment( $comment_id );
+ break;
+ case 'trash':
+ $result = wp_trash_comment( $comment_id );
+ break;
+ }
+ if ( $result ) {
+ $results[] = $comment_id;
+ }
+ }
+ return $results;
+ }
+
+ /**
+ * Permanenty delete multiple comments.
+ *
+ * Comments are only permanently deleted if trash is disabled or their status is `trash` or `spam`.
+ * Otherwise they are moved to trash.
+ *
+ * @param array $comment_ids Comments to trash or delete.
+ *
+ * @return array Deleted comments IDs.
+ */
+ function bulk_delete_comments( $comment_ids ) {
+ if ( count( $comment_ids ) < 1 ) {
+ return new WP_Error( 'empty_comment_ids', 'The request must include comment_ids', 400 );
+ }
+ $results = array();
+ foreach( $comment_ids as $comment_id ) {
+ if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
+ continue;
+ }
+ if ( wp_delete_comment( $comment_id ) ) {
+ $results[] = $comment_id;
+ }
+ }
+ return $results;
+ }
+
+ /**
+ * Delete all spam or trash comments.
+ *
+ * Comments are only permanently deleted if trash is disabled or their status is `trash` or `spam`.
+ * Otherwise they are moved to trash.
+ *
+ * @param string $status Can be `spam` or `trash`.
+ *
+ * @return array Deleted comments IDs.
+ */
+ function delete_all( $status ) {
+ global $wpdb;
+ // This could potentially take a long time, so we only want to delete comments created
+ // before this operation.
+ // Comments marked `spam` or `trash` after this moment won't be touched.
+ // Core uses the `pagegen_timestamp` hidden field for this same reason.
+ $delete_time = gmdate('Y-m-d H:i:s');
+ $comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_approved = %s AND %s > comment_date_gmt", $status, $delete_time ) );
+
+ if ( count( $comment_ids ) < 1 ) {
+ return array();
+ }
+
+ return $this->bulk_delete_comments( $comment_ids );
+ }
+}
diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-comment-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-comment-endpoint.php
index 7d25d7aa..20aee2b8 100644
--- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-comment-endpoint.php
+++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-comment-endpoint.php
@@ -23,6 +23,7 @@ abstract class WPCOM_JSON_API_Comment_Endpoint extends WPCOM_JSON_API_Endpoint {
'comment' => 'The comment is a regular comment.',
'trackback' => 'The comment is a trackback.',
'pingback' => 'The comment is a pingback.',
+ 'review' => 'The comment is a product review.',
),
'like_count' => '(int) The number of likes for this comment.',
'i_like' => '(bool) Does the current user like this comment?',
@@ -47,7 +48,7 @@ abstract class WPCOM_JSON_API_Comment_Endpoint extends WPCOM_JSON_API_Endpoint {
return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
}
- $types = array( '', 'comment', 'pingback', 'trackback' );
+ $types = array( '', 'comment', 'pingback', 'trackback', 'review' );
if ( !in_array( $comment->comment_type, $types ) ) {
return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
}
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 2366653d..89d1a67c 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,8 +2,8 @@
jetpack_require_lib( 'class.media' );
-const REVISION_HISTORY_MAXIMUM_AMOUNT = 0;
-const WP_ATTACHMENT_IMAGE_ALT = '_wp_attachment_image_alt';
+define( 'REVISION_HISTORY_MAXIMUM_AMOUNT', 0 );
+define( 'WP_ATTACHMENT_IMAGE_ALT', '_wp_attachment_image_alt' );
new WPCOM_JSON_API_Edit_Media_v1_2_Endpoint( array(
'description' => 'Edit a media item.',
diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-comments-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-comments-endpoint.php
index 1e17bc18..024d1b6b 100644
--- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-comments-endpoint.php
+++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-comments-endpoint.php
@@ -195,9 +195,10 @@ class WPCOM_JSON_API_List_Comments_Endpoint extends WPCOM_JSON_API_Comment_Endpo
}
$query = array(
- 'order' => $args['order'],
- 'type' => 'any' === $args['type'] ? false : $args['type'],
- 'status' => $status,
+ 'order' => $args['order'],
+ 'type' => 'any' === $args['type'] ? false : $args['type'],
+ 'status' => $status,
+ 'type__not_in' => array( 'review' ),
);
if ( isset( $args['page'] ) ) {
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 e85b00f7..6c293b4d 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
@@ -45,6 +45,8 @@ new WPCOM_JSON_API_Site_Settings_Endpoint( array(
'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?',
'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?',
'jetpack_protect_whitelist' => '(array) List of IP addresses to whitelist',
+ 'jetpack_search_enabled' => '(bool) Enable Jetpack Search',
+ 'jetpack_search_supported' => '(bool) Jetpack Search is supported',
'infinite_scroll' => '(bool) Support infinite scroll of posts?',
'default_category' => '(int) Default post category',
'default_post_format' => '(string) Default post format',
@@ -302,6 +304,19 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint {
$jetpack_relatedposts_options[ 'enabled' ] = Jetpack::is_module_active( 'related-posts' );
}
+ $jetpack_search_supported = false;
+ if ( function_exists( 'wpcom_is_jetpack_search_supported' ) ) {
+ $jetpack_search_supported = wpcom_is_jetpack_search_supported( $blog_id );
+ }
+
+ $jetpack_search_active = false;
+ if ( method_exists( 'Jetpack', 'is_module_active' ) ) {
+ $jetpack_search_active = Jetpack::is_module_active( 'search' );
+ }
+ if ( function_exists( 'is_jetpack_module_active' ) ) {
+ $jetpack_search_active = is_jetpack_module_active( 'search', $blog_id );
+ }
+
// array_values() is necessary to ensure the array starts at index 0.
$post_categories = array_values(
array_map(
@@ -331,6 +346,8 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint {
'jetpack_relatedposts_enabled' => (bool) $jetpack_relatedposts_options[ 'enabled' ],
'jetpack_relatedposts_show_headline' => (bool) isset( $jetpack_relatedposts_options[ 'show_headline' ] ) ? $jetpack_relatedposts_options[ 'show_headline' ] : false,
'jetpack_relatedposts_show_thumbnails' => (bool) isset( $jetpack_relatedposts_options[ 'show_thumbnails' ] ) ? $jetpack_relatedposts_options[ 'show_thumbnails' ] : false,
+ 'jetpack_search_enabled' => (bool) $jetpack_search_active,
+ 'jetpack_search_supported'=> (bool) $jetpack_search_supported,
'default_category' => (int) get_option('default_category'),
'post_categories' => (array) $post_categories,
'default_post_format' => get_option( 'default_post_format' ),
@@ -523,6 +540,22 @@ class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint {
case 'jetpack_sync_non_public_post_stati':
Jetpack_Options::update_option( 'sync_non_public_post_stati', $value );
break;
+ case 'jetpack_search_enabled':
+ if ( ! method_exists( 'Jetpack', 'activate_module' ) ) {
+ break;
+ }
+ $is_wpcom = defined( 'IS_WPCOM' ) && IS_WPCOM;
+ if ( $value ) {
+ $jetpack_search_update_success = $is_wpcom
+ ? Jetpack::activate_module( $blog_id, 'search' )
+ : Jetpack::activate_module( 'search', false, false );
+ } else {
+ $jetpack_search_update_success = $is_wpcom
+ ? Jetpack::deactivate_module( $blog_id, 'search' )
+ : Jetpack::deactivate_module( 'search' );
+ }
+ $updated[ $key ] = (bool) $value;
+ break;
case 'jetpack_relatedposts_enabled':
case 'jetpack_relatedposts_show_thumbnails':
case 'jetpack_relatedposts_show_headline':
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 e494a1bb..0613352b 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
@@ -42,6 +42,8 @@ new WPCOM_JSON_API_Site_Settings_V1_2_Endpoint( array(
'jetpack_relatedposts_enabled' => '(bool) Enable related posts?',
'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?',
'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?',
+ 'jetpack_search_enabled' => '(bool) Enable Jetpack Search',
+ 'jetpack_search_supported' => '(bool) Jetpack Search supported',
'jetpack_protect_whitelist' => '(array) List of IP addresses to whitelist',
'infinite_scroll' => '(bool) Support infinite scroll of posts?',
'default_category' => '(int) Default post category',
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 316c64a4..8287a4b4 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
@@ -42,6 +42,8 @@ new WPCOM_JSON_API_Site_Settings_V1_3_Endpoint( array(
'jetpack_relatedposts_enabled' => '(bool) Enable related posts?',
'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?',
'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?',
+ 'jetpack_search_enabled' => '(bool) Enable Jetpack Search',
+ 'jetpack_search_supported' => '(bool) Jetpack Search supported',
'jetpack_protect_whitelist' => '(array) List of IP addresses to whitelist',
'infinite_scroll' => '(bool) Support infinite scroll of posts?',
'default_category' => '(int) Default post category',
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 929acde3..f6a4fbee 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
@@ -42,6 +42,8 @@ new WPCOM_JSON_API_Site_Settings_V1_4_Endpoint( array(
'jetpack_relatedposts_enabled' => '(bool) Enable related posts?',
'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?',
'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?',
+ 'jetpack_search_enabled' => '(bool) Enable Jetpack Search',
+ 'jetpack_search_supported' => '(bool) Jetpack Search supported',
'jetpack_protect_whitelist' => '(array) List of IP addresses to whitelist',
'infinite_scroll' => '(bool) Support infinite scroll of posts?',
'default_category' => '(int) Default post category',
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 6deae172..4ad5e26c 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
@@ -783,7 +783,7 @@ class WPCOM_JSON_API_Update_Post_v1_2_Endpoint extends WPCOM_JSON_API_Update_Pos
$unslashed_meta_key = wp_unslash( $meta->key ); // should match what the final key will be
$meta->key = wp_slash( $meta->key );
- $unslashed_existing_meta_key = wp_unslash( $existing_meta_item->meta_key );
+ $unslashed_existing_meta_key = isset( $existing_meta_item->meta_key ) ? wp_unslash( $existing_meta_item->meta_key ) : '';
$existing_meta_item->meta_key = wp_slash( $existing_meta_item->meta_key );
// make sure that the meta id passed matches the existing meta key
diff --git a/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-user-endpoint.php b/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-user-endpoint.php
index ef5cb2d8..8ec4c59c 100644
--- a/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-user-endpoint.php
+++ b/plugins/jetpack/json-endpoints/class.wpcom-json-api-update-user-endpoint.php
@@ -66,6 +66,30 @@ class WPCOM_JSON_API_Update_User_Endpoint extends WPCOM_JSON_API_Endpoint {
}
/**
+ * Return the domain name of a subscription
+ *
+ * @param Store_Subscription $subscription
+ * @return string
+ */
+ protected function get_subscription_domain_name( $subscription ) {
+ return $subscription->meta;
+ }
+
+ /**
+ * Get a list of the domains owned by the given user.
+ *
+ * @param int $user_id
+ * @return array
+ */
+ protected function domain_subscriptions_for_site_owned_by_user( $user_id ) {
+ $subscriptions = WPCOM_Store::get_subscriptions( get_current_blog_id(), $user_id, domains::get_domain_products() );
+
+ $domains = array_unique( array_map( array( $this, 'get_subscription_domain_name' ), $subscriptions ) );
+
+ return $domains;
+ }
+
+ /**
* Validates user input and then decides whether to remove or delete a user.
* @param int $user_id
* @return array|WP_Error
@@ -75,7 +99,14 @@ class WPCOM_JSON_API_Update_User_Endpoint extends WPCOM_JSON_API_Endpoint {
return new WP_Error( 'invalid_input', 'A valid user ID must be specified.', 400 );
}
- if ( get_current_user_id() == $user_id ) {
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $domains = $this->domain_subscriptions_for_site_owned_by_user( $user_id );
+ if ( ! empty( $domains ) ) {
+ return new WP_Error( 'user_owns_domain_subscription', join( ', ', $domains ) );
+ }
+ }
+
+ if ( get_current_user_id() == $user_id ) {
return new WP_Error( 'invalid_input', 'User can not remove or delete self through this endpoint.', 400 );
}
diff --git a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-get-database-object-backup-endpoint.php b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-get-database-object-backup-endpoint.php
new file mode 100644
index 00000000..b7134730
--- /dev/null
+++ b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-get-database-object-backup-endpoint.php
@@ -0,0 +1,97 @@
+<?php
+
+class Jetpack_JSON_API_Get_Database_Object_Backup_Endpoint extends Jetpack_JSON_API_Endpoint {
+ // /sites/%s/database-object/backup -> $blog_id
+
+ protected $needed_capabilities = array(); // This endpoint is only accessible using a site token
+ protected $object_type;
+ protected $object_id;
+
+ // Full list of database objects that can be retrieved via this endpoint.
+ protected $object_types = array(
+ 'woocommerce_attribute' => array(
+ 'table' => 'woocommerce_attribute_taxonomies',
+ 'id_field' => 'attribute_id',
+ ),
+
+ 'woocommerce_downloadable_product_permission' => array(
+ 'table' => 'woocommerce_downloadable_product_permissions',
+ 'id_field' => 'permission_id',
+ ),
+
+ 'woocommerce_order_item' => array(
+ 'table' => 'woocommerce_order_items',
+ 'id_field' => 'order_item_id',
+ 'meta_type' => 'order_item',
+ ),
+
+ 'woocommerce_payment_token' => array(
+ 'table' => 'woocommerce_payment_tokens',
+ 'id_field' => 'token_id',
+ 'meta_type' => 'payment_token',
+ ),
+
+ 'woocommerce_tax_rate' => array(
+ 'table' => 'woocommerce_tax_rates',
+ 'id_field' => 'tax_rate_id',
+ 'child_table' => 'woocommerce_tax_rate_locations',
+ 'child_id_field' => 'tax_rate_id',
+ ),
+
+ 'woocommerce_webhook' => array(
+ 'table' => 'wc_webhooks',
+ 'id_field' => 'webhook_id',
+ ),
+ );
+
+ function validate_input( $object ) {
+ $query_args = $this->query_args();
+
+ if ( empty( $query_args['object_type'] ) || empty( $query_args['object_id'] ) ) {
+ return new WP_Error( 'invalid_args', __( 'You must specify both an object type and id to fetch', 'jetpack' ), 400 );
+ }
+
+ if ( empty( $this->object_types[ $query_args['object_type'] ] ) ) {
+ return new WP_Error( 'invalid_args', __( 'Specified object_type not recognized', 'jetpack' ), 400 );
+ }
+
+ $this->object_type = $this->object_types[ $query_args['object_type'] ];
+ $this->object_id = $query_args['object_id'];
+
+ return true;
+ }
+
+ protected function result() {
+ global $wpdb;
+
+ $table = $wpdb->prefix . $this->object_type['table'];
+ $id_field = $this->object_type['id_field'];
+
+ // Fetch the requested object
+ $query = $wpdb->prepare( 'select * from `' . $table . '` where `' . $id_field . '` = %d', $this->object_id );
+ $object = $wpdb->get_row( $query );
+
+ if ( empty( $object ) ) {
+ return new WP_Error( 'object_not_found', __( 'Object not found', 'jetpack' ), 404 );
+ }
+
+ $result = array( 'object' => $object );
+
+ // Fetch associated metadata (if this object type has any)
+ if ( ! empty( $this->object_type['meta_type'] ) ) {
+ $result['meta'] = get_metadata( $this->object_type['meta_type'], $this->object_id );
+ }
+
+ // If there is a child linked table (eg: woocommerce_tax_rate_locations), fetch linked records
+ if ( ! empty( $this->object_type['child_table'] ) ) {
+ $child_table = $wpdb->prefix . $this->object_type['child_table'];
+ $child_id_field = $this->object_type['child_id_field'];
+
+ $query = $wpdb->prepare( 'select * from `' . $child_table . '` where `' . $child_id_field . '` = %d', $this->object_id );
+ $result[ 'children' ] = $wpdb->get_results( $query );
+ }
+
+ return $result;
+ }
+
+}
diff --git a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-plugins-modify-endpoint.php b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-plugins-modify-endpoint.php
index 68f6782c..7b4b854b 100644
--- a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-plugins-modify-endpoint.php
+++ b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-plugins-modify-endpoint.php
@@ -395,7 +395,7 @@ class Jetpack_JSON_API_Plugins_Modify_Endpoint extends Jetpack_JSON_API_Plugins_
/**
* Pre-upgrade action
*
- * @since 4.4
+ * @since 4.4.0
*
* @param array $plugin Plugin data
* @param array $plugin Array of plugin objects
diff --git a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-themes-modify-endpoint.php b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-themes-modify-endpoint.php
index c041158b..072bfc5c 100644
--- a/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-themes-modify-endpoint.php
+++ b/plugins/jetpack/json-endpoints/jetpack/class.jetpack-json-api-themes-modify-endpoint.php
@@ -105,7 +105,7 @@ class Jetpack_JSON_API_Themes_Modify_Endpoint extends Jetpack_JSON_API_Themes_En
/**
* Pre-upgrade action
*
- * @since 4.4
+ * @since 4.4.0
*
* @param object $theme WP_Theme object
* @param array $themes Array of theme objects
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 919c9ee6..e6f25903 100644
--- a/plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php
+++ b/plugins/jetpack/json-endpoints/jetpack/json-api-jetpack-endpoints.php
@@ -956,6 +956,35 @@ new Jetpack_JSON_API_Cron_Unschedule_Endpoint( array(
// BACKUPS
+// GET /sites/%s/database-object/backup
+require_once( $json_jetpack_endpoints_dir . 'class.jetpack-json-api-get-database-object-backup-endpoint.php' );
+new Jetpack_JSON_API_Get_Database_Object_Backup_Endpoint( array(
+ 'description' => 'Fetch a backup of a database object, along with all of its metadata',
+ 'group' => '__do_not_document',
+ 'method' => 'GET',
+ 'path' => '/sites/%s/database-object/backup',
+ 'stat' => 'database-objects:1:backup',
+ 'allow_jetpack_site_auth' => true,
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+ 'query_parameters' => array(
+ 'object_type' => '(string) Type of object to fetch from the database',
+ 'object_id' => '(int) ID of the database object to fetch',
+ ),
+ 'response_format' => array(
+ 'object' => '(array) Database object row',
+ 'meta' => '(array) Associative array of key/value metadata associated with the row',
+ 'children' => '(array) Where appropriate, child records associated with the object. eg: Woocommerce tax rate locations',
+ ),
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ ),
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/example.wordpress.org/database-object/backup'
+) );
+
// GET /sites/%s/comments/%d/backup
require_once( $json_jetpack_endpoints_dir . 'class.jetpack-json-api-get-comment-backup-endpoint.php' );
new Jetpack_JSON_API_Get_Comment_Backup_Endpoint( array(