Passed
Push — master ( 6176aa...f7c939 )
by Mike
03:08
created

Webhooks   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 678
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 355
dl 0
loc 678
rs 7.44
c 0
b 0
f 0
wmc 52

12 Methods

Rating   Name   Duplication   Size   Complexity  
A delete_item() 0 40 6
B register_routes() 0 78 1
A prepare_item_for_response() 0 39 4
A get_default_api_version() 0 2 1
A prepare_links() 0 11 1
A prepare_item_for_database() 0 45 6
B get_item_schema() 0 90 1
A get_collection_params() 0 69 1
C update_item() 0 66 12
B create_item() 0 52 9
B get_items() 0 62 8
A get_item() 0 11 2

How to fix   Complexity   

Complex Class

Complex classes like Webhooks often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Webhooks, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * REST API Webhooks controller
4
 *
5
 * Handles requests to the /webhooks endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4;
11
12
defined( 'ABSPATH' ) || exit;
13
14
/**
15
 * REST API Webhooks controller class.
16
 */
17
class Webhooks extends AbstractController {
18
19
	/**
20
	 * Route base.
21
	 *
22
	 * @var string
23
	 */
24
	protected $rest_base = 'webhooks';
25
26
	/**
27
	 * Permission to check.
28
	 *
29
	 * @var string
30
	 */
31
	protected $resource_type = 'webhooks';
32
33
	/**
34
	 * Post type.
35
	 *
36
	 * @var string
37
	 */
38
	protected $post_type = 'shop_webhook';
39
40
	/**
41
	 * Register the routes for webhooks.
42
	 */
43
	public function register_routes() {
44
		register_rest_route(
45
			$this->namespace,
46
			'/' . $this->rest_base,
47
			array(
48
				array(
49
					'methods'             => \WP_REST_Server::READABLE,
50
					'callback'            => array( $this, 'get_items' ),
51
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
52
					'args'                => $this->get_collection_params(),
53
				),
54
				array(
55
					'methods'             => \WP_REST_Server::CREATABLE,
56
					'callback'            => array( $this, 'create_item' ),
57
					'permission_callback' => array( $this, 'create_item_permissions_check' ),
58
					'args'                => array_merge(
59
						$this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ),
60
						array(
61
							'topic'        => array(
62
								'required'    => true,
63
								'type'        => 'string',
64
								'description' => __( 'Webhook topic.', 'woocommerce' ),
65
							),
66
							'delivery_url' => array(
67
								'required'    => true,
68
								'type'        => 'string',
69
								'description' => __( 'Webhook delivery URL.', 'woocommerce' ),
70
							),
71
						)
72
					),
73
				),
74
				'schema' => array( $this, 'get_public_item_schema' ),
75
			),
76
			true
77
		);
78
79
		register_rest_route(
80
			$this->namespace,
81
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
82
			array(
83
				'args'   => array(
84
					'id' => array(
85
						'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
86
						'type'        => 'integer',
87
					),
88
				),
89
				array(
90
					'methods'             => \WP_REST_Server::READABLE,
91
					'callback'            => array( $this, 'get_item' ),
92
					'permission_callback' => array( $this, 'get_item_permissions_check' ),
93
					'args'                => array(
94
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
95
					),
96
				),
97
				array(
98
					'methods'             => \WP_REST_Server::EDITABLE,
99
					'callback'            => array( $this, 'update_item' ),
100
					'permission_callback' => array( $this, 'update_item_permissions_check' ),
101
					'args'                => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ),
102
				),
103
				array(
104
					'methods'             => \WP_REST_Server::DELETABLE,
105
					'callback'            => array( $this, 'delete_item' ),
106
					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
107
					'args'                => array(
108
						'force' => array(
109
							'default'     => false,
110
							'type'        => 'boolean',
111
							'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
112
						),
113
					),
114
				),
115
				'schema' => array( $this, 'get_public_item_schema' ),
116
			),
117
			true
118
		);
119
120
		$this->register_batch_route();
121
	}
122
123
	/**
124
	 * Get the default REST API version.
125
	 *
126
	 * @since  3.0.0
127
	 * @return string
128
	 */
129
	protected function get_default_api_version() {
130
		return 'wp_api_v4';
131
	}
132
133
	/**
134
	 * Get all webhooks.
135
	 *
136
	 * @param \WP_REST_Request $request Full details about the request.
137
	 * @return \WP_Error|\WP_REST_Response
138
	 */
