From 9934ec8420522748092faab26c7f40e3c9126dc9 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Thu, 30 May 2019 14:20:45 +0100 Subject: [PATCH] Webhooks --- .../Webhooks.php} | 86 ++--- ...-rest-webhook-deliveries-v1-controller.php | 314 ------------------ 2 files changed, 49 insertions(+), 351 deletions(-) rename src/RestApi/Version4/{class-wc-rest-webhooks-v1-controller.php => Controllers/Webhooks.php} (92%) delete mode 100644 src/RestApi/Version4/class-wc-rest-webhook-deliveries-v1-controller.php diff --git a/src/RestApi/Version4/class-wc-rest-webhooks-v1-controller.php b/src/RestApi/Version4/Controllers/Webhooks.php similarity index 92% rename from src/RestApi/Version4/class-wc-rest-webhooks-v1-controller.php rename to src/RestApi/Version4/Controllers/Webhooks.php index 97b1640ac56..69f882c76a2 100644 --- a/src/RestApi/Version4/class-wc-rest-webhooks-v1-controller.php +++ b/src/RestApi/Version4/Controllers/Webhooks.php @@ -5,27 +5,25 @@ * Handles requests to the /webhooks endpoint. * * @package WooCommerce/RestApi - * @since 3.0.0 */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} +namespace WooCommerce\RestApi\Version4\Controllers; + +defined( 'ABSPATH' ) || exit; + +use \WC_REST_Controller; /** * REST API Webhooks controller class. - * - * @package WooCommerce/RestApi - * @extends WC_REST_Controller */ -class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller { +class Webhooks extends WC_REST_Controller { /** * Endpoint namespace. * * @var string */ - protected $namespace = 'wc/v1'; + protected $namespace = 'wc/v4'; /** * Route base. @@ -214,7 +212,7 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller { * @return string */ protected function get_default_api_version() { - return 'wp_api_v1'; + return 'wp_api_v4'; } /** @@ -538,9 +536,9 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller { /** * Prepare a single webhook output for response. * - * @param int $id Webhook ID or object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response $response Response data. + * @param int $id Webhook ID. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response $response */ public function prepare_item_for_response( $id, $request ) { $webhook = wc_get_webhook( $id ); @@ -549,17 +547,19 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller { return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) ); } - $data = array( - 'id' => $webhook->get_id(), - 'name' => $webhook->get_name(), - 'status' => $webhook->get_status(), - 'topic' => $webhook->get_topic(), - 'resource' => $webhook->get_resource(), - 'event' => $webhook->get_event(), - 'hooks' => $webhook->get_hooks(), - 'delivery_url' => $webhook->get_delivery_url(), - 'date_created' => wc_rest_prepare_date_response( $webhook->get_date_created() ), - 'date_modified' => wc_rest_prepare_date_response( $webhook->get_date_modified() ), + $data = array( + 'id' => $webhook->get_id(), + 'name' => $webhook->get_name(), + 'status' => $webhook->get_status(), + 'topic' => $webhook->get_topic(), + 'resource' => $webhook->get_resource(), + 'event' => $webhook->get_event(), + 'hooks' => $webhook->get_hooks(), + 'delivery_url' => $webhook->get_delivery_url(), + 'date_created' => wc_rest_prepare_date_response( $webhook->get_date_created(), false ), + 'date_created_gmt' => wc_rest_prepare_date_response( $webhook->get_date_created() ), + 'date_modified' => wc_rest_prepare_date_response( $webhook->get_date_modified(), false ), + 'date_modified_gmt' => wc_rest_prepare_date_response( $webhook->get_date_modified() ), ); $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; @@ -569,7 +569,7 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $webhook->get_id() ) ); + $response->add_links( $this->prepare_links( $webhook->get_id(), $request ) ); /** * Filter webhook object returned from the REST API. @@ -611,74 +611,86 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller { 'title' => 'webhook', 'type' => 'object', 'properties' => array( - 'id' => array( + 'id' => array( 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'name' => array( + 'name' => array( 'description' => __( 'A friendly name for the webhook.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), ), - 'status' => array( + 'status' => array( 'description' => __( 'Webhook status.', 'woocommerce' ), 'type' => 'string', 'default' => 'active', 'enum' => array_keys( wc_get_webhook_statuses() ), 'context' => array( 'view', 'edit' ), ), - 'topic' => array( + 'topic' => array( 'description' => __( 'Webhook topic.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), ), - 'resource' => array( + 'resource' => array( 'description' => __( 'Webhook resource.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'event' => array( + 'event' => array( 'description' => __( 'Webhook event.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'hooks' => array( + 'hooks' => array( 'description' => __( 'WooCommerce action names associated with the webhook.', 'woocommerce' ), 'type' => 'array', 'context' => array( 'view', 'edit' ), 'readonly' => true, 'items' => array( - 'type' => 'string', + 'type' => 'string', ), ), - 'delivery_url' => array( + 'delivery_url' => array( 'description' => __( 'The URL where the webhook payload is delivered.', 'woocommerce' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'secret' => array( + 'secret' => array( 'description' => __( "Secret key used to generate a hash of the delivered webhook and provided in the request headers. This will default to a MD5 hash from the current user's ID|username if not provided.", 'woocommerce' ), 'type' => 'string', 'context' => array( 'edit' ), ), - 'date_created' => array( + 'date_created' => array( 'description' => __( "The date the webhook was created, in the site's timezone.", 'woocommerce' ), 'type' => 'date-time', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'date_modified' => array( + 'date_created_gmt' => array( + 'description' => __( 'The date the webhook was created, as GMT.', 'woocommerce' ), + 'type' => 'date-time', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + ), + 'date_modified' => array( 'description' => __( "The date the webhook was last modified, in the site's timezone.", 'woocommerce' ), 'type' => 'date-time', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), + 'date_modified_gmt' => array( + 'description' => __( 'The date the webhook was last modified, as GMT.', 'woocommerce' ), + 'type' => 'date-time', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + ), ), ); diff --git a/src/RestApi/Version4/class-wc-rest-webhook-deliveries-v1-controller.php b/src/RestApi/Version4/class-wc-rest-webhook-deliveries-v1-controller.php deleted file mode 100644 index a3b2cd81981..00000000000 --- a/src/RestApi/Version4/class-wc-rest-webhook-deliveries-v1-controller.php +++ /dev/null @@ -1,314 +0,0 @@ -/deliveries endpoint. - * - * @author WooThemes - * @category API - * @package WooCommerce/RestApi - * @since 3.0.0 - */ - -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - -/** - * REST API Webhook Deliveries controller class. - * - * @deprecated 3.3.0 Webhooks deliveries logs now uses logging system. - * @package WooCommerce/RestApi - * @extends WC_REST_Controller - */ -class WC_REST_Webhook_Deliveries_V1_Controller extends WC_REST_Controller { - - /** - * Endpoint namespace. - * - * @var string - */ - protected $namespace = 'wc/v1'; - - /** - * Route base. - * - * @var string - */ - protected $rest_base = 'webhooks/(?P[\d]+)/deliveries'; - - /** - * Register the routes for webhook deliveries. - */ - public function register_routes() { - register_rest_route( $this->namespace, '/' . $this->rest_base, array( - 'args' => array( - 'webhook_id' => array( - 'description' => __( 'Unique identifier for the webhook.', 'woocommerce' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - 'args' => $this->get_collection_params(), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) ); - - register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( - 'args' => array( - 'webhook_id' => array( - 'description' => __( 'Unique identifier for the webhook.', 'woocommerce' ), - 'type' => 'integer', - ), - 'id' => array( - 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) ); - } - - /** - * Check whether a given request has permission to read taxes. - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_Error|boolean - */ - public function get_items_permissions_check( $request ) { - if ( ! wc_rest_check_manager_permissions( 'webhooks', 'read' ) ) { - return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); - } - - return true; - } - - /** - * Check if a given request has access to read a tax. - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_Error|boolean - */ - public function get_item_permissions_check( $request ) { - if ( ! wc_rest_check_manager_permissions( 'webhooks', 'read' ) ) { - return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); - } - - return true; - } - - /** - * Get all webhook deliveries. - * - * @param WP_REST_Request $request - * - * @return array|WP_Error - */ - public function get_items( $request ) { - $webhook = wc_get_webhook( (int) $request['webhook_id'] ); - - if ( empty( $webhook ) || is_null( $webhook ) ) { - return new WP_Error( 'woocommerce_rest_webhook_invalid_id', __( 'Invalid webhook ID.', 'woocommerce' ), array( 'status' => 404 ) ); - } - - $logs = array(); - $data = array(); - foreach ( $logs as $log ) { - $delivery = $this->prepare_item_for_response( (object) $log, $request ); - $delivery = $this->prepare_response_for_collection( $delivery ); - $data[] = $delivery; - } - - return rest_ensure_response( $data ); - } - - /** - * Get a single webhook delivery. - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_Error|WP_REST_Response - */ - public function get_item( $request ) { - $id = (int) $request['id']; - $webhook = wc_get_webhook( (int) $request['webhook_id'] ); - - if ( empty( $webhook ) || is_null( $webhook ) ) { - return new WP_Error( 'woocommerce_rest_webhook_invalid_id', __( 'Invalid webhook ID.', 'woocommerce' ), array( 'status' => 404 ) ); - } - - $log = array(); - - if ( empty( $id ) || empty( $log ) ) { - return new WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 404 ) ); - } - - $delivery = $this->prepare_item_for_response( (object) $log, $request ); - $response = rest_ensure_response( $delivery ); - - return $response; - } - - /** - * Prepare a single webhook delivery output for response. - * - * @param stdClass $log Delivery log object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response $response Response data. - */ - public function prepare_item_for_response( $log, $request ) { - $data = (array) $log; - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - // Wrap the data in a response object. - $response = rest_ensure_response( $data ); - - $response->add_links( $this->prepare_links( $log ) ); - - /** - * Filter webhook delivery object returned from the REST API. - * - * @param WP_REST_Response $response The response object. - * @param stdClass $log Delivery log object used to create response. - * @param WP_REST_Request $request Request object. - */ - return apply_filters( 'woocommerce_rest_prepare_webhook_delivery', $response, $log, $request ); - } - - /** - * Prepare links for the request. - * - * @param stdClass $log Delivery log object. - * @return array Links for the given webhook delivery. - */ - protected function prepare_links( $log ) { - $webhook_id = (int) $log->request_headers['X-WC-Webhook-ID']; - $base = str_replace( '(?P[\d]+)', $webhook_id, $this->rest_base ); - $links = array( - 'self' => array( - 'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $base, $log->id ) ), - ), - 'collection' => array( - 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ), - ), - 'up' => array( - 'href' => rest_url( sprintf( '/%s/webhooks/%d', $this->namespace, $webhook_id ) ), - ), - ); - - return $links; - } - - /** - * Get the Webhook's schema, conforming to JSON Schema. - * - * @return array - */ - public function get_item_schema() { - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'webhook_delivery', - 'type' => 'object', - 'properties' => array( - 'id' => array( - 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), - 'type' => 'integer', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'duration' => array( - 'description' => __( 'The delivery duration, in seconds.', 'woocommerce' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'summary' => array( - 'description' => __( 'A friendly summary of the response including the HTTP response code, message, and body.', 'woocommerce' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'request_url' => array( - 'description' => __( 'The URL where the webhook was delivered.', 'woocommerce' ), - 'type' => 'string', - 'format' => 'uri', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'request_headers' => array( - 'description' => __( 'Request headers.', 'woocommerce' ), - 'type' => 'array', - 'context' => array( 'view' ), - 'readonly' => true, - 'items' => array( - 'type' => 'string', - ), - ), - 'request_body' => array( - 'description' => __( 'Request body.', 'woocommerce' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'response_code' => array( - 'description' => __( 'The HTTP response code from the receiving server.', 'woocommerce' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'response_message' => array( - 'description' => __( 'The HTTP response message from the receiving server.', 'woocommerce' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'response_headers' => array( - 'description' => __( 'Array of the response headers from the receiving server.', 'woocommerce' ), - 'type' => 'array', - 'context' => array( 'view' ), - 'readonly' => true, - 'items' => array( - 'type' => 'string', - ), - ), - 'response_body' => array( - 'description' => __( 'The response body from the receiving server.', 'woocommerce' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'date_created' => array( - 'description' => __( "The date the webhook delivery was logged, in the site's timezone.", 'woocommerce' ), - 'type' => 'date-time', - 'context' => array( 'view', 'edit' ), - 'readonly' => true, - ), - ), - ); - - return $this->add_additional_fields_schema( $schema ); - } - - /** - * Get the query params for collections. - * - * @return array - */ - public function get_collection_params() { - return array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ); - } -}