WC_Admin_Webhooks::save()   B
last analyzed

Complexity

Conditions 8
Paths 8

Size

Total Lines 53
Code Lines 23

Duplication

Lines 3
Ratio 5.66 %

Importance

Changes 0
Metric Value
cc 8
eloc 23
c 0
b 0
f 0
nc 8
nop 0
dl 3
loc 53
rs 7.1199

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * WooCommerce Admin Webhooks Class
4
 *
5
 * @author   WooThemes
6
 * @category Admin
7
 * @package  WooCommerce/Admin
8
 * @version  2.4.0
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit; // Exit if accessed directly
13
}
14
15
/**
16
 * WC_Admin_Webhooks.
17
 */
18
class WC_Admin_Webhooks {
19
20
	/**
21
	 * Initialize the webhooks admin actions.
22
	 */
23
	public function __construct() {
24
		add_action( 'admin_init', array( $this, 'actions' ) );
25
	}
26
27
	/**
28
	 * Check if is webhook settings page.
29
	 *
30
	 * @return bool
31
	 */
32 View Code Duplication
	private function is_webhook_settings_page() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
33
		return isset( $_GET['page'] )
34
			&& 'wc-settings' == $_GET['page']
35
			&& isset( $_GET['tab'] )
36
			&& 'api' == $_GET['tab']
37
			&& isset( $_GET['section'] )
38
			&& 'webhooks' == isset( $_GET['section'] );
39
	}
40
41
	/**
42
	 * Updated the Webhook name.
43
	 *
44
	 * @param int $webhook_id
45
	 */
46
	private function update_name( $webhook_id ) {
47
		global $wpdb;
48
49
		$name = ! empty( $_POST['webhook_name'] ) ? $_POST['webhook_name'] : sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) );
50
		$wpdb->update( $wpdb->posts, array( 'post_title' => $name ), array( 'ID' => $webhook_id ) );
51
	}
52
53
	/**
54
	 * Updated the Webhook status.
55
	 *
56
	 * @param WC_Webhook $webhook
57
	 */
58
	private function update_status( $webhook ) {
59
		$status = ! empty( $_POST['webhook_status'] ) ? wc_clean( $_POST['webhook_status'] ) : '';
60
61
		$webhook->update_status( $status );
62
	}
63
64
	/**
65
	 * Updated the Webhook delivery URL.
66
	 *
67
	 * @param WC_Webhook $webhook
68
	 */
69
	private function update_delivery_url( $webhook ) {
70
		$delivery_url = ! empty( $_POST['webhook_delivery_url'] ) ? $_POST['webhook_delivery_url'] : '';
71
72
		if ( wc_is_valid_url( $delivery_url ) ) {
73
			$webhook->set_delivery_url( $delivery_url );
74
		}
75
	}
76
77
	/**
78
	 * Updated the Webhook secret.
79
	 *
80
	 * @param WC_Webhook $webhook
81
	 */
82
	private function update_secret( $webhook ) {
83
		$secret = ! empty( $_POST['webhook_secret'] ) ? $_POST['webhook_secret'] : wc_webhook_generate_secret();
84
85
		$webhook->set_secret( $secret );
86
	}
87
88
	/**
89
	 * Updated the Webhook topic.
90
	 *
91
	 * @param WC_Webhook $webhook
92
	 */
93
	private function update_topic( $webhook ) {
94
		if ( ! empty( $_POST['webhook_topic'] ) ) {
95
96
			$resource = '';
97
			$event    = '';
98
99
			switch ( $_POST['webhook_topic'] ) {
100
				case 'custom' :
101
					if ( ! empty( $_POST['webhook_custom_topic'] ) ) {
102
						list( $resource, $event ) = explode( '.', wc_clean( $_POST['webhook_custom_topic'] ) );
103
					}
104
					break;
105
				case 'action' :
106
					$resource = 'action';
107
					$event    = ! empty( $_POST['webhook_action_event'] ) ? wc_clean( $_POST['webhook_action_event'] ) : '';
108
					break;
109
110
				default :
111
					list( $resource, $event ) = explode( '.', wc_clean( $_POST['webhook_topic'] ) );
112
					break;
113
			}
114
115
			$topic = $resource . '.' . $event;
116
117
			if ( wc_is_webhook_valid_topic( $topic ) ) {
118
				$webhook->set_topic( $topic );
119
			}
120
		}
121
	}
122
123
	/**
124
	 * Save method.
125
	 */
126
	private function save() {
127 View Code Duplication
		if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) {
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...
128
			wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
129
		}
130
131
		$webhook_id = absint( $_POST['webhook_id'] );
