44
55use Ramsey \Uuid \Uuid ;
66use WC_Data ;
7+ use WC_Product ;
78use WCPOS \WooCommercePOS \Logger ;
89use WP_Query ;
910use WP_REST_Request ;
1819 */
1920class Products {
2021 private $ request ;
22+ private $ uuids ;
2123
2224 /**
2325 * Products constructor.
@@ -26,6 +28,7 @@ class Products {
2628 */
2729 public function __construct ( WP_REST_Request $ request ) {
2830 $ this ->request = $ request ;
31+ $ this ->uuids = $ this ->get_all_uuids ();
2932
3033 add_filter ( 'rest_request_before_callbacks ' , array ( $ this , 'rest_request_before_callbacks ' ), 10 , 3 );
3134 add_filter ( 'woocommerce_rest_prepare_product_object ' , array ( $ this , 'product_response ' ), 10 , 3 );
@@ -35,6 +38,82 @@ public function __construct( WP_REST_Request $request ) {
3538 add_filter ( 'woocommerce_rest_product_schema ' , array ( $ this , 'add_barcode_to_product_schema ' ) );
3639 add_action ( 'woocommerce_rest_insert_product_object ' , array ( $ this , 'insert_product_object ' ), 10 , 3 );
3740 add_filter ( 'wp_get_attachment_image_src ' , array ( $ this , 'product_image_src ' ), 10 , 4 );
41+
42+ // add_filter('rest_pre_echo_response', function($result, $server, $request) {
43+ // $logger = wc_get_logger();
44+ // $test = wp_json_encode( $result, 0 );
45+ // if(is_array($result)) {
46+ // foreach($result as $record) {
47+ // if(is_array($record) && isset($record['meta_data'])) {
48+ // $test = wp_json_encode( $record, 0 );
49+ // $logger->info($test, array('source' => 'wcpos-support-3'));
50+ // }
51+ // }
52+ // }
53+ // return $result;
54+ // }, 10, 3);
55+
56+ // add_filter('rest_pre_serve_request', function($served, $result, $request, $server) {
57+ // $logger = wc_get_logger();
58+ //// $logger->info(wp_json_encode($result), array('source' => 'wcpos-support'));
59+ // $data = $result->get_data();
60+ // if(is_array($data)) {
61+ // foreach($data as $record) {
62+ // if(isset($record['meta_data'])) {
63+ // $logger->info(wp_json_encode($record['meta_data']), array('source' => 'wcpos-support'));
64+ // }
65+ // }
66+ // }
67+ // return $served;
68+ // }, 10, 4);
69+ }
70+
71+ /**
72+ * Note: this gets all postmeta uuids, including orders, we're just interested in doing a check sanity check
73+ * This addresses a bug where I have seen two products with the same uuid
74+ *
75+ * @return array
76+ */
77+ private function get_all_uuids () : array {
78+ global $ wpdb ;
79+ $ result = $ wpdb ->get_col (
80+ "
81+ SELECT meta_value
82+ FROM $ wpdb ->postmeta
83+ WHERE meta_key = '_woocommerce_pos_uuid'
84+ "
85+ );
86+ return $ result ;
87+ }
88+
89+ /**
90+ * Make sure the product has a uuid
91+ */
92+ private function maybe_add_uuid ( WC_Product $ product ) {
93+ $ uuids = get_post_meta ( $ product ->get_id (), '_woocommerce_pos_uuid ' , false );
94+ $ uuid_counts = array_count_values ( $ this ->uuids );
95+
96+ if ( empty ( $ uuids ) ) {
97+ $ this ->add_uuid_meta_data ( $ product );
98+ }
99+
100+ if ( count ( $ uuids ) > 1 || count ( $ uuids ) === 1 && $ uuid_counts [ $ uuids [0 ] ] > 1 ) {
101+ delete_post_meta ( $ product ->get_id (), '_woocommerce_pos_uuid ' );
102+ $ this ->add_uuid_meta_data ( $ product );
103+ }
104+ }
105+
106+ /**
107+ *
108+ */
109+ private function add_uuid_meta_data ( WC_Product $ product ) {
110+ $ uuid = Uuid::uuid4 ()->toString ();
111+ while ( in_array ( $ uuid , $ this ->uuids ) ) { // ensure the new UUID is unique
112+ $ uuid = Uuid::uuid4 ()->toString ();
113+ }
114+ $ this ->uuids [] = $ uuid ; // update the UUID list
115+ $ product ->update_meta_data ( '_woocommerce_pos_uuid ' , $ uuid );
116+ $ product ->save_meta_data ();
38117 }
39118
40119 /**
@@ -133,24 +212,18 @@ public function insert_product_object( WC_Data $object, WP_REST_Request $request
133212 * Filter the product response.
134213 *
135214 * @param WP_REST_Response $response The response object.
136- * @param WC_Data $product Product data.
215+ * @param WC_Product $product Product data.
137216 * @param WP_REST_Request $request Request object.
138217 *
139218 * @return WP_REST_Response $response The response object.
140219 */
141- public function product_response ( WP_REST_Response $ response , WC_Data $ product , WP_REST_Request $ request ): WP_REST_Response {
220+ public function product_response ( WP_REST_Response $ response , WC_Product $ product , WP_REST_Request $ request ): WP_REST_Response {
142221 $ data = $ response ->get_data ();
143222
144223 /**
145224 * Make sure the product has a uuid
146225 */
147- $ uuid = $ product ->get_meta ( '_woocommerce_pos_uuid ' );
148- if ( ! $ uuid ) {
149- $ uuid = Uuid::uuid4 ()->toString ();
150- $ product ->update_meta_data ( '_woocommerce_pos_uuid ' , $ uuid );
151- $ product ->save_meta_data ();
152- $ data ['meta_data ' ] = $ product ->get_meta_data ();
153- }
226+ $ this ->maybe_add_uuid ( $ product );
154227
155228 /**
156229 * Add barcode field
@@ -172,7 +245,7 @@ public function product_response( WP_REST_Response $response, WC_Data $product,
172245 * Check the response size and log a debug message if it is over the maximum size.
173246 */
174247 $ response_size = strlen ( serialize ( $ response ->data ) );
175- $ max_response_size = 10000 ;
248+ $ max_response_size = 100000 ;
176249 if ( $ response_size > $ max_response_size ) {
177250 Logger::log ( "Product ID {$ product ->get_id ()} has a response size of {$ response_size } bytes, exceeding the limit of {$ max_response_size } bytes. " );
178251 }
@@ -182,29 +255,44 @@ public function product_response( WP_REST_Response $response, WC_Data $product,
182255 * @TODO - only need to update if there is a change
183256 */
184257 if ( $ product ->is_type ( 'variable ' ) ) {
185- $ product ->update_meta_data ( '_woocommerce_pos_variable_prices ' , wp_json_encode (
186- array (
187- 'price ' => array (
188- 'min ' => $ product ->get_variation_price (),
189- 'max ' => $ product ->get_variation_price ( 'max ' ),
190- ),
191- 'regular_price ' => array (
192- 'min ' => $ product ->get_variation_regular_price (),
193- 'max ' => $ product ->get_variation_regular_price ( 'max ' ),
194- ),
195- 'sale_price ' => array (
196- 'min ' => $ product ->get_variation_sale_price (),
197- 'max ' => $ product ->get_variation_sale_price ( 'max ' ),
198- ),
199- )
200- ) );
201- $ product ->save_meta_data ();
202- $ data ['meta_data ' ] = $ product ->get_meta_data ();
258+ // Initialize price variables
259+ $ price_array = array (
260+ 'price ' => array (
261+ 'min ' => $ product ->get_variation_price (),
262+ 'max ' => $ product ->get_variation_price ( 'max ' ),
263+ ),
264+ 'regular_price ' => array (
265+ 'min ' => $ product ->get_variation_regular_price (),
266+ 'max ' => $ product ->get_variation_regular_price ( 'max ' ),
267+ ),
268+ 'sale_price ' => array (
269+ 'min ' => $ product ->get_variation_sale_price (),
270+ 'max ' => $ product ->get_variation_sale_price ( 'max ' ),
271+ ),
272+ );
273+
274+ // Try encoding the array into JSON
275+ $ encoded_price = wp_json_encode ( $ price_array );
276+
277+ // Check if the encoding was successful
278+ if ( $ encoded_price === false ) {
279+ // JSON encode failed, log the original array for debugging
280+ Logger::log ( 'JSON encoding of price array failed: ' . json_last_error_msg (), $ price_array );
281+ } else {
282+ // Update the meta data with the successfully encoded price data
283+ $ product ->update_meta_data ( '_woocommerce_pos_variable_prices ' , $ encoded_price );
284+ $ product ->save_meta_data ();
285+ }
203286 }
204287
288+
205289 /**
206290 * Reset the new response data
291+ * BUG FIX: some servers are not returning the correct meta_data if it is left as WC_Meta_Data objects
207292 */
293+ $ data ['meta_data ' ] = array_map ( function ( $ meta_data ) {
294+ return $ meta_data ->get_data ();
295+ }, $ product ->get_meta_data ());
208296 $ response ->set_data ( $ data );
209297
210298 return $ response ;
0 commit comments