PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.3.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.3.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 / admin-core / ajax / flows.php

flows.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce 3.3.0, at admin-core/ajax/flows.php

1,279 lines 34.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CartFlows Flows ajax actions.
4 *
5 * @package CartFlows
6 */
7
8 namespace CartflowsAdmin\AdminCore\Ajax;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 use CartflowsAdmin\AdminCore\Ajax\AjaxBase;
16 use CartflowsAdmin\AdminCore\Inc\AdminHelper;
17 use CartflowsAdmin\AdminCore\Inc\MetaOps;
18
19 /**
20 * Class Flows.
21 */
22 class Flows extends AjaxBase {
23
24 /**
25 * Instance
26 *
27 * @access private
28 * @var object Class object.
29 * @since 1.0.0
30 */
31 private static $instance;
32
33 /**
34 * Initiator
35 *
36 * @since 1.0.0
37 * @return object initialized object of class.
38 */
39 public static function get_instance() {
40 if ( ! isset( self::$instance ) ) {
41 self::$instance = new self();
42 }
43 return self::$instance;
44 }
45
46 /**
47 * Register ajax events.
48 *
49 * @since 1.0.0
50 * @return void
51 */
52 public function register_ajax_events() {
53
54 $ajax_events = array(
55 'update_flow_title',
56 'clone_flow',
57 'delete_flow',
58 'trash_flow',
59 'restore_flow',
60 'reorder_flow_steps',
61 'trash_flows_in_bulk',
62 'update_flow_post_status',
63 'delete_flows_permanently',
64 'save_flow_meta_settings',
65 'export_flows_in_bulk',
66 'update_status',
67 'update_store_checkout_status',
68 'hide_instant_checkout_notice',
69 'get_published_flows',
70 );
71
72 $this->init_ajax_events( $ajax_events );
73 }
74
75 /**
76 * Export the flows and it's data.
77 */
78 public function export_flows_in_bulk() {
79
80 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
81
82 /**
83 * Check permission
84 */
85 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
86 wp_send_json_error( $response_data );
87 }
88
89 /**
90 * Nonce verification
91 */
92 if ( ! check_ajax_referer( 'cartflows_export_flows_in_bulk', 'security', false ) ) {
93 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
94 wp_send_json_error( $response_data );
95 }
96
97 if ( ! isset( $_POST['flow_ids'] ) ) {
98 $response_data = array( 'message' => __( 'No Funnel IDs has been supplied to export!', 'cartflows' ) );
99 wp_send_json_error( $response_data );
100 }
101
102 $flow_ids = array_map( 'intval', explode( ',', sanitize_text_field( $_POST['flow_ids'] ) ) );
103
104 $flows = array();
105 $export = \CartFlows_Importer::get_instance();
106 foreach ( $flow_ids as $key => $flow_id ) {
107 $flows[] = $export->get_flow_export_data( $flow_id );
108 }
109
110 $response_data = array(
111 'message' => __( 'Funnel exported successfully', 'cartflows' ),
112 'flows' => wp_json_encode( $flows ),
113 );
114
115 wp_send_json_success( $response_data );
116 }
117
118 /**
119 * Save flow meta data.
120 */
121 public function save_flow_meta_settings() {
122
123 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
124
125 /**
126 * Check permission
127 */
128 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
129 wp_send_json_error( $response_data );
130 }
131
132 /**
133 * Nonce verification
134 */
135 if ( ! check_ajax_referer( 'cartflows_save_flow_meta_settings', 'security', false ) ) {
136 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
137 wp_send_json_error( $response_data );
138 }
139
140 $response_data = array(
141 'status' => false,
142 'text' => __( 'Can\'t update the flow data', 'cartflows' ),
143 );
144
145 $skipped_fields = array();
146
147 if ( isset( $_POST['flow_id'] ) ) {
148 $flow_id = intval( $_POST['flow_id'] );
149
150 if ( empty( $flow_id ) ) {
151 wp_send_json_error( $response_data );
152 }
153
154 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
155 wp_send_json_error( $response_data );
156 }
157
158 $new_flow_title = isset( $_POST['post_title'] ) ? sanitize_text_field( wp_unslash( $_POST['post_title'] ) ) : get_the_title( $flow_id );
159
160 if ( '' === $new_flow_title ) {
161 $new_flow_title = __( '(no title)', 'cartflows' );
162 }
163
164 $new_flow_slug = isset( $_POST['post_name'] ) ? sanitize_text_field( wp_unslash( $_POST['post_name'] ) ) : '';
165
166 $post_meta = wcf()->options->get_flow_fields( $flow_id );
167 $skipped_fields = MetaOps::save_meta_fields( $flow_id, $post_meta, 'cartflows_save_flow_meta_settings' );
168
169 $instant_layout_style = isset( $_POST['instant-layout-style'] ) ? sanitize_text_field( wp_unslash( $_POST['instant-layout-style'] ) ) : null;
170
171 if ( 'yes' === $instant_layout_style ) {
172 update_post_meta( $flow_id, 'wcf-instant-checkout-notice-skipped', 'yes' );
173 update_option( 'wcf-instant-checkout-notice-skipped', 'yes' );
174 \Cartflows_Helper::set_analytics_flag( 'first_instant_layout_enabled' );
175 }
176
177 $new_flow_data = array(
178 'ID' => $flow_id,
179 'post_title' => $new_flow_title,
180 'post_name' => $new_flow_slug,
181 );
182
183 wp_update_post( $new_flow_data );
184 }
185
186 $response_data = array(
187 'message' => __( 'Successfully saved the flow data!', 'cartflows' ),
188 );
189
190 // Name anything the save dropped rather than reporting a clean save the user did not get.
191 if ( ! empty( $skipped_fields ) ) {
192 $response_data['skipped_fields'] = $skipped_fields;
193 $response_data['message'] = __( 'Saved, but the custom script fields were not updated because your account cannot edit scripts.', 'cartflows' );
194 }
195
196 wp_send_json_success( $response_data );
197 }
198
199 /**
200 * Delete the flow and it's data.
201 */
202 public function delete_flows_permanently() {
203
204 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
205
206 /**
207 * Check permission
208 */
209 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
210 wp_send_json_error( $response_data );
211 }
212
213 /**
214 * Nonce verification
215 */
216 if ( ! check_ajax_referer( 'cartflows_delete_flows_permanently', 'security', false ) ) {
217 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
218 wp_send_json_error( $response_data );
219 }
220
221 $flow_ids = isset( $_POST['flow_ids'] ) ? array_map( 'intval', explode( ',', sanitize_text_field( $_POST['flow_ids'] ) ) ) : array();
222
223 foreach ( $flow_ids as $key => $flow_id ) {
224
225 /* Check if CartFlows Post type */
226 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
227 continue;
228 }
229
230 /* Get Steps */
231 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
232
233 /* delte All steps */
234 if ( $steps && is_array( $steps ) ) {
235 foreach ( $steps as $step ) {
236
237 /* Need to delete ab test data as well */
238 wp_delete_post( $step['id'], true );
239 }
240 }
241 /* Trash term */
242 $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
243
244 if ( is_array( $term_data ) ) {
245 wp_trash_post( $term_data['term_id'], CARTFLOWS_TAXONOMY_STEP_FLOW );
246 }
247
248 /* Finally trash flow post and it's data */
249 wp_delete_post( $flow_id, true );
250 }
251
252 /**
253 * Redirect to the new flow edit screen
254 */
255 $response_data = array(
256 'message' => __( 'Successfully deleted the Funnels!', 'cartflows' ),
257 );
258 wp_send_json_success( $response_data );
259 }
260
261 /**
262 * Update flow status.
263 */
264 public function update_flow_post_status() {
265
266 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
267
268 /**
269 * Check permission
270 */
271 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
272 wp_send_json_error( $response_data );
273 }
274
275 /**
276 * Nonce verification
277 */
278 if ( ! check_ajax_referer( 'cartflows_update_flow_post_status', 'security', false ) ) {
279 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
280 wp_send_json_error( $response_data );
281 }
282
283 if ( ! isset( $_POST['flow_ids'] ) ) {
284 $response_data = array( 'message' => __( 'No Funnel IDs has been supplied to delete!', 'cartflows' ) );
285 wp_send_json_error( $response_data );
286 }
287
288 $flow_ids = isset( $_POST['flow_ids'] ) ? array_map( 'intval', explode( ',', sanitize_text_field( $_POST['flow_ids'] ) ) ) : array();
289
290 $new_status = isset( $_POST['new_status'] ) ? sanitize_text_field( wp_unslash( $_POST['new_status'] ) ) : '';
291 $allowed_statuses = array( 'publish', 'draft', 'trash', 'pending' );
292 if ( ! in_array( $new_status, $allowed_statuses, true ) ) {
293 wp_send_json_error( array( 'message' => __( 'Invalid post status.', 'cartflows' ) ) );
294 }
295
296 foreach ( $flow_ids as $key => $flow_id ) {
297
298 /* Check if CartFlows Post type */
299 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
300 continue;
301 }
302
303 /* Get Steps */
304 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
305
306 /* Trash All steps */
307 if ( $steps && is_array( $steps ) ) {
308 foreach ( $steps as $step ) {
309
310 $my_post = array();
311 $my_post['ID'] = $step['id'];
312 $my_post['post_status'] = $new_status;
313 wp_update_post( wp_slash( $my_post ) );
314
315 }
316 }
317
318 /*
319 Trash term
320 // $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
321 // if ( is_array( $term_data ) ) {
322 // wp_trash_post( $term_data['term_id'], CARTFLOWS_TAXONOMY_STEP_FLOW );
323 // }
324 */
325
326 /* Finally trash flow post and it's data */
327 $flow_post = array();
328 $flow_post['ID'] = $flow_id;
329 $flow_post['post_status'] = $new_status;
330 wp_update_post( $flow_post );
331 }
332
333 $flow_count = count( $flow_ids );
334
335 switch ( $new_status ) {
336 case 'publish':
337 $success_message = _n(
338 'Successfully published the Funnel!',
339 'Successfully published the Funnels!',
340 $flow_count,
341 'cartflows'
342 );
343 break;
344 case 'draft':
345 $success_message = _n(
346 'Successfully moved the Funnel to draft!',
347 'Successfully moved the Funnels to draft!',
348 $flow_count,
349 'cartflows'
350 );
351 break;
352 case 'trash':
353 $success_message = _n(
354 'Successfully trashed the Funnel!',
355 'Successfully trashed the Funnels!',
356 $flow_count,
357 'cartflows'
358 );
359 break;
360 case 'pending':
361 $success_message = _n(
362 'Successfully marked the Funnel as pending!',
363 'Successfully marked the Funnels as pending!',
364 $flow_count,
365 'cartflows'
366 );
367 break;
368 default:
369 $success_message = __( 'Successfully updated the Funnel status!', 'cartflows' );
370 break;
371 }
372
373 $response_data = array(
374 'message' => $success_message,
375 );
376 wp_send_json_success( $response_data );
377 }
378
379
380 /**
381 * Trash the flows and it's data.
382 */
383 public function trash_flows_in_bulk() {
384
385 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
386
387 /**
388 * Check permission
389 */
390 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
391 wp_send_json_error( $response_data );
392 }
393
394 /**
395 * Nonce verification
396 */
397 if ( ! check_ajax_referer( 'cartflows_trash_flows_in_bulk', 'security', false ) ) {
398 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
399 wp_send_json_error( $response_data );
400 }
401
402 if ( ! isset( $_POST['flow_ids'] ) ) {
403 $response_data = array( 'message' => __( 'No Funnel IDs has been supplied to delete!', 'cartflows' ) );
404 wp_send_json_error( $response_data );
405 }
406
407 $flow_ids = isset( $_POST['flow_ids'] ) ? array_map( 'intval', explode( ',', sanitize_text_field( $_POST['flow_ids'] ) ) ) : array();
408
409 foreach ( $flow_ids as $key => $flow_id ) {
410
411 /* Check if CartFlows Post type */
412 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
413 continue;
414 }
415 /* Get Steps */
416 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
417
418 /* Trash All steps */
419 if ( $steps && is_array( $steps ) ) {
420 foreach ( $steps as $step ) {
421
422 /* Need to delete ab test data as well */
423 wp_trash_post( $step['id'], true );
424 }
425 }
426
427 /* Trash term */
428 $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
429
430 if ( is_array( $term_data ) ) {
431 wp_trash_post( $term_data['term_id'], CARTFLOWS_TAXONOMY_STEP_FLOW );
432 }
433
434 /* Finally trash flow post and it's data */
435 wp_trash_post( $flow_id, true );
436 }
437
438 /**
439 * Redirect to the new flow edit screen
440 */
441 $response_data = array(
442 'message' => __( 'Successfully trashed the Funnels!', 'cartflows' ),
443 );
444 wp_send_json_success( $response_data );
445 }
446 /**
447 * Update flow title.
448 */
449 public function update_flow_title() {
450
451 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
452
453 /**
454 * Check permission
455 */
456 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
457 wp_send_json_error( $response_data );
458 }
459
460 /**
461 * Nonce verification
462 */
463 if ( ! check_ajax_referer( 'cartflows_update_flow_title', 'security', false ) ) {
464 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
465 wp_send_json_error( $response_data );
466 }
467
468 $flow_id = isset( $_POST['flow_id'] ) ? intval( $_POST['flow_id'] ) : 0;
469 $new_flow_title = isset( $_POST['new_flow_title'] ) ? sanitize_text_field( $_POST['new_flow_title'] ) : '';
470
471 /* Check if CartFlows Post type */
472 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
473 wp_send_json_error( array( 'message' => __( 'Invalid Funnel ID has been supplied to update title.', 'cartflows' ) ) );
474 }
475
476 $result = array(
477 'status' => false,
478 'text' => __( 'Can\'t update the flow title', 'cartflows' ),
479 );
480
481 if ( empty( $flow_id ) || empty( $new_flow_title ) ) {
482 wp_send_json( $result );
483 }
484
485 $new_flow_data = array(
486 'ID' => $flow_id,
487 'post_title' => $new_flow_title,
488 );
489 wp_update_post( $new_flow_data );
490
491 $result = array(
492 'status' => true,
493 /* translators: %s flow id */
494 'text' => sprintf( __( 'Funnel title updated - %s', 'cartflows' ), $flow_id ),
495 );
496
497 wp_send_json( $result );
498 }
499
500 /**
501 * Clone the Flow.
502 */
503 public function clone_flow() {
504
505 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
506
507 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
508 wp_send_json_error( $response_data );
509 }
510
511 /**
512 * Nonce verification
513 */
514 if ( ! check_ajax_referer( 'cartflows_clone_flow', 'security', false ) ) {
515 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
516 wp_send_json_error( $response_data );
517 }
518
519 $response_data = array( 'message' => __( 'Invalid Funnel ID has been supplied to clone!', 'cartflows' ) );
520
521 /**
522 * Check flow id
523 */
524 if ( empty( $_POST['id'] ) ) {
525 wp_send_json_error( $response_data );
526 }
527
528 /**
529 * Get the original post id
530 */
531 $post_id = absint( $_POST['id'] );
532
533 /* Check if CartFlows Post type */
534 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $post_id ) ) {
535 wp_send_json_error( $response_data );
536 }
537
538 /**
539 * And all the original post data then
540 */
541 $post = get_post( $post_id );
542
543 /**
544 * Assign current user to be the new post author
545 */
546 $current_user = wp_get_current_user();
547 $new_post_author = $current_user->ID;
548
549 /**
550 * If post data not exists, throw error
551 */
552 if ( ! isset( $post ) || null === $post ) {
553 $response_data = array( 'message' => __( 'Invalid Funnel ID has been supplied to duplicate!', 'cartflows' ) );
554 wp_send_json_error( $response_data );
555 }
556
557 global $wpdb;
558
559 /**
560 * Let's start cloning
561 */
562
563 /**
564 * New post data array
565 */
566 $args = array(
567 'comment_status' => $post->comment_status,
568 'ping_status' => $post->ping_status,
569 'post_author' => $new_post_author,
570 'post_content' => $post->post_content,
571 'post_excerpt' => $post->post_excerpt,
572 'post_name' => $post->post_name,
573 'post_parent' => $post->post_parent,
574 'post_password' => $post->post_password,
575 'post_status' => $post->post_status,
576 'post_title' => $post->post_title . ' Clone',
577 'post_type' => $post->post_type,
578 'to_ping' => $post->to_ping,
579 'menu_order' => $post->menu_order,
580 );
581
582 /**
583 * Insert the post
584 */
585 $new_flow_id = wp_insert_post( $args );
586
587 /**
588 * Get all current post terms ad set them to the new post
589 *
590 * Returns array of taxonomy names for post type, ex array("category", "post_tag");.
591 */
592 $taxonomies = get_object_taxonomies( $post->post_type );
593
594 foreach ( $taxonomies as $taxonomy ) {
595
596 $post_terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'slugs' ) );
597
598 wp_set_object_terms( $new_flow_id, $post_terms, $taxonomy, false );
599 }
600
601 /**
602 * Duplicate all post meta just in two SQL queries
603 */
604 // Using custom query to clone flow & step meta data as it is better than WP functions in case in large data.
605 $post_meta_infos = $wpdb->get_results( //phpcs:ignore WordPress.DB.DirectDatabaseQuery
606 $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=%d", $post_id )
607 );
608
609 if ( ! empty( $post_meta_infos ) ) {
610
611 $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) VALUES ";
612
613 $sql_query_sel = array();
614
615 foreach ( $post_meta_infos as $meta_info ) {
616
617 $meta_key = $meta_info->meta_key;
618
619 if ( '_wp_old_slug' === $meta_key ) {
620 continue;
621 }
622
623 $sql_query_sel[] = $wpdb->prepare( '( %d, %s, %s )', $new_flow_id, $meta_key, $meta_info->meta_value );
624
625 }
626
627 $sql_query .= implode( ',', $sql_query_sel );
628
629 $wpdb->query( $sql_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery
630 }
631
632 /* Steps Cloning */
633 $flow_steps = get_post_meta( $post_id, 'wcf-steps', true );
634 $new_flow_steps = array();
635
636 /* Set Steps Empty */
637 update_post_meta( $new_flow_id, 'wcf-steps', $new_flow_steps );
638
639 if ( is_array( $flow_steps ) && ! empty( $flow_steps ) ) {
640
641 foreach ( $flow_steps as $index => $step_data ) {
642
643 $step_id = $step_data['id'];
644 $step_type = get_post_meta( $step_id, 'wcf-step-type', true );
645
646 $step_object = get_post( $step_id );
647
648 /**
649 * New step post data array
650 */
651 $step_args = array(
652 'comment_status' => $step_object->comment_status,
653 'ping_status' => $step_object->ping_status,
654 'post_author' => $new_post_author,
655 'post_content' => $step_object->post_content,
656 'post_excerpt' => $step_object->post_excerpt,
657 'post_name' => $step_object->post_name,
658 'post_parent' => $step_object->post_parent,
659 'post_password' => $step_object->post_password,
660 'post_status' => $step_object->post_status,
661 'post_title' => $step_object->post_title,
662 'post_type' => $step_object->post_type,
663 'to_ping' => $step_object->to_ping,
664 'menu_order' => $step_object->menu_order,
665 );
666
667 /**
668 * Insert the post
669 */
670 $new_step_id = wp_insert_post( $step_args );
671
672 /**
673 * Duplicate all step meta
674 */
675 $post_meta_infos = $wpdb->get_results( //phpcs:ignore WordPress.DB.DirectDatabaseQuery
676 $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=%d", $step_id )
677 );
678
679 if ( ! empty( $post_meta_infos ) ) {
680
681 $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) VALUES ";
682
683 $sql_query_sel = array();
684
685 foreach ( $post_meta_infos as $meta_info ) {
686
687 $meta_key = $meta_info->meta_key;
688
689 $meta_value = $meta_info->meta_value;
690
691 $sql_query_sel[] = $wpdb->prepare( '( %d, %s, %s )', $new_step_id, $meta_key, $meta_value );
692 }
693
694 $sql_query .= implode( ',', $sql_query_sel );
695
696 $wpdb->query( $sql_query ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery
697 }
698
699 // insert post meta.
700 update_post_meta( $new_step_id, 'wcf-flow-id', $new_flow_id );
701 update_post_meta( $new_step_id, 'wcf-step-type', $step_type );
702
703 /**
704 * @ to_do later
705 * delete split test connecctivity
706 */
707
708 wp_set_object_terms( $new_step_id, $step_type, CARTFLOWS_TAXONOMY_STEP_TYPE );
709 wp_set_object_terms( $new_step_id, 'flow-' . $new_flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
710
711 /* Add New Flow Steps */
712 $new_flow_steps[] = array(
713 'id' => $new_step_id,
714 'title' => $step_object->post_title,
715 'type' => $step_type,
716 );
717 }
718 }
719
720 /* Update New Flow Step Post Meta */
721 update_post_meta( $new_flow_id, 'wcf-steps', $new_flow_steps );
722
723 /* Clear Page Builder Cache */
724 AdminHelper::clear_cache();
725
726 /**
727 * Redirect to the new flow edit screen
728 */
729 $response_data = array(
730 'message' => __( 'Successfully cloned the Funnel!', 'cartflows' ),
731 'redirect_url' => admin_url( 'post.php?action=edit&post=' . $new_flow_id ),
732 );
733 wp_send_json_success( $response_data );
734 }
735
736 /**
737 * Restore the flow and it's data.
738 */
739 public function restore_flow() {
740
741 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
742
743 /**
744 * Check permission
745 */
746 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
747 wp_send_json_error( $response_data );
748 }
749
750 /**
751 * Nonce verification
752 */
753 if ( ! check_ajax_referer( 'cartflows_restore_flow', 'security', false ) ) {
754 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
755 wp_send_json_error( $response_data );
756 }
757
758 $response_data = array( 'message' => __( 'Invalid Funnel ID has been supplied to restore!', 'cartflows' ) );
759
760
761 if ( ! isset( $_POST['flow_id'] ) ) {
762 wp_send_json_error( $response_data );
763 }
764
765 $flow_id = intval( $_POST['flow_id'] );
766
767 /* Check if CartFlows Post type */
768 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
769 wp_send_json_error( $response_data );
770 }
771
772 /* Get Steps */
773 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
774
775 /* Untrash All steps */
776 if ( $steps && is_array( $steps ) ) {
777 foreach ( $steps as $step ) {
778
779 /* Need to delete ab test data as well */
780 wp_untrash_post( $step['id'] );
781 }
782 }
783
784 /* Untrash term */
785 $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
786
787 if ( is_array( $term_data ) ) {
788 wp_untrash_post( $term_data['term_id'] );
789 }
790
791 /* Finally untrash flow post and it's data */
792 wp_untrash_post( $flow_id );
793
794 /**
795 * Redirect to the new flow edit screen
796 */
797 $response_data = array(
798 'message' => __( 'Successfully restored the Funnel!', 'cartflows' ),
799 );
800 wp_send_json_success( $response_data );
801 }
802
803 /**
804 * Trash the flow and it's data.
805 */
806 public function trash_flow() {
807
808 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
809
810 /**
811 * Check permission
812 */
813 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
814 wp_send_json_error( $response_data );
815 }
816
817 /**
818 * Nonce verification
819 */
820 if ( ! check_ajax_referer( 'cartflows_trash_flow', 'security', false ) ) {
821 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
822 wp_send_json_error( $response_data );
823 }
824
825 $response_data = array( 'message' => __( 'Invalid Funnel ID has been supplied to trash!', 'cartflows' ) );
826
827 if ( ! isset( $_POST['flow_id'] ) ) {
828 wp_send_json_error( $response_data );
829 }
830
831 $flow_id = intval( $_POST['flow_id'] );
832
833 /* Check if CartFlows Post type */
834 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
835 wp_send_json_error( $response_data );
836 }
837
838 /* Get Steps */
839 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
840
841 /* Trash All steps */
842 if ( $steps && is_array( $steps ) ) {
843 foreach ( $steps as $step ) {
844
845 /* Need to delete ab test data as well */
846 wp_trash_post( $step['id'], true );
847 }
848 }
849
850 /* Trash term */
851 $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
852
853 if ( is_array( $term_data ) ) {
854 wp_trash_post( $term_data['term_id'], CARTFLOWS_TAXONOMY_STEP_FLOW );
855 }
856
857 /* Finally trash flow post and it's data */
858 wp_trash_post( $flow_id, true );
859
860 /**
861 * Redirect to the new flow edit screen
862 */
863 $response_data = array(
864 'message' => __( 'Successfully trashed the Funnel!', 'cartflows' ),
865 );
866 wp_send_json_success( $response_data );
867 }
868
869 /**
870 * Delete the flow and it's data.
871 */
872 public function delete_flow() {
873
874 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
875
876 /**
877 * Check permission
878 */
879 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
880 wp_send_json_error( $response_data );
881 }
882
883 /**
884 * Nonce verification
885 */
886 if ( ! check_ajax_referer( 'cartflows_delete_flow', 'security', false ) ) {
887 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
888 wp_send_json_error( $response_data );
889 }
890
891 $response_data = array( 'message' => __( 'Invalid Funnel ID has been supplied to delete!', 'cartflows' ) );
892
893 if ( ! isset( $_POST['flow_id'] ) ) {
894 wp_send_json_error( $response_data );
895 }
896
897 $flow_id = intval( $_POST['flow_id'] );
898
899 /* Check if CartFlows Post type */
900 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
901 wp_send_json_error( $response_data );
902 }
903
904 /* Get Steps */
905 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
906
907 /* Delete All steps */
908 if ( $steps && is_array( $steps ) ) {
909 foreach ( $steps as $step ) {
910
911 /* Need to delete ab test data as well */
912 wp_delete_post( $step['id'], true );
913 }
914 }
915
916 /* Delete term */
917 $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
918
919 if ( is_array( $term_data ) ) {
920 wp_delete_term( $term_data['term_id'], CARTFLOWS_TAXONOMY_STEP_FLOW );
921 }
922
923 /* Finally delete flow post and it's data */
924 wp_delete_post( $flow_id, true );
925
926 do_action( 'cartflows_admin_after_delete_flow', $flow_id );
927
928 /**
929 * Redirect to the new flow edit screen
930 */
931 $response_data = array(
932 'message' => __( 'Successfully deleted the Funnel!', 'cartflows' ),
933 );
934 wp_send_json_success( $response_data );
935 }
936
937 /**
938 * Update status.
939 */
940 public function update_status() {
941
942 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
943
944 /**
945 * Check permission
946 */
947 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
948 wp_send_json_error( $response_data );
949 }
950
951 /**
952 * Nonce verification
953 */
954 if ( ! check_ajax_referer( 'cartflows_update_status', 'security', false ) ) {
955 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
956 wp_send_json_error( $response_data );
957 }
958
959 $response_data = array( 'message' => __( 'Invalid Funnel IDs has been supplied to update status!', 'cartflows' ) );
960
961 if ( ! isset( $_POST['flow_id'] ) ) {
962 wp_send_json_error( $response_data );
963 }
964
965 $flow_id = isset( $_POST['flow_id'] ) ? intval( $_POST['flow_id'] ) : 0;
966
967 /* Check if CartFlows Post type */
968 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
969 wp_send_json_error( $response_data );
970 }
971
972 $new_status = isset( $_POST['new_status'] ) ? sanitize_text_field( wp_unslash( $_POST['new_status'] ) ) : '';
973 $allowed_statuses = array( 'publish', 'draft', 'trash', 'pending' );
974 if ( ! in_array( $new_status, $allowed_statuses, true ) ) {
975 wp_send_json_error( array( 'message' => __( 'Invalid post status.', 'cartflows' ) ) );
976 }
977
978 /* Get Steps */
979 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
980
981 /* Trash All steps */
982 if ( $steps && is_array( $steps ) ) {
983 foreach ( $steps as $step ) {
984
985 $my_post = array();
986 $my_post['ID'] = $step['id'];
987 $my_post['post_status'] = $new_status;
988 wp_update_post( wp_slash( $my_post ) );
989
990 }
991 }
992
993 /*
994 Trash term
995 // $term_data = term_exists( 'flow-' . $flow_id, CARTFLOWS_TAXONOMY_STEP_FLOW );
996
997 // if ( is_array( $term_data ) ) {
998 // wp_trash_post( $term_data['term_id'], CARTFLOWS_TAXONOMY_STEP_FLOW );
999 // }
1000 */
1001
1002 /* Finally trash flow post and it's data */
1003 $flow_post = array();
1004 $flow_post['ID'] = $flow_id;
1005 $flow_post['post_status'] = $new_status;
1006 wp_update_post( $flow_post );
1007
1008 /**
1009 * Redirect to the new flow edit screen
1010 */
1011 $response_data = array(
1012 'message' => __( 'Successfully updated the Funnel status!', 'cartflows' ),
1013 );
1014 wp_send_json_success( $response_data );
1015 }
1016
1017 /**
1018 * Enables / Disables Store Checkout on toggle click
1019 *
1020 * @return void
1021 * @since X.X.X
1022 */
1023 public function update_store_checkout_status() {
1024 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
1025
1026 /**
1027 * Check permission
1028 */
1029 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
1030 wp_send_json_error( $response_data );
1031 }
1032
1033 /**
1034 * Nonce verification
1035 */
1036 if ( ! check_ajax_referer( 'cartflows_update_store_checkout_status', 'security', false ) ) {
1037 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
1038 wp_send_json_error( $response_data );
1039 }
1040
1041 if ( ! isset( $_POST['enable_store_checkout'] ) ) {
1042 $response_data = array( 'message' => __( 'No Funnel IDs has been supplied to delete!', 'cartflows' ) );
1043 wp_send_json_error( $response_data );
1044 }
1045
1046 $enable_store_checkout = isset( $_POST['enable_store_checkout'] ) ? sanitize_text_field( wp_unslash( $_POST['enable_store_checkout'] ) ) : '';
1047 $checkout_id = isset( $_POST['checkout_id'] ) ? absint( wp_unslash( $_POST['checkout_id'] ) ) : '';
1048
1049 $old_global_checkout = get_option( '_cartflows_old_global_checkout ', false );
1050 $checkout_id = $old_global_checkout ? absint( $old_global_checkout ) : $checkout_id;
1051
1052 $common_settings = \Cartflows_Helper::get_common_settings();
1053
1054 $override_status = 'enable';
1055 if ( 'false' === $enable_store_checkout ) {
1056 $checkout_id = '';
1057 $override_status = 'disable';
1058 }
1059
1060 $common_settings['global_checkout'] = $checkout_id;
1061 $common_settings['override_global_checkout'] = $override_status;
1062
1063 AdminHelper::update_admin_settings_option( '_cartflows_common', $common_settings, false );
1064
1065 do_action( 'cartflows_after_save_store_checkout' );
1066
1067 /**
1068 * Redirect to the new flow edit screen
1069 */
1070 $response_data = array(
1071 'message' => __( 'Successfully updated the Funnel status!', 'cartflows' ),
1072 'checkout_id' => $checkout_id,
1073 );
1074 wp_send_json_success( $response_data );
1075 }
1076
1077
1078 /**
1079 * Prepare where items for query.
1080 */
1081 public function reorder_flow_steps() {
1082
1083 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
1084
1085 /**
1086 * Check permission
1087 */
1088 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
1089 wp_send_json_error( $response_data );
1090 }
1091
1092 /**
1093 * Nonce verification
1094 */
1095 if ( ! check_ajax_referer( 'cartflows_reorder_flow_steps', 'security', false ) ) {
1096 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
1097 wp_send_json_error( $response_data );
1098 }
1099
1100 $flow_id = false;
1101 $step_ids = array();
1102
1103 if ( isset( $_POST['post_id'] ) && isset( $_POST['step_ids'] ) ) {
1104 $flow_id = intval( $_POST['post_id'] );
1105 $step_ids = explode( ',', sanitize_text_field( $_POST['step_ids'] ) );
1106 $step_ids = array_map( 'intval', $step_ids );
1107 }
1108
1109 $response_data = array(
1110 'status' => false,
1111 'text' => __( 'Invalid flow ID has been provided.', 'cartflows' ),
1112 );
1113
1114 if ( ! $flow_id ) {
1115 wp_send_json( $response_data );
1116 }
1117
1118 if ( CARTFLOWS_FLOW_POST_TYPE !== get_post_type( $flow_id ) ) {
1119 wp_send_json( $response_data );
1120 }
1121
1122 if ( empty( $step_ids ) ) {
1123 wp_send_json(
1124 array(
1125 'status' => false,
1126 /* translators: %s flow id */
1127 'text' => sprintf( __( 'Steps not sorted for flow - %s', 'cartflows' ), $flow_id ),
1128 )
1129 );
1130 }
1131
1132 $flow_steps = get_post_meta( $flow_id, 'wcf-steps', true );
1133 $flow_steps_map = array();
1134
1135 if ( is_array( $flow_steps ) ) {
1136 foreach ( $flow_steps as $key => $value ) {
1137 $flow_steps_map[ $value['id'] ] = $value;
1138 }
1139 }
1140
1141 $new_flow_steps = array();
1142
1143 foreach ( $step_ids as $index => $step_id ) {
1144
1145 $new_flow_step_data = array();
1146
1147 if ( isset( $flow_steps_map[ $step_id ] ) ) {
1148 $new_flow_step_data = $flow_steps_map[ $step_id ];
1149 }
1150
1151 $new_flow_step_data['id'] = intval( $step_id );
1152 $new_flow_step_data['title'] = get_the_title( $step_id );
1153 $new_flow_step_data['type'] = get_post_meta( $step_id, 'wcf-step-type', true );
1154
1155 $new_flow_steps[] = $new_flow_step_data;
1156 }
1157
1158 update_post_meta( $flow_id, 'wcf-steps', $new_flow_steps );
1159
1160 /* Setup steps data */
1161 $meta_options = AdminHelper::get_flow_meta_options( $flow_id );
1162 $steps = AdminHelper::prepare_step_data( $flow_id, $meta_options );
1163
1164 $result = array(
1165 'status' => true,
1166 /* translators: %s flow id */
1167 'text' => sprintf( __( 'Steps sorted for flow - %s', 'cartflows' ), $flow_id ),
1168 'steps' => $steps,
1169 );
1170
1171 wp_send_json( $result );
1172 }
1173
1174 /**
1175 * Hide the instant Checkout Notice.
1176 *
1177 * @since X.X.X
1178 * @return void
1179 */
1180 public function hide_instant_checkout_notice() {
1181
1182 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
1183
1184 /**
1185 * Check permission
1186 */
1187 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
1188 wp_send_json_error( $response_data );
1189 }
1190
1191 /**
1192 * Nonce verification
1193 */
1194 if ( ! check_ajax_referer( 'cartflows_hide_instant_checkout_notice', 'security', false ) ) {
1195 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
1196 wp_send_json_error( $response_data );
1197 }
1198
1199 if ( ! isset( $_POST['flow_id'] ) ) {
1200 $response_data = array( 'message' => __( 'No Funnel ID is been supplied', 'cartflows' ) );
1201 wp_send_json_error( $response_data );
1202 }
1203
1204 $flow_id = isset( $_POST['flow_id'] ) ? intval( $_POST['flow_id'] ) : 0;
1205
1206 // Set dismiss notice option for all flows.
1207 update_post_meta( $flow_id, 'wcf-instant-checkout-notice-skipped', 'yes' );
1208 update_option( 'wcf-instant-checkout-notice-skipped', 'yes' );
1209
1210 $result = array(
1211 'status' => true,
1212 /* translators: %s flow id */
1213 'text' => __( 'Notice Dismissed', 'cartflows' ),
1214 'instant_notice_status' => 'yes',
1215 );
1216
1217 wp_send_json( $result );
1218 }
1219
1220 /**
1221 * Get published flows for analytics dropdown.
1222 *
1223 * Returns only ID and title for better performance.
1224 *
1225 * @since 2.1.19
1226 * @return void
1227 */
1228 public function get_published_flows() {
1229 $response_data = array( 'message' => $this->get_error_msg( 'permission' ) );
1230
1231 /**
1232 * Check permission
1233 */
1234 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
1235 wp_send_json_error( $response_data );
1236 }
1237
1238 /**
1239 * Nonce verification
1240 */
1241 if ( ! check_ajax_referer( 'cartflows_get_published_flows', 'security', false ) ) {
1242 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
1243 wp_send_json_error( $response_data );
1244 }
1245
1246 // Query only IDs for better performance.
1247 $flow_ids = get_posts(
1248 array(
1249 'post_type' => CARTFLOWS_FLOW_POST_TYPE,
1250 'post_status' => 'publish',
1251 'posts_per_page' => -1,
1252 'fields' => 'ids',
1253 'orderby' => 'title',
1254 'order' => 'ASC',
1255 'no_found_rows' => true, // Skip pagination calculations.
1256 'update_post_meta_cache' => false, // Skip meta cache.
1257 'update_post_term_cache' => false, // Skip term cache.
1258 )
1259 );
1260
1261 $flows = array();
1262
1263 if ( ! empty( $flow_ids ) && is_array( $flow_ids ) ) {
1264 foreach ( $flow_ids as $flow_id ) {
1265 $flow_title = get_the_title( $flow_id );
1266
1267 if ( ! empty( $flow_title ) ) {
1268 $flows[] = array(
1269 'flow_id' => $flow_id,
1270 'flow_title' => $flow_title,
1271 );
1272 }
1273 }
1274 }
1275
1276 wp_send_json_success( array( 'flows' => $flows ) );
1277 }
1278 }
1279