132
133
		if ( ! current_user_can( 'edit_shop_webhook', $webhook_id ) ) {
134
			return;
135
		}
136
137
		$webhook = new WC_Webhook( $webhook_id );
138
139
		// Name
140
		$this->update_name( $webhook->id );
141
142
		// Status
143
		$this->update_status( $webhook );
144
145
		// Delivery URL
146
		$this->update_delivery_url( $webhook );
147
148
		// Secret
149
		$this->update_secret( $webhook );
150
151
		// Topic
152
		$this->update_topic( $webhook );
153
154
		// Update date.
155
		wp_update_post( array( 'ID' => $webhook->id, 'post_modified' => current_time( 'mysql' ) ) );
156
157
		// Run actions
158
		do_action( 'woocommerce_webhook_options_save', $webhook->id );
159
160
		delete_transient( 'woocommerce_webhook_ids' );
161
162
		// Ping the webhook at the first time that is activated
163
		$pending_delivery = get_post_meta( $webhook->id, '_webhook_pending_delivery', true );
164
165
		if ( isset( $_POST['webhook_status'] ) && 'active' === $_POST['webhook_status'] && $pending_delivery ) {
166
			$result = $webhook->deliver_ping();
167
168
			if ( is_wp_error( $result ) ) {
169
				// Redirect to webhook edit page to avoid settings save actions
170
				wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->id . '&error=' . urlencode( $result->get_error_message() ) ) );
171
				exit();
172
			}
173
		}
174
175
		// Redirect to webhook edit page to avoid settings save actions
176
		wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->id . '&updated=1' ) );
177
		exit();
178
	}
179
180
	/**
181
	 * Create Webhook.
182
	 */
183
	private function create() {
184
		if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'create-webhook' ) ) {
185
			wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
186
		}
187
188
		if ( ! current_user_can( 'publish_shop_webhooks' ) ) {
189
			wp_die( __( 'You don\'t have permissions to create Webhooks!', 'woocommerce' ) );
190
		}
191
192
		$webhook_id = wp_insert_post( array(
193
			'post_type'     => 'shop_webhook',
194
			'post_status'   => 'pending',
195
			'ping_status'   => 'closed',
196
			'post_author'   => get_current_user_id(),
197
			'post_password' => strlen( ( $password = uniqid( 'webhook_' ) ) ) > 20 ? substr( $password, 0, 20 ) : $password,
198
			'post_title'    => sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ),
199
			'comment_status' => 'open'
200
		) );
201
202
		if ( is_wp_error( $webhook_id ) ) {
203
			wp_die( $webhook_id->get_error_messages() );
204
		}
205
206
		update_post_meta( $webhook_id, '_webhook_pending_delivery', true );
207
208
		delete_transient( 'woocommerce_webhook_ids' );
209
210
		// Redirect to edit page
211
		wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook_id . '&created=1' ) );
212
		exit();
213
	}
214
215
	/**
216
	 * Bulk trash/delete.
217
	 *
218
	 * @param array $webhooks
219
	 * @param bool  $delete
220
	 */
221
	private function bulk_trash( $webhooks, $delete = false ) {
222
		foreach ( $webhooks as $webhook_id ) {
223
			if ( $delete ) {
224
				wp_delete_post( $webhook_id, true );
225
			} else {
226
				wp_trash_post( $webhook_id );
227
			}
228
		}
229
230
		$type   = ! EMPTY_TRASH_DAYS || $delete ? 'deleted' : 'trashed';
231
		$qty    = count( $webhooks );
232
		$status = isset( $_GET['status'] ) ? '&status=' . sanitize_text_field( $_GET['status'] ) : '';
233
234
		delete_transient( 'woocommerce_webhook_ids' );
235
236
		// Redirect to webhooks page
237
		wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' . $status . '&' . $type . '=' . $qty ) );
238
		exit();
239
	}
240
241
	/**
242
	 * Bulk untrash.
243
	 *
244
	 * @param array $webhooks
245
	 */
246
	private function bulk_untrash( $webhooks ) {
247
		foreach ( $webhooks as $webhook_id ) {
248
			wp_untrash_post( $webhook_id );
249
		}
250
251
		$qty = count( $webhooks );
252
253
		delete_transient( 'woocommerce_webhook_ids' );
254
255
		// Redirect to webhooks page
256
		wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&status=trash&untrashed=' . $qty ) );
257
		exit();
258
	}
259
260
	/**
261
	 * Bulk actions.
262
	 */
263
	private function bulk_actions() {
264 View Code Duplication
		if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) {
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...
265
			wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
266
		}
