PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.17
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.17
1.10.26 1.10.25 1.10.24 1.10.23 1.10.22 1.10.21 1.10.20 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 All 170 releases
← All changes | includes/Sync/Collection_Rules.php +80 -0 1.10.3 → 1.10.17 View file →
@@ -7,8 +7,9 @@
7 7
8 8 namespace WCPOS\WooCommercePOS\Sync;
9 9
10 10 use Automattic\WooCommerce\Utilities\OrderUtil;
11 +use WCPOS\WooCommercePOS\Services\Barcode_Field;
11 12 use WP_REST_Request;
12 13
13 14 /**
14 15 * THE declaration table for POS collection query behaviour — one Collection Rule per
@@ -195,8 +196,13 @@
195 196 * - `posts` => `array( 'posts_orderby' => <wp_posts column> )` for a column the
196 197 * WP_Query `orderby` vocabulary cannot express (rewritten through
197 198 * `posts_orderby`), OR
198 199 * `array( 'meta_key' => ..., 'orderby' => meta_value|meta_value_num )`.
200 + * - `posts` => `array( 'meta_sort' => array( 'key' => ..., 'numeric' => bool ) )`
201 + * a postmeta sort that must NOT filter: applied as a LEFT JOIN through
202 + * `posts_clauses`, with rows that have no value for the key ordered
203 + * LAST in both directions. Use this for any user-facing column sort —
204 + * `meta_key`/`orderby` INNER JOINs and silently drops rows.
199 205 *
200 206 * Filter row shape:
201 207 * - `meta` => `array( 'key' => <meta key>, 'storage' => <optional storage lock> )`
202 208 * a `meta_query` row on the WC query args (works on both storages).
@@ -286,8 +292,34 @@
286 292 ),
287 293 ),
288 294
289 295 /*
296 + * The POS grid's SKU / barcode / stock columns, for the product grid and the
297 + * variation grid alike — the SAME four rows, from one builder, because the two
298 + * surfaces drifted apart once already and a cashier sorting a column expects
299 + * the same thing of both.
300 + *
301 + * A `meta_sort` row sorts on a postmeta value WITHOUT letting the sort decide
302 + * which records exist. The obvious encoding — WP_Query's `meta_key` +
303 + * `orderby => meta_value` — INNER JOINs `postmeta`, so a record with no row for
304 + * that key VANISHES from the result. On a default store the barcode field is
305 + * `_global_unique_id`, which most catalogues never populate, so sorting by
306 + * barcode returned an EMPTY page; `orderby=sku` silently dropped everything
307 + * without a SKU. A sort must never hide a record from a cashier, so these rows
308 + * are applied as a LEFT JOIN with the meta-less rows ordered LAST in both
309 + * directions (`Collection_Rules_Plan::apply_meta_sort_clauses()`).
310 + *
311 + * Neither collection is ever HPOS — both are posts on every store — so there is
312 + * no `hpos` half to these rows.
313 + */
314 + 'products' => array(
315 + 'sorts' => self::catalog_meta_sorts(),
316 + ),
317 + 'variations' => array(
318 + 'sorts' => self::catalog_meta_sorts(),
319 + ),
320 +
321 + /*
290 322 * SORT NAMES ONLY — deliberately no clause bodies.
291 323 *
292 324 * Customers are a `WP_User_Query` over `wp_users`/`wp_usermeta`, a storage
293 325 * this table does not speak: it knows `hpos` and `posts`, and both are ORDER
@@ -313,8 +345,56 @@
313 345 ),
314 346 );
315 347
316 348 return $rules[ $collection ] ?? array();
349 + }
350 +
351 + /**
352 + * The four POS column sorts, shared by `products` and `variations`.
353 + *
354 + * One builder rather than two copied blocks: these two collections carry the same
355 + * cashier-facing columns, and the previous copy-per-controller encoding is exactly how
356 + * the variation lane kept a defect the product lane had already fixed.
357 + *
358 + * @return array<string, array>
359 + */
360 + private static function catalog_meta_sorts(): array {
361 + return array(
362 + 'sku' => array(
363 + 'posts' => array(
364 + 'meta_sort' => array( 'key' => '_sku' ),
365 + ),
366 + ),
367 +
368 + /*
369 + * The barcode meta key is a store setting, so the row reads the same accessor
370 + * the controllers do rather than hard-coding a key that would drift.
371 + */
372 + 'barcode' => array(
373 + 'posts' => array(
374 + 'meta_sort' => array( 'key' => Barcode_Field::orderby_key() ),
375 + ),
376 + ),
377 +
378 + /*
379 + * `_stock` is written as NULL for everything that does not manage stock, so this
380 + * row needs the same meta-less-last ordering as the rest — it is not a special
381 + * case, it was merely the first one noticed.
382 + */
383 + 'stock_quantity' => array(
384 + 'posts' => array(
385 + 'meta_sort' => array(
386 + 'key' => '_stock',
387 + 'numeric' => true,
388 + ),
389 + ),
390 + ),
391 + 'stock_status' => array(
392 + 'posts' => array(
393 + 'meta_sort' => array( 'key' => '_stock_status' ),
394 + ),
395 + ),
396 + );
317 397 }
318 398
319 399 /**
320 400 * Resolve the storage dialect for a collection when the caller did not name one.