Completed
Pull Request — master (#11372)
by Matty
08:38
created

WC_Webhook::get_status()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 14

Duplication

Lines 17
Ratio 80.95 %

Importance

Changes 0
Metric Value
cc 4
eloc 14
nc 4
nop 0
dl 17
loc 21
rs 9.0534
c 0
b 0
f 0
1
<?php
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * WooCommerce Webhook class.
9
 *
10
 * This class handles storing and retrieving webhook data from the associated.
11
 * `shop_webhook` custom post type, as well as delivery logs from the `webhook_delivery`.
12
 * comment type.
13
 *
14
 * Webhooks are enqueued to their associated actions, delivered, and logged.
15
 *
16
 * @author      WooThemes
17
 * @category    Webhooks
18
 * @package     WooCommerce/Webhooks
19
 * @since       2.2
20
 */
21
class WC_Webhook {
22
23
	/** @var int webhook ID (post ID) */
24
	public $id;
25
26
	/**
27
	 * Setup webhook & load post data.
28
	 *
29
	 * @since 2.2
30
	 * @param string|int $id
31
	 */
32
	public function __construct( $id ) {
33
		$id = absint( $id );
34
35
		if ( ! $id ) {
36
			return;
37
		}
38
39
		$this->id        = $id;
40
		$this->post_data = get_post( $id );
41
	}
42
43
	/**
44
	 * Magic isset as a wrapper around metadata_exists().
45
	 *
46
	 * @since 2.2
47
	 * @param  string $key
48
	 * @return bool        true if $key isset, false otherwise
49
	 */
50
	public function __isset( $key ) {
51
		if ( ! $this->id ) {
52
			return false;
53
		}
54
		return metadata_exists( 'post', $this->id, '_' . $key );
55
	}
56
57
	/**
58
	 * Magic get, wraps get_post_meta() for all keys except $status.
59
	 *
60
	 * @since 2.2
61
	 * @param  string $key
62
	 * @return mixed       value
63
	 */
64
	public function __get( $key ) {
65
		if ( 'status' === $key ) {
66
			$value = $this->get_status();
67
		} else {
68
			$value = get_post_meta( $this->id, '_' . $key, true );
69
		}
70
71
		return $value;
72
	}
73
74
	/**
75
	 * Enqueue the hooks associated with the webhook.
76
	 *
77
	 * @since 2.2
78
	 */
79
	public function enqueue() {
80
		$hooks = $this->get_hooks();
81
		$url   = $this->get_delivery_url();
82
83
		if ( is_array( $hooks ) && ! empty( $url ) ) {
84
			foreach ( $hooks as $hook ) {
85
				add_action( $hook, array( $this, 'process' ) );
86
			}
87
		}
88
	}
89
90
	/**
91
	 * Process the webhook for delivery by verifying that it should be delivered.
92
	 * and scheduling the delivery (in the background by default, or immediately).
93
	 *
94
	 * @since 2.2
95
	 * @param mixed $arg the first argument provided from the associated hooks
96
	 */
97
	public function process( $arg ) {
98
		// verify that webhook should be processed for delivery
99
		if ( ! $this->should_deliver( $arg ) ) {
100
			return;
101
		}
102
103
		// webhooks are processed in the background by default
104
		// so as to avoid delays or failures in delivery from affecting the
105
		// user who triggered it
106
		if ( apply_filters( 'woocommerce_webhook_deliver_async', true, $this, $arg ) ) {
107
108
			// deliver in background
109
			wp_schedule_single_event( time(), 'woocommerce_deliver_webhook_async', array( $this->id, $arg ) );
110
111
		} else {
112
113
			// deliver immediately
114
			$this->deliver( $arg );
115
		}
116
	}
117
118
	/**
119
	 * Helper to check if the webhook should be delivered, as some hooks.
120
	 * (like `wp_trash_post`) will fire for every post type, not just ours.
121
	 *
122
	 * @since 2.2
123
	 * @param  mixed $arg first hook argument
124
	 * @return bool       true if webhook should be delivered, false otherwise
125
	 */
126
	private function should_deliver( $arg ) {
127
		$should_deliver = true;
128
		$current_action = current_action();
129
130
		// only active webhooks can be delivered
131
		if ( 'active' != $this->get_status() ) {
132
			$should_deliver = false;
133
134
		// only deliver deleted event for coupons, orders, and products
135
		} elseif ( 'delete_post' === $current_action && ! in_array( $GLOBALS['post_type'], array( 'shop_coupon', 'shop_order', 'product' ) ) ) {
136
			$should_deliver = false;
137
138
		} elseif ( 'delete_user' == $current_action ) {
139
			$user = get_userdata( absint( $arg ) );
140
141
			// only deliver deleted customer event for users with customer role
142
			if ( ! $user || ! in_array( 'customer', (array) $user->roles ) ) {
143
				$should_deliver = false;
144
			}
145
146
		// check if the custom order type has chosen to exclude order webhooks from triggering along with its own webhooks.
147
		} elseif ( 'order' == $this->get_resource() && ! in_array( get_post_type( absint( $arg ) ), wc_get_order_types( 'order-webhooks' ) ) ) {
148
			$should_deliver = false;
149
150
		} elseif ( 0 === strpos( $current_action, 'woocommerce_process_shop' ) || 0 === strpos( $current_action, 'woocommerce_process_product' ) ) {
151
			// the `woocommerce_process_shop_*` and `woocommerce_process_product_*` hooks
152
			// fire for create and update of products and orders, so check the post
153
			// creation date to determine the actual event
154
			$resource = get_post( absint( $arg ) );
155
156
			// a resource is considered created when the hook is executed within 10 seconds of the post creation date
157
			$resource_created = ( ( time() - 10 ) <= strtotime( $resource->post_date_gmt ) );
158
159
			if ( 'created' == $this->get_event() && ! $resource_created ) {
160
				$should_deliver = false;
161
			} elseif ( 'updated' == $this->get_event() && $resource_created ) {
162
				$should_deliver = false;
163
			}
164
		}
165
166
		/**
167
		 * Let other plugins intercept deliver for some messages queue like rabbit/zeromq
168
		 */
169
		return apply_filters( 'woocommerce_webhook_should_deliver', $should_deliver, $this, $arg );
170
	}
171
172
	/**
173
	 * Deliver the webhook payload using wp_safe_remote_request().
174
	 *
175
	 * @since 2.2
176
	 * @param mixed $arg First hook argument.
177
	 */
178
	public function deliver( $arg ) {
179
		$payload = $this->build_payload( $arg );
180
181
		// Setup request args.
182
		$http_args = array(
183
			'method'      => 'POST',
184
			'timeout'     => MINUTE_IN_SECONDS,
185
			'redirection' => 0,
186
			'httpversion' => '1.0',
187
			'blocking'    => true,
188
			'user-agent'  => sprintf( 'WooCommerce/%s Hookshot (WordPress/%s)', WC_VERSION, $GLOBALS['wp_version'] ),
189
			'body'        => trim( json_encode( $payload ) ),
190
			'headers'     => array( 'Content-Type' => 'application/json' ),
191
			'cookies'     => array(),
192
		);
193
194
		$http_args = apply_filters( 'woocommerce_webhook_http_args', $http_args, $arg, $this->id );
195
196
		// Add custom headers.
197
		$http_args['headers']['X-WC-Webhook-Source']      = home_url( '/' ); // Since 2.6.0.
198
		$http_args['headers']['X-WC-Webhook-Topic']       = $this->get_topic();
199
		$http_args['headers']['X-WC-Webhook-Resource']    = $this->get_resource();
200
		$http_args['headers']['X-WC-Webhook-Event']       = $this->get_event();
201
		$http_args['headers']['X-WC-Webhook-Signature']   = $this->generate_signature( $http_args['body'] );
202
		$http_args['headers']['X-WC-Webhook-ID']          = $this->id;
203
		$http_args['headers']['X-WC-Webhook-Delivery-ID'] = $delivery_id = $this->get_new_delivery_id();
204
205
		$start_time = microtime( true );
206
207
		// Webhook away!
208
		$response = wp_safe_remote_request( $this->get_delivery_url(), $http_args );
209
210
		$duration = round( microtime( true ) - $start_time, 5 );
211
212
		$this->log_delivery( $delivery_id, $http_args, $response, $duration );
213
214
		do_action( 'woocommerce_webhook_delivery', $http_args, $response, $duration, $arg, $this->id );
215
	}
216
217
	/**
218
	 * Build the payload data for the webhook.
219
	 *
220
	 * @since 2.2
221
	 * @param  mixed $resource_id first hook argument, typically the resource ID
222
	 * @return mixed              payload data
223
	 */
224
	private function build_payload( $resource_id ) {
225
		// build the payload with the same user context as the user who created
226
		// the webhook -- this avoids permission errors as background processing
227
		// runs with no user context
228
		$current_user = get_current_user_id();
229
		wp_set_current_user( $this->get_user_id() );
230
231
		$resource = $this->get_resource();
232
		$event    = $this->get_event();
233
234
		// if a resource has been deleted, just include the ID
235
		if ( 'deleted' == $event ) {
236
237
			$payload = array(
238
				'id' => $resource_id,
239
			);
240
241
		} else {
242
243
			// include & load API classes
244
			WC()->api->includes();
245
			WC()->api->register_resources( new WC_API_Server( '/' ) );
246
247
			switch ( $resource ) {
248
249
				case 'coupon':
250
					$payload = WC()->api->WC_API_Coupons->get_coupon( $resource_id );
251
					break;
252
253
				case 'customer':
254
					$payload = WC()->api->WC_API_Customers->get_customer( $resource_id );
255
					break;
256
257
				case 'order':
258
					$payload = WC()->api->WC_API_Orders->get_order( $resource_id );
259
					break;
260
261
				case 'product':
262
					$payload = WC()->api->WC_API_Products->get_product( $resource_id );
263
					break;
264
265
				// custom topics include the first hook argument
266
				case 'action':
267
					$payload = array(
268
						'action' => current( $this->get_hooks() ),
269
						'arg'    => $resource_id,
270
					);
271
					break;
272
273
				default:
274
					$payload = array();
275
			}
276
		}
277
278
		// restore the current user
279
		wp_set_current_user( $current_user );
280
281
		return apply_filters( 'woocommerce_webhook_payload', $payload, $resource, $resource_id, $this->id );
282
	}
283
284
	/**
285
	 * Generate a base64-encoded HMAC-SHA256 signature of the payload body so the.
286
	 * recipient can verify the authenticity of the webhook. Note that the signature.
287
	 * is calculated after the body has already been encoded (JSON by default).
288
	 *
289
	 * @since 2.2
290
	 * @param  string $payload payload data to hash
291
	 * @return string          hash
292
	 */
293
	public function generate_signature( $payload ) {
294
		$hash_algo = apply_filters( 'woocommerce_webhook_hash_algorithm', 'sha256', $payload, $this->id );
295
296
		return base64_encode( hash_hmac( $hash_algo, $payload, $this->get_secret(), true ) );
297
	}
298
299
	/**
300
	 * Create a new comment for log the delivery request/response and.
301
	 * return the ID for inclusion in the webhook request.
302
	 *
303
	 * @since 2.2
304
	 * @return int delivery (comment) ID
305
	 */
306
	public function get_new_delivery_id() {
307
		$comment_data = apply_filters( 'woocommerce_new_webhook_delivery_data', array(
308
			'comment_author'       => __( 'WooCommerce', 'woocommerce' ),
309
			'comment_author_email' => sanitize_email( sprintf( '%s@%s', strtolower( __( 'WooCommerce', 'woocommerce' ) ), isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com' ) ),
310
			'comment_post_ID'      => $this->id,
311
			'comment_agent'        => 'WooCommerce Hookshot',
312
			'comment_type'         => 'webhook_delivery',
313
			'comment_parent'       => 0,
314
			'comment_approved'     => 1,
315
		), $this->id );
316
317
		$comment_id = wp_insert_comment( $comment_data );
318
319
		return $comment_id;
320
	}
321
322
	/**
323
	 * Log the delivery request/response.
324
	 *
325
	 * @since 2.2
326
	 * @param int            $delivery_id previously created comment ID
327
	 * @param array          $request     request data
328
	 * @param array|WP_Error $response    response data
329
	 * @param float          $duration    request duration
330
	 */
331
	public function log_delivery( $delivery_id, $request, $response, $duration ) {
332
		// save request data
333
		add_comment_meta( $delivery_id, '_request_method', $request['method'] );
334
		add_comment_meta( $delivery_id, '_request_headers', array_merge( array( 'User-Agent' => $request['user-agent'] ), $request['headers'] ) );
335
		add_comment_meta( $delivery_id, '_request_body', $request['body'] );
336
337
		// parse response
338
		if ( is_wp_error( $response ) ) {
339
			$response_code    = $response->get_error_code();
340
			$response_message = $response->get_error_message();
341
			$response_headers = $response_body = array();
342
343
		} else {
344
			$response_code    = wp_remote_retrieve_response_code( $response );
345
			$response_message = wp_remote_retrieve_response_message( $response );
346
			$response_headers = wp_remote_retrieve_headers( $response );
347
			$response_body    = wp_remote_retrieve_body( $response );
348
		}
349
350
		// save response data
351
		add_comment_meta( $delivery_id, '_response_code', $response_code );
352
		add_comment_meta( $delivery_id, '_response_message', $response_message );
353
		add_comment_meta( $delivery_id, '_response_headers', $response_headers );
354
		add_comment_meta( $delivery_id, '_response_body', $response_body );
355
356
		// save duration
357
		add_comment_meta( $delivery_id, '_duration', $duration );
358
359
		// set a summary for quick display
360
		$args = array(
361
			'comment_ID'      => $delivery_id,
362
			'comment_content' => sprintf( 'HTTP %s %s: %s', $response_code, $response_message, $response_body ),
363
		);
364
365
		wp_update_comment( $args );
366
367
		// track failures
368
		if ( intval( $response_code ) >= 200 && intval( $response_code ) < 300 ) {
369
			delete_post_meta( $this->id, '_failure_count' );
370
		} else {
371
			$this->failed_delivery();
372
		}
373
374
		// keep the 25 most recent delivery logs
375
		$log = wp_count_comments( $this->id );
376
		if ( $log->total_comments > apply_filters( 'woocommerce_max_webhook_delivery_logs', 25 ) ) {
377
			global $wpdb;
378
379
			$comment_id = $wpdb->get_var( $wpdb->prepare( "SELECT comment_ID FROM {$wpdb->comments} WHERE comment_post_ID = %d ORDER BY comment_date_gmt ASC LIMIT 1", $this->id ) );
380
381
			if ( $comment_id ) {
382
				wp_delete_comment( $comment_id, true );
383
			}
384
		}
385
	}
386
387
	/**
388
	 * Track consecutive delivery failures and automatically disable the webhook.
389
	 * if more than 5 consecutive failures occur. A failure is defined as a.
390
	 * non-2xx response.
391
	 *
392
	 * @since 2.2
393
	 */
394
	private function failed_delivery() {
395
		$failures = $this->get_failure_count();
396
397
		if ( $failures > apply_filters( 'woocommerce_max_webhook_delivery_failures', 5 ) ) {
398
399
			$this->update_status( 'disabled' );
400
401
		} else {
402
403
			update_post_meta( $this->id, '_failure_count', ++$failures );
404
		}
405
	}
406
407
	/**
408
	 * Get the delivery logs for this webhook.
409
	 *
410
	 * @since 2.2
411
	 * @return array
412
	 */
413
	public function get_delivery_logs() {
414
		$args = array(
415
			'post_id' => $this->id,
416
			'status'  => 'approve',
417
			'type'    => 'webhook_delivery',
418
		);
419
420
		remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_webhook_comments' ), 10, 1 );
421
422
		$logs = get_comments( $args );
423
424
		add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_webhook_comments' ), 10, 1 );
425
426
		$delivery_logs = array();
427
428
		foreach ( $logs as $log ) {
429
430
			$log = $this->get_delivery_log( $log->comment_ID );
431
432
			$delivery_logs[] = ( ! empty( $log )  ? $log : array() );
433
		}
434
435
		return $delivery_logs;
436
	}
437
438
	/**
439
	 * Get the delivery log specified by the ID. The delivery log includes:
440
	 *
441
	 * + duration
442
	 * + summary
443
	 * + request method/url
444
	 * + request headers/body
445
	 * + response code/message/headers/body
446
	 *
447
	 * @since 2.2
448
	 * @param  int        $delivery_id
449
	 * @return bool|array              false if invalid delivery ID, array of log data otherwise
450
	 */
451
	public function get_delivery_log( $delivery_id ) {
452
		$log = get_comment( $delivery_id );
453
454
		// valid comment and ensure delivery log belongs to this webhook
455
		if ( is_null( $log ) || $log->comment_post_ID != $this->id ) {
456
			return false;
457
		}
458
459
		$delivery_log = array(
460
			'id'               => intval( $delivery_id ),
461
			'duration'         => get_comment_meta( $delivery_id, '_duration', true ),
462
			'summary'          => $log->comment_content,
463
			'request_method'   => get_comment_meta( $delivery_id, '_request_method', true ),
464
			'request_url'      => $this->get_delivery_url(),
465
			'request_headers'  => get_comment_meta( $delivery_id, '_request_headers', true ),
466
			'request_body'     => get_comment_meta( $delivery_id, '_request_body', true ),
467
			'response_code'    => get_comment_meta( $delivery_id, '_response_code', true ),
468
			'response_message' => get_comment_meta( $delivery_id, '_response_message', true ),
469
			'response_headers' => get_comment_meta( $delivery_id, '_response_headers', true ),
470
			'response_body'    => get_comment_meta( $delivery_id, '_response_body', true ),
471
			'comment'          => $log,
472
		);
473
474
		return apply_filters( 'woocommerce_webhook_delivery_log', $delivery_log, $delivery_id, $this->id );
475
	}
476
477
	/**
478
	 * Set the webhook topic and associated hooks. The topic resource & event.
479
	 * are also saved separately.
480
	 *
481
	 * @since 2.2
482
	 * @param string $topic
483
	 */
484
	public function set_topic( $topic ) {
485
		$topic = strtolower( $topic );
486
487
		list( $resource, $event ) = explode( '.', $topic );
488
489
		update_post_meta( $this->id, '_topic', $topic );
490
		update_post_meta( $this->id, '_resource', $resource );
491
		update_post_meta( $this->id, '_event', $event );
492
493
		// custom topics are mapped to a single hook
494
		if ( 'action' === $resource ) {
495
496
			update_post_meta( $this->id, '_hooks', array( $event ) );
497
498
		} else {
499
500
			// API topics have multiple hooks
501
			update_post_meta( $this->id, '_hooks', $this->get_topic_hooks( $topic ) );
502
		}
503
	}
504
505
	/**
506
	 * Get the associated hook names for a topic.
507
	 *
508
	 * @since 2.2
509
	 * @param  string $topic
510
	 * @return array         hook names
511
	 */
512
	private function get_topic_hooks( $topic ) {
513
		$topic_hooks = array(
514
			'coupon.created'   => array(
515
				'woocommerce_process_shop_coupon_meta',
516
				'woocommerce_api_create_coupon',
517
			),
518
			'coupon.updated'   => array(
519
				'woocommerce_process_shop_coupon_meta',
520
				'woocommerce_api_edit_coupon',
521
			),
522
			'coupon.deleted'   => array(
523
				'wp_trash_post',
524
			),
525
			'customer.created' => array(
526
				'user_register',
527
				'woocommerce_created_customer',
528
				'woocommerce_api_create_customer'
529
			),
530
			'customer.updated' => array(
531
				'profile_update',
532
				'woocommerce_api_edit_customer',
533
				'woocommerce_customer_save_address',
534
			),
535
			'customer.deleted' => array(
536
				'delete_user',
537
			),
538
			'order.created'    => array(
539
				'woocommerce_checkout_order_processed',
540
				'woocommerce_process_shop_order_meta',
541
				'woocommerce_api_create_order',
542
			),
543
			'order.updated'    => array(
544
				'woocommerce_process_shop_order_meta',
545
				'woocommerce_api_edit_order',
546
				'woocommerce_order_edit_status',
547
				'woocommerce_order_status_changed'
548
			),
549
			'order.deleted'    => array(
550
				'wp_trash_post',
551
			),
552
			'product.created'  => array(
553
				'woocommerce_process_product_meta',
554
				'woocommerce_api_create_product',
555
			),
556
			'product.updated'  => array(
557
				'woocommerce_process_product_meta',
558
				'woocommerce_api_edit_product',
559
			),
560
			'product.deleted'  => array(
561
				'wp_trash_post',
562
			),
563
		);
564
565
		$topic_hooks = apply_filters( 'woocommerce_webhook_topic_hooks', $topic_hooks, $this );
566
567
		return isset( $topic_hooks[ $topic ] ) ? $topic_hooks[ $topic ] : array();
568
	}
569
570
	/**
571
	 * Send a test ping to the delivery URL, sent when the webhook is first created.
572
	 *
573
	 * @since 2.2
574
	 * @return bool|WP_Error
575
	 */
576
	public function deliver_ping() {
577
		$args = array(
578
			'user-agent' => sprintf( 'WooCommerce/%s Hookshot (WordPress/%s)', WC_VERSION, $GLOBALS['wp_version'] ),
579
			'body'       => "webhook_id={$this->id}",
580
		);
581
582
		$test          = wp_safe_remote_post( $this->get_delivery_url(), $args );
583
		$response_code = wp_remote_retrieve_response_code( $test );
584
585
		if ( is_wp_error( $test ) ) {
586
			return new WP_Error( 'error', sprintf( __( 'Error: Delivery URL cannot be reached: %s', 'woocommerce' ), $test->get_error_message() ) );
587
		}
588
589
		if ( 200 !== $response_code ) {
590
			return new WP_Error( 'error', sprintf( __( 'Error: Delivery URL returned response code: %s', 'woocommerce' ), absint( $response_code ) ) );
591
		}
592
593
		return true;
594
	}
595
596
	/**
597
	 * Get the webhook status:
598
	 *
599
	 * + `active` - delivers payload.
600
	 * + `paused` - does not deliver payload, paused by admin.
601
	 * + `disabled` - does not delivery payload, paused automatically due to.
602
	 * consecutive failures.
603
	 *
604
	 * @since 2.2
605
	 * @return string status
606
	 */
607
	public function get_status() {
608 View Code Duplication
		switch ( $this->get_post_data()->post_status ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
609
610
			case 'publish':
611
				$status = 'active';
612
				break;
613
614
			case 'draft':
615
				$status = 'paused';
616
				break;
617
618
			case 'pending':
619
				$status = 'disabled';
620
				break;
621
622
			default:
623
				$status = 'paused';
624
		}
625
626
		return apply_filters( 'woocommerce_webhook_status', $status, $this->id );
627
	}
628
629
	/**
630
	 * Get the webhook i18n status.
631
	 *
632
	 * @return string
633
	 */
634
	public function get_i18n_status() {
635
		$status   = $this->get_status();
636
		$statuses = wc_get_webhook_statuses();
637
638
		return isset( $statuses[ $status ] ) ? $statuses[ $status ] : $status;
639
	}
640
641
	/**
642
	 * Update the webhook status, see get_status() for valid statuses.
643
	 *
644
	 * @since 2.2
645
	 * @param $status
646
	 */
647
	public function update_status( $status ) {
648
		global $wpdb;
649
650 View Code Duplication
		switch ( $status ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
651
652
			case 'active' :
653
				$post_status = 'publish';
654
				break;
655
656
			case 'paused' :
657
				$post_status = 'draft';
658
				break;
659
660
			case 'disabled' :
661
				$post_status = 'pending';
662
				break;
663
664
			default :
665
				$post_status = 'draft';
666
				break;
667
		}
668
669
		$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $this->id ) );
670
		clean_post_cache( $this->id );
671
	}
672
673
	/**
674
	 * Set the delivery URL.
675
	 *
676
	 * @since 2.2
677
	 * @param string $url
678
	 */
679
	public function set_delivery_url( $url ) {
680
		if ( update_post_meta( $this->id, '_delivery_url', esc_url_raw( $url, array( 'http', 'https' ) ) ) ) {
681
			update_post_meta( $this->id, '_webhook_pending_delivery', true );
682
		}
683
	}
684
685
	/**
686
	 * Get the delivery URL.
687
	 *
688
	 * @since 2.2
689
	 * @return string
690
	 */
691
	public function get_delivery_url() {
692
		return apply_filters( 'woocommerce_webhook_delivery_url', $this->delivery_url, $this->id );
693
	}
694
695
	/**
696
	 * Set the secret used for generating the HMAC-SHA256 signature.
697
	 *
698
	 * @since 2.2
699
	 * @param string $secret
700
	 */
701
	public function set_secret( $secret ) {
702
		update_post_meta( $this->id, '_secret', $secret );
703
	}
704
705
	/**
706
	 * Get the secret used for generating the HMAC-SHA256 signature.
707
	 *
708
	 * @since 2.2
709
	 * @return string
710
	 */
711
	public function get_secret() {
712
		return apply_filters( 'woocommerce_webhook_secret', $this->secret, $this->id );
713
	}
714
715
	/**
716
	 * Get the friendly name for the webhook.
717
	 *
718
	 * @since 2.2
719
	 * @return string
720
	 */
721
	public function get_name() {
722
		return apply_filters( 'woocommerce_webhook_name', $this->get_post_data()->post_title, $this->id );
723
	}
724
725
	/**
726
	 * Get the webhook topic, e.g. `order.created`.
727
	 *
728
	 * @since 2.2
729
	 * @return string
730
	 */
731
	public function get_topic() {
732
		return apply_filters( 'woocommerce_webhook_topic', $this->topic, $this->id );
733
	}
734
735
	/**
736
	 * Get the hook names for the webhook.
737
	 *
738
	 * @since 2.2
739
	 * @return array hook names
740
	 */
741
	public function get_hooks() {
742
		return apply_filters( 'woocommerce_webhook_hooks', $this->hooks, $this->id );
743
	}
744
745
	/**
746
	 * Get the resource for the webhook, e.g. `order`.
747
	 *
748
	 * @since 2.2
749
	 * @return string
750
	 */
751
	public function get_resource() {
752
		return apply_filters( 'woocommerce_webhook_resource', $this->resource, $this->id );
753
	}
754
755
	/**
756
	 * Get the event for the webhook, e.g. `created`.
757
	 *
758
	 * @since 2.2
759
	 * @return string
760
	 */
761
	public function get_event() {
762
		return apply_filters( 'woocommerce_webhook_event', $this->event, $this->id );
763
	}
764
765
	/**
766
	 * Get the failure count.
767
	 *
768
	 * @since 2.2
769
	 * @return int
770
	 */
771
	public function get_failure_count() {
772
		return intval( $this->failure_count );
773
	}
774
775
	/**
776
	 * Get the user ID for this webhook.
777
	 *
778
	 * @since 2.2
779
	 * @return int|string user ID
780
	 */
781
	public function get_user_id() {
782
		return $this->get_post_data()->post_author;
783
	}
784
785
	/**
786
	 * Get the post data for the webhook.
787
	 *
788
	 * @since 2.2
789
	 * @return null|WP_Post
790
	 */
791
	public function get_post_data() {
792
		return $this->post_data;
793
	}
794
795
}
796