PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.0
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.0
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
woocommerce-pos / includes / Sync / Product_Serializer.php

Product_Serializer.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.0, at includes/Sync/Product_Serializer.php

154 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WCPOS sync product serializer.
4 *
5 * @package WCPOS\WooCommercePOS\Sync
6 */
7
8 namespace WCPOS\WooCommercePOS\Sync;
9
10 use WC_Product;
11 use WC_REST_Products_Controller;
12 use WP_REST_Request;
13
14 /**
15 * THE product-record assembly line.
16 *
17 * Every sync surface that needs a single product (or variation) document builds
18 * it here: the changes revision-hash walk, the barcode resolver, the targeted
19 * variations read and the write acknowledgement. Before this class each of those
20 * pasted the same four lines — controller instantiation, `prepare_object_for_response`,
21 * `rest_get_server()->response_to_data()`, then the augmentation filter — and the
22 * copies drifted (see the namespace-resolution comment the variations controller
23 * used to carry).
24 *
25 * Two rules the pasted blocks encoded and this class keeps:
26 *
27 * 1. ADR 0003 — values come from the FILTERED WC REST representation, never a raw
28 * projection. `prepare_object_for_response` runs WooCommerce's own
29 * `woocommerce_rest_prepare_product_object` filter; `response_to_data` resolves
30 * embedded links exactly as a real request would.
31 * 2. Variations are serialized through the SAME products controller as products —
32 * `wc_get_product()` hands back a `WC_Product_Variation` and the controller
33 * handles it, so the two lanes cannot drift apart.
34 */
35 final class Product_Serializer {
36 /**
37 * The WooCommerce products controller, created on first use.
38 *
39 * Memoized because the callers serialize in LOOPS (a revision-hash page, an
40 * include-set of variations); instantiating a controller per record was never
41 * the intent of the pasted blocks — each of them hoisted it out of the loop.
42 *
43 * @var null|WC_REST_Products_Controller
44 */
45 private $controller = null;
46
47 /**
48 * The request used when a caller does not supply one.
49 *
50 * @var null|WP_REST_Request
51 */
52 private $default_request = null;
53
54 /**
55 * Serialize one product or variation into its augmented REST representation.
56 *
57 * @param int|WC_Product $product Product id, or an already-loaded product/variation object.
58 * @param null|WP_REST_Request $request Serialization context. A bare `GET /` request is used when omitted.
59 *
60 * @return array The augmented payload, or an empty array when the id does not resolve to a product.
61 */
62 public function serialize( $product, ?WP_REST_Request $request = null ): array {
63 $object = $product instanceof WC_Product
64 ? $product
65 : ( \function_exists( 'wc_get_product' ) ? wc_get_product( (int) $product ) : false );
66
67 if ( ! $object instanceof WC_Product ) {
68 return array();
69 }
70
71 $request = $request instanceof WP_REST_Request ? $request : $this->default_request();
72 // Every lane that hydrates a product — changes, resolve, targeted
73 // variations, the write ack — builds a bare `GET /` and hands it here, so
74 // this is the ONE place that has to carry the till's store scope into
75 // `woocommerce_rest_prepare_product_object`. Without it the assembly line
76 // serializes the global price and the till redisplays it moments after the
77 // cashier changed the store's (pro#425). Stamping is idempotent and never
78 // overrides a scope the caller set deliberately.
79 Store_Scope::stamp( $request );
80 // Ours for the duration of the serialization — this runs outside any
81 // dispatch, so the lane marker is the only signal a response filter has.
82 $response = Store_Scope::in_v2_lane(
83 function () use ( $object, $request ) {
84 return rest_ensure_response( $this->controller()->prepare_object_for_response( $object, $request ) );
85 }
86 );
87 /**
88 * WordPress response data is not guaranteed to be an array at runtime.
89 *
90 * @var mixed $payload
91 */
92 $payload = rest_get_server()->response_to_data( $response, false );
93
94 return self::augment( \is_array( $payload ) ? $payload : array(), $object, $request );
95 }
96
97 /**
98 * Run the public augmentation filter over an already-serialized payload.
99 *
100 * Exposed separately for the write acknowledgement, which already holds the
101 * bare wc/v3 data (it must hash the bare bytes for the conflict check) and only
102 * needs the stamps applied on top.
103 *
104 * @param array $payload Serialized product payload.
105 * @param mixed $object The product/variation backing the payload.
106 * @param null|WP_REST_Request $request Serialization context.
107 */
108 public static function augment( array $payload, $object = null, ?WP_REST_Request $request = null ): array {
109 if ( $request instanceof WP_REST_Request ) {
110 Store_Scope::stamp( $request );
111 }
112
113 /**
114 * Filters a serialized WCPOS product record.
115 *
116 * Additive only: it must never remove WooCommerce REST fields.
117 *
118 * @param array $payload Serialized product payload.
119 * @param mixed $object The product or variation backing the payload.
120 * @param null|WP_REST_Request $request Serialization context.
121 */
122 /**
123 * Public filters can return values outside the documented contract.
124 *
125 * @var mixed $augmented
126 */
127 $augmented = apply_filters( 'woocommerce_pos_sync_serialized_product', $payload, $object, $request );
128
129 return \is_array( $augmented ) ? $augmented : $payload;
130 }
131
132 /**
133 * The memoized WooCommerce products controller.
134 */
135 private function controller(): WC_REST_Products_Controller {
136 if ( null === $this->controller ) {
137 $this->controller = new WC_REST_Products_Controller();
138 }
139
140 return $this->controller;
141 }
142
143 /**
144 * The memoized fallback serialization request.
145 */
146 private function default_request(): WP_REST_Request {
147 if ( null === $this->default_request ) {
148 $this->default_request = new WP_REST_Request( 'GET', '/' );
149 }
150
151 return $this->default_request;
152 }
153 }
154