Skip to content

Commit 639ab16

Browse files
committed
BUGFIX: empty products
1 parent 21ebc62 commit 639ab16

File tree

4 files changed

+123
-32
lines changed

4 files changed

+123
-32
lines changed

includes/API/Products.php

Lines changed: 116 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Ramsey\Uuid\Uuid;
66
use WC_Data;
7+
use WC_Product;
78
use WCPOS\WooCommercePOS\Logger;
89
use WP_Query;
910
use WP_REST_Request;
@@ -18,6 +19,7 @@
1819
*/
1920
class 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;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@wcpos/woocommerce-pos",
3-
"version": "1.2.3",
3+
"version": "1.2.4",
44
"description": "A simple front-end for taking WooCommerce orders at the Point of Sale.",
55
"main": "index.js",
66
"workspaces": {

readme.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Contributors: kilbot
33
Tags: cart, e-commerce, ecommerce, inventory, point-of-sale, pos, sales, sell, shop, shopify, store, vend, woocommerce, wordpress-ecommerce
44
Requires at least: 5.6 & WooCommerce 5.3
55
Tested up to: 6.2
6-
Stable tag: 1.2.3
6+
Stable tag: 1.2.4
77
License: GPL-3.0
88
License URI: http://www.gnu.org/licenses/gpl-3.0.html
99

@@ -63,6 +63,9 @@ There is more information on our website at [https://wcpos.com](https://wcpos.co
6363

6464
== Changelog ==
6565

66+
= 1.2.4 - 2023/07/25 =
67+
* Fix: empty products effecting some users due to malformed meta_data
68+
6669
= 1.2.3 - 2023/06/21 =
6770
* Fix: coupon form on POS payment modal
6871
* Fix: use woocommerce_gallery_thumbnail instead of full sized images for products and variations

woocommerce-pos.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Plugin Name: WooCommerce POS
44
* Plugin URI: https://wordpress.org/plugins/woocommerce-pos/
55
* Description: A simple front-end for taking WooCommerce orders at the Point of Sale. Requires <a href="http://wordpress.org/plugins/woocommerce/">WooCommerce</a>.
6-
* Version: 1.2.3
6+
* Version: 1.2.4
77
* Author: kilbot
88
* Author URI: http://wcpos.com
99
* Text Domain: woocommerce-pos
@@ -24,7 +24,7 @@
2424
use function define;
2525

2626
// Define plugin constants.
27-
const VERSION = '1.2.3';
27+
const VERSION = '1.2.4';
2828
const PLUGIN_NAME = 'woocommerce-pos';
2929
const SHORT_NAME = 'wcpos';
3030
define( __NAMESPACE__ . '\PLUGIN_FILE', plugin_basename( __FILE__ ) ); // 'woocommerce-pos/woocommerce-pos.php'

0 commit comments

Comments
 (0)