PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.2.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.2.0
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 All 162 releases
cartflows / classes / class-cartflows-utils.php

class-cartflows-utils.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce 3.2.0, at classes/class-cartflows-utils.php

764 lines 16.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Utils.
4 *
5 * @package CARTFLOWS
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 /**
13 * Class Cartflows_Utils.
14 */
15 class Cartflows_Utils {
16
17 /**
18 * Member Variable
19 *
20 * @var instance
21 */
22 private static $instance;
23
24 /**
25 * Member Variable
26 *
27 * @var checkout_products
28 */
29 public $checkout_products = array();
30
31
32 /**
33 * Initiator
34 */
35 public static function get_instance() {
36 if ( ! isset( self::$instance ) ) {
37 self::$instance = new self();
38 }
39 return self::$instance;
40 }
41
42 /**
43 * Constructor
44 */
45 public function __construct() {
46 }
47
48 /**
49 * Get current post type
50 *
51 * @param string $post_type post type.
52 * @return string
53 */
54 public function current_post_type( $post_type = '' ) {
55
56 global $post;
57
58 if ( '' === $post_type && is_object( $post ) ) {
59 $post_type = $post->post_type;
60 }
61
62 return $post_type;
63 }
64
65 /**
66 * Check if post type is of step.
67 *
68 * @param string $post_type post type.
69 * @return bool
70 */
71 public function is_step_post_type( $post_type = '' ) {
72
73 if ( $this->get_step_post_type() === $this->current_post_type( $post_type ) ) {
74
75 return true;
76 }
77
78 return false;
79 }
80
81 /**
82 * Check if post type is of flow.
83 *
84 * @param string $post_type post type.
85 * @return bool
86 */
87 public function is_flow_post_type( $post_type = '' ) {
88
89 if ( $this->get_flow_post_type() === $this->current_post_type( $post_type ) ) {
90
91 return true;
92 }
93
94 return false;
95 }
96
97 /**
98 * Get post type of step.
99 *
100 * @return string
101 */
102 public function get_step_post_type() {
103
104 return CARTFLOWS_STEP_POST_TYPE;
105 }
106
107 /**
108 * Get post type of flow.
109 *
110 * @return string
111 */
112 public function get_flow_post_type() {
113
114 return CARTFLOWS_FLOW_POST_TYPE;
115 }
116
117 /**
118 * Get flow id
119 *
120 * @return int
121 */
122 public function get_flow_id() {
123
124 global $post;
125
126 $post_meta = false;
127
128 if ( $post ) {
129 $post_meta = get_post_meta( $post->ID, 'wcf-flow-id', true );
130 }
131
132 return $post_meta;
133 }
134
135 /**
136 * Get flow id by step
137 *
138 * @param int $step_id step ID.
139 * @return int
140 */
141 public function get_flow_id_from_step_id( $step_id ) {
142
143 return get_post_meta( $step_id, 'wcf-flow-id', true );
144 }
145
146 /**
147 * Get flow steps by id
148 *
149 * @param int $flow_id flow ID.
150 * @return int
151 */
152 public function get_flow_steps( $flow_id ) {
153
154 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
155
156 if ( is_array( $steps ) && ! empty( $steps ) ) {
157 return $steps;
158 }
159
160 return false;
161 }
162
163 /**
164 * Get template type of step
165 *
166 * @param int $step_id step ID.
167 * @return int
168 */
169 public function get_step_type( $step_id ) {
170
171 return get_post_meta( $step_id, 'wcf-step-type', true );
172 }
173
174 /**
175 * Get next id for step
176 *
177 * @param int $flow_id flow ID.
178 * @param int $step_id step ID.
179 * @return bool
180 */
181 public function get_next_step_id( $flow_id, $step_id ) {
182
183 $wcf_step_obj = wcf_get_step( $step_id );
184 $next_step_id = $wcf_step_obj->get_direct_next_step_id();
185
186 return $next_step_id;
187 }
188
189 /**
190 * Get next id for step
191 *
192 * @param object $order order object.
193 * @return int
194 */
195 public function get_flow_id_from_order( $order ) {
196
197 if ( ! is_object( $order ) ) {
198 $order = wc_get_order( $order );
199 }
200
201 $flow_id = is_object( $order ) ? $order->get_meta( '_wcf_flow_id' ) : 0;
202
203 return intval( $flow_id );
204 }
205
206 /**
207 * Get checkout id for order
208 *
209 * @param object $order order object.
210 * @return int
211 */
212 public function get_checkout_id_from_order( $order ) {
213
214 if ( ! is_object( $order ) ) {
215 $order = wc_get_order( $order );
216 }
217
218 $checkout_id = is_object( $order ) ? $order->get_meta( '_wcf_checkout_id' ) : 0;
219
220 return intval( $checkout_id );
221 }
222
223 /**
224 * We are using this function mostly in ajax on checkout page
225 *
226 * @return mixed
227 */
228 public function get_checkout_id_from_post_data() {
229
230 $checkout_id = false;
231
232 //phpcs:disable WordPress.Security.NonceVerification
233
234 if ( isset( $_POST['_wcf_checkout_id'] ) ) {
235
236 $checkout_id = intval( $_POST['_wcf_checkout_id'] );
237
238 } elseif ( isset( $_GET['wcf_checkout_id'] ) ) {
239
240 $checkout_id = intval( $_GET['wcf_checkout_id'] );
241
242 }
243 //phpcs:enable WordPress.Security.NonceVerification
244
245 return $checkout_id;
246 }
247
248 /**
249 * We are using this function mostly in ajax on checkout page
250 *
251 * @return bool
252 */
253 public function get_flow_id_from_post_data() {
254
255 $flow_id = false;
256
257 //phpcs:disable WordPress.Security.NonceVerification
258
259 if ( isset( $_POST['_wcf_flow_id'] ) ) {
260
261 $flow_id = intval( $_POST['_wcf_flow_id'] );
262
263 } elseif ( isset( $_GET['wcf_checkout_id'] ) ) {
264
265 $flow_id = wcf()->utils->get_flow_id_from_step_id( intval( $_GET['wcf_checkout_id'] ) );
266
267 }
268
269 //phpcs:enable WordPress.Security.NonceVerification
270
271 return $flow_id;
272 }
273
274 /**
275 * Get optin id for order
276 *
277 * @param object $order order object.
278 * @return int
279 */
280 public function get_optin_id_from_order( $order ) {
281
282 if ( ! is_object( $order ) ) {
283 $order = wc_get_order( $order );
284 }
285
286 $optin_id = $order ? $order->get_meta( '_wcf_optin_id' ) : 0;
287
288 return intval( $optin_id );
289 }
290
291 /**
292 * We are using this function mostly in ajax on checkout page
293 *
294 * @return bool
295 */
296 public function get_optin_id_from_post_data() {
297
298 if ( isset( $_POST['_wcf_optin_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
299
300 $optin_id = intval( $_POST['_wcf_optin_id'] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing
301
302 return $optin_id;
303 }
304
305 return false;
306 }
307
308
309 /**
310 * Check for checkout page
311 *
312 * @param int $step_id step ID.
313 * @return bool
314 */
315 public function check_is_checkout_page( $step_id ) {
316
317 $step_type = $this->get_step_type( $step_id );
318
319 if ( 'checkout' === $step_type ) {
320
321 return true;
322 }
323
324 return false;
325 }
326
327 /**
328 * Check for thank you page
329 *
330 * @param int $step_id step ID.
331 * @return bool
332 */
333 public function check_is_thankyou_page( $step_id ) {
334
335 $step_type = $this->get_step_type( $step_id );
336
337 if ( 'thankyou' === $step_type ) {
338
339 return true;
340 }
341
342 return false;
343 }
344
345 /**
346 * Check for offer page
347 *
348 * @param int $step_id step ID.
349 * @return bool
350 */
351 public function check_is_offer_page( $step_id ) {
352
353 $step_type = $this->get_step_type( $step_id );
354
355 if ( 'upsell' === $step_type || 'downsell' === $step_type ) {
356
357 return true;
358 }
359
360 return false;
361 }
362
363 /**
364 * Check if a step is disabled.
365 *
366 * @since 2.1.20
367 * @param int $step_id step ID.
368 * @return bool
369 */
370 public function is_step_disabled( $step_id ) {
371
372 if ( empty( $step_id ) ) {
373 return false;
374 }
375
376 $is_disabled = get_post_meta( $step_id, 'wcf-disable-step', true );
377
378 // Step is enabled by default, so if disabled step meta is set to 'yes', the step is disabled.
379 return ( 'yes' === $is_disabled );
380 }
381
382 /**
383 * Check if loaded page requires woo.
384 *
385 * @return bool
386 */
387 public function check_is_woo_required_page() {
388
389 global $post;
390 $step_id = $post->ID;
391 $woo_not_required_type = array( 'landing' );
392 $step_type = $this->get_step_type( $step_id );
393 return ( ! in_array( $step_type, $woo_not_required_type, true ) );
394 }
395
396 /**
397 * Define constant for cache
398 *
399 * @return void
400 */
401 public function do_not_cache() {
402
403 global $post;
404
405 if ( ! apply_filters( 'cartflows_do_not_cache_step', true, $post->ID ) ) {
406 return;
407 }
408
409 $this->get_cache_headers();
410 }
411
412 /**
413 * Function to get/set the do not cache page constants.
414 *
415 * @return void
416 */
417 public function get_cache_headers() {
418
419 wcf_maybe_define_constant( 'DONOTCACHEPAGE', true );
420 wcf_maybe_define_constant( 'DONOTCACHEOBJECT', true );
421 wcf_maybe_define_constant( 'DONOTCACHEDB', true );
422
423 nocache_headers();
424 }
425
426 /**
427 * Get linking url
428 *
429 * @param array $args query args.
430 * @return string
431 */
432 public function get_linking_url( $args = array() ) {
433
434 $url = get_home_url();
435
436 $url = add_query_arg( $args, $url );
437
438 return $url;
439 }
440
441 /**
442 * Get assets urls
443 *
444 * @return array
445 * @since 1.1.6
446 */
447 public function get_assets_path() {
448
449 $rtl = '';
450
451 if ( is_rtl() ) {
452 $rtl = '-rtl';
453 }
454
455 $file_prefix = '';
456 $dir_name = '';
457
458 $is_min = apply_filters( 'cartflows_load_min_assets', false );
459
460 if ( $is_min ) {
461 $file_prefix = '.min';
462 $dir_name = 'min-';
463 }
464
465 $js_gen_path = CARTFLOWS_URL . 'assets/' . $dir_name . 'js/';
466 $css_gen_path = CARTFLOWS_URL . 'assets/' . $dir_name . 'css/';
467
468 return array(
469 'css' => $css_gen_path,
470 'js' => $js_gen_path,
471 'file_prefix' => $file_prefix,
472 'rtl' => $rtl,
473 );
474 }
475
476 /**
477 * Get assets css url
478 *
479 * @param string $file file name.
480 * @return string
481 * @since 1.1.6
482 */
483 public function get_css_url( $file ) {
484
485 $assets_vars = wcf()->assets_vars;
486
487 $url = $assets_vars['css'] . $file . $assets_vars['rtl'] . $assets_vars['file_prefix'] . '.css';
488
489 return $url;
490 }
491
492 /**
493 * Get assets js url
494 *
495 * @param string $file file name.
496 * @return string
497 * @since 1.1.6
498 */
499 public function get_js_url( $file ) {
500
501 $assets_vars = wcf()->assets_vars;
502
503 $url = $assets_vars['js'] . $file . $assets_vars['file_prefix'] . '.js';
504
505 return $url;
506 }
507
508 /**
509 * Get unique id.
510 *
511 * @param int $length Length.
512 *
513 * @return string|false
514 */
515 public function get_unique_id( $length = 8 ) {
516
517 return substr( wp_generate_password( $length * 2, false ), 0, $length );
518 }
519
520 /**
521 * Get selected checkout products and data
522 *
523 * @param int $checkout_id Checkout id..
524 * @param array $saved_products Saved product.
525 *
526 * @return array
527 */
528 public function get_selected_checkout_products( $checkout_id = '', $saved_products = array() ) {
529
530 if ( empty( $checkout_id ) ) {
531
532 global $post;
533
534 $checkout_id = $post->ID;
535 }
536
537 if ( ! isset( $this->checkout_products[ $checkout_id ] ) ) {
538
539 if ( ! empty( $saved_products ) ) {
540
541 $products = $saved_products;
542 } else {
543
544 $products = wcf()->options->get_checkout_meta_value( $checkout_id, 'wcf-checkout-products' );
545 }
546
547 $default_add_to_cart = true;
548
549 if ( is_array( $products ) ) {
550
551 foreach ( $products as $in => $data ) {
552
553 $default_data = array(
554 'quantity' => 1,
555 'discount_type' => '',
556 'discount_value' => '',
557 'unique_id' => $this->get_unique_id(),
558 'add_to_cart' => $default_add_to_cart,
559 );
560
561 $products[ $in ] = wp_parse_args( $products[ $in ], $default_data );
562 }
563 }
564
565 $products = apply_filters( 'cartflows_selected_checkout_products', $products, $checkout_id );
566
567 // This is frontend. Ignoring nonce rule.
568 if ( isset( $_GET['wcf-default'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
569 $products = $this->update_the_add_to_cart_param( $products );
570 }
571
572 $this->checkout_products[ $checkout_id ] = $products;
573 }
574
575 return $this->checkout_products[ $checkout_id ];
576 }
577
578 /**
579 * Update product add to cart option.
580 *
581 * @param array $products product data.
582 */
583 public function update_the_add_to_cart_param( $products ) {
584
585 $default_sequence = isset( $_GET['wcf-default'] ) ? sanitize_text_field( wp_unslash( $_GET['wcf-default'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
586 $default_ids = array_map( 'intval', explode( ',', $default_sequence ) );
587
588 if ( is_array( $products ) ) {
589
590 foreach ( $products as $in => $data ) {
591
592 $default_add_to_cart = 'no';
593 $sequence = $in + 1;
594
595 if ( in_array( $sequence, $default_ids, true ) ) {
596 $default_add_to_cart = 'yes';
597
598 }
599
600 $products[ $in ]['add_to_cart'] = $default_add_to_cart;
601 }
602 }
603
604 return $products;
605 }
606
607 /**
608 * Get selected checkout products and data
609 *
610 * @param int $checkout_id Checkout id..
611 * @param array $products_data Saved product.
612 *
613 * @return array
614 */
615 public function set_selcted_checkout_products( $checkout_id = '', $products_data = array() ) {
616
617 if ( empty( $checkout_id ) ) {
618
619 global $post;
620
621 $checkout_id = $post->ID;
622 }
623
624 if ( isset( $this->checkout_products[ $checkout_id ] ) ) {
625
626 $products = $this->checkout_products[ $checkout_id ];
627 } else {
628 $products = $this->get_selected_checkout_products( $checkout_id );
629 }
630
631 if ( is_array( $products ) && ! empty( $products_data ) ) {
632
633 foreach ( $products as $in => $data ) {
634
635 if ( isset( $products_data[ $in ] ) ) {
636 $products[ $in ] = wp_parse_args( $products_data[ $in ], $products[ $in ] );
637 }
638 }
639 }
640
641 $this->checkout_products[ $checkout_id ] = $products;
642
643 return $this->checkout_products[ $checkout_id ];
644 }
645
646 /**
647 * Clear Installed Page Builder Cache
648 */
649 public function clear_cache() {
650
651 // Clear 'Elementor' file cache.
652 if ( class_exists( '\Elementor\Plugin' ) ) {
653 Elementor\Plugin::$instance->files_manager->clear_cache();
654 }
655 }
656
657 /**
658 * Append the query strings present in the URL to pass it to the next step URL.
659 * This will carry-forward the passed query strings to the next step URL.
660 *
661 * @param array $original_query_strings Default query strings of CartFlows.
662 * @return array $original_query_strings Modified query strings.
663 */
664 public function may_be_append_query_string( $original_query_strings ) {
665
666 // Return if the feature is not enabled. Default is disabled.
667 if ( ! apply_filters( 'cartflows_enable_append_query_string', false ) ) {
668 return $original_query_strings;
669 }
670
671 // Check if HTTP_REFERER is set and fetch its query strings.
672 if ( empty( $_SERVER['HTTP_REFERER'] ) ) {
673 return $original_query_strings;
674 }
675
676 // Get the current page URL and parse it to explode the URL in different URL components.
677 $url_params_components = wp_parse_url( esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) );
678
679 // Process only if the URL components is not empty and query i:e query strings are not empty.
680 if ( is_array( $url_params_components ) && ! empty( $url_params_components['query'] ) ) {
681
682 $forwarded_params = $url_params_components['query'];
683
684 // Convert the string query from string to array format.
685 parse_str( $forwarded_params, $parsed_query_string );
686
687 // Remove the already present wcf-key and wcf-order params from the URl and append the rest of.
688 if ( $parsed_query_string['wcf-key'] && $parsed_query_string['wcf-order'] ) {
689 unset( $parsed_query_string['wcf-key'] );
690 unset( $parsed_query_string['wcf-order'] );
691 }
692
693 // Merge the new and already existing query strings.
694 $original_query_strings = array_merge( $original_query_strings, $parsed_query_string );
695 }
696
697 // Return the query strings.
698 return apply_filters( 'cartflows_may_be_append_query_strings_args', $original_query_strings );
699 }
700
701 /**
702 * Checks if the WooCommerce cart is empty.
703 *
704 * This function checks if the WooCommerce cart is empty and if the session has not expired.
705 * It returns true if the cart is empty and the session is valid, otherwise it returns false.
706 *
707 * @return bool True if the cart is empty and the session is valid, otherwise false.
708 */
709 public function is_woo_cart_empty() {
710
711 $wc = function_exists( 'WC' ) ? WC() : null;
712 $cart = ( $wc && $wc->cart instanceof WC_Cart ) ? $wc->cart : null;
713 $cart_is_empty = ! $cart || $cart->is_empty();
714
715 return $cart_is_empty
716 && ! is_customize_preview()
717 && apply_filters( 'woocommerce_checkout_update_order_review_expired', true );
718 }
719
720 /**
721 * Checks if WooCommerce HPOS (High-Performance Order Storage) is enabled.
722 *
723 * @since 2.2.2
724 *
725 * @return bool True if HPOS is enabled, false otherwise.
726 */
727 public function is_hpos_enabled() {
728
729 if (
730 class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' )
731 && method_exists( '\Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled' )
732 ) {
733 return \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
734 }
735 return false;
736 }
737 }
738
739 /**
740 * Get a specific property of an array without needing to check if that property exists.
741 *
742 * Provide a default value if you want to return a specific value if the property is not set.
743 *
744 * @param array $array Array from which the property's value should be retrieved.
745 * @param string $prop Name of the property to be retrieved.
746 * @param string $default Optional. Value that should be returned if the property is not set or empty. Defaults to null.
747 *
748 * @return null|string|mixed The value
749 */
750 function wcf_get_prop( $array, $prop, $default = null ) { // phpcs:ignore Universal.Files.SeparateFunctionsFromOO.Mixed
751
752 if ( ! is_array( $array ) && ! ( is_object( $array ) && $array instanceof ArrayAccess ) ) {
753 return $default;
754 }
755
756 if ( isset( $array[ $prop ] ) ) {
757 $value = $array[ $prop ];
758 } else {
759 $value = '';
760 }
761
762 return empty( $value ) && null !== $default ? $default : $value;
763 }
764