Skip to content

Commit

Permalink
Fix: remove POS Only products from frontend WC REST API response
Browse files Browse the repository at this point in the history
  • Loading branch information
kilbot committed Mar 7, 2024
1 parent a080b70 commit 04352ad
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 90 deletions.
2 changes: 0 additions & 2 deletions includes/Init.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ public function __construct() {
// Headers for API discoverability
add_filter( 'rest_pre_serve_request', array( $this, 'rest_pre_serve_request' ), 5, 4 );
add_action( 'send_headers', array( $this, 'send_headers' ), 99, 1 );

// add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
}

/**
Expand Down
70 changes: 22 additions & 48 deletions includes/WC_API.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,70 +22,44 @@ public function __construct() {
$pos_only_products = woocommerce_pos_get_settings( 'general', 'pos_only_products' );

if ( $pos_only_products ) {
add_action( 'woocommerce_product_query', array( $this, 'hide_pos_only_products' ) );
add_filter( 'woocommerce_variation_is_visible', array( $this, 'hide_pos_only_variations' ), 10, 4 );
add_filter( 'woocommerce_rest_product_object_query', array( $this, 'hide_pos_only_products' ), 10, 2 );
add_filter( 'woocommerce_rest_product_variation_object_query', array( $this, 'hide_pos_only_products' ), 10, 2 );
}
}

/**
* Hide POS Only products from the shop and category pages.
* Filter the query arguments for a request.
*
* @TODO - this should be improved so that admin users can see the product, but get a message
* Enables adding extra arguments or setting defaults for a post
* collection request.
*
* @param WP_Query $query Query instance.
*
* @return void
* @param array $args Key value array of query var to query value.
* @param WP_REST_Request $request The request used.
*/
public function hide_pos_only_products( $query ) {
$meta_query = $query->get( 'meta_query' );

// Define your default meta query.
$default_meta_query = array(
public function hide_pos_only_products( $args, $request ) {
$meta_query = array(
'relation' => 'OR',
array(
'key' => '_pos_visibility',
'value' => 'pos_only',
'compare' => '!=',
'key' => '_pos_visibility',
'compare' => 'NOT EXISTS',
),
array(
'key' => '_pos_visibility',
'compare' => 'NOT EXISTS',
'key' => '_pos_visibility',
'value' => 'pos_only',
'compare' => '!=',
),
);

// Check if an existing meta query exists.
if ( is_array( $meta_query ) ) {
if ( ! isset( $meta_query ['relation'] ) ) {
$meta_query['relation'] = 'AND';
}
$meta_query[] = $default_meta_query;
if ( empty( $args['meta_query'] ) ) {
$args['meta_query'] = $meta_query;
} else {
$meta_query = $default_meta_query;
}

// Set the updated meta query back to the query.
$query->set( 'meta_query', $meta_query );
}

/**
* Remove POS Only variations from the storefront.
*
* @param bool $visible Whether the variation is visible.
* @param int $variation_id The variation ID.
* @param int $product_id The product ID.
* @param \WC_Product_Variation $variation The variation object.
*/
public function hide_pos_only_variations( $visible, $variation_id, $product_id, $variation ) {
if ( \is_shop() || \is_product_category() || \is_product() ) {
// Get the _pos_visibility meta value for the variation.
$pos_visibility = get_post_meta( $variation_id, '_pos_visibility', true );

// Check if _pos_visibility is 'pos_only' for this variation.
if ( $pos_visibility === 'pos_only' ) {
return false;
}
$args['meta_query'] = array(
'relation' => 'AND',
$args['meta_query'],
$meta_query,
);
}

return $visible;
return $args;
}
}
41 changes: 2 additions & 39 deletions tests/includes/Test_Products.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
namespace WCPOS\WooCommercePOS\Tests;

use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper;
use WC_REST_Unit_Test_Case;
use WP_UnitTestCase;
use WP_Query;
use WC_Query;
use WCPOS\WooCommercePOS\Products;
use WC_Product_Variation;

Expand All @@ -14,7 +13,7 @@
*
* @coversNothing
*/
class Test_Products extends WC_REST_Unit_Test_Case {
class Test_Products extends WP_UnitTestCase {
public function setup(): void {
parent::setup();
}
Expand Down Expand Up @@ -118,40 +117,4 @@ function () {
// Assert that the variation without '_pos_visibility' set is in the query
$this->assertContains( $variation_ids[2], $queried_variation_ids );
}

/**
*
*/
public function test_pos_only_products_via_store_api() {
add_filter(
'woocommerce_pos_general_settings',
function () {
return array(
'pos_only_products' => true,
);
}
);
new Products(); // reinstantiate the class to apply the filter

// Create a visible product
$visible_product = ProductHelper::create_simple_product();

// Create a product with _pos_visibility set to 'pos_only'
$hidden_product = ProductHelper::create_simple_product();
update_post_meta( $hidden_product->get_id(), '_pos_visibility', 'pos_only' );

// Verify that the meta value is set correctly
$pos_visibility = get_post_meta( $hidden_product->get_id(), '_pos_visibility', true );
$this->assertEquals( 'pos_only', $pos_visibility, 'Meta value for _pos_visibility not set correctly' );

// Make WC REST request
add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
$request = new \WP_REST_Request( 'GET', '/wc/v3/products' );
$response = $this->server->dispatch( $request );

$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $visible_product->get_id(), $data[0]['id'] );
}
}
107 changes: 107 additions & 0 deletions tests/includes/Test_WC_API.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace WCPOS\WooCommercePOS\Tests;

use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper;
use WC_REST_Unit_Test_Case;
use WCPOS\WooCommercePOS\WC_API;

/**
* @internal
*
* @coversNothing
*/
class Test_WC_API extends WC_REST_Unit_Test_Case {
public function setup(): void {
parent::setup();
}

public function tearDown(): void {
parent::tearDown();
}

/**
*
*/
public function test_pos_only_products_via_store_api() {
add_filter(
'woocommerce_pos_general_settings',
function () {
return array(
'pos_only_products' => true,
);
}
);
new WC_API(); // reinstantiate the class to apply the filter

// Create a visible product
$visible_product = ProductHelper::create_simple_product();

// Create a product with _pos_visibility set to 'pos_only'
$hidden_product = ProductHelper::create_simple_product();
update_post_meta( $hidden_product->get_id(), '_pos_visibility', 'pos_only' );

// Verify that the meta value is set correctly
$pos_visibility = get_post_meta( $hidden_product->get_id(), '_pos_visibility', true );
$this->assertEquals( 'pos_only', $pos_visibility, 'Meta value for _pos_visibility not set correctly' );

// Make WC REST request
add_filter( 'woocommerce_rest_check_permissions', '__return_true' );
$request = new \WP_REST_Request( 'GET', '/wc/v3/products' );
$response = $this->server->dispatch( $request );

$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $visible_product->get_id(), $data[0]['id'] );
}

/**
*
*/
public function test_pos_only_variations_via_store_api() {
add_filter(
'woocommerce_pos_general_settings',
function () {
return array(
'pos_only_products' => true,
);
}
);
new WC_API(); // reinstantiate the class to apply the filter

// Create a variable product
$variable = ProductHelper::create_variation_product();
$variation_ids = $variable->get_children();
update_post_meta( $variation_ids[0], '_pos_visibility', 'pos_only' );

// Verify that the meta value is set correctly
$pos_visibility = get_post_meta( $variation_ids[0], '_pos_visibility', true );
$this->assertEquals( 'pos_only', $pos_visibility, 'Meta value for _pos_visibility not set correctly' );

// Make WC REST request
add_filter( 'woocommerce_rest_check_permissions', '__return_true' );

$request = new \WP_REST_Request( 'GET', '/wc/v3/products/' . $variable->get_id() . '/variations' );
$response = $this->server->dispatch( $request );

$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $variation_ids[1], $data[0]['id'] );

/**
* @TODO should we remove the id from the parent response also?
* The WooCommerce code uses $object->get_children() to get the variation ids, NOT
* $object->get_visible_children() so it seems they return all variations ids regardless of visibility.
*/
// $request = new \WP_REST_Request( 'GET', '/wc/v3/products/' . $variable->get_id() );
// $response = $this->server->dispatch( $request );

// $data = $response->get_data();
// $this->assertEquals( 200, $response->get_status() );
// $this->assertEquals( $variable->get_id(), $data['id'] );
// $this->assertEquals( 1, \count( $data['variations'] ) );
// $this->assertEquals( $variation_ids[1], $data['variations'][0] );
}
}
9 changes: 8 additions & 1 deletion tests/includes/Test_Wcpos_Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,14 @@ public function test_woocommerce_pos_get_payment_gateways_settings(): void {
$this->assertIsArray( $payment_gateways_settings );
$this->assertArrayHasKey( 'default_gateway', $payment_gateways_settings );
$this->assertArrayHasKey( 'gateways', $payment_gateways_settings );
$this->assertEquals( count( $payment_gateways_settings['gateways'] ), 2 );

$active_gateways = array_filter(
$payment_gateways_settings['gateways'],
function ( $gateway ) {
return $gateway['enabled'];
}
);
$this->assertEquals( count( $active_gateways ), 2 );

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

0 comments on commit 04352ad

Please sign in to comment.