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 / learn.php

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

180 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CartFlows Learn 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
17 /**
18 * Class Learn.
19 */
20 class Learn extends AjaxBase {
21
22 /**
23 * Instance
24 *
25 * @access private
26 * @var object Class object.
27 * @since 1.0.0
28 */
29 private static $instance;
30
31 /**
32 * Initiator
33 *
34 * @since 1.0.0
35 * @return object initialized object of class.
36 */
37 public static function get_instance() {
38 if ( ! isset( self::$instance ) ) {
39 self::$instance = new self();
40 }
41 return self::$instance;
42 }
43
44 /**
45 * Register_ajax_events.
46 *
47 * @return void
48 */
49 public function register_ajax_events() {
50
51 if ( current_user_can( 'cartflows_manage_settings' ) ) {
52
53 $ajax_events = array(
54 'save_learn_completed',
55 'track_learn_event',
56 );
57 $this->init_ajax_events( $ajax_events );
58 }
59 }
60
61 /**
62 * Localize nonce for ajax call — Learn handlers require the settings capability, not the flows one.
63 *
64 * @since x.x.x
65 * @param string $action Action name.
66 * @return void
67 */
68 public function localize_ajax_action_nonce( $action ) {
69
70 if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
71 return;
72 }
73
74 add_filter(
75 'cartflows_admin_localized_vars',
76 function( $localize ) use ( $action ) {
77
78 $localize[ $action . '_nonce' ] = wp_create_nonce( 'cartflows_' . $action );
79 return $localize;
80 }
81 );
82 }
83
84 /**
85 * AJAX handler – persist completed module IDs to option.
86 *
87 * @return void
88 */
89 public function save_learn_completed() {
90 check_ajax_referer( 'cartflows_save_learn_completed', 'nonce' );
91
92 $module_ids = isset( $_POST['module_ids'] )
93 ? json_decode( sanitize_text_field( wp_unslash( $_POST['module_ids'] ) ), true )
94 : array();
95
96 if ( ! is_array( $module_ids ) ) {
97 wp_send_json_error();
98 }
99
100 $module_ids = array_map( 'sanitize_text_field', $module_ids );
101
102 // Store manual ticks only — auto-completed IDs would otherwise stick after the store stops satisfying them.
103 $module_ids = \Cartflows_Learn_Progress::get_instance()->filter_manual_ids( $module_ids );
104
105 update_option( 'wcf_learn_data', $module_ids );
106
107 wp_send_json_success();
108 }
109
110 /**
111 * AJAX handler – record a browser-side Learn event via BSF Analytics.
112 *
113 * Every value is whitelisted so this endpoint cannot become an arbitrary-event writer.
114 *
115 * @since x.x.x
116 * @return void
117 */
118 public function track_learn_event() {
119 check_ajax_referer( 'cartflows_track_learn_event', 'nonce' );
120
121 if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
122 wp_send_json_error();
123 }
124
125 $event = isset( $_POST['event'] ) ? sanitize_key( wp_unslash( $_POST['event'] ) ) : '';
126
127 if ( ! in_array( $event, \Cartflows_Analytics::get_trackable_learn_events(), true ) ) {
128 wp_send_json_error();
129 }
130
131 $analytics = \Cartflows_Analytics::get_instance();
132
133 if ( 'learn_page_viewed' === $event ) {
134 $analytics->track_learn_page_view();
135 wp_send_json_success();
136 }
137
138 if ( 'learn_video_opened' === $event ) {
139 $analytics->track_learn_video_opened();
140 wp_send_json_success();
141 }
142
143 $module_id = isset( $_POST['module_id'] ) ? sanitize_key( wp_unslash( $_POST['module_id'] ) ) : '';
144
145 if ( ! in_array( $module_id, \Cartflows_Learn_Progress::get_module_ids(), true ) ) {
146 wp_send_json_error();
147 }
148
149 if ( 'learn_action_failed' === $event ) {
150 $reason = isset( $_POST['reason'] ) ? sanitize_key( wp_unslash( $_POST['reason'] ) ) : '';
151
152 if ( ! in_array( $reason, \Cartflows_Analytics::get_learn_failure_reasons(), true ) ) {
153 wp_send_json_error();
154 }
155
156 $plugin_slug = isset( $_POST['plugin_slug'] ) ? sanitize_key( wp_unslash( $_POST['plugin_slug'] ) ) : '';
157 $plugin_slug = in_array( $plugin_slug, \Cartflows_Analytics::get_learn_plugin_slugs(), true ) ? $plugin_slug : '';
158
159 $analytics->track_learn_action_failed( $module_id, $reason, $plugin_slug );
160 wp_send_json_success();
161 }
162
163 // Fail closed: a newly whitelisted event must be routed explicitly, never treated as a CTA click.
164 if ( 'learn_module_action' !== $event ) {
165 wp_send_json_error();
166 }
167
168 $action_type = isset( $_POST['action_type'] ) ? sanitize_key( wp_unslash( $_POST['action_type'] ) ) : '';
169
170 if ( ! in_array( $action_type, \Cartflows_Analytics::get_learn_action_types(), true ) ) {
171 wp_send_json_error();
172 }
173
174 $is_pro = isset( $_POST['is_pro'] ) && 'yes' === sanitize_key( wp_unslash( $_POST['is_pro'] ) );
175
176 $analytics->track_learn_module_action( $module_id, $action_type, $is_pro );
177 wp_send_json_success();
178 }
179 }
180