PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / trunk
WCPOS – Point of Sale (POS) plugin for WooCommerce vtrunk
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 1.9.13 1.9.12 1.9.11 1.9.10 1.9.9 All 158 releases
woocommerce-pos / includes / Services / Decimal_Quantities.php

Decimal_Quantities.php in WCPOS – Point of Sale (POS) plugin for WooCommerce trunk, at includes/Services/Decimal_Quantities.php

78 lines 2.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * POS decimal quantity REST schema relaxation.
4 *
5 * @package WCPOS\WooCommercePOS
6 */
7
8 namespace WCPOS\WooCommercePOS\Services;
9
10 /**
11 * Relaxes integer-typed wc/v3 quantity schemas for POS requests when decimal
12 * stock/cart quantities are enabled.
13 *
14 * The v2 write surface forwards mutation envelopes to the stock wc/v3
15 * controllers (Write_Controller::dispatch_write), whose schemas type order
16 * `line_items[].quantity` and variation `stock_quantity` as `integer` — a
17 * POS push carrying 0.5 is rejected with rest_invalid_param before WooCommerce
18 * ever sees it. The v1 surface relaxed these on its own controller subclasses
19 * (V1\Orders_Controller / the products trait); the forwarded wc/v3 dispatch
20 * needs the same relaxation applied to the registered endpoint args instead.
21 *
22 * Products' own `stock_quantity` is only relaxed where WC still hardcodes
23 * `integer`: current WC keys that schema off wc_is_stock_amount_integer(), so
24 * the existing woocommerce_stock_amount floatval swap (Products.php) already
25 * yields `number` there and this filter is a no-op for it.
26 *
27 * Gated the same way as Stock_Validator: the hook is always registered, the
28 * callback bails unless this is a POS request AND the setting is enabled — so
29 * direct (non-POS) wc/v3 requests keep WooCommerce's strict schema.
30 */
31 class Decimal_Quantities {
32 /**
33 * Register the REST endpoint args filter.
34 */
35 public function __construct() {
36 add_filter( 'rest_endpoints', array( $this, 'relax_quantity_schemas' ) );
37 }
38
39 /**
40 * Retype integer quantity args to `number` on the wc/v3 order and product
41 * endpoints for a decimal-enabled POS request.
42 *
43 * @param array $endpoints Registered REST endpoints, keyed by route.
44 *
45 * @return array The (possibly relaxed) endpoints.
46 */
47 public function relax_quantity_schemas( array $endpoints ): array {
48 if ( ! \wcpos_request() || ! Settings::instance()->decimal_qty_enabled() ) {
49 return $endpoints;
50 }
51
52 foreach ( $endpoints as $route => $handlers ) {
53 if ( ! \is_array( $handlers ) ) {
54 continue;
55 }
56 $is_orders = 1 === preg_match( '#^/wc/v3/orders(?:/\(\?P<id>[^/]+\))?$#', $route );
57 $is_products = 0 === strpos( $route, '/wc/v3/products' );
58 if ( ! $is_orders && ! $is_products ) {
59 continue;
60 }
61 foreach ( $handlers as $key => $handler ) {
62 // Route-level option keys (e.g. 'namespace') are not handler arrays.
63 if ( ! \is_array( $handler ) || ! isset( $handler['args'] ) || ! \is_array( $handler['args'] ) ) {
64 continue;
65 }
66 if ( $is_orders && 'integer' === ( $handler['args']['line_items']['items']['properties']['quantity']['type'] ?? null ) ) {
67 $endpoints[ $route ][ $key ]['args']['line_items']['items']['properties']['quantity']['type'] = 'number';
68 }
69 if ( $is_products && 'integer' === ( $handler['args']['stock_quantity']['type'] ?? null ) ) {
70 $endpoints[ $route ][ $key ]['args']['stock_quantity']['type'] = 'number';
71 }
72 }
73 }
74
75 return $endpoints;
76 }
77 }
78