PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.18
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.18
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
← All changes | includes/API/V1/Product_Variations_Controller.php +36 -66 1.10.51.10.18 View file →
@@ -20,8 +20,9 @@
20 20 use WCPOS\WooCommercePOS\Services\Barcode_Field;
21 21 use WCPOS\WooCommercePOS\Sync\Collection_Rules;
22 22 use WCPOS\WooCommercePOS\Sync\Collection_Rules_Plan;
23 23 use WCPOS\WooCommercePOS\Sync\Pos_Visibility;
24 +use WCPOS\WooCommercePOS\Sync\Product_Search;
24 25 use WP_Error;
25 26 use WP_Query;
26 27 use WP_REST_Request;
27 28 use WP_REST_Response;
@@ -63,8 +64,9 @@
63 64 */
64 65 private const WCPOS_SORT_PARAM_MAP = array(
65 66 'orderby' => 'orderby',
66 67 'order' => 'order',
68 + 'search' => 'search',
67 69 );
68 70
69 71 /**
70 72 * Dispatch request to parent controller, or override if needed.
@@ -79,10 +81,8 @@
79 81
80 82 add_filter( 'woocommerce_rest_prepare_product_variation_object', array( $this, 'wcpos_variation_response' ), 10, 3 );
81 83 add_action( 'woocommerce_rest_insert_product_variation_object', array( $this, 'wcpos_insert_product_variation_object' ), 10, 3 );
82 84 add_filter( 'woocommerce_rest_product_variation_object_query', array( $this, 'wcpos_product_variation_query' ), 10, 2 );
83 - add_filter( 'posts_search', array( $this, 'wcpos_posts_search' ), 10, 2 );
84 - add_filter( 'posts_clauses', array( $this, 'wcpos_posts_clauses' ), 10, 2 );
85 85
86 86 /*
87 87 * Check if the request is for all products and if the 'posts_per_page' is set to -1.
88 88 * Optimised query for getting all product IDs.
@@ -94,8 +94,23 @@
94 94 return $dispatch_result;
95 95 }
96 96
97 97 /**
98 + * Apply the collection's declared rules for nested and flat direct reads.
99 + *
100 + * @param WP_REST_Request $request Full details about the request.
101 + * @return \WP_Error|\WP_REST_Response
102 + */
103 + public function get_items( $request ) {
104 + $plan = Collection_Rules::for_request( 'variations', $request, self::WCPOS_SORT_PARAM_MAP );
105 + return $plan->around(
106 + function () use ( $request ) {
107 + return parent::get_items( $request );
108 + }
109 + );
110 + }
111 +
112 + /**
98 113 * Register routes.
99 114 */
100 115 public function register_routes(): void {
101 116 parent::register_routes();
@@ -185,8 +200,14 @@
185 200 if ( isset( $params['per_page'] ) && \is_array( $params['per_page'] ) ) {
186 201 $params['per_page']['minimum'] = -1;
187 202 }
188 203
204 + // Search text is literal on every lane: `sanitize_text_field` would strip `%30`
205 + // and blank malformed UTF-8 before the declared search rule ever saw them.
206 + if ( isset( $params['search'] ) && \is_array( $params['search'] ) ) {
207 + $params['search']['sanitize_callback'] = 'rest_sanitize_request_arg';
208 + }
209 +
189 210 // Ensure 'orderby' is set and is an array before attempting to modify it.
190 211 if ( isset( $params['orderby']['enum'] ) && \is_array( $params['orderby']['enum'] ) ) {
191 212 // DECLARED once, in Sync\Collection_Rules, and projected here — so a sort cannot
192 213 // be advertised on one lane and rejected on the other.
@@ -270,45 +291,12 @@
270 291 * @param string $search Search string.
271 292 * @param WP_Query $wp_query WP_Query object.
272 293 *
273 294 * @return string
295 + * @deprecated Collection Rules now installs this behavior.
274 296 */
275 297 public function wcpos_posts_search( string $search, WP_Query $wp_query ) {
276 - global $wpdb;
277 -
278 - if ( empty( $search ) ) {
279 - return $search; // skip processing - no search term in query.
280 - }
281 -
282 - $q = $wp_query->query_vars;
283 - $n = ! empty( $q['exact'] ) ? '' : '%';
284 - $search_terms = (array) $q['search_terms'];
285 -
286 - // Fields in the main 'posts' table.
287 - $post_fields = array(); // nothing at the moment for variations.
288 -
289 - // Meta fields to search.
290 - $meta_fields = Barcode_Field::search_keys();
291 -
292 - $search_conditions = array();
293 -
294 - foreach ( $search_terms as $term ) {
295 - $term = $n . $wpdb->esc_like( $term ) . $n;
296 -
297 - // Search in meta fields.
298 - foreach ( $meta_fields as $field ) {
299 - $search_conditions[] = $wpdb->prepare( '(pm1.meta_value LIKE %s AND pm1.meta_key = %s)', $term, $field );
300 - }
301 - }
302 -
303 - if ( ! empty( $search_conditions ) ) {
304 - $search = ' AND (' . implode( ' OR ', $search_conditions ) . ') ';
305 - if ( ! is_user_logged_in() ) {
306 - $search .= " AND ($wpdb->posts.post_password = '') ";
307 - }
308 - }
309 -
310 - return $search;
298 + return Product_Search::variation_posts_search( $search, $wp_query->query_vars, Collection_Rules::rules( 'variations' )['search'] );
311 299 }
312 300
313 301 /**
314 302 * Filters the JOIN clause of the query.
@@ -316,17 +304,12 @@
316 304 * @param string $join The JOIN clause of the query.
317 305 * @param WP_Query $query The WP_Query instance (passed by reference).
318 306 *
319 307 * @return string
308 + * @deprecated Collection Rules now installs this behavior.
320 309 */
321 310 public function wcpos_posts_join_to_posts_search( string $join, WP_Query $query ) {
322 - global $wpdb;
323 -
324 - if ( ! empty( $query->query_vars['s'] ) && false === strpos( $join, 'pm1' ) ) {
325 - $join .= " LEFT JOIN {$wpdb->postmeta} pm1 ON {$wpdb->posts}.ID = pm1.post_id ";
326 - }
327 -
328 - return $join;
311 + return empty( $query->query_vars['s'] ) ? $join : Product_Search::posts_join( $join, $query->query_vars );
329 312 }
330 313
331 314 /**
332 315 * Filters the GROUP BY clause of the query.
@@ -334,17 +317,12 @@
334 317 * @param string $groupby The GROUP BY clause of the query.
335 318 * @param WP_Query $query The WP_Query instance (passed by reference).
336 319 *
337 320 * @return string
321 + * @deprecated Collection Rules now installs this behavior.
338 322 */
339 323 public function wcpos_posts_groupby_posts_search( string $groupby, WP_Query $query ) {
340 - global $wpdb;
341 -
342 - if ( ! empty( $query->query_vars['s'] ) ) {
343 - $groupby = "{$wpdb->posts}.ID";
344 - }
345 -
346 - return $groupby;
324 + return empty( $query->query_vars['s'] ) ? $groupby : Product_Search::posts_groupby( $groupby, $query->query_vars );
347 325 }
348 326
349 327 /**
350 328 * Filter the query arguments for a request.
@@ -354,21 +332,10 @@
354 332 *
355 333 * @return array $args Key value array of query var to query value.
356 334 */
357 335 public function wcpos_product_variation_query( array $args, WP_REST_Request $request ) {
358 - if ( ! empty( $request['search'] ) ) {
359 - // We need to set the query up for a postmeta join.
360 - add_filter( 'posts_join', array( $this, 'wcpos_posts_join_to_posts_search' ), 10, 2 );
361 - add_filter( 'posts_groupby', array( $this, 'wcpos_posts_groupby_posts_search' ), 10, 2 );
362 - }
363 -
364 - // if POS only products are enabled, exclude online-only products.
365 - if ( $this->wcpos_pos_only_products_enabled() ) {
366 - add_filter( 'posts_where', array( $this, 'wcpos_posts_where_product_variation_exclude_online_only' ), 10, 2 );
367 - }
368 -
369 336 // Check for wcpos_include/wcpos_exclude parameter.
370 - // NOTE: do this after POS visibility filter so that takes precedence.
337 + // The Collection Rules visibility backstop runs first, at priority 10.
371 338 if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
372 339 add_filter( 'posts_where', array( $this, 'wcpos_posts_where_product_variation_include_exclude' ), 20, 2 );
373 340 }
374 341
@@ -384,8 +351,9 @@
384 351 * @param string $where The WHERE clause of the query.
385 352 * @param WP_Query $query The WP_Query instance (passed by reference).
386 353 *
387 354 * @return string
355 + * @deprecated Collection Rules now installs this behavior.
388 356 */
389 357 public function wcpos_posts_where_product_variation_exclude_online_only( string $where, WP_Query $query ) {
390 358 global $wpdb;
391 359
@@ -467,9 +435,9 @@
467 435 *
468 436 * @param WP_REST_Request $request Full details about the request.
469 437 */
470 438 public function wcpos_get_all_items( $request ) {
471 - return parent::get_items( $request );
439 + return $this->get_items( $request );
472 440 }
473 441
474 442
475 443 /**
@@ -482,8 +450,9 @@
482 450 * @param array $clauses Associative array of the clauses for the query.
483 451 * @param WP_Query $wp_query The WP_Query instance.
484 452 *
485 453 * @return array
454 + * @deprecated Collection Rules now installs this behavior.
486 455 */
487 456 public function wcpos_posts_clauses( array $clauses, WP_Query $wp_query ): array {
488 457 if ( ! isset( $this->wcpos_request ) ) {
489 458 return $clauses;
@@ -512,11 +481,12 @@
512 481 /*
513 482 * The POS sorts (`sku`, `barcode`, `stock_quantity`, `stock_status`) are NOT mapped
514 483 * onto `meta_key` + `orderby => meta_value` here any more. That pair INNER JOINs
515 484 * postmeta, so it dropped every variation with no value for the key — a sort acting
516 - * as a filter. `Sync\Collection_Rules` declares them and `wcpos_posts_clauses()`
485 + * as a filter. `Sync\Collection_Rules` declares them and its scoped plan
517 486 * applies them as a LEFT JOIN, on this lane and on `wcpos/v2` alike.
518 487 */
519 488
520 - return $args;
489 + $plan = Collection_Rules::for_request( 'variations', $request, self::WCPOS_SORT_PARAM_MAP );
490 + return $plan->filter( Collection_Rules_Plan::HOOK_PREPARE_ARGS, $args );
521 491 }
522 492 }