PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.7.4
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.7.4
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / elementor / modules / checkout / classes / helper.php

helper.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 1.7.4, at includes/elementor/modules/checkout/classes/helper.php

745 lines 23.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Sellkit\Elementor\Modules\Checkout\Classes;
4
5 defined( 'ABSPATH' ) || exit;
6
7 use Elementor\Plugin as Elementor;
8
9 /**
10 * Helper class.
11 *
12 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
13 * @SuppressWarnings(PHPMD.NPathComplexity)
14 * @since 1.1.0
15 */
16 class Helper {
17
18 /**
19 * Instance of this class.
20 *
21 * @since NEXT
22 * @access public
23 * @var Checkout
24 */
25 public static $instance;
26
27 /**
28 * Provides access to a single instance of a module using the singleton pattern.
29 *
30 * @since NEXT
31 * @return object
32 */
33 public static function instance() {
34 if ( null === self::$instance ) {
35 self::$instance = new self();
36 }
37
38 return self::$instance;
39 }
40
41 /**
42 * Default sellkit checkout widget billing fields.
43 *
44 * @return array
45 * @since 1.1.0
46 */
47 public function billing_fields() {
48 return [
49 'billing_first_name' => esc_html__( 'Billing First Name', 'sellkit' ),
50 'billing_last_name' => esc_html__( 'Billing Last Name', 'sellkit' ),
51 'billing_company' => esc_html__( 'Billing Company', 'sellkit' ),
52 'billing_address_1' => esc_html__( 'Billing Address 1', 'sellkit' ),
53 'billing_address_2' => esc_html__( 'Billing Address 2', 'sellkit' ),
54 'billing_city' => esc_html__( 'Billing City', 'sellkit' ),
55 'billing_postcode' => esc_html__( 'Billing Postal Code', 'sellkit' ),
56 'billing_country' => esc_html__( 'Billing Country', 'sellkit' ),
57 'billing_state' => esc_html__( 'Billing State', 'sellkit' ),
58 'billing_email' => esc_html__( 'Billing State', 'sellkit' ),
59 'billing_phone' => esc_html__( 'Billing Phone', 'sellkit' ),
60 ];
61 }
62
63 /**
64 * Default sellkit checkout widget shipping fields.
65 *
66 * @return array
67 * @since 1.1.0
68 */
69 public function shipping_fields() {
70 return [
71 'shipping_first_name' => esc_html__( 'shipping First Name', 'sellkit' ),
72 'shipping_last_name' => esc_html__( 'shipping Last Name', 'sellkit' ),
73 'shipping_address_1' => esc_html__( 'shipping Address 1', 'sellkit' ),
74 'shipping_address_2' => esc_html__( 'shipping Address 2', 'sellkit' ),
75 'shipping_city' => esc_html__( 'shipping City', 'sellkit' ),
76 'shipping_postcode' => esc_html__( 'shipping Postal Code', 'sellkit' ),
77 'shipping_country' => esc_html__( 'shipping Country', 'sellkit' ),
78 'shipping_state' => esc_html__( 'shipping State', 'sellkit' ),
79 ];
80 }
81
82 /**
83 * Gets user defined fields and return array of slug.
84 *
85 * @param array $user_defined_fields widget fields.
86 * @param string $type billing/shipping field.
87 * @return array
88 * @since 1.1.0
89 */
90 public function get_user_defined_fields_slug( $user_defined_fields, $type ) {
91 $fields = [];
92
93 foreach ( $user_defined_fields as $field ) {
94 $fields[] = $field[ $type ];
95 }
96
97 return $fields;
98 }
99
100 /**
101 * Assign user defined values to each field.
102 *
103 * @param array $default_fields : default woocommerce fields.
104 * @param array $widget_fields : fields get added by user from widget option.
105 * @param string $type : shipping / billing.
106 * @param array $settings : whole widget settings.
107 * @return array
108 * @since 1.1.0
109 * @SuppressWarnings(PHPMD.NPathComplexity)
110 */
111 public function assign_settings_per_field( $default_fields, $widget_fields, $type, $settings ) {
112 // Assign user properties.
113 foreach ( $widget_fields as $key => $field ) {
114 $field_slug = $field[ $type . '_list_field' ];
115 $is_custom = false;
116
117 // IF field is a custom field we replace key with id. So it will be unique.
118 // !important: user has to define id for each field using custom id field.
119 if ( 'custom_role' === $field_slug ) {
120 // Create billing_bla_bla & shipping_bla_bla for custom field.
121 $field_slug = $type . '_' . $field['_id'];
122
123 if ( ! empty( $field[ $type . '_custom_id' ] ) ) {
124 $field_slug = $type . '_' . $field[ $type . '_custom_id' ];
125 }
126
127 $is_custom = true;
128 }
129
130 $default_fields[ $field_slug ]['label'] = $field[ $type . '_list_placeholder' ];
131 $default_fields[ $field_slug ]['class'] = explode( ' ', $field[ $type . '_list_class' ] ); // phpcs:ignore
132 $default_fields[ $field_slug ]['class'][] = $field[ $type . '_width' ];
133 $default_fields[ $field_slug ]['class'][] = 'sellkit-widget-checkout-fields';
134 $default_fields[ $field_slug ]['class'][] = 'sellkit-checkout-fields-validation-' . $field[ $type . '_list_validation' ];
135 $default_fields[ $field_slug ]['required'] = ( 'yes' === $field[ $type . '_list_required' ] ) ? true : false;
136 $default_fields[ $field_slug ]['clear'] = ( 'yes' === $field[ $type . '_list_clear' ] ) ? true : false;
137 $default_fields[ $field_slug ]['priority'] = ( $key + 1 ) * 10;
138 // Widget defined fields are local. third party plugins's fields are not.
139 $default_fields[ $field_slug ]['local'] = true;
140
141 // Append postal code autocomplete class.
142 if (
143 array_key_exists( 'state_lookup_by_postcode', $settings )
144 && 'yes' === $settings['state_lookup_by_postcode']
145 && ( 'billing_postcode' === $field_slug || 'shipping_postcode' === $field_slug )
146 ) {
147 $default_fields[ $field_slug ]['class'][] = 'post_code_autocomplete';
148 }
149
150 // IF not custom field, go next.
151 if ( false === $is_custom ) {
152 continue;
153 }
154
155 $default_fields = $this->custom_field_setup( $field, $type, $field_slug, $default_fields );
156 }
157
158 foreach ( $default_fields as $key => $details ) {
159 if ( ! array_key_exists( 'local', $details ) || false === $details['local'] ) {
160 $default_fields[ $key ]['priority'] = 500;
161 }
162 }
163
164 return $default_fields;
165 }
166
167 /**
168 * Setup custom field options and assign required things to custom fields.
169 * also helps to reduce assign_settings_per_field method complexity.
170 *
171 * @param array $field html string of checkout fields.
172 * @param string $type type of checkout fields.
173 * @param string $field_slug unique sluf per field.
174 * @param array $default_fields default checkout fields.
175 * @return array
176 * @since 1.1.0
177 */
178 private function custom_field_setup( $field, $type, $field_slug, $default_fields ) {
179 $tag = $field[ $type . '_custom_type' ];
180
181 // Set default options.
182 $default_fields[ $field_slug ]['class'][] = ( $field[ $type . '_width' ] ) ? $field[ $type . '_width' ] : 'w-100';
183 $default_fields[ $field_slug ]['type'] = ( $field[ $type . '_custom_type' ] ) ? $field[ $type . '_custom_type' ] : 'text';
184 $default_fields[ $field_slug ]['default'] = $field[ $type . '_custom_value' ];
185
186 // Convert select to multiselect.
187 if ( 'multiselect' === $tag ) {
188 $default_fields[ $field_slug ]['type'] = 'multiselect';
189 }
190
191 // Assign one extra class to style radio group wrapper.
192 if ( 'radio' === $tag ) {
193 $default_fields[ $field_slug ]['type'] = 'radio';
194 $default_fields[ $field_slug ]['class'][] = 'radio-group-wrapper';
195 $default_fields[ $field_slug ]['mode'] = $field[ $type . '_radio_field_mode' ];
196 }
197
198 // Check if checkbox must be checked on default.
199 if ( 'checkbox' === $tag ) {
200 $default_fields[ $field_slug ]['checked'] = $field[ $type . '_checkbox_custom_value' ];
201 }
202
203 // Assign options.
204 $tags = [ 'select', 'multiselect', 'radio' ];
205 if ( in_array( $tag, $tags, true ) ) {
206 $options = $this->convert_value_to_array( $field[ $type . '_custom_options' ] );
207
208 $default_fields[ $field_slug ]['options'] = $options;
209 }
210
211 return $default_fields;
212 }
213
214 /**
215 * Gets widget options string and convert it to array to be used for select / radio and etc.
216 *
217 * @param string $value string of options.
218 * @return array
219 * @since 1.1.0
220 */
221 private function convert_value_to_array( $value ) {
222 $array = [];
223 $values = preg_split( '/\r\n|\r|\n/', $value );
224
225 foreach ( $values as $option ) {
226 $split = explode( ':', $option );
227 $array[ $split[0] ] = $split[1];
228 }
229
230 return $array;
231 }
232
233 /**
234 * Is used to validate user defined custom fields after pressing place order button at checkout page.
235 * Validate both custom shipping and billing fields at once if exists.
236 *
237 * @uses sellkit_Core\Raven\Modules\Checkout\Classes\Global_Hooks::validate_user_defined_fields
238 * @param array $shipping_fields custom shipping fields.
239 * @param array $billing_fields custom billing fields.
240 * @return void
241 * @since 1.1.0
242 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
243 */
244 public function validate_user_defined_fields( $shipping_fields, $billing_fields ) {
245 foreach ( $shipping_fields as $data ) {
246 // Escape all if cart does not need shipping information.
247 if ( ! WC()->cart->needs_shipping() ) {
248 continue;
249 }
250
251 $final_name = isset( $data['shipping_list_field'] ) ? $data['shipping_list_field'] : '';
252
253 if ( 'custom_role' === $final_name ) {
254 $final_name = 'shipping_' . $data['_id'];
255
256 if ( ! empty( $data['shipping_custom_id'] ) ) {
257 $id = $data['shipping_custom_id'];
258 $final_name = "shipping_$id";
259 }
260 }
261
262 // Get $name variable from label or placeholder and/or id to be used in validate error.
263 $label = $this->create_name_for_errors( $data, __( 'Shipping', 'sellkit' ), 'shipping', $final_name );
264
265 // Field value.
266 $value = filter_input( INPUT_POST, $final_name, FILTER_DEFAULT );
267
268 // #1. Required validation.
269 $is_required = ( ! empty( $data['shipping_list_required'] ) && 'yes' === $data['shipping_list_required'] ) ? true : false;
270
271 if ( true === $is_required && ( ! array_key_exists( $final_name, $_POST ) || empty( $value ) ) ) { // phpcs:ignore
272 /* translators: %s field_name. */
273 wc_add_notice( sprintf( __( '%s is a required field.', 'sellkit' ), '<strong>' . $label . '</strong>' ), 'error' );
274 }
275
276 // #2. Phone validation.
277 $this->phone_validation( $data, $final_name, 'shipping', $label );
278
279 // #3. Postcode validation.
280 $this->postcode_validation( $data, $final_name, 'shipping', $label );
281 }
282
283 foreach ( $billing_fields as $data ) {
284 $final_name = $data['billing_list_field'];
285
286 if ( 'custom_role' !== $final_name ) {
287 continue;
288 }
289
290 $final_name = 'billing_' . $data['_id'];
291
292 if ( ! empty( $data['billing_custom_id'] ) ) {
293 $id = $data['billing_custom_id'];
294 $final_name = "billing_$id";
295 }
296
297 // Get $name variable from label or placeholder and/or id to be used in validate error.
298 $label = $this->create_name_for_errors( $data, __( 'Billing', 'sellkit' ), 'billing', $final_name );
299
300 // Field value.
301 $value = filter_input( INPUT_POST, $final_name, FILTER_DEFAULT );
302
303 // #1. Required validation.
304 $is_required = ( ! empty( $data['billing_list_required'] ) && 'yes' === $data['billing_list_required'] ) ? true : false;
305
306 if ( true === $is_required && empty( $value ) ) { // phpcs:ignore
307 /* translators: %s field_name. */
308 wc_add_notice( sprintf( __( '%s is a required field.', 'sellkit' ), '<strong>' . $label . '</strong>' ), 'error' );
309 }
310
311 // #2. phone validation.
312 $this->phone_validation( $data, $final_name, 'billing', $label );
313
314 // #3. Postcode validation.
315 $this->postcode_validation( $data, $final_name, 'billing', $label );
316 }
317
318 // Validate main checkout email.
319 $email = filter_input( INPUT_POST, 'billing_email', FILTER_SANITIZE_EMAIL );
320 $valid = filter_var( $email, FILTER_VALIDATE_EMAIL );
321
322 if ( ! $email ) {
323 /* translators: %s field_name. */
324 wc_add_notice( sprintf( __( '%s is a required field.', 'sellkit' ), '<strong>' . __( 'Email address', 'sellkit' ) . '</strong>' ), 'error' );
325 return;
326 }
327
328 if ( ! $valid ) {
329 /* translators: %s field_name. */
330 wc_add_notice( sprintf( __( '%s is not a valid email.', 'sellkit' ), '<strong>' . __( 'Email address', 'sellkit' ) . '</strong>' ), 'error' );
331 }
332 }
333
334 /**
335 * Create name for each field to be used in errors text.
336 *
337 * @param array $data field data.
338 * @param string $display_type shipping / billing with text-domain.
339 * @param string $type shipping / billing.
340 * @param string $final_name field key.
341 * @return string
342 * @since 1.1.0
343 */
344 private function create_name_for_errors( $data, $display_type, $type, $final_name ) {
345 $name = $data[ $type . '_list_placeholder' ];
346
347 if ( empty( $data[ $type . '_list_placeholder' ] ) ) {
348 $name = $data[ $type . '_list_label' ];
349 }
350
351 $label = $display_type . ' ' . $name;
352
353 if ( empty( $name ) ) {
354 $label = $final_name;
355 }
356
357 return $label;
358 }
359
360 /**
361 * Validate phone number using woocommerce way.
362 *
363 * @see woocommerce/includes/class-wc-validation.php
364 * @param array $data widget field data.
365 * @param string $final_name key of field in checkout form.
366 * @param string $type shipping/billing.
367 * @param string $label field label for error.
368 * @return boolean
369 * @since 1.1.0
370 */
371 private function phone_validation( $data, $final_name, $type, $label ) {
372 if ( ! array_key_exists( $type . '_list_validation', $data ) || 'phone' !== $data[ $type . '_list_validation' ] ) {
373 return true;
374 }
375
376 $phone = filter_input( INPUT_POST, $final_name, FILTER_DEFAULT );
377 $valid = \WC_Validation::is_phone( $phone );
378
379 if ( ! $valid ) {
380 /* translators: %s field_name. */
381 wc_add_notice( sprintf( __( '%s is not a valid phone.', 'sellkit' ), '<strong>' . $label . '</strong>' ), 'error' );
382 }
383 }
384
385 /**
386 * Validate postcode using woocommerce way.
387 *
388 * @param array $data field data.
389 * @param string $final_name field key in checkout form.
390 * @param string $type shipping / billing.
391 * @param string $label field label to be used in error text.
392 * @return void
393 * @since 1.1.0
394 */
395 private function postcode_validation( $data, $final_name, $type, $label ) {
396 if ( ! array_key_exists( $type . '_list_validation', $data ) || 'postcode' !== $data[ $type . '_list_validation' ] ) {
397 return;
398 }
399
400 $postcode = filter_input( INPUT_POST, $final_name, FILTER_DEFAULT );
401 $country = filter_input( INPUT_POST, $type . '_country' );
402 $postcode = wc_format_postcode( $postcode, $country );
403 $valid = \WC_Validation::is_postcode( $postcode, $country );
404
405 if ( ! $valid ) {
406 /* translators: %s field_name. */
407 wc_add_notice( sprintf( __( '%s is not a valid postcode.', 'sellkit' ), '<strong>' . $label . '</strong>' ), 'error' );
408 }
409 }
410
411 /**
412 * Is used to save user defined custom fields in database for the current order id.
413 * save both billing and shipping custom fields at once if exists.
414 *
415 * @uses sellkit_Core\Raven\Modules\Checkout\Classes\Global_Hooks::save_user_defined_fields
416 * @param array $shipping_fields custom shipping fields.
417 * @param array $billing_fields custom billing fields.
418 * @param int $order_id order id.
419 * @return void
420 * @since 1.1.0
421 */
422 public function save_user_defined_fields( $shipping_fields, $billing_fields, $order_id ) {
423 // We store saved fields in this array and save keys as a meta for this order, to use it later.
424 $saved_fields = [];
425
426 foreach ( $shipping_fields as $field ) {
427 if ( empty( $field['shipping_custom_id'] ) ) {
428 continue;
429 }
430
431 $item = $this->prepare_custom_fields_to_save( $field, 'shipping' );
432 $final_name = $item['key_name'];
433
434 // Field value.
435 $value = sellkit_htmlspecialchars( INPUT_POST, $final_name );
436 if ( 'multiselect' === $field['shipping_custom_type'] ) {
437 $value = filter_input( INPUT_POST, $final_name, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
438 }
439
440 // Some user defined field might be not required ( & empty ). so again we check if field is has value save it.
441 if ( ! empty( $value ) ) { // phpcs:ignore
442 update_post_meta( $order_id, $final_name, sanitize_text_field( $value ) ); // phpcs:ignore
443 array_push( $saved_fields, $item );
444 }
445 }
446
447 foreach ( $billing_fields as $field ) {
448 if ( empty( $field['billing_custom_id'] ) ) {
449 continue;
450 }
451
452 $item = $this->prepare_custom_fields_to_save( $field, 'billing' );
453 $final_name = $item['key_name'];
454
455 // Field value.
456 $value = sellkit_htmlspecialchars( INPUT_POST, $final_name );
457 if ( 'multiselect' === $field['billing_custom_type'] ) {
458 $value = filter_input( INPUT_POST, $final_name, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
459 }
460
461 // Some user defined field might be not required ( & empty ). so again we check if field has value save it.
462 if ( ! empty( $value ) ) { // phpcs:ignore
463 update_post_meta( $order_id, $final_name, sanitize_text_field( $value ) ); // phpcs:ignore
464 array_push( $saved_fields, $item );
465 }
466 }
467
468 // Save id of those custom fields that are validate and has value as an meta for order to be used later.
469 if ( count( $saved_fields ) > 0 ) {
470 update_post_meta( $order_id, 'sellkit_checkout_widget_custom_field_of_order', $saved_fields );
471 }
472 }
473
474 /**
475 * The way to save custom fields names as array for order as meta to be used later.
476 *
477 * @param array $data sent data from checkout.
478 * @param string $type shippin/billing.
479 * @return array
480 * @since 1.1.0
481 */
482 private function prepare_custom_fields_to_save( $data, $type ) {
483 $id = $data[ $type . '_custom_id' ];
484 $final_name = $type . '_' . $id;
485 $item = [
486 'show_in_thank_you' => ( 'yes' === $data[ $type . '_show_in_thankyou' ] ) ? 'yes' : 'no',
487 'show_in_email' => ( 'yes' === $data[ $type . '_show_in_order_mail' ] ) ? 'yes' : 'no',
488 'key_name' => $final_name,
489 ];
490
491 return $item;
492 }
493
494 /**
495 * Convert required fields to optional based on widget options.
496 * will be called after clicking place order button.
497 *
498 * @uses sellkit_Core\Raven\Modules\Checkout\Classes\Global_Hooks::validate_user_defined_fields
499 * @param array $widget_shipping_fields user defined fields in widget.
500 * @param array $widget_billing_fields user defined fields in widget.
501 * @return void
502 * @since 1.1.0
503 */
504 public function make_sure_to_convert_required_field_to_optional( $widget_shipping_fields, $widget_billing_fields ) {
505 add_filter( 'woocommerce_checkout_fields', function( $default_fields ) use ( $widget_shipping_fields, $widget_billing_fields ) {
506 // Make phone field optional at beginning.
507 $default_fields['billing']['billing_phone']['required'] = false;
508 unset( $default_fields['billing']['billing_email'] );
509
510 // Make it optional.
511 foreach ( $widget_billing_fields as $data ) {
512 $slug = $data['billing_list_field'];
513 $is_required = false;
514
515 if ( 'custom_role' === $slug ) {
516 continue;
517 }
518
519 if ( ! empty( $data['billing_list_required'] ) && 'yes' === $data['billing_list_required'] ) {
520 $is_required = true;
521 }
522
523 $default_fields['billing'][ $slug ]['required'] = $is_required;
524 }
525
526 foreach ( $widget_shipping_fields as $data ) {
527 $slug = isset( $data['shipping_list_field'] ) ? $data['shipping_list_field'] : '';
528 $is_required = false;
529
530 if ( 'custom_role' === $slug ) {
531 continue;
532 }
533
534 if ( ! empty( $data['shipping_list_required'] ) && 'yes' === $data['shipping_list_required'] ) {
535 $is_required = true;
536 }
537
538 $default_fields['shipping'][ $slug ]['required'] = $is_required;
539 }
540
541 return $default_fields;
542 } );
543 }
544
545 /**
546 * Retrieve required widget settings of current checkout widget.
547 *
548 * @param int $post_id page id.
549 * @param string $form_id form id.
550 * @return array
551 * @since 1.1.0
552 */
553 public function retrieve_checkout_widget_settings( $post_id, $form_id ) {
554 $form_meta = Elementor::$instance->documents->get( $post_id )->get_elements_data();
555 $form = self::find_element_recursive( $form_meta, $form_id );
556
557 if ( ! is_array( $form ) || ! array_key_exists( 'settings', $form ) ) {
558 return [];
559 }
560
561 $settings = $form['settings'];
562
563 return $settings;
564 }
565
566 /**
567 * Find elementor element.
568 * Code block copied from sellkit-core directly.
569 *
570 * @param array $elements elements of elementor.
571 * @param string $form_id elementor form id.
572 * @return array
573 * @since 1.1.0
574 */
575 public static function find_element_recursive( $elements, $form_id ) {
576 foreach ( $elements as $element ) {
577 if ( $form_id === $element['id'] ) {
578 return $element;
579 }
580
581 if ( ! empty( $element['elements'] ) ) {
582 $element = self::find_element_recursive( $element['elements'], $form_id );
583
584 if ( $element ) {
585 return $element;
586 }
587 }
588 }
589
590 return false;
591 }
592
593 /**
594 * Hide checkout order product quantity input and show raw quantity.
595 *
596 * @param string $input_html default quantity input.
597 * @param int $quantity product quantity in cart.
598 * @since 1.1.0
599 * @return void
600 *
601 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
602 */
603 public function checkout_order_hidden_quantity( $input_html, $quantity ) {
604 echo sprintf(
605 /** Translators: %s: product quantity */
606 '<strong class="product-quantity"> <i class="fa fa-times" aria-hidden="true"></i>%s</strong>',
607 esc_html( $quantity )
608 );
609 }
610
611 /**
612 * Calculate item discount.
613 *
614 * @param int $id product id.
615 * @param string $type discount type.
616 * @param int $value discount value.
617 * @return int|boolean
618 * @since 1.2.8
619 */
620 public static function calculate_discount( $id, $type, $value ) {
621 if ( false === $type && false === $value ) {
622 return false;
623 }
624
625 $product = wc_get_product( $id );
626 $regular = $product->get_regular_price();
627 $sale = $product->get_sale_price();
628 $price = false;
629
630 if ( strpos( $type, 'sale' ) !== false ) {
631 $discount = ( 'fixed-sale' === $type ) ? floatval( $value ) : ( floatval( $sale ) * floatval( $value ) ) / 100;
632 $discount = floatval( $sale ) - $discount;
633
634 return ( $discount > 0 ) ? $discount : 0;
635 }
636
637 if ( strpos( $type, 'sale' ) === false ) {
638 $discount = ( 'fixed' === $type ) ? floatval( $value ) : ( floatval( $regular ) * floatval( $value ) ) / 100;
639 $discount = floatval( $regular ) - $discount;
640
641 return ( $discount > 0 ) ? $discount : 0;
642 }
643
644 return $price;
645 }
646
647 /**
648 * Add extra js in editor mode.
649 *
650 * @since 1.1.0
651 * @return void
652 */
653 public function editor_mode_extra_js() {
654 ?>
655 <script>
656 jQuery( document ).on( 'mousemove', function() {
657 $( '.sellkit-coupon-toggle' ).off( 'click' ).on( 'click', function() {
658 let direction = 'row';
659 const status = $( '.sellkit-custom-coupon-form' ).css( 'display' );
660 let displayValue = '';
661
662 if ( $( window ).width() < 600 ) {
663 direction = 'column';
664 }
665
666 if ( 'none' === status ) {
667 displayValue = 'inline-flex';
668 } else {
669 displayValue = 'none';
670 }
671
672 $( '.sellkit-custom-coupon-form' ).css( {
673 display: displayValue,
674 flexDirection: direction,
675 } );
676 } );
677 } );
678 </script>
679 <?php
680 }
681
682 /**
683 * Assigning checkout ajax default shipping fields after ajax is sent.
684 *
685 * @param array $post post request.
686 * @param array $clear checkout form data.
687 * @return array
688 * @since 1.2.8
689 */
690 public function assigning_default_ajax_shipping_fields( $post, $clear ) {
691 if ( array_key_exists( 'billing_state', $clear ) ) {
692 $post['state'] = $clear['billing_state'];
693 }
694
695 if ( array_key_exists( 'shipping_country', $clear ) ) {
696 $post['s_country'] = $clear['shipping_country'];
697 }
698
699 if ( array_key_exists( 'shipping_state', $clear ) ) {
700 $post['s_state'] = $clear['shipping_state'];
701 }
702
703 if ( array_key_exists( 'shipping_postcode', $clear ) ) {
704 $post['s_postcode'] = $clear['shipping_postcode'];
705 }
706
707 if ( array_key_exists( 'shipping_city', $clear ) ) {
708 $post['s_city'] = $clear['shipping_city'];
709 }
710
711 if ( array_key_exists( 'shipping_address_1', $clear ) ) {
712 $post['s_address'] = $clear['shipping_address_1'];
713 }
714
715 if ( array_key_exists( 'shipping_address_2', $clear ) ) {
716 $post['s_address_2'] = $clear['shipping_address_2'];
717 }
718
719 return $post;
720 }
721
722 /**
723 * Check if product is in cart.
724 *
725 * @param int $product_id product id.
726 * @since 1.7.4
727 */
728 public function is_product_in_cart( $product_id ) {
729 // Get the WooCommerce cart.
730 $cart = WC()->cart;
731
732 foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
733 // Get the product ID for each cart item.
734 $item_product_id = $cart_item['product_id'];
735
736 // Check if the product ID matches the provided product ID.
737 if ( $item_product_id === $product_id ) {
738 return true;
739 }
740 }
741
742 return false;
743 }
744 }
745