267
268
		if ( ! current_user_can( 'edit_shop_webhooks' ) ) {
269
			wp_die( __( 'You don\'t have permissions to edit Webhooks!', 'woocommerce' ) );
270
		}
271
272
		$webhooks = array_map( 'absint', (array) $_GET['webhook'] );
273
274
		switch ( $_GET['action'] ) {
275
			case 'trash' :
276
				$this->bulk_trash( $webhooks );
277
				break;
278
			case 'untrash' :
279
				$this->bulk_untrash( $webhooks );
280
				break;
281
			case 'delete' :
282
				$this->bulk_trash( $webhooks, true );
283
				break;
284
			default :
285
				break;
286
		}
287
	}
288
289
	/**
290
	 * Empty Trash.
291
	 */
292
	private function empty_trash() {
293
		if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'empty_trash' ) ) {
294
			wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
295
		}
296
297
		if ( ! current_user_can( 'delete_shop_webhooks' ) ) {
298
			wp_die( __( 'You don\'t have permissions to delete Webhooks!', 'woocommerce' ) );
299
		}
300
301
		$webhooks = get_posts( array(
302
			'post_type'           => 'shop_webhook',
303
			'ignore_sticky_posts' => true,
304
			'nopaging'            => true,
305
			'post_status'         => 'trash',
306
			'fields'              => 'ids'
307
		) );
308
309
		foreach ( $webhooks as $webhook_id ) {
310
			wp_delete_post( $webhook_id, true );
311
		}
312
313
		$qty = count( $webhooks );
314
315
		// Redirect to webhooks page
316
		wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&deleted=' . $qty ) );
317
		exit();
318
	}
319
320
	/**
321
	 * Webhooks admin actions.
322
	 */
323
	public function actions() {
324
		if ( $this->is_webhook_settings_page() ) {
325
			// Save
326
			if ( isset( $_POST['save'] ) && isset( $_POST['webhook_id'] ) ) {
327
				$this->save();
328
			}
329
330
			// Create
331
			if ( isset( $_GET['create-webhook'] ) ) {
332
				$this->create();
333
			}
334
335
			// Bulk actions
336
			if ( isset( $_GET['action'] ) && isset( $_GET['webhook'] ) ) {
337
				$this->bulk_actions();
338
			}
339
340
			// Empty trash
341
			if ( isset( $_GET['empty_trash'] ) ) {
342
				$this->empty_trash();
343
			}
344
		}
345
	}
346
347
	/**
348
	 * Page output.
349
	 */
350
	public static function page_output() {
351
		// Hide the save button
352
		$GLOBALS['hide_save_button'] = true;
353
354 View Code Duplication
		if ( isset( $_GET['edit-webhook'] ) ) {
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...
355
			$webhook_id = absint( $_GET['edit-webhook'] );
356
			$webhook    = new WC_Webhook( $webhook_id );
357
358
			if ( 'trash' != $webhook->post_data->post_status ) {
359
				include( 'settings/views/html-webhooks-edit.php' );
360
				return;
361
			}
362
		}
363
364
		self::table_list_output();
365
	}
366
367
	/**
368
	 * Notices.
369
	 */
370
	public static function notices() {
371 View Code Duplication
		if ( isset( $_GET['trashed'] ) ) {
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...
372
			$trashed = absint( $_GET['trashed'] );
373
374
			WC_Admin_Settings::add_message( sprintf( _n( '1 webhook moved to the Trash.', '%d webhooks moved to the Trash.', $trashed, 'woocommerce' ), $trashed ) );
375
		}
376
377 View Code Duplication
		if ( isset( $_GET['untrashed'] ) ) {
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...
378
			$untrashed = absint( $_GET['untrashed'] );
379
380
			WC_Admin_Settings::add_message( sprintf( _n( '1 webhook restored from the Trash.', '%d webhooks restored from the Trash.', $untrashed, 'woocommerce' ), $untrashed ) );
381
		}
382
383 View Code Duplication
		if ( isset( $_GET['deleted'] ) ) {
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...
384
			$deleted = absint( $_GET['deleted'] );
385
386
			WC_Admin_Settings::add_message( sprintf( _n( '1 webhook permanently deleted.', '%d webhooks permanently deleted.', $deleted, 'woocommerce' ), $deleted ) );
387
		}
388
389
		if ( isset( $_GET['updated'] ) ) {
390
			WC_Admin_Settings::add_message( __( 'Webhook updated successfully.', 'woocommerce' ) );
391
		}
392
393
		if ( isset( $_GET['created'] ) ) {
394
			WC_Admin_Settings::add_message( __( 'Webhook created successfully.', 'woocommerce' ) );
395
		}
396
397
		if ( isset( $_GET['error'] ) ) {
398
			WC_Admin_Settings::add_error( wc_clean( $_GET['error'] ) );
399
		}
400
	}
