-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathProducts.php
210 lines (180 loc) · 6.49 KB
/
Products.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<?php
/**
* POS Product Class.
*
* @author Paul Kilmurray <[email protected]>
*
* @see https://wcpos.com
*/
namespace WCPOS\WooCommercePOS;
use WC_Product;
use Automattic\WooCommerce\StoreApi\Exceptions\NotPurchasableException;
use WCPOS\WooCommercePOS\Services\Settings;
/**
*
*/
class Products {
/**
* Constructor.
*/
public function __construct() {
add_action( 'woocommerce_product_set_stock', array( $this, 'product_set_stock' ) );
add_action( 'woocommerce_variation_set_stock', array( $this, 'product_set_stock' ) );
$pos_only_products = woocommerce_pos_get_settings( 'general', 'pos_only_products' );
if ( $pos_only_products ) {
add_action( 'pre_get_posts', array( $this, 'hide_pos_only_products' ) );
add_filter( 'woocommerce_variation_is_visible', array( $this, 'hide_pos_only_variations' ), 10, 4 );
add_action( 'woocommerce_store_api_validate_add_to_cart', array( $this, 'store_api_prevent_pos_only_add_to_cart' ) );
// NOTE: this hook is marked as deprecated.
add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'prevent_pos_only_add_to_cart' ), 10, 2 );
// add_filter( 'woocommerce_get_product_subcategories_args', array( $this, 'filter_category_count_exclude_pos_only' ) );
}
/**
* Allow decimal quantities for products and variations.
*
* @TODO - this will affect the online store as well, should I make it POS only?
*/
$allow_decimal_quantities = woocommerce_pos_get_settings( 'general', 'decimal_qty' );
if ( \is_bool( $allow_decimal_quantities ) && $allow_decimal_quantities ) {
remove_filter( 'woocommerce_stock_amount', 'intval' );
add_filter( 'woocommerce_stock_amount', 'floatval' );
add_action( 'woocommerce_before_product_object_save', array( $this, 'save_decimal_quantities' ) );
}
}
/**
* Bump modified date on stock change.
* - variation->id = parent id.
*
* @param WC_Product $product
*/
public function product_set_stock( WC_Product $product ): void {
$post_modified = current_time( 'mysql' );
$post_modified_gmt = current_time( 'mysql', 1 );
wp_update_post(
array(
'ID' => $product->get_id(),
'post_modified' => $post_modified,
'post_modified_gmt' => $post_modified_gmt,
)
);
}
/**
* Filters the WHERE clause of the query.
*
* @param string $where The WHERE clause of the query.
* @param WP_Query $query The WP_Query instance (passed by reference).
*
* @return string
*/
public function hide_pos_only_products( $query ) {
// Ensure this only runs for the main WooCommerce queries on product-related queries
if ( ! is_admin() && ! woocommerce_pos_request() && 'product' === $query->get( 'post_type' ) ) {
$settings_instance = Settings::instance();
$settings = $settings_instance->get_pos_only_product_visibility_settings();
if ( isset( $settings['ids'] ) && ! empty( $settings['ids'] ) ) {
$exclude_ids = array_map( 'intval', (array) $settings['ids'] ); // Sanitize IDs as integers
// Merge any existing excluded IDs with the new ones
$existing_excludes = $query->get( 'post__not_in' );
if ( ! is_array( $existing_excludes ) ) {
$existing_excludes = array();
}
// Set the post__not_in query parameter to exclude specified IDs
$query->set( 'post__not_in', array_merge( $existing_excludes, $exclude_ids ) );
}
}
}
/**
* 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() ) {
$settings_instance = Settings::instance();
$pos_only = $settings_instance->is_variation_pos_only( $variation_id );
if ( $pos_only ) {
return false;
}
}
return $visible;
}
/**
* Filter category count to exclude pos_only products.
*
* @param array $args The arguments for getting product subcategories.
*
* @return array The modified arguments.
*/
public function filter_category_count_exclude_pos_only( $args ) {
// @TODO: Do we need this?
return $args;
}
/**
* Prevent POS Only products from being added to the cart.
*
* NOTE: this hook is marked as deprecated.
*
* @param bool $passed
* @param int $product_id
*
* @return bool
*/
public function prevent_pos_only_add_to_cart( $passed, $product_id ) {
$settings_instance = Settings::instance();
$product_pos_only = $settings_instance->is_product_pos_only( $product_id );
$variation_pos_only = $settings_instance->is_variation_pos_only( $product_id );
if ( $product_pos_only || $variation_pos_only ) {
return false;
}
return $passed;
}
/**
* Prevent POS Only products from being added to the cart via the Store API.
*
* @throws NotPurchasableException Exception if product is POS Only.
* @param WC_Product $product Product.
*
* @return void
*/
public function store_api_prevent_pos_only_add_to_cart( WC_Product $product ) {
$settings_instance = Settings::instance();
if ( $product->is_type( 'variation' ) ) {
$pos_only = $settings_instance->is_variation_pos_only( $product->get_id() );
} else {
$pos_only = $settings_instance->is_product_pos_only( $product->get_id() );
}
if ( $pos_only ) {
throw new NotPurchasableException(
'woocommerce_pos_product_not_purchasable',
$product->get_name()
);
}
}
/**
* Save decimal quantities for products and variations.
*
* @param WC_Product $product Product.
*/
public function save_decimal_quantities( WC_Product $product ) {
if ( ! $product->get_manage_stock() ) {
$product->set_stock_status( 'instock' );
return;
}
$stock_quantity = $product->get_stock_quantity();
$stock_notification_threshold = absint( get_option( 'woocommerce_notify_no_stock_amount', 0 ) );
// Adjust the condition to consider stock quantities between 0 and 1 as instock if greater than 0.
$stock_is_above_notification_threshold = ( $stock_quantity > 0 && $stock_quantity > $stock_notification_threshold );
$backorders_are_allowed = ( 'no' !== $product->get_backorders() );
if ( $stock_is_above_notification_threshold ) {
$new_stock_status = 'instock';
} elseif ( $backorders_are_allowed ) {
$new_stock_status = 'onbackorder';
} else {
$new_stock_status = 'outofstock';
}
$product->set_stock_status( $new_stock_status );
}
}