PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.18
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.18
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.10.18, at includes/Admin/Products/Single_Product.php

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