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
← All changes | admin-core/ajax/learn.php +97 -0 3.1.3 → 3.3.0 View file →
@@ -51,8 +51,9 @@
51 51 if ( current_user_can( 'cartflows_manage_settings' ) ) {
52 52
53 53 $ajax_events = array(
54 54 'save_learn_completed',
55 + 'track_learn_event',
55 56 );
56 57 $this->init_ajax_events( $ajax_events );
57 58 }
58 59 }
@@ -57,8 +58,31 @@
57 58 }
58 59 }
59 60
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 + /**
61 85 * AJAX handler – persist completed module IDs to option.
62 86 *
63 87 * @return void
64 88 */
@@ -74,9 +98,82 @@
74 98 }
75 99
76 100 $module_ids = array_map( 'sanitize_text_field', $module_ids );
77 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 +
78 105 update_option( 'wcf_learn_data', $module_ids );
79 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 );
80 177 wp_send_json_success();
81 178 }
82 179 }