Add $status param to wc_load_webhooks()

And the corresponding data stores. Defaults to '', meaning do not
load only webhooks with a specific status. This maintains backward
compatibility. However, the call to wc_load_webhooks() within
WooCommerce::load_webhooks() can now only load active webhooks, as
they are the only ones that should be enqueued.
This commit is contained in:
Brent Shepherd 2018-09-24 13:22:16 +10:00
parent 8ee3e8a6e9
commit 67bf101aaf
4 changed files with 119 additions and 11 deletions

View File

@ -59,7 +59,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$webhook->set_id( $webhook_id ); $webhook->set_id( $webhook_id );
$webhook->apply_changes(); $webhook->apply_changes();
delete_transient( 'woocommerce_webhook_ids' ); $this->delete_transients( $webhook->get_status( 'edit' ) );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' ); WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
do_action( 'woocommerce_new_webhook', $webhook_id ); do_action( 'woocommerce_new_webhook', $webhook_id );
} }
@ -180,7 +180,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
array( '%d' ) array( '%d' )
); // WPCS: cache ok, DB call ok. ); // WPCS: cache ok, DB call ok.
delete_transient( 'woocommerce_webhook_ids' ); $this->delete_transients( 'all' );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' ); WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
do_action( 'woocommerce_webhook_deleted', $webhook->get_id(), $webhook ); do_action( 'woocommerce_webhook_deleted', $webhook->get_id(), $webhook );
} }
@ -200,18 +200,31 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
* Get all webhooks IDs. * Get all webhooks IDs.
* *
* @since 3.3.0 * @since 3.3.0
* @throws InvalidArgumentException If a $status value is passed in that is not in the known wc_get_webhook_statuses() keys.
* @param string $status Optional - status to filter results by. Must be a key in return value of @see wc_get_webhook_statuses(). @since 3.5.0.
* @return int[] * @return int[]
*/ */
public function get_webhooks_ids() { public function get_webhooks_ids( $status = '' ) {
global $wpdb; global $wpdb;
$ids = get_transient( 'woocommerce_webhook_ids' ); if ( ! empty( $status ) ) {
$this->validate_status( $status );
}
$ids = get_transient( $this->get_transient_key( $status ) );
if ( false === $ids ) { if ( false === $ids ) {
$results = $wpdb->get_results( "SELECT webhook_id FROM {$wpdb->prefix}wc_webhooks" ); // WPCS: cache ok, DB call ok.
$query = "SELECT webhook_id FROM {$wpdb->prefix}wc_webhooks";
if ( ! empty( $status ) ) {
$query .= $wpdb->prepare( " AND status = %s", $status );
}
$results = $wpdb->get_results( $query ); // WPCS: cache ok, DB call ok.
$ids = array_map( 'intval', wp_list_pluck( $results, 'webhook_id' ) ); $ids = array_map( 'intval', wp_list_pluck( $results, 'webhook_id' ) );
set_transient( 'woocommerce_webhook_ids', $ids ); set_transient( $this->get_transient_key( $status ), $ids );
} }
return $ids; return $ids;
@ -349,4 +362,50 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
return $counts; return $counts;
} }
/**
* Check if a given string is in known statuses, based on return value of @see wc_get_webhook_statuses().
*
* @since 3.5.0
* @throws InvalidArgumentException If $status is not empty and not in the known wc_get_webhook_statuses() keys.
* @param string $status Status to check.
*/
private function validate_status( $status ) {
if ( ! array_key_exists( $status, wc_get_webhook_statuses() ) ) {
throw new InvalidArgumentException( sprintf( 'Invalid status given: %s. Status must be one of: %s.', $status, implode( ', ', array_keys( wc_get_webhook_statuses() ) ) ) );
}
}
/**
* Get the transient key used to cache a set of webhook IDs, optionally filtered by status.
*
* @since 3.5.0
* @param string $status Optional - status of cache key.
* @return string
*/
private function get_transient_key( $status = '' ) {
return empty( $status ) ? 'woocommerce_webhook_ids' : sprintf( 'woocommerce_webhook_ids_status_%s', $status );
}
/**
* Delete the transients used to cache a set of webhook IDs, optionally filtered by status.
*
* @since 3.5.0
* @param string $status Optional - status of cache to delete, or 'all' to delete all caches.
*/
private function delete_transients( $status = '' ) {
// Always delete the non-filtered cache.
delete_transient( $this->get_transient_key( '' ) );
if ( ! empty( $status ) ) {
if ( 'all' === $status ) {
foreach ( wc_get_webhook_statuses() as $status_key => $status_string ) {
delete_transient( $this->get_transient_key( $status_key ) );
}
} else {
delete_transient( $this->get_transient_key( $status ) );
}
}
}
} }