139
	public function get_items( $request ) {
140
		$args            = array();
141
		$args['order']   = $request['order'];
142
		$args['orderby'] = $request['orderby'];
143
		$args['status']  = 'all' === $request['status'] ? '' : $request['status'];
144
		$args['include'] = implode( ',', $request['include'] );
0 ignored issues
show
Bug introduced by
It seems like $request['include'] can also be of type null; however, parameter $pieces of implode() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
		$args['include'] = implode( ',', /** @scrutinizer ignore-type */ $request['include'] );
Loading history...
145
		$args['exclude'] = implode( ',', $request['exclude'] );
146
		$args['limit']   = $request['per_page'];
147
		$args['search']  = $request['search'];
148
		$args['before']  = $request['before'];
149
		$args['after']   = $request['after'];
150
151
		if ( empty( $request['offset'] ) ) {
152
			$args['offset'] = 1 < $request['page'] ? ( $request['page'] - 1 ) * $args['limit'] : 0;
153
		}
154
155
		/**
156
		 * Filter arguments, before passing to WC_Webhook_Data_Store->search_webhooks, when querying webhooks via the REST API.
157
		 *
158
		 * @param array           $args    Array of arguments for $wpdb->get_results().
159
		 * @param \WP_REST_Request $request The current request.
160
		 */
161
		$prepared_args = apply_filters( 'woocommerce_rest_webhook_query', $args, $request );
162
		unset( $prepared_args['page'] );
163
		$prepared_args['paginate'] = true;
164
165
		// Get the webhooks.
166
		$webhooks    = array();
167
		$data_store  = \WC_Data_Store::load( 'webhook' );
168
		$results     = $data_store->search_webhooks( $prepared_args );
169
		$webhook_ids = $results->webhooks;
170
171
		foreach ( $webhook_ids as $webhook_id ) {
172
			$data       = $this->prepare_item_for_response( $webhook_id, $request );
173
			$webhooks[] = $this->prepare_response_for_collection( $data );
174
		}
175
176
		$response       = rest_ensure_response( $webhooks );
177
		$per_page       = (int) $prepared_args['limit'];
178
		$page           = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
179
		$total_webhooks = $results->total;
180
		$max_pages      = $results->max_num_pages;
181
		$base           = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
182
183
		$response->header( 'X-WP-Total', $total_webhooks );
184
		$response->header( 'X-WP-TotalPages', $max_pages );
185
186
		if ( $page > 1 ) {
187
			$prev_page = $page - 1;
188
			if ( $prev_page > $max_pages ) {
189
				$prev_page = $max_pages;
190
			}
191
			$prev_link = add_query_arg( 'page', $prev_page, $base );
192
			$response->link_header( 'prev', $prev_link );
193
		}
194
		if ( $max_pages > $page ) {
195
			$next_page = $page + 1;
196
			$next_link = add_query_arg( 'page', $next_page, $base );
197
			$response->link_header( 'next', $next_link );
198
		}
199
200
		return $response;
201
	}
202
203
	/**
204
	 * Get a single item.
205
	 *
206
	 * @param \WP_REST_Request $request Full details about the request.
207
	 * @return \WP_Error|\WP_REST_Response
208
	 */
209
	public function get_item( $request ) {
210
		$id = (int) $request['id'];
211
212
		if ( empty( $id ) ) {
213
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 404 ) );
214
		}
215
216
		$data     = $this->prepare_item_for_response( $id, $request );
217
		$response = rest_ensure_response( $data );
218
219
		return $response;
220
	}
221
222
	/**
223
	 * Create a single webhook.
224
	 *
225
	 * @param \WP_REST_Request $request Full details about the request.
226
	 * @return \WP_Error|\WP_REST_Response
227
	 */
