Skip to content

Commit 04352ad

Browse files
committed
Fix: remove POS Only products from frontend WC REST API response
1 parent a080b70 commit 04352ad

File tree

5 files changed

+139
-90
lines changed

5 files changed

+139
-90
lines changed

includes/Init.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ public function __construct() {
3939
// Headers for API discoverability
4040
add_filter( 'rest_pre_serve_request', array( $this, 'rest_pre_serve_request' ), 5, 4 );
4141
add_action( 'send_headers', array( $this, 'send_headers' ), 99, 1 );
42-
43-
// add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
4442
}
4543

4644
/**

includes/WC_API.php

Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -22,70 +22,44 @@ public function __construct() {
2222
$pos_only_products = woocommerce_pos_get_settings( 'general', 'pos_only_products' );
2323

2424
if ( $pos_only_products ) {
25-
add_action( 'woocommerce_product_query', array( $this, 'hide_pos_only_products' ) );
26-
add_filter( 'woocommerce_variation_is_visible', array( $this, 'hide_pos_only_variations' ), 10, 4 );
25+
add_filter( 'woocommerce_rest_product_object_query', array( $this, 'hide_pos_only_products' ), 10, 2 );
26+
add_filter( 'woocommerce_rest_product_variation_object_query', array( $this, 'hide_pos_only_products' ), 10, 2 );
2727
}
2828
}
2929

3030
/**
31-
* Hide POS Only products from the shop and category pages.
31+
* Filter the query arguments for a request.
3232
*
33-
* @TODO - this should be improved so that admin users can see the product, but get a message
33+
* Enables adding extra arguments or setting defaults for a post
34+
* collection request.
3435
*
35-
* @param WP_Query $query Query instance.
36-
*
37-
* @return void
36+
* @param array $args Key value array of query var to query value.
37+
* @param WP_REST_Request $request The request used.
3838
*/
39-
public function hide_pos_only_products( $query ) {
40-
$meta_query = $query->get( 'meta_query' );
41-
42-
// Define your default meta query.
43-
$default_meta_query = array(
39+
public function hide_pos_only_products( $args, $request ) {
40+
$meta_query = array(
4441
'relation' => 'OR',
4542
array(
46-
'key' => '_pos_visibility',
47-
'value' => 'pos_only',
48-
'compare' => '!=',
43+
'key' => '_pos_visibility',
44+
'compare' => 'NOT EXISTS',
4945
),
5046
array(
51-
'key' => '_pos_visibility',
52-
'compare' => 'NOT EXISTS',
47+
'key' => '_pos_visibility',
48+
'value' => 'pos_only',
49+
'compare' => '!=',
5350
),
5451
);
5552

56-
// Check if an existing meta query exists.
57-
if ( is_array( $meta_query ) ) {
58-
if ( ! isset( $meta_query ['relation'] ) ) {
59-
$meta_query['relation'] = 'AND';
60-
}
61-
$meta_query[] = $default_meta_query;
53+
if ( empty( $args['meta_query'] ) ) {
54+
$args['meta_query'] = $meta_query;
6255
} else {
63-
$meta_query = $default_meta_query;
64-
}
65-
66-
// Set the updated meta query back to the query.
67-
$query->set( 'meta_query', $meta_query );
68-
}
69-
70-
/**
71-
* Remove POS Only variations from the storefront.
72-
*
73-
* @param bool $visible Whether the variation is visible.
74-
* @param int $variation_id The variation ID.
75-
* @param int $product_id The product ID.
76-
* @param \WC_Product_Variation $variation The variation object.
77-
*/
78-
public function hide_pos_only_variations( $visible, $variation_id, $product_id, $variation ) {
79-
if ( \is_shop() || \is_product_category() || \is_product() ) {
80-
// Get the _pos_visibility meta value for the variation.
81-
$pos_visibility = get_post_meta( $variation_id, '_pos_visibility', true );
82-
83-
// Check if _pos_visibility is 'pos_only' for this variation.
84-
if ( $pos_visibility === 'pos_only' ) {
85-
return false;
86-
}
56+
$args['meta_query'] = array(
57+
'relation' => 'AND',
58+
$args['meta_query'],
59+
$meta_query,
60+
);
8761
}
8862

89-
return $visible;
63+
return $args;
9064
}
9165
}

tests/includes/Test_Products.php

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
namespace WCPOS\WooCommercePOS\Tests;
44

55
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper;
6-
use WC_REST_Unit_Test_Case;
6+
use WP_UnitTestCase;
77
use WP_Query;
8-
use WC_Query;
98
use WCPOS\WooCommercePOS\Products;
109
use WC_Product_Variation;
1110

@@ -14,7 +13,7 @@
1413
*
1514
* @coversNothing
1615
*/
17-
class Test_Products extends WC_REST_Unit_Test_Case {
16+
class Test_Products extends WP_UnitTestCase {
1817
public function setup(): void {
1918
parent::setup();
2019
}
@@ -118,40 +117,4 @@ function () {
118117
// Assert that the variation without '_pos_visibility' set is in the query
119118
$this->assertContains( $variation_ids[2], $queried_variation_ids );
120119
}
121-
122-
/**
123-
*
124-
*/
125-
public function test_pos_only_products_via_store_api() {
126-
add_filter(
127-
'woocommerce_pos_general_settings',
128-
function () {
129-
return array(
130-
'pos_only_products' => true,
131-
);
132-
}
133-
);
134-
new Products(); // reinstantiate the class to apply the filter
135-
136-
// Create a visible product
137-
$visible_product = ProductHelper::create_simple_product();
138-
139-
// Create a product with _pos_visibility set to 'pos_only'
140-
$hidden_product = ProductHelper::create_simple_product();
141-
update_post_meta( $hidden_product->get_id(), '_pos_visibility', 'pos_only' );
142-
143-
// Verify that the meta value is set correctly
144-
$pos_visibility = get_post_meta( $hidden_product->get_id(), '_pos_visibility', true );
145-
$this->assertEquals( 'pos_only', $pos_visibility, 'Meta value for _pos_visibility not set correctly' );
146-
147-
// Make WC REST request
148-
add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
149-
$request = new \WP_REST_Request( 'GET', '/wc/v3/products' );
150-
$response = $this->server->dispatch( $request );
151-
152-
$data = $response->get_data();
153-
$this->assertEquals( 200, $response->get_status() );
154-
$this->assertEquals( 1, \count( $data ) );
155-
$this->assertEquals( $visible_product->get_id(), $data[0]['id'] );
156-
}
157120
}

tests/includes/Test_WC_API.php

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace WCPOS\WooCommercePOS\Tests;
4+
5+
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper;
6+
use WC_REST_Unit_Test_Case;
7+
use WCPOS\WooCommercePOS\WC_API;
8+
9+
/**
10+
* @internal
11+
*
12+
* @coversNothing
13+
*/
14+
class Test_WC_API extends WC_REST_Unit_Test_Case {
15+
public function setup(): void {
16+
parent::setup();
17+
}
18+
19+
public function tearDown(): void {
20+
parent::tearDown();
21+
}
22+
23+
/**
24+
*
25+
*/
26+
public function test_pos_only_products_via_store_api() {
27+
add_filter(
28+
'woocommerce_pos_general_settings',
29+
function () {
30+
return array(
31+
'pos_only_products' => true,
32+
);
33+
}
34+
);
35+
new WC_API(); // reinstantiate the class to apply the filter
36+
37+
// Create a visible product
38+
$visible_product = ProductHelper::create_simple_product();
39+
40+
// Create a product with _pos_visibility set to 'pos_only'
41+
$hidden_product = ProductHelper::create_simple_product();
42+
update_post_meta( $hidden_product->get_id(), '_pos_visibility', 'pos_only' );
43+
44+
// Verify that the meta value is set correctly
45+
$pos_visibility = get_post_meta( $hidden_product->get_id(), '_pos_visibility', true );
46+
$this->assertEquals( 'pos_only', $pos_visibility, 'Meta value for _pos_visibility not set correctly' );
47+
48+
// Make WC REST request
49+
add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
50+
$request = new \WP_REST_Request( 'GET', '/wc/v3/products' );
51+
$response = $this->server->dispatch( $request );
52+
53+
$data = $response->get_data();
54+
$this->assertEquals( 200, $response->get_status() );
55+
$this->assertEquals( 1, \count( $data ) );
56+
$this->assertEquals( $visible_product->get_id(), $data[0]['id'] );
57+
}
58+
59+
/**
60+
*
61+
*/
62+
public function test_pos_only_variations_via_store_api() {
63+
add_filter(
64+
'woocommerce_pos_general_settings',
65+
function () {
66+
return array(
67+
'pos_only_products' => true,
68+
);
69+
}
70+
);
71+
new WC_API(); // reinstantiate the class to apply the filter
72+
73+
// Create a variable product
74+
$variable = ProductHelper::create_variation_product();
75+
$variation_ids = $variable->get_children();
76+
update_post_meta( $variation_ids[0], '_pos_visibility', 'pos_only' );
77+
78+
// Verify that the meta value is set correctly
79+
$pos_visibility = get_post_meta( $variation_ids[0], '_pos_visibility', true );
80+
$this->assertEquals( 'pos_only', $pos_visibility, 'Meta value for _pos_visibility not set correctly' );
81+
82+
// Make WC REST request
83+
add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
84+
85+
$request = new \WP_REST_Request( 'GET', '/wc/v3/products/' . $variable->get_id() . '/variations' );
86+
$response = $this->server->dispatch( $request );
87+
88+
$data = $response->get_data();
89+
$this->assertEquals( 200, $response->get_status() );
90+
$this->assertEquals( 1, \count( $data ) );
91+
$this->assertEquals( $variation_ids[1], $data[0]['id'] );
92+
93+
/**
94+
* @TODO should we remove the id from the parent response also?
95+
* The WooCommerce code uses $object->get_children() to get the variation ids, NOT
96+
* $object->get_visible_children() so it seems they return all variations ids regardless of visibility.
97+
*/
98+
// $request = new \WP_REST_Request( 'GET', '/wc/v3/products/' . $variable->get_id() );
99+
// $response = $this->server->dispatch( $request );
100+
101+
// $data = $response->get_data();
102+
// $this->assertEquals( 200, $response->get_status() );
103+
// $this->assertEquals( $variable->get_id(), $data['id'] );
104+
// $this->assertEquals( 1, \count( $data['variations'] ) );
105+
// $this->assertEquals( $variation_ids[1], $data['variations'][0] );
106+
}
107+
}

tests/includes/Test_Wcpos_Functions.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,14 @@ public function test_woocommerce_pos_get_payment_gateways_settings(): void {
5858
$this->assertIsArray( $payment_gateways_settings );
5959
$this->assertArrayHasKey( 'default_gateway', $payment_gateways_settings );
6060
$this->assertArrayHasKey( 'gateways', $payment_gateways_settings );
61-
$this->assertEquals( count( $payment_gateways_settings['gateways'] ), 2 );
61+
62+
$active_gateways = array_filter(
63+
$payment_gateways_settings['gateways'],
64+
function ( $gateway ) {
65+
return $gateway['enabled'];
66+
}
67+
);
68+
$this->assertEquals( count( $active_gateways ), 2 );
6269

6370
$payment_gateways_settings = woocommerce_pos_get_settings( 'payment_gateways', 'default_gateway' );
6471
$this->assertEquals( 'pos_cash', $payment_gateways_settings );

0 commit comments

Comments
 (0)