PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.1.2
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.1.2
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-frontend.php

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

949 lines 25.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CartFlows Frontend.
4 *
5 * @package CartFlows
6 */
7
8 // Exit if accessed directly.
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12 /**
13 * Class Cartflows_Frontend.
14 */
15 class Cartflows_Frontend {
16
17 /**
18 * Member Variable
19 *
20 * @var instance
21 */
22 private static $instance;
23
24 /**
25 * Initiator
26 */
27 public static function get_instance() {
28 if ( ! isset( self::$instance ) ) {
29 self::$instance = new self();
30 }
31 return self::$instance;
32 }
33
34 /**
35 * Constructor
36 */
37 public function __construct() {
38
39 /* Set / Destroy Flow Sessions. Set data */
40 add_action( 'wp', array( $this, 'init_actions' ), 1 );
41
42 add_action( 'init', array( $this, 'debug_data_setting_actions' ) );
43 add_action( 'init', array( $this, 'setup_optin_checkout_filter' ) );
44 /* Enqueue global required scripts */
45 add_action( 'wp', array( $this, 'wp_actions' ), 55 );
46
47 /* Modify the checkout order received url to go thank you page in our flow */
48 add_filter( 'woocommerce_get_checkout_order_received_url', array( $this, 'redirect_to_thankyou_page' ), 10, 2 );
49 }
50
51 /**
52 * Redirect to thank page if upsell not exists
53 *
54 * @param string $order_receive_url url.
55 * @param object $order order object.
56 * @return string $order_receive_url next step URL.
57 * @since 1.0.0
58 */
59 public function redirect_to_thankyou_page( $order_receive_url, $order ) {
60
61 /* Only for thank you page */
62 wcf()->logger->log( 'Start-' . __CLASS__ . '::' . __FUNCTION__ );
63 wcf()->logger->log( 'Only for thank you page' );
64
65 if ( wcf()->flow->is_thankyou_page_exists( $order ) ) {
66
67 if ( _is_wcf_doing_checkout_ajax() ) {
68
69 $checkout_id = wcf()->utils->get_checkout_id_from_post_data();
70
71 if ( ! $checkout_id ) {
72 $checkout_id = wcf()->utils->get_checkout_id_from_order( $order );
73 }
74 } else {
75 $checkout_id = wcf()->utils->get_checkout_id_from_order( $order );
76 }
77
78 wcf()->logger->log( 'Checkout ID : ' . $checkout_id );
79
80 if ( $checkout_id ) {
81
82 $thankyou_step_id = wcf()->flow->get_thankyou_page_id( $order );
83 $thankyou_step_id = apply_filters( 'cartflows_checkout_next_step_id', $thankyou_step_id, $order, $checkout_id );
84
85 if ( $thankyou_step_id ) {
86
87 $query_param = wcf()->utils->may_be_append_query_string(
88 // Default query string args.
89 array(
90 'wcf-key' => $order->get_order_key(),
91 'wcf-order' => $order->get_id(),
92 )
93 );
94
95 $order_receive_url = add_query_arg(
96 $query_param,
97 get_permalink( $thankyou_step_id )
98 );
99
100 }
101 }
102 }
103
104 wcf()->logger->log( 'End-' . __CLASS__ . '::' . __FUNCTION__ );
105
106 return $order_receive_url;
107 }
108
109 /**
110 * Cancel and redirect to checkout
111 *
112 * @param string $return_url url.
113 * @since 1.0.0
114 */
115 public function redirect_to_checkout_on_cancel( $return_url ) {
116
117 if ( _is_wcf_doing_checkout_ajax() ) {
118
119 $checkout_id = wcf()->utils->get_checkout_id_from_post_data();
120
121 if ( ! $checkout_id ) {
122 $checkout_id = wcf()->utils->get_checkout_id_from_order( $order );
123 }
124 } else {
125 $checkout_id = wcf()->utils->get_checkout_id_from_order( $order );
126 }
127
128 if ( $checkout_id ) {
129
130 $return_url = add_query_arg(
131 array(
132 'cancel_order' => 'true',
133 '_wpnonce' => wp_create_nonce( 'woocommerce-cancel_order' ),
134 ),
135 get_permalink( $checkout_id )
136 );
137 }
138
139 return $return_url;
140 }
141
142
143 /**
144 * Remove theme styles.
145 *
146 * @since 1.0.0
147 */
148 public function remove_theme_styles() {
149
150 if ( Cartflows_Compatibility::get_instance()->is_compatibility_theme_enabled() ) {
151 return;
152 }
153
154 $page_template = Cartflows_Helper::get_current_page_template();
155
156 if ( ! _wcf_supported_template( $page_template ) ) {
157 return;
158 }
159
160 // get all styles data.
161 global $wp_styles;
162 global $wp_scripts;
163
164 $get_stylesheet = 'themes/' . get_stylesheet() . '/';
165 $get_template = 'themes/' . get_template() . '/';
166
167 $remove_styles = apply_filters( 'cartflows_remove_theme_styles', true );
168
169 if ( $remove_styles ) {
170
171 // loop over all of the registered scripts..
172 foreach ( $wp_styles->registered as $handle => $data ) {
173
174 if ( ! empty( $data->src ) && ( strpos( $data->src, $get_template ) !== false || strpos( $data->src, $get_stylesheet ) !== false ) ) {
175
176 // remove it.
177 wp_deregister_style( $handle );
178 wp_dequeue_style( $handle );
179 }
180 }
181 }
182
183 $remove_scripts = apply_filters( 'cartflows_remove_theme_scripts', true );
184
185 if ( $remove_scripts ) {
186
187 // loop over all of the registered scripts.
188 foreach ( $wp_scripts->registered as $handle => $data ) {
189
190 if ( ! empty( $data->src ) && ( strpos( $data->src, $get_template ) !== false || strpos( $data->src, $get_stylesheet ) !== false ) ) {
191
192 // remove it.
193 wp_deregister_script( $handle );
194 wp_dequeue_script( $handle );
195 }
196 }
197 }
198 }
199
200 /**
201 * Update main order data in transient.
202 *
203 * @param array $woo_styles new styles array.
204 * @since 1.0.0
205 * @return array.
206 */
207 public function woo_default_css( $woo_styles ) {
208
209 $woo_styles = array(
210 'woocommerce-layout' => array(
211 'src' => plugins_url( 'assets/css/woocommerce-layout.css', WC_PLUGIN_FILE ),
212 'deps' => '',
213 'version' => WC_VERSION,
214 'media' => 'all',
215 'has_rtl' => true,
216 ),
217 'woocommerce-smallscreen' => array(
218 'src' => plugins_url( 'assets/css/woocommerce-smallscreen.css', WC_PLUGIN_FILE ),
219 'deps' => 'woocommerce-layout',
220 'version' => WC_VERSION,
221 'media' => 'only screen and (max-width: ' . apply_filters( 'woocommerce_style_smallscreen_breakpoint', '768px' ) . ')',
222 'has_rtl' => true,
223 ),
224 'woocommerce-general' => array(
225 'src' => plugins_url( 'assets/css/woocommerce.css', WC_PLUGIN_FILE ),
226 'deps' => '',
227 'version' => WC_VERSION,
228 'media' => 'all',
229 'has_rtl' => true,
230 ),
231 );
232
233 return $woo_styles;
234 }
235
236 /**
237 * Init Actions.
238 *
239 * @since 1.0.0
240 */
241 public function init_actions() {
242
243 if ( wcf()->utils->is_step_post_type() ) {
244
245 global $post;
246
247 $GLOBALS['wcf_step'] = wcf_get_step( $post->ID );
248
249 do_action( 'cartflows_wp', $post->ID );
250
251 $this->set_flow_session();
252
253 $this->delete_checkout_cookies();
254 }
255 }
256
257 /**
258 * Set flow session.
259 *
260 * @since 1.0.0
261 */
262 public function set_flow_session() {
263
264 global $wp;
265
266 add_action( 'wp_head', array( $this, 'noindex_flow' ) );
267
268 wcf()->utils->do_not_cache();
269
270 if ( _is_wcf_thankyou_type() ) {
271 /*
272 Set key to support pixel
273 */
274 //phpcs:disable WordPress.Security.NonceVerification
275 if ( isset( $_GET['wcf-key'] ) ) {
276
277 $wcf_key = sanitize_text_field( wp_unslash( $_GET['wcf-key'] ) );
278
279 $_GET['key'] = $wcf_key;
280 $_REQUEST['key'] = $wcf_key;
281 }
282
283 if ( isset( $_GET['wcf-order'] ) ) {
284 $wcf_order = intval( wp_unslash( $_GET['wcf-order'] ) );
285 //phpcs:enable WordPress.Security.NonceVerification
286
287 $_GET['order'] = $wcf_order;
288 $_REQUEST['order'] = $wcf_order;
289 $_GET['order-received'] = $wcf_order;
290 $_REQUEST['order-received'] = $wcf_order;
291
292 $wp->set_query_var( 'order-received', $wcf_order );
293 }
294 }
295 }
296
297 /**
298 * Delete checkout cookies.
299 *
300 * @since 1.0.0
301 */
302 public function delete_checkout_cookies() {
303
304 if ( _is_wcf_thankyou_type() ) {
305
306 if ( ! wcf()->is_woo_active || ! isset( WC()->session ) ) {
307 return;
308 }
309
310 $user_key = WC()->session->get_customer_id();
311
312 if ( isset( $_COOKIE[ CARTFLOWS_ACTIVE_CHECKOUT ] ) ) {
313 delete_transient( 'wcf_user_' . $user_key . '_checkout_' . sanitize_text_field( wp_unslash( $_COOKIE[ CARTFLOWS_ACTIVE_CHECKOUT ] ) ) ); //phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE
314 unset( $_COOKIE[ CARTFLOWS_ACTIVE_CHECKOUT ] ); //phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE
315 setcookie( CARTFLOWS_ACTIVE_CHECKOUT, '', time() - 3600, '/', COOKIE_DOMAIN, CARTFLOWS_HTTPS, true ); //phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.cookies_setcookie
316 }
317 }
318 }
319
320 /**
321 * Add noindex, nofollow.
322 *
323 * @since 1.0.0
324 */
325 public function noindex_flow() {
326
327 $common = Cartflows_Helper::get_common_settings();
328
329 global $post;
330
331 $flow_id = wcf()->utils->get_flow_id_from_step_id( $post->ID );
332 $flow_indexing = get_post_meta( $flow_id, 'wcf-flow-indexing', true );
333
334 $allow_indexing = ( ( '' === $flow_indexing && 'enable' === $common['disallow_indexing'] ) || 'disallow' === $flow_indexing );
335
336 if ( apply_filters( 'cartflows_step_add_noindex_meta', $allow_indexing, $flow_id ) ) {
337 echo '<meta name="robots" content="noindex,nofollow">';
338 }
339 }
340
341 /**
342 * WP Actions.
343 *
344 * @since 1.0.0
345 */
346 public function wp_actions() {
347
348 if ( wcf()->utils->is_step_post_type() ) {
349
350 if ( ! wcf()->is_woo_active && wcf()->utils->check_is_woo_required_page() ) {
351 wp_die( ' This page requires WooCommerce plugin installed and activated!', 'WooCommerce Required' );
352 }
353
354 /* CSS Compatibility for All theme */
355 add_filter( 'woocommerce_enqueue_styles', array( $this, 'woo_default_css' ), 9999 );
356
357 add_action( 'wp_enqueue_scripts', array( $this, 'remove_theme_styles' ), 9999 );
358 add_action( 'wp_enqueue_scripts', array( $this, 'global_flow_scripts' ), 20 );
359
360 /* Load woo templates from plugin */
361 add_filter( 'woocommerce_locate_template', array( $this, 'override_woo_template' ), 20, 3 );
362
363 /* Add version class to body in frontend. */
364 add_filter( 'body_class', array( $this, 'add_cartflows_lite_version_to_body' ) );
365
366 /* Custom Script Option */
367 add_action( 'wp_head', array( $this, 'custom_script_option' ) );
368
369 /* Remove the action applied by the Flatsome theme */
370 if ( Cartflows_Compatibility::get_instance()->is_flatsome_enabled() ) {
371 $this->remove_flatsome_action();
372 }
373 }
374 }
375
376 /**
377 * Debug Data Setting Actions.
378 *
379 * @since 1.1.14
380 */
381 public function debug_data_setting_actions() {
382
383 add_filter( 'cartflows_load_min_assets', array( $this, 'allow_load_minify' ) );
384 }
385
386 /**
387 * Get/Set the allow minify option.
388 *
389 * @since 1.1.14
390 */
391 public function allow_load_minify() {
392 $debug_data = Cartflows_Helper::get_debug_settings();
393 $allow_minified = $debug_data['allow_minified_files'];
394 $allow_minify = false;
395
396 if ( 'enable' === $allow_minified ) {
397 $allow_minify = true;
398 }
399
400 return $allow_minify;
401 }
402
403 /**
404 * Global flow scripts.
405 *
406 * @since 1.0.0
407 */
408 public function global_flow_scripts() {
409
410 global $post, $wcf_step;
411
412 $flow = $wcf_step->get_flow_id();
413 $current_step = $wcf_step->get_current_step();
414 $control_step = $wcf_step->get_control_step();
415 $next_step_link = '';
416 $compatibility = Cartflows_Compatibility::get_instance();
417 $is_checkout = _is_wcf_checkout_type();
418 $is_optin = _is_wcf_optin_type();
419
420 if ( _is_wcf_landing_type() ) {
421
422 $next_step_id = $wcf_step->get_direct_next_step_id();
423 $next_step_link = get_permalink( $next_step_id );
424 }
425
426 $page_template = get_post_meta( $current_step, '_wp_page_template', true );
427
428 $fb_tracking_settings = Cartflows_Helper::get_facebook_settings();
429 $ga_tracking_settings = Cartflows_Helper::get_google_analytics_settings();
430 $tik_pixel_settings = Cartflows_Helper::get_tiktok_settings();
431 $pinterest_settings = Cartflows_Helper::get_pinterest_settings();
432 $gads_settings = Cartflows_Helper::get_google_ads_settings();
433 $snapchat_settings = Cartflows_Helper::get_snapchat_settings();
434
435 $localize = array(
436 'ajax_url' => admin_url( 'admin-ajax.php', 'relative' ),
437 'is_pb_preview' => $compatibility->is_page_builder_preview(),
438 'current_theme' => $compatibility->get_current_theme(),
439 'current_flow' => $flow,
440 'current_step' => $current_step,
441 'control_step' => $control_step,
442 'next_step' => $next_step_link,
443 'page_template' => $page_template,
444 'default_page_builder' => \Cartflows_Helper::get_common_setting( 'default_page_builder' ),
445 'is_checkout_page' => $is_checkout,
446 'fb_setting' => $fb_tracking_settings,
447 'ga_setting' => $ga_tracking_settings,
448 'tik_setting' => $tik_pixel_settings,
449 'pin_settings' => $pinterest_settings,
450 'gads_setting' => $gads_settings,
451 'snap_settings' => $snapchat_settings,
452 'active_checkout_cookie' => CARTFLOWS_ACTIVE_CHECKOUT,
453 'is_optin' => $is_optin,
454 );
455
456 if ( $is_checkout ) {
457 $localize['ajax_url'] = add_query_arg(
458 array(
459 'wcf_checkout_id' => $current_step,
460 ),
461 $localize['ajax_url']
462 );
463 }
464
465 $localize = apply_filters( 'global_cartflows_js_localize', $localize );
466
467 $localize_script = '<!-- script to print the admin localized variables -->';
468 $localize_script .= '<script type="text/javascript">';
469 $localize_script .= 'var cartflows = ' . wp_json_encode( $localize ) . ';';
470 $localize_script .= '</script>';
471
472 echo $localize_script; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
473
474 if ( _wcf_supported_template( $page_template ) ) {
475 $page_builder = Cartflows_Helper::get_common_setting( 'default_page_builder' );
476 if ( ! ( 'bricks-builder' === $page_builder && function_exists( 'bricks_is_builder' ) && bricks_is_builder() ) ) {
477 wp_enqueue_style( 'wcf-normalize-frontend-global', wcf()->utils->get_css_url( 'cartflows-normalize' ), array(), CARTFLOWS_VER );
478 }
479 }
480
481 if ( ! wcf()->is_woo_active ) {
482 wp_register_script(
483 'jquery-cookie',
484 CARTFLOWS_URL . 'assets/js/lib/jquery-cookie/jquery.cookie.min.js',
485 array( 'jquery' ),
486 CARTFLOWS_VER,
487 false
488 );
489 }
490
491 wp_enqueue_style( 'wcf-frontend-global', wcf()->utils->get_css_url( 'frontend' ), array(), CARTFLOWS_VER );
492
493 wp_enqueue_script(
494 'wcf-frontend-global',
495 wcf()->utils->get_js_url( 'frontend' ),
496 array( 'jquery', 'jquery-cookie' ),
497 CARTFLOWS_VER,
498 false
499 );
500 }
501
502 /**
503 * Custom Script in head.
504 *
505 * @since 1.0.0
506 */
507 public function custom_script_option() {
508
509 // Check if migration to separate JS/CSS fields is completed.
510 $migration_completed = 'completed' === Cartflows_Helper::get_script_migration_status();
511
512 $global_css = trim( $this->get_global_custom_css() );
513 $global_js = trim( $this->get_global_custom_js() );
514 $flow_css = '';
515 $flow_js = '';
516 $step_css = '';
517 $step_js = '';
518
519 // Old combined script values (used only if migration not completed).
520 $script = '';
521 $flow_script = '';
522
523 if ( $migration_completed ) {
524 // Migration completed: load from new separate JS and CSS meta keys.
525 $flow_css = trim( $this->get_flow_custom_css() );
526 $flow_js = trim( $this->get_flow_custom_js() );
527 $step_css = trim( $this->get_step_custom_css() );
528 $step_js = trim( $this->get_step_custom_js() );
529 } else {
530 // Migration not completed: load from old combined script meta keys.
531 $script = $this->get_custom_script();
532 $flow_script = $this->get_flow_custom_script();
533 }
534
535 // -------------------------
536 // CSS Output (Global → Flow → Step)
537 // Step CSS takes priority due to later output.
538 // -------------------------
539 if ( '' !== $global_css || '' !== $flow_css || '' !== $step_css ) {
540 echo '<!-- CartFlows Custom CSS -->';
541 echo '<style>';
542
543 if ( '' !== $global_css ) {
544 // Global CSS is already pure CSS from settings.
545 echo html_entity_decode( $global_css ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
546 }
547
548 if ( '' !== $flow_css ) {
549 // New format: pure CSS. Old format: strip style tags.
550 $flow_css_output = $migration_completed ? $flow_css : $this->strip_script_style_tags( $flow_css );
551 echo html_entity_decode( $flow_css_output ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
552 }
553
554 if ( '' !== $step_css ) {
555 // New format: pure CSS. Old format: strip style tags.
556 $step_css_output = $migration_completed ? $step_css : $this->strip_script_style_tags( $step_css );
557 echo html_entity_decode( $step_css_output ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
558 }
559
560 echo '</style>';
561 echo '<!-- End CartFlows Custom CSS -->';
562 echo PHP_EOL;
563 }
564
565 // -------------------------
566 // JS Output (Global → Flow → Step)
567 // Step JS takes priority due to later execution.
568 // -------------------------
569 echo '<!-- CartFlows Custom JS -->';
570 echo '<script>';
571
572 // Global JS.
573 if ( '' !== $global_js ) {
574 echo str_replace( '</script>', '<\/script>', html_entity_decode( $global_js ) ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
575 }
576
577 // Flow JS (new or old format).
578 if ( $migration_completed && '' !== $flow_js ) {
579 // New format: already pure JS, just escape closing tags.
580 echo str_replace( '</script>', '<\/script>', html_entity_decode( $flow_js ) ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
581 } elseif ( ! $migration_completed && '' !== $flow_script ) {
582 // Old format: strip any existing script/style tags and output raw JS.
583 $flow_script_output = $this->strip_script_style_tags( $flow_script );
584 echo str_replace( '</script>', '<\/script>', html_entity_decode( $flow_script_output ) ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
585 }
586
587 // Step JS (new or old format).
588 if ( $migration_completed && '' !== $step_js ) {
589 // New format: already pure JS, just escape closing tags.
590 echo str_replace( '</script>', '<\/script>', html_entity_decode( $step_js ) ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
591 } elseif ( ! $migration_completed && '' !== $script ) {
592 // Old format: strip any existing script/style tags and output raw JS.
593 $step_script_output = $this->strip_script_style_tags( $script );
594 echo str_replace( '</script>', '<\/script>', html_entity_decode( $step_script_output ) ) . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
595 }
596
597 echo '</script>';
598 echo '<!-- End CartFlows Custom JS -->';
599 echo PHP_EOL;
600 }
601
602 /**
603 * Strip <script> and <style> tags from content, returning only the inner content.
604 *
605 * @since 2.2.3
606 * @param string $content Content to strip tags from.
607 * @return string Content with script/style tags removed.
608 */
609 private function strip_script_style_tags( $content ) {
610 // Remove <script>...</script> tags but keep inner content.
611 $content = preg_replace( '/<script[^>]*>(.*?)<\/script>/is', '$1', $content );
612 // Remove <style>...</style> tags but keep inner content.
613 $content = preg_replace( '/<style[^>]*>(.*?)<\/style>/is', '$1', $content );
614 return trim( $content );
615 }
616
617 /**
618 * Override woo templates.
619 *
620 * @param string $template new Template full path.
621 * @param string $template_name Template name.
622 * @param string $template_path Template Path.
623 * @since 1.1.5
624 * @return string.
625 */
626 public function override_woo_template( $template, $template_name, $template_path ) {
627
628 global $woocommerce;
629
630 $_template = $template;
631
632 $plugin_path = CARTFLOWS_DIR . 'woocommerce/template/';
633
634 if ( file_exists( $plugin_path . $template_name ) ) {
635 $template = $plugin_path . $template_name;
636 }
637
638 if ( ! $template ) {
639 $template = $_template;
640 }
641
642 return $template;
643 }
644
645 /**
646 * Remove the action applied by the Flatsome theme.
647 *
648 * @since 1.1.5
649 * @return void.
650 */
651 public function remove_flatsome_action() {
652
653 // Remove action where flatsome dequeued the woocommerce's default styles.
654 remove_action( 'wp_enqueue_scripts', 'flatsome_woocommerce_scripts_styles', 98 );
655 }
656
657 /**
658 * Add version class to body in frontend.
659 *
660 * @since 1.1.5
661 * @param array $classes classes.
662 * @return array $classes classes.
663 */
664 public function add_cartflows_lite_version_to_body( $classes ) {
665
666 $classes[] = 'cartflows-' . CARTFLOWS_VER;
667
668 return $classes;
669 }
670
671 /**
672 * Get custom script data.
673 *
674 * @since 1.0.0
675 */
676 public function get_custom_script() {
677
678 global $post;
679
680 $script = get_post_meta( $post->ID, 'wcf-custom-script', true );
681
682 $script = $this->maybe_replace_vars( $script );
683
684 return $script;
685 }
686
687 /**
688 * Replace the dynamic vars in the custom script.
689 *
690 }
691
692 /**
693 * Get custom script data.
694 *
695 * @since 1.0.0
696 */
697 public function get_flow_custom_script() {
698
699 global $post;
700
701 $step_id = $post->ID;
702
703 $flow_id = wcf()->utils->get_flow_id_from_step_id( $step_id );
704
705 $script = get_post_meta( $flow_id, 'wcf-flow-custom-script', true );
706
707 $script = $this->maybe_replace_vars( $script );
708
709 return $script;
710 }
711
712 /**
713 * Get custom JS script for steps.
714 *
715 * @since 2.2.2
716 */
717 public function get_step_custom_js() {
718
719 global $post;
720
721 $script = get_post_meta( $post->ID, 'wcf-step-custom-js', true );
722
723 $script = $this->maybe_replace_vars( $script );
724
725 return $script;
726 }
727
728 /**
729 * Get custom CSS script for steps.
730 *
731 * @since 2.2.2
732 */
733 public function get_step_custom_css() {
734
735 global $post;
736
737 $style = get_post_meta( $post->ID, 'wcf-step-custom-css', true );
738
739 return is_string( $style ) ? $style : '';
740 }
741
742 /**
743 * Replace the dynamic vars in the custom script.
744 *
745 * @param string $script custom script.
746 * @return string $script modified custom script.
747 *
748 * @since 1.10.0
749 */
750 public function maybe_replace_vars( $script ) {
751 //phpcs:disable WordPress.Security.NonceVerification
752 if ( isset( $_GET['wcf-order'] ) && isset( $_GET['wcf-key'] ) ) {
753
754 $order_id = intval( wp_unslash( $_GET['wcf-order'] ) );
755 $order_key = wc_clean( wp_unslash( $_GET['wcf-key'] ) );
756 //phpcs:enable WordPress.Security.NonceVerification
757 $order = wc_get_order( $order_id );
758
759 if ( $order && $order_key === $order->get_order_key() ) {
760
761 // These variables will be available to use on Upsell, Downsell, Thank you pages of CartFlows only.
762 $script = str_replace( '{{order_id}}', $order_id, $script );
763 $script = str_replace( '{{txn_id}}', $order->get_transaction_id(), $script );
764 $script = str_replace( '{{order_total}}', $order->get_total(), $script );
765
766 $script = apply_filters( 'cartflows_dynamic_js_vars', $script );
767 }
768 }
769
770 return $script;
771 }
772
773 /**
774 * Get global custom CSS from settings.
775 *
776 * @since 2.2.2
777 * @return string
778 */
779 public function get_global_custom_css() {
780
781 $global_scripts = get_option( '_cartflows_global_scripts', array() );
782
783 if ( ! is_array( $global_scripts ) || empty( $global_scripts['global_css'] ) ) {
784 return '';
785 }
786
787 return (string) $global_scripts['global_css'];
788 }
789
790 /**
791 * Get global custom JS from settings.
792 *
793 * @since 2.2.2
794 * @return string
795 */
796 public function get_global_custom_js() {
797
798 $global_scripts = get_option( '_cartflows_global_scripts', array() );
799
800 if ( ! is_array( $global_scripts ) || empty( $global_scripts['global_js'] ) ) {
801 return '';
802 }
803
804 return (string) $global_scripts['global_js'];
805 }
806
807 /**
808 * Get custom JS script for flow.
809 *
810 * @since 2.2.2
811 * @return string
812 */
813 public function get_flow_custom_js() {
814
815 global $post;
816
817 $step_id = $post->ID;
818
819 $flow_id = wcf()->utils->get_flow_id_from_step_id( $step_id );
820
821 $script = get_post_meta( $flow_id, 'wcf-flow-custom-js', true );
822
823 $script = $this->maybe_replace_vars( $script );
824
825 return $script;
826 }
827
828 /**
829 * Get custom CSS script for flow.
830 *
831 * @since 2.2.2
832 * @return string
833 */
834 public function get_flow_custom_css() {
835
836 global $post;
837
838 $step_id = $post->ID;
839
840 $flow_id = wcf()->utils->get_flow_id_from_step_id( $step_id );
841
842 $style = get_post_meta( $flow_id, 'wcf-flow-custom-css', true );
843
844 return is_string( $style ) ? $style : '';
845 }
846
847 /**
848 * Set appropriate filter sctions.
849 *
850 * @since 1.1.14
851 */
852 public function setup_optin_checkout_filter() {
853
854 if ( _is_wcf_doing_optin_ajax() ) {
855 /* Modify the optin order received url to go next step */
856 remove_filter( 'woocommerce_get_checkout_order_received_url', array( $this, 'redirect_to_thankyou_page' ), 10, 2 );
857 add_filter( 'woocommerce_get_checkout_order_received_url', array( $this, 'redirect_optin_to_next_step' ), 10, 2 );
858 }
859 }
860
861 /**
862 * Redirect to thank page if upsell not exists
863 *
864 * @param string $order_receive_url url.
865 * @param object $order order object.
866 * @return string $order_receive_url next step URL.
867 * @since 1.0.0
868 */
869 public function redirect_optin_to_next_step( $order_receive_url, $order ) {
870
871 /* Only for optin page */
872 wcf()->logger->log( 'Start-' . __CLASS__ . '::' . __FUNCTION__ );
873 wcf()->logger->log( 'Only for optin page' );
874
875 if ( _is_wcf_doing_optin_ajax() ) {
876
877 $optin_id = wcf()->utils->get_optin_id_from_post_data();
878
879 if ( ! $optin_id ) {
880 $optin_id = wcf()->utils->get_optin_id_from_order( $order );
881 }
882 } else {
883 $optin_id = wcf()->utils->get_optin_id_from_order( $order );
884 }
885
886 wcf()->logger->log( 'Optin ID : ' . $optin_id );
887
888 if ( $optin_id ) {
889
890 $wcf_step_obj = wcf_get_step( $optin_id );
891 $next_step_id = $wcf_step_obj->get_direct_next_step_id();
892
893 if ( $next_step_id ) {
894
895 $order_receive_url = get_permalink( $next_step_id );
896 $query_param = array(
897 'wcf-key' => $order->get_order_key(),
898 'wcf-order' => $order->get_id(),
899 );
900
901 if ( 'yes' === wcf()->options->get_optin_meta_value( $optin_id, 'wcf-optin-pass-fields' ) ) {
902
903 $fields_string = wcf()->options->get_optin_meta_value( $optin_id, 'wcf-optin-pass-specific-fields' );
904
905 $fields = array_map( 'trim', explode( ',', $fields_string ) );
906
907 if ( is_array( $fields ) ) {
908
909 foreach ( $fields as $in => $key ) {
910 switch ( $key ) {
911 case 'first_name':
912 $query_param[ $key ] = $order->get_billing_first_name();
913 break;
914 case 'last_name':
915 $query_param[ $key ] = $order->get_billing_last_name();
916 break;
917 case 'email':
918 $query_param[ $key ] = $order->get_billing_email();
919 break;
920 default:
921 $query_param[ $key ] = $order->get_meta( '_billing_' . $key, true );
922 break;
923 }
924 }
925 }
926 }
927
928 // Add any existing URL parameters at the end of the URL before redirecting.
929 $query_param = wcf()->utils->may_be_append_query_string( $query_param );
930
931 $order_receive_url = add_query_arg(
932 $query_param,
933 $order_receive_url
934 );
935 }
936 }
937
938 wcf()->logger->log( 'End-' . __CLASS__ . '::' . __FUNCTION__ );
939
940 return $order_receive_url;
941 }
942 }
943
944 /**
945 * Prepare if class 'Cartflows_Frontend' exist.
946 * Kicking this off by calling 'get_instance()' method
947 */
948 Cartflows_Frontend::get_instance();
949