228
	public function create_item( $request ) {
229
		if ( ! empty( $request['id'] ) ) {
230
			/* translators: %s: post type */
231
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
232
		}
233
234
		// Validate topic.
235
		if ( empty( $request['topic'] ) || ! wc_is_webhook_valid_topic( strtolower( $request['topic'] ) ) ) {
236
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_topic", __( 'Webhook topic is required and must be valid.', 'woocommerce' ), array( 'status' => 400 ) );
237
		}
238
239
		// Validate delivery URL.
240
		if ( empty( $request['delivery_url'] ) || ! wc_is_valid_url( $request['delivery_url'] ) ) {
241
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_delivery_url", __( 'Webhook delivery URL must be a valid URL starting with http:// or https://.', 'woocommerce' ), array( 'status' => 400 ) );
242
		}
243
244
		$post = $this->prepare_item_for_database( $request );
245
		if ( is_wp_error( $post ) ) {
246
			return $post;
247
		}
248
249
		$webhook = new \WC_Webhook();
250
		$webhook->set_name( $post->post_title );
0 ignored issues
show
Bug introduced by
The property post_title does not seem to exist on WP_Error.
Loading history...
251
		$webhook->set_user_id( $post->post_author );
0 ignored issues
show
Bug introduced by
The property post_author does not seem to exist on WP_Error.
Loading history...
252
		$webhook->set_status( 'publish' === $post->post_status ? 'active' : 'disabled' );
0 ignored issues
show
Bug introduced by
The property post_status does not seem to exist on WP_Error.
Loading history...
253
		$webhook->set_topic( $request['topic'] );
254
		$webhook->set_delivery_url( $request['delivery_url'] );
255
		$webhook->set_secret( ! empty( $request['secret'] ) ? $request['secret'] : wp_generate_password( 50, true, true ) );
256
		$webhook->set_api_version( $this->get_default_api_version() );
257
		$webhook->save();
258
259
		$this->update_additional_fields_for_object( $webhook, $request );
0 ignored issues
show
Bug introduced by
$webhook of type WC_Webhook is incompatible with the type array expected by parameter $object of WP_REST_Controller::upda...nal_fields_for_object(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

259
		$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $webhook, $request );
Loading history...
260
261
		/**
262
		 * Fires after a single item is created or updated via the REST API.
263
		 *
264
		 * @param WC_Webhook      $webhook  Webhook data.
265
		 * @param \WP_REST_Request $request  Request object.
266
		 * @param bool            $creating True when creating item, false when updating.
267
		 */
268
		do_action( 'woocommerce_rest_insert_webhook_object', $webhook, $request, true );
269
270
		$request->set_param( 'context', 'edit' );
271
		$response = $this->prepare_item_for_response( $webhook->get_id(), $request );
272
		$response = rest_ensure_response( $response );
273
		$response->set_status( 201 );
274
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $webhook->get_id() ) ) );
275
276
		// Send ping.
277
		$webhook->deliver_ping();
278
279
		return $response;
280
	}
281
282
	/**
283
	 * Update a single webhook.
284
	 *
285
	 * @param \WP_REST_Request $request Full details about the request.
286
	 * @return \WP_Error|\WP_REST_Response
287
	 */
288
	public function update_item( $request ) {
289
		$id      = (int) $request['id'];
290
		$webhook = wc_get_webhook( $id );
291
292
		if ( empty( $webhook ) || is_null( $webhook ) ) {
293
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
294
		}
295
296
		// Update topic.
297
		if ( ! empty( $request['topic'] ) ) {
298
			if ( wc_is_webhook_valid_topic( strtolower( $request['topic'] ) ) ) {
299
				$webhook->set_topic( $request['topic'] );
300
			} else {
301
				return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_topic", __( 'Webhook topic must be valid.', 'woocommerce' ), array( 'status' => 400 ) );
302
			}
303
		}
304
305
		// Update delivery URL.
306
		if ( ! empty( $request['delivery_url'] ) ) {
307
			if ( wc_is_valid_url( $request['delivery_url'] ) ) {
308
				$webhook->set_delivery_url( $request['delivery_url'] );
309
			} else {
310
				return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_delivery_url", __( 'Webhook delivery URL must be a valid URL starting with http:// or https://.', 'woocommerce' ), array( 'status' => 400 ) );
311
			}
312
		}
313
314
		// Update secret.
315
		if ( ! empty( $request['secret'] ) ) {
316
			$webhook->set_secret( $request['secret'] );
317
		}
318
319
		// Update status.
320
		if ( ! empty( $request['status'] ) ) {
321
			if ( wc_is_webhook_valid_status( strtolower( $request['status'] ) ) ) {
322
				$webhook->set_status( $request['status'] );
323
			} else {
324
				return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_status", __( 'Webhook status must be valid.', 'woocommerce' ), array( 'status' => 400 ) );
325
			}
326
		}
327
328
		$post = $this->prepare_item_for_database( $request );
329
		if ( is_wp_error( $post ) ) {
330
			return $post;
331
		}
332
333
		if ( isset( $post->post_title ) ) {
334
			$webhook->set_name( $post->post_title );
335
		}
336
337
		$webhook->save();
338
339
		$this->update_additional_fields_for_object( $webhook, $request );
0 ignored issues
show
Bug introduced by
$webhook of type WC_Webhook is incompatible with the type array expected by parameter $object of WP_REST_Controller::upda...nal_fields_for_object(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

339
		$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $webhook, $request );
Loading history...
340
341
		/**
342
		 * Fires after a single item is created or updated via the REST API.
343
		 *
344
		 * @param WC_Webhook      $webhook  Webhook data.
345
		 * @param \WP_REST_Request $request  Request object.
346
		 * @param bool            $creating True when creating item, false when updating.
347
		 */
348
		do_action( 'woocommerce_rest_insert_webhook_object', $webhook, $request, false );
349
350
		$request->set_param( 'context', 'edit' );
351
		$response = $this->prepare_item_for_response( $webhook->get_id(), $request );
352
353
		return rest_ensure_response( $response );
354
	}
