Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/admin/class-wc-admin-webhooks.php (10 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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
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
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
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
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
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
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
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
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
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