PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.8.0-beta.2
WooCommerce v10.8.0-beta.2
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / data-stores / class-wc-webhook-data-store.php
woocommerce / includes / data-stores Last commit date
abstract-wc-order-data-store-cpt.php 3 weeks ago abstract-wc-order-item-type-data-store.php 6 months ago class-wc-coupon-data-store-cpt.php 1 month ago class-wc-customer-data-store-session.php 7 months ago class-wc-customer-data-store.php 2 months ago class-wc-customer-download-data-store.php 3 years ago class-wc-customer-download-log-data-store.php 1 year ago class-wc-data-store-wp.php 7 months ago class-wc-order-data-store-cpt.php 1 month ago class-wc-order-item-coupon-data-store.php 8 years ago class-wc-order-item-data-store.php 1 month ago class-wc-order-item-fee-data-store.php 8 years ago class-wc-order-item-product-data-store.php 3 years ago class-wc-order-item-shipping-data-store.php 1 year ago class-wc-order-item-tax-data-store.php 6 years ago class-wc-order-refund-data-store-cpt.php 3 weeks ago class-wc-payment-token-data-store.php 2 months ago class-wc-product-data-store-cpt.php 1 month ago class-wc-product-grouped-data-store-cpt.php 2 months ago class-wc-product-variable-data-store-cpt.php 1 month ago class-wc-product-variation-data-store-cpt.php 7 months ago class-wc-shipping-zone-data-store.php 4 months ago class-wc-webhook-data-store.php 2 years ago
class-wc-webhook-data-store.php
463 lines
1 <?php
2 /**
3 * Webhook Data Store
4 *
5 * @version 3.3.0
6 * @package WooCommerce\Classes\Data_Store
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Webhook data store class.
15 */
16 class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
17
18 /**
19 * Create a new webhook in the database.
20 *
21 * @since 3.3.0
22 * @param WC_Webhook $webhook Webhook instance.
23 */
24 public function create( &$webhook ) {
25 global $wpdb;
26
27 $changes = $webhook->get_changes();
28 if ( isset( $changes['date_created'] ) ) {
29 $date_created = $webhook->get_date_created()->date( 'Y-m-d H:i:s' );
30 $date_created_gmt = gmdate( 'Y-m-d H:i:s', $webhook->get_date_created()->getTimestamp() );
31 } else {
32 $date_created = current_time( 'mysql' );
33 $date_created_gmt = current_time( 'mysql', 1 );
34 $webhook->set_date_created( $date_created );
35 }
36
37 // Pending delivery by default if not set while creating a new webhook.
38 if ( ! isset( $changes['pending_delivery'] ) ) {
39 $webhook->set_pending_delivery( true );
40 }
41
42 $data = array(
43 'status' => $webhook->get_status( 'edit' ),
44 'name' => $webhook->get_name( 'edit' ),
45 'user_id' => $webhook->get_user_id( 'edit' ),
46 'delivery_url' => $webhook->get_delivery_url( 'edit' ),
47 'secret' => $webhook->get_secret( 'edit' ),
48 'topic' => $webhook->get_topic( 'edit' ),
49 'date_created' => $date_created,
50 'date_created_gmt' => $date_created_gmt,
51 'api_version' => $this->get_api_version_number( $webhook->get_api_version( 'edit' ) ),
52 'failure_count' => $webhook->get_failure_count( 'edit' ),
53 'pending_delivery' => $webhook->get_pending_delivery( 'edit' ),
54 );
55
56 $wpdb->insert( $wpdb->prefix . 'wc_webhooks', $data ); // WPCS: DB call ok.
57
58 $webhook_id = $wpdb->insert_id;
59 $webhook->set_id( $webhook_id );
60 $webhook->apply_changes();
61
62 $this->delete_transients( $webhook->get_status( 'edit' ) );
63 WC_Cache_Helper::invalidate_cache_group( 'webhooks' );
64 do_action( 'woocommerce_new_webhook', $webhook_id, $webhook );
65 }
66
67 /**
68 * Read a webhook from the database.
69 *
70 * @since 3.3.0
71 * @param WC_Webhook $webhook Webhook instance.
72 * @throws Exception When webhook is invalid.
73 */
74 public function read( &$webhook ) {
75 global $wpdb;
76
77 $data = wp_cache_get( $webhook->get_id(), 'webhooks' );
78
79 if ( false === $data ) {
80 $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.
81
82 wp_cache_add( $webhook->get_id(), $data, 'webhooks' );
83 }
84
85 if ( is_array( $data ) ) {
86 $webhook->set_props(
87 array(
88 'id' => $data['webhook_id'],
89 'status' => $data['status'],
90 'name' => $data['name'],
91 'user_id' => $data['user_id'],
92 'delivery_url' => $data['delivery_url'],
93 'secret' => $data['secret'],
94 'topic' => $data['topic'],
95 'date_created' => '0000-00-00 00:00:00' === $data['date_created'] ? null : $data['date_created'],
96 'date_modified' => '0000-00-00 00:00:00' === $data['date_modified'] ? null : $data['date_modified'],
97 'api_version' => $data['api_version'],
98 'failure_count' => $data['failure_count'],
99 'pending_delivery' => $data['pending_delivery'],
100 )
101 );
102 $webhook->set_object_read( true );
103
104 do_action( 'woocommerce_webhook_loaded', $webhook );
105 } else {
106 throw new Exception( __( 'Invalid webhook.', 'woocommerce' ) );
107 }
108 }
109
110 /**
111 * Update a webhook.
112 *
113 * @since 3.3.0
114 * @param WC_Webhook $webhook Webhook instance.
115 */
116 public function update( &$webhook ) {
117 global $wpdb;
118
119 $changes = $webhook->get_changes();
120 $trigger = isset( $changes['delivery_url'] );
121
122 if ( isset( $changes['date_modified'] ) ) {
123 $date_modified = $webhook->get_date_modified()->date( 'Y-m-d H:i:s' );
124 $date_modified_gmt = gmdate( 'Y-m-d H:i:s', $webhook->get_date_modified()->getTimestamp() );
125 } else {
126 $date_modified = current_time( 'mysql' );
127 $date_modified_gmt = current_time( 'mysql', 1 );
128 $webhook->set_date_modified( $date_modified );
129 }
130
131 $data = array(
132 'status' => $webhook->get_status( 'edit' ),
133 'name' => $webhook->get_name( 'edit' ),
134 'user_id' => $webhook->get_user_id( 'edit' ),
135 'delivery_url' => $webhook->get_delivery_url( 'edit' ),
136 'secret' => $webhook->get_secret( 'edit' ),
137 'topic' => $webhook->get_topic( 'edit' ),
138 'date_modified' => $date_modified,
139 'date_modified_gmt' => $date_modified_gmt,
140 'api_version' => $this->get_api_version_number( $webhook->get_api_version( 'edit' ) ),
141 'failure_count' => $webhook->get_failure_count( 'edit' ),
142 'pending_delivery' => $webhook->get_pending_delivery( 'edit' ),
143 );
144
145 $wpdb->update(
146 $wpdb->prefix . 'wc_webhooks',
147 $data,
148 array(
149 'webhook_id' => $webhook->get_id(),
150 )
151 ); // WPCS: DB call ok.
152
153 $webhook->apply_changes();
154
155 if ( isset( $changes['status'] ) ) {
156 // We need to delete all transients, because we can't be sure of the old status.
157 $this->delete_transients( 'all' );
158 }
159 wp_cache_delete( $webhook->get_id(), 'webhooks' );
160 WC_Cache_Helper::invalidate_cache_group( 'webhooks' );
161
162 if ( 'active' === $webhook->get_status() && ( $trigger || $webhook->get_pending_delivery() ) ) {
163 $webhook->deliver_ping();
164 }
165
166 do_action( 'woocommerce_webhook_updated', $webhook->get_id() );
167 }
168
169 /**
170 * Remove a webhook from the database.
171 *
172 * @since 3.3.0
173 * @param WC_Webhook $webhook Webhook instance.
174 */
175 public function delete( &$webhook ) {
176 global $wpdb;
177
178 $wpdb->delete(
179 $wpdb->prefix . 'wc_webhooks',
180 array(
181 'webhook_id' => $webhook->get_id(),
182 ),
183 array( '%d' )
184 ); // WPCS: cache ok, DB call ok.
185
186 $this->delete_transients( 'all' );
187 wp_cache_delete( $webhook->get_id(), 'webhooks' );
188 WC_Cache_Helper::invalidate_cache_group( 'webhooks' );
189 do_action( 'woocommerce_webhook_deleted', $webhook->get_id(), $webhook );
190 }
191
192 /**
193 * Get API version number.
194 *
195 * @since 3.3.0
196 * @param string $api_version REST API version.
197 * @return int
198 */
199 public function get_api_version_number( $api_version ) {
200 return 'legacy_v3' === $api_version ? -1 : intval( substr( $api_version, -1 ) );
201 }
202
203 /**
204 * Get webhooks IDs from the database.
205 *
206 * @since 3.3.0
207 * @throws InvalidArgumentException If a $status value is passed in that is not in the known wc_get_webhook_statuses() keys.
208 * @param string $status Optional - status to filter results by. Must be a key in return value of @see wc_get_webhook_statuses(). @since 3.6.0.
209 * @return int[]
210 */
211 public function get_webhooks_ids( $status = '' ) {
212 if ( ! empty( $status ) ) {
213 $this->validate_status( $status );
214 }
215
216 $ids = get_transient( $this->get_transient_key( $status ) );
217
218 if ( false === $ids ) {
219 $ids = $this->search_webhooks(
220 array(
221 'limit' => -1,
222 'status' => $status,
223 )
224 );
225 $ids = array_map( 'absint', $ids );
226 set_transient( $this->get_transient_key( $status ), $ids );
227 }
228
229 return $ids;
230 }
231
232 /**
233 * Search webhooks.
234 *
235 * @param array $args Search arguments.
236 * @return array|object
237 */
238 public function search_webhooks( $args ) {
239 global $wpdb;
240
241 $args = wp_parse_args(
242 $args,
243 array(
244 'limit' => 10,
245 'offset' => 0,
246 'order' => 'DESC',
247 'orderby' => 'id',
248 'paginate' => false,
249 )
250 );
251
252 // Map post statuses.
253 $statuses = array(
254 'publish' => 'active',
255 'draft' => 'paused',
256 'pending' => 'disabled',
257 );
258
259 // Map orderby to support a few post keys.
260 $orderby_mapping = array(
261 'ID' => 'webhook_id',
262 'id' => 'webhook_id',
263 'name' => 'name',
264 'title' => 'name',
265 'post_title' => 'name',
266 'post_name' => 'name',
267 'date_created' => 'date_created_gmt',
268 'date' => 'date_created_gmt',
269 'post_date' => 'date_created_gmt',
270 'date_modified' => 'date_modified_gmt',
271 'modified' => 'date_modified_gmt',
272 'post_modified' => 'date_modified_gmt',
273 );
274 $orderby = isset( $orderby_mapping[ $args['orderby'] ] ) ? $orderby_mapping[ $args['orderby'] ] : 'webhook_id';
275 $sort = 'ASC' === strtoupper( $args['order'] ) ? 'ASC' : 'DESC';
276 $order = "ORDER BY {$orderby} {$sort}";
277 $limit = -1 < $args['limit'] ? $wpdb->prepare( 'LIMIT %d', $args['limit'] ) : '';
278 $offset = 0 < $args['offset'] ? $wpdb->prepare( 'OFFSET %d', $args['offset'] ) : '';
279 $status = ! empty( $args['status'] ) ? $wpdb->prepare( 'AND `status` = %s', isset( $statuses[ $args['status'] ] ) ? $statuses[ $args['status'] ] : $args['status'] ) : '';
280 $search = ! empty( $args['search'] ) ? $wpdb->prepare( 'AND `name` LIKE %s', '%' . $wpdb->esc_like( sanitize_text_field( $args['search'] ) ) . '%' ) : '';
281 $include = '';
282 $exclude = '';
283 $date_created = '';
284 $date_modified = '';
285 $user_id = '';
286 $api_version = '';
287
288 if ( ! empty( $args['include'] ) ) {
289 $args['include'] = implode( ',', wp_parse_id_list( $args['include'] ) );
290 $include = 'AND webhook_id IN (' . $args['include'] . ')';
291 }
292
293 if ( ! empty( $args['exclude'] ) ) {
294 $args['exclude'] = implode( ',', wp_parse_id_list( $args['exclude'] ) );
295 $exclude = 'AND webhook_id NOT IN (' . $args['exclude'] . ')';
296 }
297
298 if ( ! empty( $args['user_id'] ) ) {
299 $user_id = $wpdb->prepare( 'AND `user_id` = %d', absint( $args['user_id'] ) );
300 }
301
302 if ( ! empty( $args['after'] ) || ! empty( $args['before'] ) ) {
303 $args['after'] = empty( $args['after'] ) ? '0000-00-00' : $args['after'];
304 $args['before'] = empty( $args['before'] ) ? current_time( 'mysql', 1 ) : $args['before'];
305
306 $date_created = "AND `date_created_gmt` BETWEEN STR_TO_DATE('" . esc_sql( $args['after'] ) . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . esc_sql( $args['before'] ) . "', '%Y-%m-%d %H:%i:%s')";
307 }
308
309 if ( ! empty( $args['modified_after'] ) || ! empty( $args['modified_before'] ) ) {
310 $args['modified_after'] = empty( $args['modified_after'] ) ? '0000-00-00' : $args['modified_after'];
311 $args['modified_before'] = empty( $args['modified_before'] ) ? current_time( 'mysql', 1 ) : $args['modified_before'];
312
313 $date_modified = "AND `date_modified_gmt` BETWEEN STR_TO_DATE('" . esc_sql( $args['modified_after'] ) . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . esc_sql( $args['modified_before'] ) . "', '%Y-%m-%d %H:%i:%s')";
314 }
315
316 $api_version_value = $args['api_version'] ?? null;
317 if ( is_numeric( $api_version_value ) ) {
318 $api_version = 'AND `api_version`=' . esc_sql( $api_version_value );
319 }
320
321 // Check for cache.
322 $cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
323 $cache_value = wp_cache_get( $cache_key, 'webhook_search_results' );
324
325 if ( $cache_value ) {
326 return $cache_value;
327 }
328
329 if ( $args['paginate'] ) {
330 $query = trim(
331 "SELECT SQL_CALC_FOUND_ROWS webhook_id
332 FROM {$wpdb->prefix}wc_webhooks
333 WHERE 1=1
334 {$status}
335 {$search}
336 {$include}
337 {$exclude}
338 {$date_created}
339 {$date_modified}
340 {$api_version}
341 {$user_id}
342 {$order}
343 {$limit}
344 {$offset}"
345 );
346
347 $webhook_ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
348 $total = (int) $wpdb->get_var( 'SELECT FOUND_ROWS();' );
349 $return_value = (object) array(
350 'webhooks' => $webhook_ids,
351 'total' => $total,
352 'max_num_pages' => $args['limit'] > 1 ? ceil( $total / $args['limit'] ) : 1,
353 );
354 } else {
355 $query = trim(
356 "SELECT webhook_id
357 FROM {$wpdb->prefix}wc_webhooks
358 WHERE 1=1
359 {$status}
360 {$search}
361 {$include}
362 {$exclude}
363 {$date_created}
364 {$date_modified}
365 {$user_id}
366 {$order}
367 {$limit}
368 {$offset}"
369 );
370
371 $webhook_ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
372 $return_value = $webhook_ids;
373 }
374
375 wp_cache_set( $cache_key, $return_value, 'webhook_search_results' );
376
377 return $return_value;
378 }
379
380 /**
381 * Count webhooks.
382 *
383 * @since 3.6.0
384 * @param string $status Status to count.
385 * @return int
386 */
387 protected function get_webhook_count( $status = 'active' ) {
388 global $wpdb;
389 $cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . $status . '_count';
390 $count = wp_cache_get( $cache_key, 'webhooks' );
391
392 if ( false === $count ) {
393 $count = absint( $wpdb->get_var( $wpdb->prepare( "SELECT count( webhook_id ) FROM {$wpdb->prefix}wc_webhooks WHERE `status` = %s;", $status ) ) );
394
395 wp_cache_add( $cache_key, $count, 'webhooks' );
396 }
397
398 return $count;
399 }
400
401 /**
402 * Get total webhook counts by status.
403 *
404 * @return array
405 */
406 public function get_count_webhooks_by_status() {
407 $statuses = array_keys( wc_get_webhook_statuses() );
408 $counts = array();
409
410 foreach ( $statuses as $status ) {
411 $counts[ $status ] = $this->get_webhook_count( $status );
412 }
413
414 return $counts;
415 }
416
417 /**
418 * Check if a given string is in known statuses, based on return value of @see wc_get_webhook_statuses().
419 *
420 * @since 3.6.0
421 * @throws InvalidArgumentException If $status is not empty and not in the known wc_get_webhook_statuses() keys.
422 * @param string $status Status to check.
423 */
424 private function validate_status( $status ) {
425 if ( ! array_key_exists( $status, wc_get_webhook_statuses() ) ) {
426 throw new InvalidArgumentException( sprintf( 'Invalid status given: %s. Status must be one of: %s.', $status, implode( ', ', array_keys( wc_get_webhook_statuses() ) ) ) );
427 }
428 }
429
430 /**
431 * Get the transient key used to cache a set of webhook IDs, optionally filtered by status.
432 *
433 * @since 3.6.0
434 * @param string $status Optional - status of cache key.
435 * @return string
436 */
437 private function get_transient_key( $status = '' ) {
438 return empty( $status ) ? 'woocommerce_webhook_ids' : sprintf( 'woocommerce_webhook_ids_status_%s', $status );
439 }
440
441 /**
442 * Delete the transients used to cache a set of webhook IDs, optionally filtered by status.
443 *
444 * @since 3.6.0
445 * @param string $status Optional - status of cache to delete, or 'all' to delete all caches.
446 */
447 private function delete_transients( $status = '' ) {
448
449 // Always delete the non-filtered cache.
450 delete_transient( $this->get_transient_key( '' ) );
451
452 if ( ! empty( $status ) ) {
453 if ( 'all' === $status ) {
454 foreach ( wc_get_webhook_statuses() as $status_key => $status_string ) {
455 delete_transient( $this->get_transient_key( $status_key ) );
456 }
457 } else {
458 delete_transient( $this->get_transient_key( $status ) );
459 }
460 }
461 }
462 }
463