355
356
	/**
357
	 * Delete a single webhook.
358
	 *
359
	 * @param \WP_REST_Request $request Full details about the request.
360
	 * @return \WP_REST_Response|\WP_Error
361
	 */
362
	public function delete_item( $request ) {
363
		$id    = (int) $request['id'];
364
		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
365
366
		// We don't support trashing for this type, error out.
367
		if ( ! $force ) {
368
			return new \WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Webhooks do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
369
		}
370
371
		$webhook = wc_get_webhook( $id );
372
373
		if ( empty( $webhook ) || is_null( $webhook ) ) {
374
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 404 ) );
375
		}
376
377
		$request->set_param( 'context', 'edit' );
378
		$previous = $this->prepare_item_for_response( $webhook, $request );
0 ignored issues
show
Bug introduced by
$webhook of type WC_Webhook is incompatible with the type integer expected by parameter $id of WooCommerce\RestApi\Cont...are_item_for_response(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

378
		$previous = $this->prepare_item_for_response( /** @scrutinizer ignore-type */ $webhook, $request );
Loading history...
379
		$result   = $webhook->delete( true );
380
		if ( ! $result ) {
381
			/* translators: %s: post type */
382
			return new WP_Error( 'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 500 ) );
0 ignored issues
show
Bug introduced by
The type WooCommerce\RestApi\Controllers\Version4\WP_Error was not found. Did you mean WP_Error? If so, make sure to prefix the type with \.
Loading history...
383
		}
384
		$response = new \WP_REST_Response();
385
		$response->set_data(
386
			array(
387
				'deleted'  => true,
388
				'previous' => $previous->get_data(),
389
			)
390
		);
391
392
		/**
393
		 * Fires after a single item is deleted or trashed via the REST API.
394
		 *
395
		 * @param WC_Webhook       $webhook     The deleted or trashed item.
396
		 * @param \WP_REST_Response $response The response data.
397
		 * @param \WP_REST_Request  $request  The request sent to the API.
398
		 */
399
		do_action( 'woocommerce_rest_delete_webhook_object', $webhook, $response, $request );
400
401
		return $response;
402
	}
403
404
	/**
405
	 * Prepare a single webhook for create or update.
406
	 *
407
	 * @param \WP_REST_Request $request Request object.
408
	 * @return \WP_Error|stdClass $data Post object.
0 ignored issues
show
Bug introduced by
The type WooCommerce\RestApi\Controllers\Version4\stdClass was not found. Did you mean stdClass? If so, make sure to prefix the type with \.
Loading history...
409
	 */
410
	protected function prepare_item_for_database( $request ) {
411
		$data = new \stdClass();
412
413
		// Post ID.
414
		if ( isset( $request['id'] ) ) {
415
			$data->ID = absint( $request['id'] );
416
		}
417
418
		// Validate required POST fields.
419
		if ( 'POST' === $request->get_method() && empty( $data->ID ) ) {
420
			$data->post_title = ! empty( $request['name'] ) ? $request['name'] : sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ); // @codingStandardsIgnoreLine
421
422
			// Post author.
423
			$data->post_author = get_current_user_id();
424
425
			// Post password.
426
			$data->post_password = 'webhook_' . wp_generate_password();
427
428
			// Post status.
429
			$data->post_status = 'publish';
430
		} else {
431
432
			// Allow edit post title.
433
			if ( ! empty( $request['name'] ) ) {
434
				$data->post_title = $request['name'];
435
			}
436
		}
437
438
		// Comment status.
439
		$data->comment_status = 'closed';
440
441
		// Ping status.
442
		$data->ping_status = 'closed';
443
444
		/**
445
		 * Filter the query_vars used in `get_items` for the constructed query.
446
		 *
447
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
448
		 * prepared for insertion.
449
		 *
450
		 * @param \stdClass        $data An object representing a single item prepared
451
		 *                                       for inserting or updating the database.
452
		 * @param \WP_REST_Request $request       Request object.
453
		 */
454
		return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}", $data, $request );
