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

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