Merge pull request #17131 from woocommerce/feature/12439-2

Apply CRUD to Webhooks admin
This commit is contained in:
Mike Jolley 2017-11-10 16:12:55 +00:00 committed by GitHub
commit 43c6e2fd6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1227 additions and 1317 deletions

View File

@ -2,7 +2,7 @@
/**
* Setup menus in WP admin.
*
* @author WooThemes
* @author Automattic
* @category Admin
* @package WooCommerce/Admin
* @version 2.5.0
@ -12,7 +12,9 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WC_Admin_Menus', false ) ) :
if ( class_exists( 'WC_Admin_Menus', false ) ) {
return new WC_Admin_Menus();
}
/**
* WC_Admin_Menus Class.
@ -23,7 +25,7 @@ class WC_Admin_Menus {
* Hook in tabs.
*/
public function __construct() {
// Add menus
// Add menus.
add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
add_action( 'admin_menu', array( $this, 'reports_menu' ), 20 );
add_action( 'admin_menu', array( $this, 'settings_menu' ), 50 );
@ -41,7 +43,7 @@ class WC_Admin_Menus {
// Add endpoints custom URLs in Appearance > Menus > Pages.
add_action( 'admin_head-nav-menus.php', array( $this, 'add_nav_menu_meta_boxes' ) );
// Admin bar menus
// Admin bar menus.
if ( apply_filters( 'woocommerce_show_admin_bar_visit_store', true ) ) {
add_action( 'admin_bar_menu', array( $this, 'admin_bar_menus' ), 31 );
}
@ -54,7 +56,7 @@ class WC_Admin_Menus {
global $menu;
if ( current_user_can( 'manage_woocommerce' ) ) {
$menu[] = array( '', 'read', 'separator-woocommerce', '', 'wp-menu-separator woocommerce' );
$menu[] = array( '', 'read', 'separator-woocommerce', '', 'wp-menu-separator woocommerce' ); // WPCS: override ok.
}
add_menu_page( __( 'WooCommerce', 'woocommerce' ), __( 'WooCommerce', 'woocommerce' ), 'manage_woocommerce', 'woocommerce', null, null, '55.5' );
@ -91,25 +93,25 @@ class WC_Admin_Menus {
WC()->payment_gateways();
WC()->shipping();
// Include settings pages
// Include settings pages.
WC_Admin_Settings::get_settings_pages();
// Get current tab/section
$current_tab = empty( $_GET['tab'] ) ? 'general' : sanitize_title( $_GET['tab'] );
$current_section = empty( $_REQUEST['section'] ) ? '' : sanitize_title( $_REQUEST['section'] );
// Get current tab/section.
$current_tab = empty( $_GET['tab'] ) ? 'general' : sanitize_title( wp_unslash( $_GET['tab'] ) ); // WPCS: input var okay, CSRF ok.
$current_section = empty( $_REQUEST['section'] ) ? '' : sanitize_title( wp_unslash( $_REQUEST['section'] ) ); // WPCS: input var okay, CSRF ok.
// Save settings if data has been posted
if ( ! empty( $_POST ) ) {
// Save settings if data has been posted.
if ( apply_filters( '' !== $current_section ? "woocommerce_save_settings_{$current_tab}_{$current_section}" : "woocommerce_save_settings_{$current_tab}", ! empty( $_POST ) ) ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Settings::save();
}
// Add any posted messages
if ( ! empty( $_GET['wc_error'] ) ) {
WC_Admin_Settings::add_error( stripslashes( $_GET['wc_error'] ) );
// Add any posted messages.
if ( ! empty( $_GET['wc_error'] ) ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Settings::add_error( wp_kses_post( wp_unslash( $_GET['wc_error'] ) ) ); // WPCS: input var okay, CSRF ok.
}
if ( ! empty( $_GET['wc_message'] ) ) {
WC_Admin_Settings::add_message( stripslashes( $_GET['wc_message'] ) );
if ( ! empty( $_GET['wc_message'] ) ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Settings::add_message( wp_kses_post( wp_unslash( $_GET['wc_message'] ) ) ); // WPCS: input var okay, CSRF ok.
}
}
@ -125,6 +127,7 @@ class WC_Admin_Menus {
*/
public function addons_menu() {
$count_html = WC_Helper_Updater::get_updates_count_html();
/* translators: %s: extensions count */
$menu_title = sprintf( __( 'Extensions %s', 'woocommerce' ), $count_html );
add_submenu_page( 'woocommerce', __( 'WooCommerce extensions', 'woocommerce' ), $menu_title, 'manage_woocommerce', 'wc-addons', array( $this, 'addons_page' ) );
}
@ -136,17 +139,17 @@ class WC_Admin_Menus {
global $parent_file, $submenu_file, $post_type;
switch ( $post_type ) {
case 'shop_order' :
case 'shop_coupon' :
$parent_file = 'woocommerce';
break;
case 'product' :
case 'shop_order':
case 'shop_coupon':
$parent_file = 'woocommerce'; // WPCS: override ok.
break;
case 'product':
$screen = get_current_screen();
if ( $screen && taxonomy_is_product_attribute( $screen->taxonomy ) ) {
$submenu_file = 'product_attributes';
$parent_file = 'edit.php?post_type=product';
$submenu_file = 'product_attributes'; // WPCS: override ok.
$parent_file = 'edit.php?post_type=product'; // WPCS: override ok.
}
break;
break;
}
}
@ -157,14 +160,16 @@ class WC_Admin_Menus {
global $submenu;
if ( isset( $submenu['woocommerce'] ) ) {
// Remove 'WooCommerce' sub menu item
// Remove 'WooCommerce' sub menu item.
unset( $submenu['woocommerce'][0] );
// Add count if user has access
if ( apply_filters( 'woocommerce_include_processing_order_count_in_menu', true ) && current_user_can( 'manage_woocommerce' ) && ( $order_count = wc_processing_order_count() ) ) {
$order_count = wc_processing_order_count();
// Add count if user has access.
if ( apply_filters( 'woocommerce_include_processing_order_count_in_menu', true ) && current_user_can( 'manage_woocommerce' ) && $order_count ) {
foreach ( $submenu['woocommerce'] as $key => $menu_item ) {
if ( 0 === strpos( $menu_item[0], _x( 'Orders', 'Admin menu name', 'woocommerce' ) ) ) {
$submenu['woocommerce'][ $key ][0] .= ' <span class="awaiting-mod update-plugins count-' . $order_count . '"><span class="processing-count">' . number_format_i18n( $order_count ) . '</span></span>';
$submenu['woocommerce'][ $key ][0] .= ' <span class="awaiting-mod update-plugins count-' . esc_attr( $order_count ) . '"><span class="processing-count">' . number_format_i18n( $order_count ) . '</span></span>'; // WPCS: override ok.
break;
}
}
@ -175,34 +180,34 @@ class WC_Admin_Menus {
/**
* Reorder the WC menu items in admin.
*
* @param mixed $menu_order
* @param int $menu_order Menu order.
* @return array
*/
public function menu_order( $menu_order ) {
// Initialize our custom order array
// Initialize our custom order array.
$woocommerce_menu_order = array();
// Get the index of our custom separator
$woocommerce_separator = array_search( 'separator-woocommerce', $menu_order );
// Get the index of our custom separator.
$woocommerce_separator = array_search( 'separator-woocommerce', $menu_order, true );
// Get index of product menu
$woocommerce_product = array_search( 'edit.php?post_type=product', $menu_order );
// Get index of product menu.
$woocommerce_product = array_search( 'edit.php?post_type=product', $menu_order, true );
// Loop through menu order and do some rearranging
// Loop through menu order and do some rearranging.
foreach ( $menu_order as $index => $item ) {
if ( ( ( 'woocommerce' ) == $item ) ) {
if ( 'woocommerce' === $item ) {
$woocommerce_menu_order[] = 'separator-woocommerce';
$woocommerce_menu_order[] = $item;
$woocommerce_menu_order[] = 'edit.php?post_type=product';
unset( $menu_order[ $woocommerce_separator ] );
unset( $menu_order[ $woocommerce_product ] );
} elseif ( ! in_array( $item, array( 'separator-woocommerce' ) ) ) {
} elseif ( ! in_array( $item, array( 'separator-woocommerce' ), true ) ) {
$woocommerce_menu_order[] = $item;
}
}
// Return order
// Return order.
return $woocommerce_menu_order;
}
@ -301,7 +306,7 @@ class WC_Admin_Menus {
</div>
<p class="button-controls">
<span class="list-controls">
<a href="<?php echo admin_url( 'nav-menus.php?page-tab=all&selectall=1#posttype-woocommerce-endpoints' ); ?>" class="select-all"><?php _e( 'Select all', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( admin_url( 'nav-menus.php?page-tab=all&selectall=1#posttype-woocommerce-endpoints' ) ); ?>" class="select-all"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></a>
</span>
<span class="add-to-menu">
<input type="submit" class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to menu', 'woocommerce' ); ?>" name="add-post-type-menu-item" id="submit-posttype-woocommerce-endpoints">
@ -316,7 +321,7 @@ class WC_Admin_Menus {
* Add the "Visit Store" link in admin bar main menu.
*
* @since 2.4.0
* @param WP_Admin_Bar $wp_admin_bar
* @param WP_Admin_Bar $wp_admin_bar Admin bar instance.
*/
public function admin_bar_menus( $wp_admin_bar ) {
if ( ! is_admin() || ! is_user_logged_in() ) {
@ -329,7 +334,7 @@ class WC_Admin_Menus {
}
// Don't display when shop page is the same of the page on front.
if ( get_option( 'page_on_front' ) == wc_get_page_id( 'shop' ) ) {
if ( intval( get_option( 'page_on_front' ) ) === wc_get_page_id( 'shop' ) ) {
return;
}
@ -343,6 +348,4 @@ class WC_Admin_Menus {
}
}
endif;
return new WC_Admin_Menus();

File diff suppressed because it is too large Load Diff

View File

@ -2,20 +2,23 @@
/**
* WooCommerce Webhooks Table List
*
* @author WooThemes
* @author Automattic
* @category Admin
* @package WooCommerce/Admin
* @version 2.4.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
/**
* Webooks table list class.
*/
class WC_Admin_Webhooks_Table_List extends WP_List_Table {
/**
@ -47,70 +50,38 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
/**
* Column cb.
*
* @param WC_Post $webhook
* @param WC_Webhook $webhook Webhook instance.
* @return string
*/
public function column_cb( $webhook ) {
return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />', $this->_args['singular'], $webhook->ID );
}
/**
* Get Webhook object.
* @param object $webhook
* @return WC_Webhook
*/
private function get_webbook_object( $webhook ) {
global $the_webhook;
if ( empty( $the_webhook ) || $the_webhook->id != $webhook->ID ) {
$the_webhook = new WC_Webhook( $webhook->ID );
}
return $the_webhook;
return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />', $this->_args['singular'], $webhook->get_id() );
}
/**
* Return title column.
* @param object $webhook
*
* @param WC_Webhook $webhook Webhook instance.
* @return string
*/
public function column_title( $webhook ) {
$the_webhook = $this->get_webbook_object( $webhook );
$edit_link = admin_url( 'admin.php?page=wc-settings&amp;tab=api&amp;section=webhooks&amp;edit-webhook=' . $the_webhook->id );
$title = _draft_or_post_title( $the_webhook->get_post_data() );
$post_type_object = get_post_type_object( $the_webhook->get_post_data()->post_type );
$post_status = $the_webhook->get_post_data()->post_status;
$edit_link = admin_url( 'admin.php?page=wc-settings&amp;tab=api&amp;section=webhooks&amp;edit-webhook=' . $webhook->get_id() );
$output = '';
// Title
$output = '<strong>';
if ( 'trash' == $post_status ) {
$output .= esc_html( $title );
} else {
$output .= '<a href="' . esc_url( $edit_link ) . '" class="row-title">' . esc_html( $title ) . '</a>';
}
$output .= '</strong>';
// Title.
$output .= '<strong><a href="' . esc_url( $edit_link ) . '" class="row-title">' . esc_html( $webhook->get_name() ) . '</a></strong>';
// Get actions
// Get actions.
$actions = array(
'id' => sprintf( __( 'ID: %d', 'woocommerce' ), $the_webhook->id ),
/* translators: %s: webhook ID. */
'id' => sprintf( __( 'ID: %d', 'woocommerce' ), $webhook->get_id() ),
'edit' => '<a href="' . esc_url( $edit_link ) . '">' . esc_html__( 'Edit', 'woocommerce' ) . '</a>',
/* translators: %s: webhook name */
'delete' => '<a class="submitdelete" aria-label="' . esc_attr( sprintf( __( 'Delete "%s" permanently', 'woocommerce' ), $webhook->get_name() ) ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array(
'delete' => $webhook->get_id(),
), admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' ) ), 'delete-webhook' ) ) . '">' . esc_html__( 'Delete permanently', 'woocommerce' ) . '</a>',
);
if ( current_user_can( $post_type_object->cap->edit_post, $the_webhook->id ) && 'trash' !== $post_status ) {
$actions['edit'] = '<a href="' . esc_url( $edit_link ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $the_webhook->id ) ) {
if ( 'trash' == $post_status ) {
$actions['untrash'] = '<a aria-label="' . esc_attr__( 'Restore this item from the Trash', 'woocommerce' ) . '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $the_webhook->id ) ), 'untrash-post_' . $the_webhook->id ) . '">' . esc_html__( 'Restore', 'woocommerce' ) . '</a>';
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = '<a class="submitdelete" aria-label="' . esc_attr__( 'Move this item to the Trash', 'woocommerce' ) . '" href="' . get_delete_post_link( $the_webhook->id ) . '">' . esc_html__( 'Trash', 'woocommerce' ) . '</a>';
}
if ( 'trash' == $post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = '<a class="submitdelete" aria-label="' . esc_attr__( 'Delete this item permanently', 'woocommerce' ) . '" href="' . get_delete_post_link( $the_webhook->id, '', true ) . '">' . esc_html__( 'Delete permanently', 'woocommerce' ) . '</a>';
}
}
$actions = apply_filters( 'post_row_actions', $actions, $the_webhook->get_post_data() );
$actions = apply_filters( 'webhook_row_actions', $actions, $webhook );
$row_actions = array();
foreach ( $actions as $action => $link ) {
@ -124,75 +95,59 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
/**
* Return status column.
* @param object $webhook
*
* @param WC_Webhook $webhook Webhook instance.
* @return string
*/
public function column_status( $webhook ) {
return $this->get_webbook_object( $webhook )->get_i18n_status();
return $webhook->get_i18n_status();
}
/**
* Return topic column.
* @param object $webhook
*
* @param WC_Webhook $webhook Webhook instance.
* @return string
*/
public function column_topic( $webhook ) {
return $this->get_webbook_object( $webhook )->get_topic();
return $webhook->get_topic();
}
/**
* Return delivery URL column.
* @param object $webhook
*
* @param WC_Webhook $webhook Webhook instance.
* @return string
*/
public function column_delivery_url( $webhook ) {
return $this->get_webbook_object( $webhook )->get_delivery_url();
return $webhook->get_delivery_url();
}
/**
* Get the status label for webhooks.
*
* @param string $status_name
* @param stdClass $status
*
* @param string $status_name Status name.
* @param int $amount Amount of webhooks.
* @return array
*/
private function get_status_label( $status_name, $status ) {
switch ( $status_name ) {
case 'publish' :
/* translators: %s: count */
$label = array(
'singular' => __( 'Activated <span class="count">(%s)</span>', 'woocommerce' ),
'plural' => __( 'Activated <span class="count">(%s)</span>', 'woocommerce' ),
'context' => '',
'domain' => 'woocommerce',
);
break;
case 'draft' :
/* translators: %s: count */
$label = array(
'singular' => __( 'Paused <span class="count">(%s)</span>', 'woocommerce' ),
'plural' => __( 'Paused <span class="count">(%s)</span>', 'woocommerce' ),
'context' => '',
'domain' => 'woocommerce',
);
break;
case 'pending' :
/* translators: %s: count */
$label = array(
'singular' => __( 'Disabled <span class="count">(%s)</span>', 'woocommerce' ),
'plural' => __( 'Disabled <span class="count">(%s)</span>', 'woocommerce' ),
'context' => '',
'domain' => 'woocommerce',
);
break;
private function get_status_label( $status_name, $amount ) {
$statuses = wc_get_webhook_statuses();
default:
$label = $status->label_count;
break;
if ( isset( $statuses[ $status_name ] ) ) {
return array(
'singular' => sprintf( '%s <span class="count">(%s)</span>', esc_html( $statuses[ $status_name ] ), $amount ),
'plural' => sprintf( '%s <span class="count">(%s)</span>', esc_html( $statuses[ $status_name ] ), $amount ),
'context' => '',
'domain' => 'woocommerce',
);
}
return $label;
return array(
'singular' => sprintf( '%s <span class="count">(%s)</span>', esc_html( $status_name ), $amount ),
'plural' => sprintf( '%s <span class="count">(%s)</span>', esc_html( $status_name ), $amount ),
'context' => '',
'domain' => 'woocommerce',
);
}
/**
@ -201,39 +156,30 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
* @return array
*/
protected function get_views() {
$status_links = array();
$num_posts = wp_count_posts( 'shop_webhook', 'readable' );
$class = '';
$total_posts = array_sum( (array) $num_posts );
$status_links = array();
$data_store = WC_Data_Store::load( 'webhook' );
$num_webhooks = $data_store->get_count_webhooks_by_status();
$total_webhooks = array_sum( (array) $num_webhooks );
$statuses = array_keys( wc_get_webhook_statuses() );
$class = empty( $_REQUEST['status'] ) ? ' class="current"' : ''; // WPCS: input var okay. CSRF ok.
// Subtract post types that are not included in the admin all list.
foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
$total_posts -= $num_posts->$state;
}
$class = empty( $class ) && empty( $_REQUEST['status'] ) ? ' class="current"' : '';
/* translators: %s: count */
$status_links['all'] = "<a href='admin.php?page=wc-settings&amp;tab=api&amp;section=webhooks'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_posts, 'posts', 'woocommerce' ), number_format_i18n( $total_posts ) ) . '</a>';
$status_links['all'] = "<a href='admin.php?page=wc-settings&amp;tab=api&amp;section=webhooks'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_webhooks, 'posts', 'woocommerce' ), number_format_i18n( $total_webhooks ) ) . '</a>';
foreach ( get_post_stati( array( 'show_in_admin_status_list' => true ), 'objects' ) as $status ) {
foreach ( $statuses as $status_name ) {
$class = '';
$status_name = $status->name;
if ( ! in_array( $status_name, array( 'publish', 'draft', 'pending', 'trash', 'future', 'private', 'auto-draft' ) ) ) {
if ( empty( $num_webhooks[ $status_name ] ) ) {
continue;
}
if ( empty( $num_posts->$status_name ) ) {
continue;
}
if ( isset( $_REQUEST['status'] ) && $status_name == $_REQUEST['status'] ) {
if ( isset( $_REQUEST['status'] ) && sanitize_key( wp_unslash( $_REQUEST['status'] ) ) === $status_name ) { // WPCS: input var okay, CSRF ok.
$class = ' class="current"';
}
$label = $this->get_status_label( $status_name, $status );
$label = $this->get_status_label( $status_name, $num_webhooks[ $status_name ] );
$status_links[ $status_name ] = "<a href='admin.php?page=wc-settings&amp;tab=api&amp;section=webhooks&amp;status=$status_name'$class>" . sprintf( translate_nooped_plural( $label, $num_posts->$status_name ), number_format_i18n( $num_posts->$status_name ) ) . '</a>';
$status_links[ $status_name ] = "<a href='admin.php?page=wc-settings&amp;tab=api&amp;section=webhooks&amp;status=$status_name'$class>" . sprintf( translate_nooped_plural( $label, $num_webhooks[ $status_name ] ), number_format_i18n( $num_webhooks[ $status_name ] ) ) . '</a>';
}
return $status_links;
@ -245,69 +191,96 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
* @return array
*/
protected function get_bulk_actions() {
if ( isset( $_GET['status'] ) && 'trash' == $_GET['status'] ) {
return array(
'untrash' => __( 'Restore', 'woocommerce' ),
'delete' => __( 'Delete permanently', 'woocommerce' ),
);
}
return array(
'trash' => __( 'Move to trash', 'woocommerce' ),
'delete' => __( 'Delete permanently', 'woocommerce' ),
);
}
/**
* Extra controls to be displayed between bulk actions and pagination.
* Generate the table navigation above or below the table.
* Included to remove extra nonce input.
*
* @param string $which
* @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
*/
protected function extra_tablenav( $which ) {
if ( 'top' == $which && isset( $_GET['status'] ) && 'trash' == $_GET['status'] && current_user_can( 'delete_shop_webhooks' ) ) {
echo '<div class="alignleft actions"><a class="button apply" href="' . esc_url( wp_nonce_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&status=trash&empty_trash=1' ), 'empty_trash' ) ) . '">' . __( 'Empty trash', 'woocommerce' ) . '</a></div>';
protected function display_tablenav( $which ) {
echo '<div class="tablenav ' . esc_attr( $which ) . '">';
if ( $this->has_items() ) {
echo '<div class="alignleft actions bulkactions">';
$this->bulk_actions( $which );
echo '</div>';
}
$this->extra_tablenav( $which );
$this->pagination( $which );
echo '<br class="clear" />';
echo '</div>';
}
/**
* Search box.
*
* @param string $text Button text.
* @param string $input_id Input ID.
*/
public function search_box( $text, $input_id ) {
if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) { // WPCS: input var okay, CSRF ok.
return;
}
$input_id = $input_id . '-search-input';
$search_query = isset( $_REQUEST['s'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : ''; // WPCS: input var okay, CSRF ok.
echo '<p class="search-box">';
echo '<label class="screen-reader-text" for="' . esc_attr( $input_id ) . '">' . esc_html( $text ) . ':</label>';
echo '<input type="search" id="' . esc_attr( $input_id ) . '" name="s" value="' . esc_attr( $search_query ) . '" />';
submit_button( $text, '', '', false, array(
'id' => 'search-submit',
) );
echo '</p>';
}
/**
* Prepare table list items.
*/
public function prepare_items() {
$per_page = apply_filters( 'woocommerce_webhooks_settings_posts_per_page', 10 );
$per_page = absint( apply_filters( 'woocommerce_webhooks_settings_posts_per_page', 10 ) );
$per_page = 0 === $per_page ? 10 : $per_page;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
// Column headers
// Column headers.
$this->_column_headers = array( $columns, $hidden, $sortable );
$current_page = $this->get_pagenum();
// Query args
// Query args.
$args = array(
'post_type' => 'shop_webhook',
'posts_per_page' => $per_page,
'ignore_sticky_posts' => true,
'paged' => $current_page,
'limit' => $per_page,
'offset' => $per_page * ( $current_page - 1 ),
);
// Handle the status query
if ( ! empty( $_REQUEST['status'] ) ) {
$args['post_status'] = sanitize_text_field( $_REQUEST['status'] );
// Handle the status query.
if ( ! empty( $_REQUEST['status'] ) ) { // WPCS: input var okay, CSRF ok.
$args['status'] = sanitize_key( wp_unslash( $_REQUEST['status'] ) ); // WPCS: input var okay, CSRF ok.
}
if ( ! empty( $_REQUEST['s'] ) ) {
$args['s'] = sanitize_text_field( $_REQUEST['s'] );
if ( ! empty( $_REQUEST['s'] ) ) { // WPCS: input var okay, CSRF ok.
$args['search'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); // WPCS: input var okay, CSRF ok.
}
// Get the webhooks
$webhooks = new WP_Query( $args );
$this->items = $webhooks->posts;
// Get the webhooks.
$data_store = WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks( $args );
$this->items = array_map( 'wc_get_webhook', $webhooks );
$total_items = count( $data_store->get_webhooks_ids() );
// Set the pagination
// Set the pagination.
$this->set_pagination_args( array(
'total_items' => $webhooks->found_posts,
'total_items' => $total_items,
'per_page' => $per_page,
'total_pages' => $webhooks->max_num_pages,
'total_pages' => ceil( $total_items / $per_page ),
) );
}
}

View File

@ -2,14 +2,14 @@
/**
* WooCommerce Admin Webhooks Class
*
* @author WooThemes
* @author Automattic
* @category Admin
* @package WooCommerce/Admin
* @version 2.4.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -21,95 +21,94 @@ class WC_Admin_Webhooks {
* Initialize the webhooks admin actions.
*/
public function __construct() {
add_action( 'woocommerce_save_settings_api_webhooks', array( $this, 'allow_save_settings' ) );
add_action( 'admin_init', array( $this, 'actions' ) );
}
/**
* Check if should allow save settings.
* This prevents "Your settings have been saved." notices on the table list.
*
* @param bool $allow If allow save settings.
* @return bool
*/
public function allow_save_settings( $allow ) {
if ( ! isset( $_GET['edit-webhook'] ) ) {// WPCS: input var okay, CSRF ok.
return false;
}
return $allow;
}
/**
* Check if is webhook settings page.
*
* @return bool
*/
private function is_webhook_settings_page() {
return isset( $_GET['page'], $_GET['tab'], $_GET['section'] )
&& 'wc-settings' === $_GET['page']
&& 'api' === $_GET['tab']
&& 'webhooks' === $_GET['section'];
return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'api' === $_GET['tab'] && 'webhooks' === $_GET['section']; // WPCS: input var okay, CSRF ok.
}
/**
* Updated the Webhook name.
*
* @param int $webhook_id
* Save method.
*/
private function update_name( $webhook_id ) {
global $wpdb;
private function save() {
check_admin_referer( 'woocommerce-settings' );
// @codingStandardsIgnoreStart
/* translators: %s: date` */
$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' ) ) );
// @codingStandardsIgnoreEnd
$wpdb->update( $wpdb->posts, array( 'post_title' => $name ), array( 'ID' => $webhook_id ) );
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to update Webhooks', 'woocommerce' ) );
}
/**
* Updated the Webhook status.
*
* @param WC_Webhook $webhook
*/
private function update_status( $webhook ) {
$status = ! empty( $_POST['webhook_status'] ) ? wc_clean( $_POST['webhook_status'] ) : '';
$webhook_id = isset( $_POST['webhook_id'] ) ? absint( $_POST['webhook_id'] ) : 0; // WPCS: input var okay, CSRF ok.
$webhook = new WC_Webhook( $webhook_id );
$webhook->update_status( $status );
}
// Name.
if ( ! empty( $_POST['webhook_name'] ) ) { // WPCS: input var okay, CSRF ok.
$name = sanitize_text_field( wp_unslash( $_POST['webhook_name'] ) ); // WPCS: input var okay, CSRF ok.
} else {
$name = sprintf(
/* translators: %s: date */
__( 'Webhook created on %s', 'woocommerce' ),
// @codingStandardsIgnoreStart
strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) )
// @codingStandardsIgnoreEnd
);
}
/**
* Updated the Webhook delivery URL.
*
* @param WC_Webhook $webhook
*/
private function update_delivery_url( $webhook ) {
$delivery_url = ! empty( $_POST['webhook_delivery_url'] ) ? $_POST['webhook_delivery_url'] : '';
$webhook->set_name( $name );
// Status.
$webhook->set_status( ! empty( $_POST['webhook_status'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_status'] ) ) : 'disabled' ); // WPCS: input var okay, CSRF ok.
// Delivery URL.
$delivery_url = ! empty( $_POST['webhook_delivery_url'] ) ? esc_url_raw( wp_unslash( $_POST['webhook_delivery_url'] ) ) : ''; // WPCS: input var okay, CSRF ok.
if ( wc_is_valid_url( $delivery_url ) ) {
$webhook->set_delivery_url( $delivery_url );
}
}
/**
* Updated the Webhook secret.
*
* @param WC_Webhook $webhook
*/
private function update_secret( $webhook ) {
$secret = ! empty( $_POST['webhook_secret'] ) ? $_POST['webhook_secret'] : wp_generate_password( 50, true, true );
// Secret.
$secret = ! empty( $_POST['webhook_secret'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_secret'] ) ) : wp_generate_password( 50, true, true ); // WPCS: input var okay, CSRF ok.
$webhook->set_secret( $secret );
}
/**
* Updated the Webhook topic.
*
* @param WC_Webhook $webhook
*/
private function update_topic( $webhook ) {
if ( ! empty( $_POST['webhook_topic'] ) ) {
// Topic.
if ( ! empty( $_POST['webhook_topic'] ) ) { // WPCS: input var okay, CSRF ok.
$resource = '';
$event = '';
switch ( $_POST['webhook_topic'] ) {
case 'custom' :
if ( ! empty( $_POST['webhook_custom_topic'] ) ) {
list( $resource, $event ) = explode( '.', wc_clean( $_POST['webhook_custom_topic'] ) );
switch ( $_POST['webhook_topic'] ) { // WPCS: input var okay, CSRF ok.
case 'custom':
if ( ! empty( $_POST['webhook_custom_topic'] ) ) { // WPCS: input var okay, CSRF ok.
list( $resource, $event ) = explode( '.', sanitize_text_field( wp_unslash( $_POST['webhook_custom_topic'] ) ) ); // WPCS: input var okay, CSRF ok.
}
break;
case 'action' :
case 'action':
$resource = 'action';
$event = ! empty( $_POST['webhook_action_event'] ) ? wc_clean( $_POST['webhook_action_event'] ) : '';
$event = ! empty( $_POST['webhook_action_event'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_action_event'] ) ) : ''; // WPCS: input var okay, CSRF ok.
break;
default :
list( $resource, $event ) = explode( '.', wc_clean( $_POST['webhook_topic'] ) );
default:
list( $resource, $event ) = explode( '.', sanitize_text_field( wp_unslash( $_POST['webhook_topic'] ) ) ); // WPCS: input var okay, CSRF ok.
break;
}
@ -119,222 +118,84 @@ class WC_Admin_Webhooks {
$webhook->set_topic( $topic );
}
}
}
/**
* Update webhook api version.
*
* @param WC_Webhook $webhook Webhook instance.
*/
private function update_api_version( $webhook ) {
$version = ! empty( $_POST['webhook_api_version'] ) ? wc_clean( $_POST['webhook_api_version'] ) : 'wp_api_v2';
$webhook->set_api_version( $version );
}
/**
* Save method.
*/
private function save() {
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
}
$webhook_id = absint( $_POST['webhook_id'] );
if ( ! current_user_can( 'edit_shop_webhook', $webhook_id ) ) {
return;
}
$webhook = new WC_Webhook( $webhook_id );
// Name
$this->update_name( $webhook->id );
// Status
$this->update_status( $webhook );
// Delivery URL
$this->update_delivery_url( $webhook );
// Secret
$this->update_secret( $webhook );
// Topic
$this->update_topic( $webhook );
// API version.
$this->update_api_version( $webhook );
$webhook->set_api_version( ! empty( $_POST['webhook_api_version'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_api_version'] ) ) : 'wp_api_v2' ); // WPCS: input var okay, CSRF ok.
// Update date.
wp_update_post( array( 'ID' => $webhook->id, 'post_modified' => current_time( 'mysql' ) ) );
$webhook->save();
// Run actions
do_action( 'woocommerce_webhook_options_save', $webhook->id );
// Run actions.
do_action( 'woocommerce_webhook_options_save', $webhook->get_id() );
delete_transient( 'woocommerce_webhook_ids' );
// Ping the webhook at the first time that is activated
$pending_delivery = get_post_meta( $webhook->id, '_webhook_pending_delivery', true );
if ( isset( $_POST['webhook_status'] ) && 'active' === $_POST['webhook_status'] && $pending_delivery ) {
// Ping the webhook at the first time that is activated.
if ( isset( $_POST['webhook_status'] ) && 'active' === $_POST['webhook_status'] && $webhook->get_pending_delivery() ) { // WPCS: input var okay, CSRF ok.
$result = $webhook->deliver_ping();
if ( is_wp_error( $result ) ) {
// Redirect to webhook edit page to avoid settings save actions
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->id . '&error=' . urlencode( $result->get_error_message() ) ) );
// Redirect to webhook edit page to avoid settings save actions.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( $result->get_error_message() ) ) );
exit();
}
}
// Redirect to webhook edit page to avoid settings save actions
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->id . '&updated=1' ) );
// Redirect to webhook edit page to avoid settings save actions.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&updated=1' ) );
exit();
}
/**
* Create Webhook.
*/
private function create() {
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'create-webhook' ) ) {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
}
if ( ! current_user_can( 'publish_shop_webhooks' ) ) {
wp_die( __( 'You do not have permission to create Webhooks', 'woocommerce' ) );
}
$webhook_id = wp_insert_post( array(
'post_type' => 'shop_webhook',
'post_status' => 'pending',
'ping_status' => 'closed',
'post_author' => get_current_user_id(),
'post_password' => strlen( ( $password = uniqid( 'webhook_' ) ) ) > 20 ? substr( $password, 0, 20 ) : $password,
// @codingStandardsIgnoreStart
/* translators: %s: date */
'post_title' => sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ),
// @codingStandardsIgnoreEnd
'comment_status' => 'open',
) );
if ( is_wp_error( $webhook_id ) ) {
wp_die( $webhook_id->get_error_messages() );
}
update_post_meta( $webhook_id, '_webhook_pending_delivery', true );
$webhook = new WC_Webhook( $webhook_id );
$webhook->set_api_version( 'wp_api_v2' );
delete_transient( 'woocommerce_webhook_ids' );
// Redirect to edit page
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook_id . '&created=1' ) );
exit();
}
/**
* Bulk trash/delete.
* Bulk delete.
*
* @param array $webhooks
* @param bool $delete
* @param array $webhooks List of webhooks IDs.
*/
private function bulk_trash( $webhooks, $delete = false ) {
private function bulk_delete( $webhooks ) {
foreach ( $webhooks as $webhook_id ) {
if ( $delete ) {
wp_delete_post( $webhook_id, true );
} else {
wp_trash_post( $webhook_id );
$webhook = new WC_Webhook( (int) $webhook_id );
$webhook->delete( true );
}
$qty = count( $webhooks );
$status = isset( $_GET['status'] ) ? '&status=' . sanitize_text_field( wp_unslash( $_GET['status'] ) ) : ''; // WPCS: input var okay, CSRF ok.
// Redirect to webhooks page.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' . $status . '&deleted=' . $qty ) );
exit();
}
/**
* Delete webhook.
*/
private function delete() {
check_admin_referer( 'delete-webhook' );
if ( isset( $_GET['delete'] ) ) { // WPCS: input var okay, CSRF ok.
$webhook_id = absint( $_GET['delete'] ); // WPCS: input var okay, CSRF ok.
if ( $webhook_id ) {
$this->bulk_delete( array( $webhook_id ) );
}
}
$type = ! EMPTY_TRASH_DAYS || $delete ? 'deleted' : 'trashed';
$qty = count( $webhooks );
$status = isset( $_GET['status'] ) ? '&status=' . sanitize_text_field( $_GET['status'] ) : '';
delete_transient( 'woocommerce_webhook_ids' );
// Redirect to webhooks page
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' . $status . '&' . $type . '=' . $qty ) );
exit();
}
/**
* Bulk untrash.
*
* @param array $webhooks
*/
private function bulk_untrash( $webhooks ) {
foreach ( $webhooks as $webhook_id ) {
wp_untrash_post( $webhook_id );
}
$qty = count( $webhooks );
delete_transient( 'woocommerce_webhook_ids' );
// Redirect to webhooks page
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&status=trash&untrashed=' . $qty ) );
exit();
}
/**
* Bulk actions.
*/
private function bulk_actions() {
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
check_admin_referer( 'woocommerce-settings' );
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to edit Webhooks', 'woocommerce' ) );
}
if ( ! current_user_can( 'edit_shop_webhooks' ) ) {
wp_die( __( 'You do not have permission to edit Webhooks', 'woocommerce' ) );
if ( isset( $_REQUEST['action'] ) ) { // WPCS: input var okay, CSRF ok.
$webhooks = isset( $_REQUEST['webhook'] ) ? array_map( 'absint', (array) $_REQUEST['webhook'] ) : array(); // WPCS: input var okay, CSRF ok.
$action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ); // WPCS: input var okay, CSRF ok.
if ( 'delete' === $action ) {
$this->bulk_delete( $webhooks );
}
}
$webhooks = array_map( 'absint', (array) $_GET['webhook'] );
switch ( $_GET['action'] ) {
case 'trash' :
$this->bulk_trash( $webhooks );
break;
case 'untrash' :
$this->bulk_untrash( $webhooks );
break;
case 'delete' :
$this->bulk_trash( $webhooks, true );
break;
default :
break;
}
}
/**
* Empty Trash.
*/
private function empty_trash() {
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'empty_trash' ) ) {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
}
if ( ! current_user_can( 'delete_shop_webhooks' ) ) {
wp_die( __( 'You do not have permission to delete Webhooks', 'woocommerce' ) );
}
$webhooks = get_posts( array(
'post_type' => 'shop_webhook',
'ignore_sticky_posts' => true,
'nopaging' => true,
'post_status' => 'trash',
'fields' => 'ids',
) );
foreach ( $webhooks as $webhook_id ) {
wp_delete_post( $webhook_id, true );
}
$qty = count( $webhooks );
// Redirect to webhooks page
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&deleted=' . $qty ) );
exit();
}
/**
@ -342,24 +203,19 @@ class WC_Admin_Webhooks {
*/
public function actions() {
if ( $this->is_webhook_settings_page() ) {
// Save
if ( isset( $_POST['save'] ) && isset( $_POST['webhook_id'] ) ) {
// Save.
if ( isset( $_POST['save'] ) && isset( $_POST['webhook_id'] ) ) { // WPCS: input var okay, CSRF ok.
$this->save();
}
// Create
if ( isset( $_GET['create-webhook'] ) ) {
$this->create();
}
// Bulk actions
if ( isset( $_GET['action'] ) && isset( $_GET['webhook'] ) ) {
// Bulk actions.
if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['webhook'] ) ) { // WPCS: input var okay, CSRF ok.
$this->bulk_actions();
}
// Empty trash
if ( isset( $_GET['empty_trash'] ) ) {
$this->empty_trash();
// Delete webhook.
if ( isset( $_GET['delete'] ) ) { // WPCS: input var okay, CSRF ok.
$this->delete();
}
}
}
@ -368,17 +224,15 @@ class WC_Admin_Webhooks {
* Page output.
*/
public static function page_output() {
// Hide the save button
// Hide the save button.
$GLOBALS['hide_save_button'] = true;
if ( isset( $_GET['edit-webhook'] ) ) {
$webhook_id = absint( $_GET['edit-webhook'] );
if ( isset( $_GET['edit-webhook'] ) ) { // WPCS: input var okay, CSRF ok.
$webhook_id = absint( $_GET['edit-webhook'] ); // WPCS: input var okay, CSRF ok.
$webhook = new WC_Webhook( $webhook_id );
if ( 'trash' != $webhook->post_data->post_status ) {
include( 'settings/views/html-webhooks-edit.php' );
return;
}
include( 'settings/views/html-webhooks-edit.php' );
return;
}
self::table_list_output();
@ -388,37 +242,23 @@ class WC_Admin_Webhooks {
* Notices.
*/
public static function notices() {
if ( isset( $_GET['trashed'] ) ) {
$trashed = absint( $_GET['trashed'] );
/* translators: %d: count */
WC_Admin_Settings::add_message( sprintf( _n( '%d webhook moved to the Trash.', '%d webhooks moved to the Trash.', $trashed, 'woocommerce' ), $trashed ) );
}
if ( isset( $_GET['untrashed'] ) ) {
$untrashed = absint( $_GET['untrashed'] );
/* translators: %d: count */
WC_Admin_Settings::add_message( sprintf( _n( '%d webhook restored from the Trash.', '%d webhooks restored from the Trash.', $untrashed, 'woocommerce' ), $untrashed ) );
}
if ( isset( $_GET['deleted'] ) ) {
$deleted = absint( $_GET['deleted'] );
if ( isset( $_GET['deleted'] ) ) { // WPCS: input var okay, CSRF ok.
$deleted = absint( $_GET['deleted'] ); // WPCS: input var okay, CSRF ok.
/* translators: %d: count */
WC_Admin_Settings::add_message( sprintf( _n( '%d webhook permanently deleted.', '%d webhooks permanently deleted.', $deleted, 'woocommerce' ), $deleted ) );
}
if ( isset( $_GET['updated'] ) ) {
if ( isset( $_GET['updated'] ) ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Settings::add_message( __( 'Webhook updated successfully.', 'woocommerce' ) );
}
if ( isset( $_GET['created'] ) ) {
if ( isset( $_GET['created'] ) ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Settings::add_message( __( 'Webhook created successfully.', 'woocommerce' ) );
}
if ( isset( $_GET['error'] ) ) {
WC_Admin_Settings::add_error( wc_clean( $_GET['error'] ) );
if ( isset( $_GET['error'] ) ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Settings::add_error( sanitize_text_field( wp_unslash( $_GET['error'] ) ) ); // WPCS: input var okay, CSRF ok.
}
}
@ -426,12 +266,13 @@ class WC_Admin_Webhooks {
* Table list output.
*/
private static function table_list_output() {
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>';
echo '<h2>' . esc_html__( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=0' ) ) . '" class="add-new-h2">' . esc_html__( 'Add webhook', 'woocommerce' ) . '</a></h2>';
// Get the webhooks count
$count = array_sum( (array) wp_count_posts( 'shop_webhook', 'readable' ) );
// Get the webhooks count.
$data_store = WC_Data_Store::load( 'webhook' );
$count = count( $data_store->get_webhooks_ids() );
if ( absint( $count ) && $count > 0 ) {
if ( 0 < $count ) {
$webhooks_table_list = new WC_Admin_Webhooks_Table_List();
$webhooks_table_list->prepare_items();
@ -445,22 +286,23 @@ class WC_Admin_Webhooks {
} else {
echo '<div class="woocommerce-BlankState woocommerce-BlankState--webhooks">';
?>
<h2 class="woocommerce-BlankState-message"><?php _e( 'Webhooks are event notifications sent to URLs of your choice. They can be used to integrate with third-party services which support them.', 'woocommerce' ); ?></h2>
<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&create-webhook=1' ), 'create-webhook' ) ); ?>"><?php _e( 'Create a new webhook', 'woocommerce' ); ?></a>
<h2 class="woocommerce-BlankState-message"><?php esc_html_e( 'Webhooks are event notifications sent to URLs of your choice. They can be used to integrate with third-party services which support them.', 'woocommerce' ); ?></h2>
<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=0' ) ); ?>"><?php esc_html_e( 'Create a new webhook', 'woocommerce' ); ?></a>
<?php echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; } </style></div>';
<?php
echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; } </style></div>';
}
}
/**
* Logs output.
*
* @param WC_Webhook $webhook
* @param WC_Webhook $webhook Webhook instance.
*/
public static function logs_output( $webhook ) {
$current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1;
$current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1; // WPCS: input var okay, CSRF ok.
$args = array(
'post_id' => $webhook->id,
'post_id' => $webhook->get_id(),
'status' => 'approve',
'type' => 'webhook_delivery',
'number' => 10,
@ -479,14 +321,14 @@ class WC_Admin_Webhooks {
if ( $logs ) {
include_once( dirname( __FILE__ ) . '/settings/views/html-webhook-logs.php' );
} else {
echo '<p>' . __( 'This Webhook has no log yet.', 'woocommerce' ) . '</p>';
echo '<p>' . esc_html__( 'This Webhook has no log yet.', 'woocommerce' ) . '</p>';
}
}
/**
* Get the webhook topic data.
*
* @param WC_Webhook $webhook
* @param WC_Webhook $webhook Webhook instance.
*
* @return array
*/
@ -500,7 +342,7 @@ class WC_Admin_Webhooks {
if ( 'action' === $resource ) {
$topic = 'action';
} elseif ( ! in_array( $resource, array( 'coupon', 'customer', 'order', 'product' ) ) ) {
} elseif ( ! in_array( $resource, array( 'coupon', 'customer', 'order', 'product' ), true ) ) {
$topic = 'custom';
}
}
@ -515,43 +357,45 @@ class WC_Admin_Webhooks {
/**
* Get the logs navigation.
*
* @param int $total
* @param WC_Webhook $webhook
* @param int $total Number of logs.
* @param WC_Webhook $webhook Webhook instance.
*
* @return string
*/
public static function get_logs_navigation( $total, $webhook ) {
$pages = ceil( $total / 10 );
$current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1;
$current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1; // WPCS: input var okay, CSRF ok.
$html = '<div class="webhook-logs-navigation">';
$html .= '<p class="info" style="float: left;"><strong>';
$html .= '<p class="info" style="float: left;"><strong>';
$html .= sprintf(
/* translators: 1: items count (i.e. 8 items) 2: current page 3: total pages */
$html .= sprintf(
__( '%1$s &ndash; Page %2$d of %3$d', 'woocommerce' ),
sprintf( _n( '%d item', '%d items', $total, 'woocommerce' ), $total ),
$current,
$pages
);
$html .= '</strong></p>';
esc_html__( '%1$s &ndash; Page %2$d of %3$d', 'woocommerce' ),
/* translators: %d: items count */
esc_html( sprintf( _n( '%d item', '%d items', $total, 'woocommerce' ), $total ) ),
$current,
$pages
);
$html .= '</strong></p>';
if ( 1 < $pages ) {
$html .= '<p class="tools" style="float: right;">';
if ( 1 == $current ) {
$html .= '<button class="button-primary" disabled="disabled">' . __( '&lsaquo; Previous', 'woocommerce' ) . '</button> ';
} else {
$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> ';
}
if ( $pages == $current ) {
$html .= '<button class="button-primary" disabled="disabled">' . __( 'Next &rsaquo;', 'woocommerce' ) . '</button>';
} else {
$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>';
}
$html .= '</p>';
if ( 1 < $pages ) {
$html .= '<p class="tools" style="float: right;">';
if ( 1 === $current ) {
$html .= '<button class="button-primary" disabled="disabled">' . __( '&lsaquo; Previous', 'woocommerce' ) . '</button> ';
} else {
$html .= '<a class="button-primary" href="' . admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&log_page=' . ( $current - 1 ) ) . '#webhook-logs">' . __( '&lsaquo; Previous', 'woocommerce' ) . '</a> ';
}
if ( $pages === $current ) {
$html .= '<button class="button-primary" disabled="disabled">' . __( 'Next &rsaquo;', 'woocommerce' ) . '</button>';
} else {
$html .= '<a class="button-primary" href="' . admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&log_page=' . ( $current + 1 ) ) . '#webhook-logs">' . __( 'Next &rsaquo;', 'woocommerce' ) . '</a>';
}
$html .= '</p>';
}
$html .= '<div class="clear"></div></div>';
return $html;

View File

@ -2,17 +2,22 @@
/**
* WooCommerce API Settings
*
* @author WooThemes
* @author Automattic
* @category Admin
* @package WooCommerce/Admin
* @version 2.4.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Settings_Rest_API', false ) ) :
/**
* Settings for API.
*/
if ( class_exists( 'WC_Settings_Rest_API', false ) ) {
return new WC_Settings_Rest_API();
}
/**
* WC_Settings_Rest_API.
@ -50,7 +55,7 @@ class WC_Settings_Rest_API extends WC_Settings_Page {
/**
* Get settings array.
*
* @param string $current_section
* @param string $current_section Current section slug.
* @return array
*/
public function get_settings( $current_section = '' ) {
@ -86,28 +91,15 @@ class WC_Settings_Rest_API extends WC_Settings_Page {
/**
* Form method.
*
* @param string $method
* @param string $method Method name.
*
* @return string
*/
public function form_method( $method ) {
global $current_section;
if ( 'webhooks' == $current_section ) {
if ( isset( $_GET['edit-webhook'] ) ) {
$webhook_id = absint( $_GET['edit-webhook'] );
$webhook = new WC_Webhook( $webhook_id );
if ( 'trash' != $webhook->post_data->post_status ) {
return 'post';
}
}
return 'get';
}
if ( 'keys' == $current_section ) {
if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) {
if ( 'keys' === $current_section ) {
if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) { // WPCS: input var okay, CSRF ok.
return 'post';
}
@ -121,10 +113,10 @@ class WC_Settings_Rest_API extends WC_Settings_Page {
* Notices.
*/
private function notices() {
if ( isset( $_GET['section'] ) && 'webhooks' == $_GET['section'] ) {
if ( isset( $_GET['section'] ) && 'webhooks' === $_GET['section'] ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Webhooks::notices();
}
if ( isset( $_GET['section'] ) && 'keys' == $_GET['section'] ) {
if ( isset( $_GET['section'] ) && 'keys' === $_GET['section'] ) { // WPCS: input var okay, CSRF ok.
WC_Admin_API_Keys::notices();
}
}
@ -135,7 +127,7 @@ class WC_Settings_Rest_API extends WC_Settings_Page {
public function output() {
global $current_section;
if ( 'webhooks' == $current_section ) {
if ( 'webhooks' === $current_section ) {
WC_Admin_Webhooks::page_output();
} elseif ( 'keys' === $current_section ) {
WC_Admin_API_Keys::page_output();
@ -151,13 +143,11 @@ class WC_Settings_Rest_API extends WC_Settings_Page {
public function save() {
global $current_section;
if ( apply_filters( 'woocommerce_rest_api_valid_to_save', ! in_array( $current_section, array( 'keys', 'webhooks' ) ) ) ) {
if ( apply_filters( 'woocommerce_rest_api_valid_to_save', ! in_array( $current_section, array( 'keys', 'webhooks' ), true ) ) ) {
$settings = $this->get_settings();
WC_Admin_Settings::save_fields( $settings );
}
}
}
endif;
return new WC_Settings_Rest_API();

View File

@ -1,22 +1,27 @@
<?php
/**
* Admin View: Edit Webhooks
*
* @package WooCommerce/Admin/Webhooks/Views
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<input type="hidden" name="webhook_id" value="<?php echo esc_attr( $webhook->id ); ?>" />
<input type="hidden" name="webhook_id" value="<?php echo esc_attr( $webhook->get_id() ); ?>" />
<div id="webhook-options" class="settings-panel">
<h2><?php _e( 'Webhook data', 'woocommerce' ); ?></h2>
<h2><?php esc_html_e( 'Webhook data', 'woocommerce' ); ?></h2>
<table class="form-table">
<tbody>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="webhook_name"><?php _e( 'Name', 'woocommerce' ); ?></label>
<label for="webhook_name"><?php esc_html_e( 'Name', 'woocommerce' ); ?></label>
<?php
// @codingStandardsIgnoreStart
echo wc_help_tip( sprintf( __( 'Friendly name for identifying this webhook, defaults to Webhook created on %s.', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ) );
// @codingStandardsIgnoreEnd
/* translators: %s: date */
echo wc_help_tip( sprintf( __( 'Friendly name for identifying this webhook, defaults to Webhook created on %s.', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ) ); // @codingStandardsIgnoreLine
?>
</th>
<td class="forminp">
@ -25,16 +30,17 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="webhook_status"><?php _e( 'Status', 'woocommerce' ); ?></label>
<label for="webhook_status"><?php esc_html_e( 'Status', 'woocommerce' ); ?></label>
<?php wc_help_tip( __( 'The options are &quot;Active&quot; (delivers payload), &quot;Paused&quot; (does not deliver), or &quot;Disabled&quot; (does not deliver due delivery failures).', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
<select name="webhook_status" id="webhook_status" class="wc-enhanced-select">
<?php
$statuses = wc_get_webhook_statuses();
$current_status = $webhook->get_status();
$statuses = wc_get_webhook_statuses();
$current_status = $webhook->get_status();
foreach ( $statuses as $status_slug => $status_name ) : ?>
foreach ( $statuses as $status_slug => $status_name ) :
?>
<option value="<?php echo esc_attr( $status_slug ); ?>" <?php selected( $current_status, $status_slug, true ); ?>><?php echo esc_html( $status_name ); ?></option>
<?php endforeach; ?>
</select>
@ -42,7 +48,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="webhook_topic"><?php _e( 'Topic', 'woocommerce' ); ?></label>
<label for="webhook_topic"><?php esc_html_e( 'Topic', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( __( 'Select when the webhook will fire.', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
@ -71,7 +77,8 @@ if ( ! defined( 'ABSPATH' ) ) {
'custom' => __( 'Custom', 'woocommerce' ),
) );
foreach ( $topics as $topic_slug => $topic_name ) : ?>
foreach ( $topics as $topic_slug => $topic_name ) :
?>
<option value="<?php echo esc_attr( $topic_slug ); ?>" <?php selected( $topic_data['topic'], $topic_slug, true ); ?>><?php echo esc_html( $topic_name ); ?></option>
<?php endforeach; ?>
</select>
@ -79,8 +86,8 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top" id="webhook-action-event-wrap">
<th scope="row" class="titledesc">
<label for="webhook_action_event"><?php _e( 'Action event', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( __( 'Enter the action that will trigger this webhook.', 'woocommerce' ) ); ?>
<label for="webhook_action_event"><?php esc_html_e( 'Action event', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( esc_html__( 'Enter the action that will trigger this webhook.', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
<input name="webhook_action_event" id="webhook_action_event" type="text" class="input-text regular-input" value="<?php echo esc_attr( $topic_data['event'] ); ?>" />
@ -88,8 +95,8 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top" id="webhook-custom-topic-wrap">
<th scope="row" class="titledesc">
<label for="webhook_custom_topic"><?php _e( 'Custom topic', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( __( 'Enter the custom topic that will trigger this webhook.', 'woocommerce' ) ); ?>
<label for="webhook_custom_topic"><?php esc_html_e( 'Custom topic', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( esc_html__( 'Enter the custom topic that will trigger this webhook.', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
<input name="webhook_custom_topic" id="webhook_custom_topic" type="text" class="input-text regular-input" value="<?php echo esc_attr( $webhook->get_topic() ); ?>" />
@ -97,8 +104,8 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="webhook_delivery_url"><?php _e( 'Delivery URL', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( __( 'URL where the webhook payload is delivered.', 'woocommerce' ) ); ?>
<label for="webhook_delivery_url"><?php esc_html_e( 'Delivery URL', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( esc_html__( 'URL where the webhook payload is delivered.', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
<input name="webhook_delivery_url" id="webhook_delivery_url" type="text" class="input-text regular-input" value="<?php echo esc_attr( $webhook->get_delivery_url() ); ?>" />
@ -106,8 +113,8 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="webhook_secret"><?php _e( 'Secret', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( __( 'The secret key is used to generate a hash of the delivered webhook and provided in the request headers.', 'woocommerce' ) ); ?>
<label for="webhook_secret"><?php esc_html_e( 'Secret', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( esc_html__( 'The secret key is used to generate a hash of the delivered webhook and provided in the request headers.', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
<input name="webhook_secret" id="webhook_secret" type="text" class="input-text regular-input" value="<?php echo esc_attr( $webhook->get_secret() ); ?>" />
@ -115,14 +122,14 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="webhook_api_version"><?php _e( 'API Version', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( __( 'REST API version used in the webhook deliveries.', 'woocommerce' ) ); ?>
<label for="webhook_api_version"><?php esc_html_e( 'API Version', 'woocommerce' ); ?></label>
<?php echo wc_help_tip( esc_html__( 'REST API version used in the webhook deliveries.', 'woocommerce' ) ); ?>
</th>
<td class="forminp">
<select name="webhook_api_version" id="webhook_api_version">
<option value="wp_api_v2" <?php selected( 'wp_api_v2', $webhook->get_api_version(), true ); ?>><?php _e( 'WP REST API Integration v2', 'woocommerce' ); ?></option>
<option value="wp_api_v1" <?php selected( 'wp_api_v1', $webhook->get_api_version(), true ); ?>><?php _e( 'WP REST API Integration v1', 'woocommerce' ); ?></option>
<option value="legacy_v3" <?php selected( 'legacy_v3', $webhook->get_api_version(), true ); ?>><?php _e( 'Legacy API v3 (deprecated)', 'woocommerce' ); ?></option>
<option value="wp_api_v2" <?php selected( 'wp_api_v2', $webhook->get_api_version(), true ); ?>><?php esc_html_e( 'WP REST API Integration v2', 'woocommerce' ); ?></option>
<option value="wp_api_v1" <?php selected( 'wp_api_v1', $webhook->get_api_version(), true ); ?>><?php esc_html_e( 'WP REST API Integration v1', 'woocommerce' ); ?></option>
<option value="legacy_v3" <?php selected( 'legacy_v3', $webhook->get_api_version(), true ); ?>><?php esc_html_e( 'Legacy API v3 (deprecated)', 'woocommerce' ); ?></option>
</select>
</td>
</tr>
@ -133,34 +140,34 @@ if ( ! defined( 'ABSPATH' ) ) {
</div>
<div id="webhook-actions" class="settings-panel">
<h2><?php _e( 'Webhook actions', 'woocommerce' ); ?></h2>
<h2><?php esc_html_e( 'Webhook actions', 'woocommerce' ); ?></h2>
<table class="form-table">
<tbody>
<?php if ( '0000-00-00 00:00:00' != $webhook->post_data->post_modified_gmt ) : ?>
<?php if ( '0000-00-00 00:00:00' == $webhook->post_data->post_date_gmt ) : ?>
<?php if ( $webhook->get_date_created() && '0000-00-00 00:00:00' !== $webhook->get_date_created()->date( 'Y-m-d H:i:s' ) ) : ?>
<?php if ( is_null( $webhook->get_date_modified() ) ) : ?>
<tr valign="top">
<th scope="row" class="titledesc">
<?php _e( 'Created at', 'woocommerce' ); ?>
<?php esc_html_e( 'Created at', 'woocommerce' ); ?>
</th>
<td class="forminp">
<?php echo date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->post_data->post_modified_gmt ) ); ?>
<?php echo esc_html( date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->get_date_created()->date( 'Y-m-d H:i:s' ) ) ) ); ?>
</td>
</tr>
<?php else : ?>
<tr valign="top">
<th scope="row" class="titledesc">
<?php _e( 'Created at', 'woocommerce' ); ?>
<?php esc_html_e( 'Created at', 'woocommerce' ); ?>
</th>
<td class="forminp">
<?php echo date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->post_data->post_date_gmt ) ); ?>
<?php echo esc_html( date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->get_date_created()->date( 'Y-m-d H:i:s' ) ) ) ); ?>
</td>
</tr>
<tr valign="top">
<th scope="row" class="titledesc">
<?php _e( 'Updated at', 'woocommerce' ); ?>
<?php esc_html_e( 'Updated at', 'woocommerce' ); ?>
</th>
<td class="forminp">
<?php echo date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->post_data->post_modified_gmt ) ); ?>
<?php echo esc_html( date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->get_date_modified()->date( 'Y-m-d H:i:s' ) ) ) ); ?>
</td>
</tr>
<?php endif; ?>
@ -169,8 +176,13 @@ if ( ! defined( 'ABSPATH' ) ) {
<td colspan="2" scope="row" style="padding-left: 0;">
<p class="submit">
<input type="submit" class="button button-primary button-large" name="save" id="publish" accesskey="p" value="<?php esc_attr_e( 'Save webhook', 'woocommerce' ); ?>" />
<?php if ( current_user_can( 'delete_post', $webhook->id ) ) : ?>
<a style="color: #a00; text-decoration: none; margin-left: 10px;" href="<?php echo esc_url( get_delete_post_link( $webhook->id ) ); ?>"><?php echo ( ! EMPTY_TRASH_DAYS ) ? __( 'Delete permanently', 'woocommerce' ) : __( 'Move to trash', 'woocommerce' ); ?></a>
<?php
if ( $webhook->get_id() ) :
$delete_url = wp_nonce_url( add_query_arg( array(
'delete' => $webhook->get_id(),
), admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' ) ), 'delete-webhook' );
?>
<a style="color: #a00; text-decoration: none; margin-left: 10px;" href="<?php echo esc_url( $delete_url ); ?>"><?php esc_html_e( 'Delete permanently', 'woocommerce' ); ?></a>
<?php endif; ?>
</p>
</td>
@ -179,12 +191,6 @@ if ( ! defined( 'ABSPATH' ) ) {
</table>
</div>
<div id="webhook-logs" class="settings-panel">
<h2><?php _e( 'Webhook logs', 'woocommerce' ); ?></h2>
<?php WC_Admin_Webhooks::logs_output( $webhook ); ?>
</div>
<script type="text/javascript">
jQuery( function ( $ ) {
$( '#webhook-options' ).find( '#webhook_topic' ).on( 'change', function() {

View File

@ -2,7 +2,7 @@
/**
* Webhook Data Store
*
* @version 3.2.0
* @version 3.3.0
* @package WooCommerce/Classes/Data_Store
* @category Class
* @author Automattic
@ -20,7 +20,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
/**
* Create a new webhook in the database.
*
* @since 3.2.0
* @since 3.3.0
* @param WC_Webhook $webhook Webhook instance.
*/
public function create( &$webhook ) {
@ -50,22 +50,21 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
'pending_delivery' => $webhook->get_pending_delivery( 'edit' ),
);
// @codingStandardsIgnoreStart
$wpdb->insert( $wpdb->prefix . 'wc_webhooks', $data );
// @codingStandardsIgnoreEnd
$wpdb->insert( $wpdb->prefix . 'wc_webhooks', $data ); // WPCS: DB call ok.
$webhook_id = $wpdb->insert_id;
$webhook->set_id( $webhook_id );
$webhook->apply_changes();
delete_transient( 'woocommerce_webhook_ids' );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
do_action( 'woocommerce_new_webhook', $webhook_id );
}
/**
* Read a webhook from the database.
*
* @since 3.2.0
* @since 3.3.0
* @param WC_Webhook $webhook Webhook instance.
* @throws Exception When webhook is invalid.
*/
@ -75,9 +74,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$data = wp_cache_get( $webhook->get_id(), 'webhooks' );
if ( false === $data ) {
// @codingStandardsIgnoreStart
$data = $wpdb->get_row( $wpdb->prepare( "SELECT webhook_id, status, name, user_id, delivery_url, secret, topic, date_created, date_modified, api_version, failure_count, pending_delivery FROM {$wpdb->prefix}wc_webhooks WHERE webhook_id = %d LIMIT 1;", $webhook->get_id() ), ARRAY_A );
// @codingStandardsIgnoreEnd
$data = $wpdb->get_row( $wpdb->prepare( "SELECT webhook_id, status, name, user_id, delivery_url, secret, topic, date_created, date_modified, api_version, failure_count, pending_delivery FROM {$wpdb->prefix}wc_webhooks WHERE webhook_id = %d LIMIT 1;", $webhook->get_id() ), ARRAY_A ); // WPCS: cache ok, DB call ok.
wp_cache_add( $webhook->get_id(), $data, 'webhooks' );
}
@ -91,8 +88,8 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
'delivery_url' => $data['delivery_url'],
'secret' => $data['secret'],
'topic' => $data['topic'],
'date_created' => $data['date_created'],
'date_modified' => $data['date_modified'],
'date_created' => '0000-00-00 00:00:00' === $data['date_created'] ? null : $data['date_created'],
'date_modified' => '0000-00-00 00:00:00' === $data['date_modified'] ? null : $data['date_modified'],
'api_version' => $data['api_version'],
'failure_count' => $data['failure_count'],
'pending_delivery' => $data['pending_delivery'],
@ -108,7 +105,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
/**
* Update a webhook.
*
* @since 3.2.0
* @since 3.3.0
* @param WC_Webhook $webhook Webhook instance.
*/
public function update( &$webhook ) {
@ -138,50 +135,48 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
'pending_delivery' => $webhook->get_pending_delivery( 'edit' ),
);
// @codingStandardsIgnoreStart
$wpdb->update(
$wpdb->prefix . 'wc_webhooks',
$data,
array(
'webhook_id' => $webhook->get_id( 'edit' ),
)
);
// @codingStandardsIgnoreEnd
); // WPCS: DB call ok.
$webhook->apply_changes();
wp_cache_delete( $webhook->get_id(), 'webhooks' );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
do_action( 'woocommerce_webhook_updated', $webhook->get_id() );
}
/**
* Remove a webhook from the database.
*
* @since 3.2.0
* @since 3.3.0
* @param WC_Webhook $webhook Webhook instance.
* @param bool $force_delete Skip trash bin forcing to delete.
*/
public function delete( &$webhook, $force_delete = false ) {
global $wpdb;
// @codingStandardsIgnoreStart
$wpdb->delete(
$wpdb->prefix . 'wc_webhooks',
array(
'webhook_id' => $webhook->get_id(),
),
array( '%d' )
);
// @codingStandardsIgnoreEnd
); // WPCS: cache ok, DB call ok.
delete_transient( 'woocommerce_webhook_ids' );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
do_action( 'woocommerce_webhook_deleted', $webhook->get_id(), $webhook );
}
/**
* Get API version number.
*
* @since 3.2.0
* @since 3.3.0
* @param string $api_version REST API version.
* @return int
*/
@ -192,7 +187,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
/**
* Get all webhooks IDs.
*
* @since 3.2.0
* @since 3.3.0
* @return int[]
*/
public function get_webhooks_ids() {
@ -201,14 +196,78 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$ids = get_transient( 'woocommerce_webhook_ids' );
if ( false === $ids ) {
// @codingStandardsIgnoreStart
$results = $wpdb->get_results( "SELECT webhook_id FROM {$wpdb->prefix}wc_webhooks" );
// @codingStandardsIgnoreEnd
$ids = array_map( 'intval', wp_list_pluck( $results, 'webhook_id' ) );
$results = $wpdb->get_results( "SELECT webhook_id FROM {$wpdb->prefix}wc_webhooks" ); // WPCS: cache ok, DB call ok.
$ids = array_map( 'intval', wp_list_pluck( $results, 'webhook_id' ) );
set_transient( 'woocommerce_webhook_ids', $ids );
}
return $ids;
}
/**
* Search webhooks.
*
* @param array $args Search arguments.
* @return array
*/
public function search_webhooks( $args ) {
global $wpdb;
$args = wp_parse_args( $args, array(
'limit' => 10,
'offset' => 0,
) );
$limit = -1 < $args['limit'] ? sprintf( 'LIMIT %d', $args['limit'] ) : '';
$offset = 0 < $args['offset'] ? sprintf( 'OFFSET %d', $args['offset'] ) : '';
$status = ! empty( $args['status'] ) ? "AND `status` = '" . sanitize_key( $args['status'] ) . "'" : '';
$search = ! empty( $args['search'] ) ? "AND `name` LIKE '%" . $wpdb->esc_like( sanitize_text_field( $args['search'] ) ) . "%'" : '';
$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
$ids = wp_cache_get( $cache_key, 'webhook_search_results' );
if ( false !== $ids ) {
return $ids;
}
$query = trim( "
SELECT webhook_id
FROM {$wpdb->prefix}wc_webhooks
WHERE 1=1
{$status}
{$search}
ORDER BY webhook_id
{$limit}
{$offset}
" );
$results = $wpdb->get_results( $query ); // WPCS: cache ok, DB call ok, unprepared SQL ok.
$ids = wp_list_pluck( $results, 'webhook_id' );
wp_cache_set( $cache_key, $ids, 'webhook_search_results' );
return $ids;
}
/**
* Get total webhook counts by status.
*
* @return array
*/
public function get_count_webhooks_by_status() {
$statuses = array_keys( wc_get_webhook_statuses() );
$counts = array();
foreach ( $statuses as $status ) {
$count = count( $this->search_webhooks( array(
'limit' => -1,
'status' => $status,
) ) );
$counts[ $status ] = $count;
}
return $counts;
}
}

View File

@ -5,7 +5,7 @@
* @author Automattic
* @category Core
* @package WooCommerce/Functions
* @version 3.2.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -62,7 +62,7 @@ function wc_get_webhook_statuses() {
/**
* Load webhooks.
*
* @since 3.2.0
* @since 3.3.0
* @return bool
*/
function wc_load_webhooks() {
@ -78,3 +78,15 @@ function wc_load_webhooks() {
return $loaded;
}
/**
* Get webhook.
*
* @param int $id Webhook ID.
* @return WC_Webhook|null
*/
function wc_get_webhook( $id ) {
$webhook = new WC_Webhook( (int) $id );
return 0 !== $webhook->get_id() ? $webhook : null;
}

View File

@ -15,4 +15,10 @@
<property name="customSanitizingFunctions" type="array" value="wc_clean" />
</properties>
</rule>
<rule ref="WordPress.XSS.EscapeOutput">
<properties>
<property name="customEscapingFunctions" type="array" value="wc_help_tip" />
</properties>
</rule>
</ruleset>