455
	}
456
457
	/**
458
	 * Prepare a single webhook output for response.
459
	 *
460
	 * @param int              $id       Webhook ID.
461
	 * @param \WP_REST_Request $request  Request object.
462
	 * @return \WP_REST_Response $response
463
	 */
464
	public function prepare_item_for_response( $id, $request ) {
465
		$webhook = wc_get_webhook( $id );
466
467
		if ( empty( $webhook ) || is_null( $webhook ) ) {
468
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
469
		}
470
471
		$data = array(
472
			'id'                => $webhook->get_id(),
473
			'name'              => $webhook->get_name(),
474
			'status'            => $webhook->get_status(),
475
			'topic'             => $webhook->get_topic(),
476
			'resource'          => $webhook->get_resource(),
477
			'event'             => $webhook->get_event(),
478
			'hooks'             => $webhook->get_hooks(),
479
			'delivery_url'      => $webhook->get_delivery_url(),
480
			'date_created'      => wc_rest_prepare_date_response( $webhook->get_date_created(), false ),
481
			'date_created_gmt'  => wc_rest_prepare_date_response( $webhook->get_date_created() ),
482
			'date_modified'     => wc_rest_prepare_date_response( $webhook->get_date_modified(), false ),
483
			'date_modified_gmt' => wc_rest_prepare_date_response( $webhook->get_date_modified() ),
484
		);
485
486
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
487
		$data    = $this->add_additional_fields_to_object( $data, $request );
488
		$data    = $this->filter_response_by_context( $data, $context );
489
490
		// Wrap the data in a response object.
491
		$response = rest_ensure_response( $data );
492
493
		$response->add_links( $this->prepare_links( $webhook->get_id() ) );
494
495
		/**
496
		 * Filter webhook object returned from the REST API.
497
		 *
498
		 * @param \WP_REST_Response $response The response object.
499
		 * @param WC_Webhook       $webhook  Webhook object used to create response.
500
		 * @param \WP_REST_Request  $request  Request object.
501
		 */
502
		return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $webhook, $request );
503
	}
504
505
	/**
506
	 * Prepare links for the request.
507
	 *
508
	 * @param int $id Webhook ID.
509
	 * @return array
510
	 */
511
	protected function prepare_links( $id ) {
512
		$links = array(
513
			'self'       => array(
514
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $id ) ),
515
			),
516
			'collection' => array(
517
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
518
			),
519
		);
520
521
		return $links;
522
	}
523
524
	/**
525
	 * Get the Webhook's schema, conforming to JSON Schema.
526
	 *
527
	 * @return array
528
	 */
