PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.9.14
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.9.14
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / includes / Admin / Products / Single_Product.php

Single_Product.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.9.14, at includes/Admin/Products/Single_Product.php

344 lines 12.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * POS Product Admin Class
4 * - pos only products.
5 * - barcode field.
6 *
7 * @author Paul Kilmurray <paul@kilbot.com.au>
8 *
9 * @see http://www.wcpos.com
10 * @package WCPOS\WooCommercePOS
11 */
12
13 namespace WCPOS\WooCommercePOS\Admin\Products;
14
15 use WCPOS\WooCommercePOS\Registry;
16 use WCPOS\WooCommercePOS\Services\Analytics;
17 use WCPOS\WooCommercePOS\Services\Settings;
18 use WP_Post;
19
20 /**
21 * Single_Product class for POS product admin functionality.
22 */
23 class Single_Product {
24 /**
25 * The barcode field key.
26 *
27 * @var string
28 */
29 private $barcode_field;
30
31 /**
32 * Visibility options for POS products.
33 *
34 * @phpstan-ignore-next-line
35 * @var array
36 */
37 private $options;
38
39 /**
40 * Constructor.
41 */
42 public function __construct() {
43 Registry::get_instance()->set( static::class, $this );
44
45 $this->barcode_field = woocommerce_pos_get_settings( 'general', 'barcode_field' );
46
47 // visibility options.
48 $this->options = array(
49 '' => /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'POS & Online', 'woocommerce-pos' ),
50 'pos_only' => /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'POS Only', 'woocommerce-pos' ),
51 'online_only' => /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'Online Only', 'woocommerce-pos' ),
52 );
53
54 if ( $this->barcode_field && ! \in_array( $this->barcode_field, $this->get_excluded_barcode_fields(), true ) ) {
55 add_action( 'woocommerce_product_options_sku', array( $this, 'woocommerce_product_options_sku' ) );
56 add_action( 'woocommerce_process_product_meta', array( $this, 'woocommerce_process_product_meta' ) );
57 add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'after_variable_attributes_barcode_field' ), 10, 3 );
58 add_action( 'woocommerce_save_product_variation', array( $this, 'save_product_variation_barcode_field' ) );
59 }
60
61 if ( woocommerce_pos_get_settings( 'general', 'pos_only_products' ) ) {
62 add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
63 add_action( 'post_submitbox_misc_actions', array( $this, 'post_submitbox_misc_actions' ), 99 );
64 add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'after_variable_attributes_pos_only_products' ), 10, 3 );
65 add_action( 'woocommerce_save_product_variation', array( $this, 'save_product_variation_pos_only_products' ) );
66 }
67
68 add_action( 'woocommerce_product_options_pricing', array( $this, 'add_store_price_fields' ) );
69 add_action( 'woocommerce_product_options_tax', array( $this, 'add_store_tax_fields' ) );
70 add_action( 'woocommerce_variation_options_pricing', array( $this, 'add_variations_store_price_fields' ), 10, 3 );
71 add_action( 'woocommerce_variation_options_tax', array( $this, 'add_variations_store_tax_fields' ), 10, 3 );
72 }
73
74 /**
75 * Show barcode input.
76 */
77 public function woocommerce_product_options_sku(): void {
78 woocommerce_wp_text_input(
79 array(
80 'id' => $this->barcode_field,
81 'label' => /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'POS Barcode', 'woocommerce-pos' ),
82 'desc_tip' => 'true',
83 'description' => __( 'Product barcode used at the point of sale', 'woocommerce-pos' ),
84 )
85 );
86 }
87
88 /**
89 * Add store price fields to the product edit page.
90 */
91 public function add_store_price_fields(): void {
92 Analytics::instance()->capture_once(
93 'upgrade_cta_viewed',
94 array(
95 'placement' => 'product_edit_price',
96 ),
97 'product_edit_price'
98 );
99
100 woocommerce_wp_checkbox(
101 array(
102 'id' => '',
103 'label' => '',
104 'value' => true,
105 'cbvalue' => false,
106 'description' => /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'Enable POS specific prices.', 'woocommerce-pos' ) . ' ' . $this->get_pro_link( 'product_edit_price' ),
107 'custom_attributes' => array( 'disabled' => 'disabled' ),
108 )
109 );
110 }
111
112 /**
113 * Add store tax fields to the product edit page.
114 */
115 public function add_store_tax_fields(): void {
116 Analytics::instance()->capture_once(
117 'upgrade_cta_viewed',
118 array(
119 'placement' => 'product_edit_tax',
120 ),
121 'product_edit_tax'
122 );
123
124 woocommerce_wp_checkbox(
125 array(
126 'id' => '',
127 'label' => '',
128 'value' => true,
129 'cbvalue' => false,
130 'description' => /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'Enable POS specific taxes.', 'woocommerce-pos' ) . ' ' . $this->get_pro_link( 'product_edit_tax' ),
131 'custom_attributes' => array( 'disabled' => 'disabled' ),
132 )
133 );
134 }
135
136 /**
137 * Save barcode field on product meta.
138 *
139 * @param int $post_id The post ID.
140 */
141 public function woocommerce_process_product_meta( $post_id ): void {
142 if ( isset( $_POST[ $this->barcode_field ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce.
143 update_post_meta( $post_id, $this->barcode_field, sanitize_text_field( wp_unslash( $_POST[ $this->barcode_field ] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce.
144 }
145 }
146
147 /**
148 * Add barcode field to variable product attributes.
149 *
150 * @param int $loop Position in the loop.
151 * @param array $variation_data Variation data.
152 * @param WP_Post $variation Post data.
153 */
154 public function after_variable_attributes_barcode_field( $loop, $variation_data, $variation ): void {
155 $value = get_post_meta( $variation->ID, $this->barcode_field, true );
156 if ( ! $value ) {
157 $value = '';
158 }
159 include 'templates/variation-metabox-pos-barcode.php';
160 }
161
162 /**
163 * Save barcode field for a product variation.
164 *
165 * @param int $variation_id The variation ID.
166 */
167 public function save_product_variation_barcode_field( $variation_id ): void {
168 if ( isset( $_POST['variable_pos_barcode'][ $variation_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce.
169 update_post_meta( $variation_id, $this->barcode_field, sanitize_text_field( wp_unslash( $_POST['variable_pos_barcode'][ $variation_id ] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce.
170 }
171 }
172
173 /**
174 * Add store price fields to the variation edit page.
175 *
176 * @param int $loop Position in the loop.
177 * @param array $variation_data Variation data.
178 * @param WP_Post $variation Post data.
179 */
180 public function add_variations_store_price_fields( $loop, $variation_data, $variation ): void {
181 echo '<p class="form-row form-row-full"><label>';
182 echo /* translators: Product POS visibility or barcode label in WooCommerce admin. */ esc_html__( 'Enable POS specific prices.', 'woocommerce-pos' ) . ' ' . wp_kses_post( $this->get_pro_link( 'product_edit_price' ) );
183 echo '<input style="vertical-align:middle;margin:0 5px 0 0 !important;" type="checkbox" class="checkbox" disabled />';
184 echo '</label></p>';
185 }
186
187 /**
188 * Add store tax fields to the variation edit page.
189 *
190 * @param int $loop Position in the loop.
191 * @param array $variation_data Variation data.
192 * @param WP_Post $variation Post data.
193 */
194 public function add_variations_store_tax_fields( $loop, $variation_data, $variation ): void {
195 echo '<p class="form-row form-row-full"><label>';
196 echo /* translators: Product POS visibility or barcode label in WooCommerce admin. */ esc_html__( 'Enable POS specific taxes.', 'woocommerce-pos' ) . ' ' . wp_kses_post( $this->get_pro_link( 'product_edit_tax' ) );
197 echo '<input style="vertical-align:middle;margin:0 5px 0 0 !important;" type="checkbox" class="checkbox" disabled />';
198 echo '</label></p>';
199 }
200
201 /**
202 * Build a tracked upgrade link for a product-edit upsell placement.
203 *
204 * @param string $placement Stable CTA placement identifier.
205 *
206 * @return string
207 */
208 private function get_pro_link( string $placement ): string {
209 return '<a href="https://wcpos.com/pro" data-wcpos-upgrade-placement="' . esc_attr( $placement ) . '">' . /* translators: Product POS visibility or barcode label in WooCommerce admin. */ __( 'Upgrade to Pro', 'woocommerce-pos' ) . '</a>.';
210 }
211
212 /**
213 * Save POS visibility on post save.
214 *
215 * @param int $post_id The post ID.
216 * @param \WP_Post $post The post object.
217 */
218 public function save_post( $post_id, $post ): void {
219 // If this is an autosave, our form has not been submitted, so we don't want to do anything.
220 if ( \defined( 'DOING_AUTOSAVE' ) && \DOING_AUTOSAVE ) { // @phpstan-ignore-line
221 return;
222 }
223
224 // Don't save revisions and autosaves.
225 if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
226 return;
227 }
228
229 // Make sure the current user has permission to edit the post.
230 if ( ! current_user_can( 'edit_post', $post_id ) ) {
231 return;
232 }
233
234 // Get the product and save.
235 $valid_options = array( 'pos_only', 'online_only', '' );
236
237 if ( isset( $_POST['_pos_visibility'] ) && \in_array( $_POST['_pos_visibility'], $valid_options, true ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WordPress save_post.
238 $settings_instance = Settings::instance();
239 $args = array(
240 'post_type' => 'products',
241 'visibility' => sanitize_text_field( wp_unslash( $_POST['_pos_visibility'] ) ), // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WordPress save_post.
242 'ids' => array( $post_id ),
243 );
244 $settings_instance->update_visibility_settings( $args );
245 }
246 }
247
248 /**
249 * Add visibility option to the Product edit page.
250 */
251 public function post_submitbox_misc_actions(): void {
252 global $post;
253
254 if ( 'product' != $post->post_type ) {
255 return;
256 }
257
258 $selected = '';
259 $settings_instance = Settings::instance();
260 $pos_only = $settings_instance->is_product_pos_only( $post->ID );
261 $online_only = $settings_instance->is_product_online_only( $post->ID );
262
263 // Set $selected based on the visibility status.
264 if ( $pos_only ) {
265 $selected = 'pos_only';
266 } elseif ( $online_only ) {
267 $selected = 'online_only';
268 }
269
270 if ( ! $selected ) {
271 $selected = '';
272 if ( 'add' == get_current_screen()->action ) {
273 $selected = apply_filters( 'woocommerce_pos_default_product_visibility', '', $post );
274 }
275 }
276
277 include 'templates/post-metabox-visibility-select.php';
278 }
279
280 /**
281 * Add POS visibility select to variable product attributes.
282 *
283 * @param int $loop Position in the loop.
284 * @param array $variation_data Variation data.
285 * @param WP_Post $variation Post data.
286 */
287 public function after_variable_attributes_pos_only_products( $loop, $variation_data, $variation ): void {
288 $selected = '';
289 $settings_instance = Settings::instance();
290 $pos_only = $settings_instance->is_variation_pos_only( $variation->ID );
291 $online_only = $settings_instance->is_variation_online_only( $variation->ID );
292
293 // Set $selected based on the visibility status.
294 if ( $pos_only ) {
295 $selected = 'pos_only';
296 } elseif ( $online_only ) {
297 $selected = 'online_only';
298 }
299
300 include 'templates/variation-metabox-visibility-select.php';
301 }
302
303 /**
304 * Save POS visibility for a product variation.
305 *
306 * @param int $variation_id The variation ID.
307 */
308 public function save_product_variation_pos_only_products( $variation_id ): void {
309 $valid_options = array( 'pos_only', 'online_only', '' );
310
311 if ( isset( $_POST['variable_pos_visibility'][ $variation_id ] ) && \in_array( $_POST['variable_pos_visibility'][ $variation_id ], $valid_options, true ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce.
312 $settings_instance = Settings::instance();
313 $args = array(
314 'post_type' => 'variations',
315 'visibility' => sanitize_text_field( wp_unslash( $_POST['variable_pos_visibility'][ $variation_id ] ) ), // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce.
316 'ids' => array( $variation_id ),
317 );
318 $settings_instance->update_visibility_settings( $args );
319 }
320 }
321
322 /**
323 * Get the list of barcode fields that should be excluded from custom barcode field functionality.
324 *
325 * These fields are built-in WooCommerce or plugin fields that don't need custom barcode input.
326 *
327 * @return array Array of excluded barcode field keys.
328 */
329 private function get_excluded_barcode_fields(): array {
330 $excluded_fields = array(
331 '_sku', // default WooCommerce SKU field.
332 '_global_unique_id', // default WooCommerce GTIN, UPC, EAN, or ISBN.
333 '_alg_ean', // https://wpfactory.com/item/ean-barcodes-woocommerce/.
334 );
335
336 /*
337 * Filter the list of barcode fields that should be excluded from custom barcode field functionality.
338 *
339 * @param array $excluded_fields Array of field keys to exclude from custom barcode input.
340 */
341 return apply_filters( 'woocommerce_pos_excluded_custom_barcode_fields', $excluded_fields );
342 }
343 }
344