401
402
	/**
403
	 * Table list output.
404
	 */
405 View Code Duplication
	private static function table_list_output() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
406
		echo '<h2>' . __( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( wp_nonce_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&create-webhook=1' ), 'create-webhook' ) ) . '" class="add-new-h2">' . __( 'Add Webhook', 'woocommerce' ) . '</a></h2>';
407
408
		$webhooks_table_list = new WC_Admin_Webhooks_Table_List();
409
		$webhooks_table_list->prepare_items();
410
411
		echo '<input type="hidden" name="page" value="wc-settings" />';
412
		echo '<input type="hidden" name="tab" value="api" />';
413
		echo '<input type="hidden" name="section" value="webhooks" />';
414
415
		$webhooks_table_list->views();
416
		$webhooks_table_list->search_box( __( 'Search Webhooks', 'woocommerce' ), 'webhook' );
417
		$webhooks_table_list->display();
418
	}
419
420
	/**
421
	 * Logs output.
422
	 *
423
	 * @param WC_Webhook $webhook
424
	 */
425
	public static function logs_output( $webhook ) {
426
		$current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1;
427
		$args    = array(
428
			'post_id' => $webhook->id,
429
			'status'  => 'approve',
430
			'type'    => 'webhook_delivery',
431
			'number'  => 10
432
		);
433
434
		if ( 1 < $current ) {
435
			$args['offset'] = ( $current - 1 ) * 10;
436
		}
437
438
		remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_webhook_comments' ), 10, 1 );
439
440
		$logs = get_comments( $args );
441
442
		add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_webhook_comments' ), 10, 1 );
443
444
		if ( $logs ) {
445
			include_once( 'settings/views/html-webhook-logs.php' );
446
		} else {
447
			echo '<p>' . __( 'This Webhook has no log yet.', 'woocommerce' ) . '</p>';
448
		}
449
	}
450
451
	/**
452
	 * Get the webhook topic data.
453
	 *
454
	 * @return array
455
	 */
456
	public static function get_topic_data( $webhook ) {
457
		$topic    = $webhook->get_topic();
458
		$event    = '';
459
		$resource = '';
460
461
		if ( $topic ) {
462
			list( $resource, $event ) = explode( '.', $topic );
463
464
			if ( 'action' === $resource ) {
465
				$topic = 'action';
466
			} else if ( ! in_array( $resource, array( 'coupon', 'customer', 'order', 'product' ) ) ) {
467
				$topic = 'custom';
468
			}
469
		}
470
471
		return array(
472
			'topic'    => $topic,
473
			'event'    => $event,
474
			'resource' => $resource
475
		);
476
	}
477
478
	/**
479
	 * Get the logs navigation.
480
	 *
481
	 * @param  int $total
482
	 *
483
	 * @return string
484
	 */
485
	public static function get_logs_navigation( $total, $webhook ) {
486
		$pages   = ceil( $total / 10 );
487
		$current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1;
488
489
		$html = '<div class="webhook-logs-navigation">';
490
491
			$html .= '<p class="info" style="float: left;"><strong>';
492
			$html .= sprintf( '%s &ndash; Page %d of %d', _n( '1 item', sprintf( '%d items', $total ), $total, 'woocommerce' ), $current, $pages );
493
			$html .= '</strong></p>';
494
495
			if ( 1 < $pages ) {
496
				$html .= '<p class="tools" style="float: right;">';
497 View Code Duplication
					if ( 1 == $current ) {
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...
498
						$html .= '<button class="button-primary" disabled="disabled">' . __( '&lsaquo; Previous', 'woocommerce' ) . '</button> ';
499
					} else {
500
						$html .= '<a class="button-primary" href="' . admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->id . '&log_page=' . ( $current - 1 ) ) . '#webhook-logs">' . __( '&lsaquo; Previous', 'woocommerce' ) . '</a> ';
501
					}
502
503 View Code Duplication
					if ( $pages == $current ) {
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...
504
						$html .= '<button class="button-primary" disabled="disabled">' . __( 'Next &rsaquo;', 'woocommerce' ) . '</button>';
505
					} else {
506
						$html .= '<a class="button-primary" href="' . admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->id . '&log_page=' . ( $current + 1 ) ) . '#webhook-logs">' . __( 'Next &rsaquo;', 'woocommerce' ) . '</a>';
507
					}
508
				$html .= '</p>';
509
			}
510
511
		$html .= '<div class="clear"></div></div>';
512
513
		return $html;
514
	}
515
}
516
517
new WC_Admin_Webhooks();
518