529
	public function get_item_schema() {
530
		$schema = array(
531
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
532
			'title'      => 'webhook',
533
			'type'       => 'object',
534
			'properties' => array(
535
				'id'                => array(
536
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
537
					'type'        => 'integer',
538
					'context'     => array( 'view', 'edit' ),
539
					'readonly'    => true,
540
				),
541
				'name'              => array(
542
					'description' => __( 'A friendly name for the webhook.', 'woocommerce' ),
543
					'type'        => 'string',
544
					'context'     => array( 'view', 'edit' ),
545
				),
546
				'status'            => array(
547
					'description' => __( 'Webhook status.', 'woocommerce' ),
548
					'type'        => 'string',
549
					'default'     => 'active',
550
					'enum'        => array_keys( wc_get_webhook_statuses() ),
551
					'context'     => array( 'view', 'edit' ),
552
				),
553
				'topic'             => array(
554
					'description' => __( 'Webhook topic.', 'woocommerce' ),
555
					'type'        => 'string',
556
					'context'     => array( 'view', 'edit' ),
557
				),
558
				'resource'          => array(
559
					'description' => __( 'Webhook resource.', 'woocommerce' ),
560
					'type'        => 'string',
561
					'context'     => array( 'view', 'edit' ),
562
					'readonly'    => true,
563
				),
564
				'event'             => array(
565
					'description' => __( 'Webhook event.', 'woocommerce' ),
566
					'type'        => 'string',
567
					'context'     => array( 'view', 'edit' ),
568
					'readonly'    => true,
569
				),
570
				'hooks'             => array(
571
					'description' => __( 'WooCommerce action names associated with the webhook.', 'woocommerce' ),
572
					'type'        => 'array',
573
					'context'     => array( 'view', 'edit' ),
574
					'readonly'    => true,
575
					'items'       => array(
576
						'type' => 'string',
577
					),
578
				),
579
				'delivery_url'      => array(
580
					'description' => __( 'The URL where the webhook payload is delivered.', 'woocommerce' ),
581
					'type'        => 'string',
582
					'format'      => 'uri',
583
					'context'     => array( 'view', 'edit' ),
584
					'readonly'    => true,
585
				),
586
				'secret'            => array(
587
					'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' ),
588
					'type'        => 'string',
589
					'context'     => array( 'edit' ),
590
				),
591
				'date_created'      => array(
592
					'description' => __( "The date the webhook was created, in the site's timezone.", 'woocommerce' ),
593
					'type'        => 'date-time',
594
					'context'     => array( 'view', 'edit' ),
595
					'readonly'    => true,
596
				),
597
				'date_created_gmt'  => array(
598
					'description' => __( 'The date the webhook was created, as GMT.', 'woocommerce' ),
599
					'type'        => 'date-time',
600
					'context'     => array( 'view', 'edit' ),
601
					'readonly'    => true,
602
				),
603
				'date_modified'     => array(
604
					'description' => __( "The date the webhook was last modified, in the site's timezone.", 'woocommerce' ),
605
					'type'        => 'date-time',
606
					'context'     => array( 'view', 'edit' ),
607
					'readonly'    => true,
608
				),
609
				'date_modified_gmt' => array(
610
					'description' => __( 'The date the webhook was last modified, as GMT.', 'woocommerce' ),
611
					'type'        => 'date-time',
612
					'context'     => array( 'view', 'edit' ),
613
					'readonly'    => true,
614
				),
615
			),
616
		);
617
618
		return $this->add_additional_fields_schema( $schema );
619
	}
620
621
	/**
622
	 * Get the query params for collections of attachments.
623
	 *
624
	 * @return array
625
	 */
626
	public function get_collection_params() {
627
		$params = parent::get_collection_params();
628
629
		$params['context']['default'] = 'view';
630
631
		$params['after']   = array(
632
			'description'       => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'woocommerce' ),
633
			'type'              => 'string',
634
			'format'            => 'date-time',
635
			'validate_callback' => 'rest_validate_request_arg',
636
		);
637
		$params['before']  = array(
638
			'description'       => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'woocommerce' ),
639
			'type'              => 'string',
640
			'format'            => 'date-time',
641
			'validate_callback' => 'rest_validate_request_arg',
642
		);
643
		$params['exclude'] = array(
644
			'description'       => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ),
645
			'type'              => 'array',
646
			'items'             => array(
647
				'type' => 'integer',
648
			),
649
			'default'           => array(),
650
			'sanitize_callback' => 'wp_parse_id_list',
651
		);
652
		$params['include'] = array(
653
			'description'       => __( 'Limit result set to specific ids.', 'woocommerce' ),
654
			'type'              => 'array',
655
			'items'             => array(
656
				'type' > 'integer',
657
			),
658
			'default'           => array(),
659
			'sanitize_callback' => 'wp_parse_id_list',
660
		);
661
		$params['offset']  = array(
662
			'description'       => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
663
			'type'              => 'integer',
664
			'sanitize_callback' => 'absint',
665
			'validate_callback' => 'rest_validate_request_arg',
666
		);
667
		$params['order']   = array(
668
			'description'       => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
669
			'type'              => 'string',
670
			'default'           => 'desc',
671
			'enum'              => array( 'asc', 'desc' ),
672
			'validate_callback' => 'rest_validate_request_arg',
673
		);
674
		$params['orderby'] = array(
675
			'description'       => __( 'Sort collection by object attribute.', 'woocommerce' ),
676
			'type'              => 'string',
677
			'default'           => 'date',
678
			'enum'              => array(
679
				'date',
680
				'id',
681
				'title',
682
			),
683
			'validate_callback' => 'rest_validate_request_arg',
684
		);
685
		$params['status']  = array(
686
			'default'           => 'all',
687
			'description'       => __( 'Limit result set to webhooks assigned a specific status.', 'woocommerce' ),
688
			'type'              => 'string',
689
			'enum'              => array( 'all', 'active', 'paused', 'disabled' ),
690
			'sanitize_callback' => 'sanitize_key',
691
			'validate_callback' => 'rest_validate_request_arg',
692
		);
693
694
		return $params;
695
	}
696
}
697