View File

@ -28,7 +28,9 @@ interface WC_Webhook_Data_Store_Interface {
* Get all webhooks IDs. * Get all webhooks IDs.
* *
* @since 3.2.0 * @since 3.2.0
* @throws InvalidArgumentException If a $status value is passed in that is not in the known wc_get_webhook_statuses() keys.
* @param string $status Optional - status to filter results by. Must be a key in return value of @see wc_get_webhook_statuses(). @since 3.5.0.
* @return int[] * @return int[]
*/ */
public function get_webhooks_ids(); public function get_webhooks_ids( $status = '' );
} }

View File

@ -128,11 +128,12 @@ function wc_get_webhook_statuses() {
* *
* @since 3.3.0 * @since 3.3.0
* @throws Exception If webhook cannot be read/found and $data parameter of WC_Webhook class constructor is set. * @throws Exception If webhook cannot be read/found and $data parameter of WC_Webhook class constructor is set.
* @param string $status Optional - status to filter results by. Must be a key in return value of @see wc_get_webhook_statuses(). @since 3.5.0.
* @return bool * @return bool
*/ */
function wc_load_webhooks() { function wc_load_webhooks( $status = '' ) {
$data_store = WC_Data_Store::load( 'webhook' ); $data_store = WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->get_webhooks_ids(); $webhooks = $data_store->get_webhooks_ids( $status );
$loaded = false; $loaded = false;
foreach ( $webhooks as $webhook_id ) { foreach ( $webhooks as $webhook_id ) {

View File

@ -109,12 +109,58 @@ class WC_Tests_Webhook_Functions extends WC_Unit_Test_Case {
$this->assertFalse( wc_load_webhooks() ); $this->assertFalse( wc_load_webhooks() );
} }
protected function create_webhook( $topic = 'action.woocommerce_some_action' ) { /**
* Provide webhook statuses for tests.
*
* @since 3.5.0
*/
public function provider_webhook_statuses() {
$webhook_statuses = array();
foreach ( wc_get_webhook_statuses() as $status_key => $status_string ) {
$webhook_statuses[] = array( $status_key );
}
return $webhook_statuses;
}
/**
* Test the $status param on wc_load_webhooks().
*
* @dataProvider provider_webhook_statuses
* @param string $status The status of the webhook to test.
* @since 3.5.0
*/
public function test_wc_load_webhooks_status( $status ) {
$webhook = $this->create_webhook( 'action.woocommerce_some_action', $status );
$this->assertTrue( wc_load_webhooks( '' ) );
$this->assertTrue( wc_load_webhooks( $status ) );
// Find a different, but still valid status.
$other_status = ( 'active' === $status ) ? 'disabled' : 'active';
$this->assertFalse( wc_load_webhooks( $other_status ) );
$webhook->delete( true );
$this->assertFalse( wc_load_webhooks( $status ) );
}
/**
* @expectedException InvalidArgumentException
*/
public function test_wc_load_webhooks_status_invalid() {
wc_load_webhooks( 'invalid_status' );
}
protected function create_webhook( $topic = 'action.woocommerce_some_action', $status = 'active' ) {
$webhook = new WC_Webhook(); $webhook = new WC_Webhook();
$webhook->set_props( $webhook->set_props(
array( array(
'status' => 'active', 'status' => $status,
'name' => 'Testing webhook', 'name' => 'Testing webhook',
'user_id' => 0, 'user_id' => 0,
'delivery_url' => 'https://requestb.in/17jajv31', 'delivery_url' => 'https://requestb.in/17jajv31',