PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.3
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / includes / core / classes / class-wpfnl-ajax-handler.php

class-wpfnl-ajax-handler.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.3, at includes/core/classes/class-wpfnl-ajax-handler.php

930 lines 33.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Ajax handler
5 *
6 * @package
7 */
8
9 namespace WPFunnels\Ajax_Handler;
10
11 use Elementor\Plugin;
12 use Elementor\Utils;
13 use WPFunnels\Frontend\Recaptcha\Google_Recaptcha_Handler;
14 use WPFunnels\Optin\Optin_Record;
15 use WPFunnels\Wpfnl_functions;
16 use function Mollie\WooCommerce\errorNotice;
17 use WPFunnels\Conditions\Wpfnl_Condition_Checker;
18
19 /**
20 * Class Ajax_Handler
21 *
22 * @package WPFunnels\Widgets\Elementor
23 */
24 class Ajax_Handler {
25
26 /**
27 * Upper bound on notification recipients for a single opt-in submission.
28 *
29 * @since 3.12.14
30 */
31 const MAX_NOTIFICATION_RECIPIENTS = 10;
32
33 /**
34 * Initializes AJAX actions and filters for handling different types of form submissions.
35 * Sets up AJAX hooks for various form submission scenarios, including shortcode and Gutenberg submissions.
36 * Also hooks into the 'mailmint_after_form_submit_response' filter for processing form submissions.
37 */
38 public function __construct() {
39 add_action( 'wp_ajax_wpfnl_optin_submission', [ $this, 'optin_form_submission' ] );
40 add_action( 'wp_ajax_nopriv_wpfnl_optin_submission', [ $this, 'optin_form_submission' ] );
41
42 add_action( 'wp_ajax_wpfnl_shortcode_optin_submission', [ $this, 'wpfnl_shortcode_optin_submission' ] );
43 add_action( 'wp_ajax_nopriv_wpfnl_shortcode_optin_submission', [ $this, 'wpfnl_shortcode_optin_submission' ] );
44
45 add_action( 'wp_ajax_wpfnl_gutenberg_optin_submission', [ $this, 'gutenberg_optin_form_submission' ] );
46 add_action( 'wp_ajax_nopriv_wpfnl_gutenberg_optin_submission', [ $this, 'gutenberg_optin_form_submission' ] );
47
48 }
49
50
51 /**
52 * Optin form submission handler for elementor
53 *
54 * @return void
55 * @since 2.5.7
56 */
57 public function optin_form_submission() {
58 check_ajax_referer( 'optin_form_nonce', 'security' );
59
60 $step_id = isset( $_POST[ 'step_id' ] ) ? $_POST[ 'step_id' ] : '';
61 $postData = isset( $_POST[ 'postData' ] ) ? $_POST[ 'postData' ] : '';
62
63 $funnel_id = Wpfnl_functions::get_funnel_id_from_step( $step_id );
64 $post_data = array();
65 wp_parse_str( $postData, $post_data );
66
67 if ( isset( $post_data[ 'email' ] ) ) {
68 $post_data[ 'email' ] = strtolower( $post_data[ 'email' ] );
69 }
70
71 $url = isset( $_POST[ 'url' ] ) ? $_POST[ 'url' ] : '';
72 $parts = parse_url( $url );
73 $query = [];
74 if ( isset( $parts[ 'query' ] ) ) {
75 parse_str( $parts[ 'query' ], $query );
76 }
77
78 $elementor = Plugin::instance();
79 $document = $elementor->documents->get( $step_id );
80 $form = null;
81 if ( $document ) {
82 $form = Utils::find_element_recursive( $document->get_elements_data(), $post_data[ 'form_id' ] );
83 }
84
85 if ( empty( $form ) ) {
86 $results = array(
87 'message' => 'invalid_form',
88 'success' => false
89 );
90 echo json_encode( $results );
91 die();
92 }
93
94 $widget = $elementor->elements_manager->create_element_instance( $form );
95 $form[ 'settings' ] = $widget->get_settings_for_display();
96 unset( $post_data[ 'post_id' ] );
97 unset( $post_data[ 'form_id' ] );
98
99 $record = new Optin_Record( $post_data, $form );
100 $fields = $record->get_fields();
101 $name = '';
102 if ( $fields ) {
103 foreach( $fields as $key => $value ) {
104 if ( 'email' === $key ) {
105 $name = strstr( $value, '@', true );;
106 }
107 elseif ( 'last_name' === $key ) {
108 $name = $value;
109 }
110 elseif ( 'first_name' === $key ) {
111 $name = $value;
112 }
113 }
114 }
115
116 $response = array(
117 'success' => true,
118 'post_action' => 'notification',
119 'notification_text' => '',
120 'redirect_url' => '#'
121 );
122
123 $post_action = $form[ 'settings' ][ 'post_action' ];
124 $response[ 'post_action' ] = $post_action;
125 $action_type = '';
126 $response[ 'notification_text' ] = isset( $form[ 'settings' ][ 'notification_text' ] ) && $form[ 'settings' ][ 'notification_text' ] ? $form[ 'settings' ][ 'notification_text' ] : '';
127 $next_step = [];
128 switch( $post_action ) {
129 case 'notification':
130 $response[ 'redirect' ] = false;
131 break;
132 case 'redirect_to':
133 $action_type = 'redirect_to_url';
134 $response[ 'redirect' ] = true;
135 if ( !empty( $form[ 'settings' ][ 'redirect_url' ] ) ) {
136 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), $form[ 'settings' ][ 'redirect_url' ][ 'url' ] );
137 }
138 else {
139 $response[ 'redirect_url' ] = '#';
140 }
141 break;
142 default:
143 $action_type = 'next_step';
144 $next_step = Wpfnl_functions::get_next_step( $funnel_id, $step_id );
145 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), get_the_permalink( $next_step[ 'step_id' ] ) );
146 $response[ 'redirect' ] = true;
147 }
148
149 $admin_email = isset( $form[ 'settings' ][ 'admin_email' ] ) ? $form[ 'settings' ][ 'admin_email' ] : false;
150 $admin_email_subject = isset( $form[ 'settings' ][ 'admin_email_subject' ] ) ? $form[ 'settings' ][ 'admin_email_subject' ] : 'Opt-in form Submission';
151
152 $user_info = $record->form_data;
153
154 /**
155 * User registration
156 */
157 if ( !empty( $form[ 'settings' ][ 'allow_registration' ] ) && 'yes' == $form[ 'settings' ][ 'allow_registration' ] ) {
158
159 $this->create_user_optin_allow_registration( $name, $user_info );
160 }
161
162
163 /**
164 * Recaptcha Check
165 */
166 $recaptcha = $this->get_trusted_recaptcha_settings();
167 $recaptcha_response = isset( $post_data[ 'wpf-optin-g-token' ] ) ? $post_data[ 'wpf-optin-g-token' ] : '';
168
169 $response = $this->send_mail_after_checking_google_recaptcha_response( $recaptcha[ 'enabled' ], $recaptcha_response, $recaptcha[ 'secret' ], $admin_email, $admin_email_subject, $user_info, $response );
170
171 if( \WPFunnels\Integrations\Helper::maybe_enabled() && !empty($form[ 'settings' ]['enable_mm_contact']) && 'yes' === $form[ 'settings' ]['enable_mm_contact'] ){
172 $lists = [];
173 $tags = [];
174 if ( !empty($form[ 'settings' ][ 'mm_lists' ]) ){
175 $data = \WPFunnels\Integrations\Helper::get_list_by_id($form[ 'settings' ][ 'mm_lists' ]);
176 if( isset($data['id'],$data['title'])){
177 $lists = [
178 [
179 'id' => $data['id'],
180 'title' => $data['title']
181 ]
182 ];
183 }
184 }
185 if ( !empty($form[ 'settings' ][ 'mm_tags' ]) ){
186 $data = \WPFunnels\Integrations\Helper::get_list_by_id($form[ 'settings' ][ 'mm_tags' ]);
187 if( isset($data['id'],$data['title'])){
188 $tags = [
189 [
190 'id' => $data['id'],
191 'title' => $data['title']
192 ]
193 ];
194 }
195 }
196
197 if ( !empty($form[ 'settings' ][ 'mm_contact_status' ]) ){
198 $user_info['status'] = $form[ 'settings' ][ 'mm_contact_status' ];
199 }
200
201 $user_info['meta_fields']['phone_number'] = isset( $user_info['phone'] ) ?$user_info['phone'] : '';
202
203 $mail_mint_object = new \WPFunnels\Integrations\MailMint( $user_info, $lists, $tags );
204 $mail_mint_object->create_or_update_contact();
205 $mail_mint_object->add_contact_to_lists();
206 $mail_mint_object->add_contact_to_tags();
207 }
208
209
210 /**
211 * Submit & process form data
212 */
213 ob_start();
214 do_action( 'wpfunnels/after_optin_submit', $step_id, $post_action, $action_type, $record, $post_data );
215 ob_get_clean();
216
217 if ( !empty( $next_step[ 'step_type' ] ) && 'conditional' == $next_step[ 'step_type' ] ) {
218 $next_step = $this->match_conditional_step( $next_step, $funnel_id, $step_id );
219 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), get_the_permalink( $next_step[ 'step_id' ] ) );
220 }
221
222 if ( isset( $next_step[ 'step_type' ] ) && 'thankyou' === $next_step[ 'step_type' ] ) {
223 $custom_url = Wpfnl_functions::custom_url_for_thankyou_page( $next_step[ 'step_id' ] );
224 if ( $custom_url ) {
225 $response[ 'redirect_url' ] = $custom_url;
226 }
227 }
228
229 echo json_encode( $response, true );
230 die();
231 }
232
233
234 /**
235 * Prepare query param for redirect url
236 *
237 * @param String $name
238 * @param array $query
239 *
240 * @return array
241 * @since 2.5.9
242 */
243 private function prepare_query_param( $name, $query ) {
244 $query_param = [ 'optin' => true, 'uname' => $name, ];
245
246 $required_keys = [ 'wpfnl-order', 'wpfnl-key', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_content' ];
247
248 foreach( $required_keys as $key ) {
249 if ( !empty( $query[ $key ] ) ) {
250 $query_param[ $key ] = $query[ $key ];
251 }
252 }
253
254 return apply_filters('wpfunnels/update_query_param', $query_param);
255 }
256
257
258 /**
259 * Optin submission handling for shortcode
260 *
261 * @return void
262 * @since @since 2.5.7
263 */
264 public function wpfnl_shortcode_optin_submission( $response = [] ) {
265 $post = filter_input_array( INPUT_POST );
266 if ( !wp_verify_nonce( htmlspecialchars( $post[ 'security' ] ?? '' ), 'optin_form_nonce' )
267 && !wp_verify_nonce( htmlspecialchars( $post[ 'wp_nonce' ] ?? '' ), 'wp_rest' ) ) {
268 wp_send_json_error( array( 'message' => __( 'Unauthorized request', 'wpfnl' ) ), 403 );
269 }
270
271 $return = true;
272 if ( empty( $response ) ) {
273 $response = [];
274 $return = false;
275 }
276
277 $response[ 'success' ] = true;
278 $response[ 'post_action' ] = 'notification';
279 $response[ 'notification_text' ] = '';
280 $response[ 'redirect_url' ] = '#';
281
282 $post_data = htmlspecialchars( $post[ 'postData' ] ?? '' );
283 $post_data = empty( $post_data ) ? htmlspecialchars( $post[ 'post_data' ] ?? '' ) : $post_data;
284 $post_data = !empty( $post_data ) ? str_replace( 'amp;', '&', $post_data ) : $post_data;
285 wp_parse_str( $post_data, $post_data );
286
287 if ( !empty( $post_data ) ) {
288 $post_data[ 'email' ] = !empty( $post_data[ 'email' ] ) && is_email( $post_data[ 'email' ] ) ? strtolower( sanitize_email( $post_data[ 'email' ] ) ) : '';
289 $parts = wp_parse_url( filter_input( INPUT_POST, 'url', FILTER_VALIDATE_URL ) );
290 $parts_query = $parts[ 'query' ] ?? '';
291 wp_parse_str( $parts_query, $query );
292 $step_id = $post_data[ 'step_id' ] ?? null;
293 if( isset($post_data[ 'post_id' ]) ){
294 $step_id = $step_id ? $step_id : $post_data[ 'post_id' ] ?? null;
295 }
296
297 $funnel_id = $step_id ? Wpfnl_functions::get_funnel_id_from_step( $step_id ) : null;
298 $post_action = $post_data[ 'post_action' ] ?? 'notification';
299 $response[ 'post_action' ] = $post_action;
300 $response[ 'notification_text' ] = $post_data[ 'notification_text' ] ?? '';
301 $user_info = $this->extract_user_info( $post_data );
302 $name = $user_info[ 'email' ] ? strstr( $user_info[ 'email' ], '@', true ) : '';
303 $query_params = $this->prepare_query_param( $name, $query );
304 $actions = $this->process_post_action( $post_action, $post_data, $response, $query_params, $step_id, $funnel_id );
305 $response = $actions[ 'response' ] ?? $response;
306 $next_step = $actions[ 'next_step' ] ?? [];
307 $action_type = $actions[ 'action_type' ] ?? '';
308 /**
309 * Filters the response after opt-in for submission.
310 *
311 * This filter hook allows developers to modify or override the response generated
312 * for an opt-in form submission.
313 *
314 * @param array $response The response generated after opt-in for submission.
315 * @param array $post_data The post data received from the opt-in form submission.
316 * @param array $user_info The user information extracted from the form submission.
317 * @return array Modified response array.
318 *
319 * @since 2.8.2
320 */
321 $response = apply_filters( 'wpfunnels/optin_submission_response', $this->process_recaptcha( $post_data, $response, $user_info ), $funnel_id, $step_id, $next_step, $query_params );
322 $record = new \stdClass();
323 $record->form_data = $user_info;
324
325 if ( isset( $next_step[ 'step_type' ] ) && 'thankyou' === $next_step[ 'step_type' ] ) {
326 $custom_url = Wpfnl_functions::custom_url_for_thankyou_page( $next_step[ 'step_id' ] );
327 if ( $custom_url ) {
328 $response[ 'redirect_url' ] = $custom_url;
329 }
330 }
331
332 if( \WPFunnels\Integrations\Helper::maybe_enabled() && !empty($post_data['enable_mm_contact']) && 'yes' === $post_data['enable_mm_contact'] ){
333 $lists = [];
334 $tags = [];
335 if ( !empty($post_data[ 'mm_lists' ]) ){
336 $data = \WPFunnels\Integrations\Helper::get_list_by_id($post_data[ 'mm_lists' ]);
337 if( isset($data['id'],$data['title'])){
338 $lists = [
339 [
340 'id' => $data['id'],
341 'title' => $data['title']
342 ]
343 ];
344 }
345 }
346 if ( !empty($post_data[ 'mm_tags' ]) ){
347 $data = \WPFunnels\Integrations\Helper::get_list_by_id($post_data[ 'mm_tags' ]);
348 if( isset($data['id'],$data['title'])){
349 $tags = [
350 [
351 'id' => $data['id'],
352 'title' => $data['title']
353 ]
354 ];
355 }
356 }
357
358 if ( !empty($post_data[ 'mm_contact_status' ]) ){
359 $user_info['status'] = $post_data[ 'mm_contact_status' ];
360 }
361
362 $user_info['meta_fields']['phone_number'] = isset( $user_info['phone'] ) ?$user_info['phone'] : '';
363
364 $mail_mint_object = new \WPFunnels\Integrations\MailMint( $user_info, $lists, $tags );
365 $mail_mint_object->create_or_update_contact();
366 $mail_mint_object->add_contact_to_lists();
367 $mail_mint_object->add_contact_to_tags();
368 }
369
370
371
372
373 /**
374 * Fires after an opt-in form submission in a funnel step.
375 *
376 * This action hook is triggered after the submission of an opt-in form in a funnel step.
377 * It provides the opportunity to perform additional actions or processes after the opt-in form is submitted.
378 *
379 * @param int $step_id The ID of the funnel step where the opt-in form was submitted.
380 * @param string $post_action The type of action taken after form submission (e.g., 'notification', 'redirect_to', 'next_step').
381 * @param string $action_type The type of action that determined the redirection or next step behavior.
382 * @param object $record An object containing data related to the form submission.
383 * @param array $post_data The post data received from the form submission.
384 *
385 * @since @since 2.5.7
386 */
387 ob_start();
388 do_action( 'wpfunnels/after_optin_submit', $step_id, $post_action, $action_type, $record, $post_data );
389 ob_get_clean();
390
391 if ( $return ) return $response;
392
393 echo json_encode( $response, true );
394 }
395 die();
396 }
397
398 /**
399 * Extracts user information from the provided post data.
400 *
401 * This function extracts specific user information fields from the given post data.
402 * The function iterates through a predefined list of user fields and extracts
403 * their values from the post data.
404 *
405 * @param array $post_data The post data containing user information.
406 *
407 * @return array The extracted user information as an associative array.
408 * @since 2.8.2
409 */
410 private function extract_user_info( $post_data ) {
411 $user_info = [];
412 $user_fields = [ 'email', 'last_name', 'first_name', 'phone', 'web-url', 'message', 'data_to_checkout' ];
413
414 // Iterate through user fields and extract their values from post data
415 foreach( $user_fields as $key ) {
416 if ( !empty( $post_data[ $key ] ) ) {
417 $user_info[ $key ] = $post_data[ $key ];
418 }
419 }
420
421 return $user_info;
422 }
423
424 /**
425 * Processes the post action based on the provided data and returns relevant response information.
426 *
427 * This function takes the post action, post data, response, query parameters, step ID, and funnel ID
428 * to determine the appropriate action and response details. It handles different post action cases,
429 * such as 'notification', 'redirect_to', and the default case. It prepares the necessary response data
430 * including whether a redirect is required, the action type, and the next step information.
431 *
432 * @param string $post_action The post action type.
433 * @param array $post_data The post data containing user inputs.
434 * @param array $response The current response data.
435 * @param array $query_params The query parameters to add to the URL.
436 * @param int $step_id The ID of the current step.
437 * @param int $funnel_id The ID of the current funnel.
438 *
439 * @return array An associative array containing the updated response, next step information, and action type.
440 * @since 2.8.2
441 */
442 private function process_post_action( $post_action, $post_data, $response, $query_params, $step_id, $funnel_id ) {
443 switch( $post_action ) {
444 case 'notification':
445 $response[ 'redirect' ] = false;
446 break;
447 case 'redirect_to':
448 $response[ 'redirect' ] = true;
449 $response[ 'confirmation_type' ] = 'to_a_custom_url';
450 $action_type = 'redirect_to_url';
451 if ( !empty( $post_data[ 'redirect_url' ] ) ) {
452 if ( 'next_step' !== $post_data[ 'redirect_url' ] ) {
453 $redirect_url = sanitize_url( add_query_arg( $query_params, $post_data[ 'redirect_url' ] ) );
454 $response[ 'redirect_url' ] = $redirect_url;
455 $response[ 'custom_url' ] = $redirect_url;
456 break;
457 }
458 $action_type = 'next_step';
459 $next_step = $funnel_id ? Wpfnl_functions::get_next_step( $funnel_id, $step_id ) : '';
460 if ( $next_step ) {
461 $redirect_url = sanitize_url( add_query_arg( $query_params, get_the_permalink( $next_step[ 'step_id' ] ) ) );
462 $response[ 'redirect_url' ] = $redirect_url;
463 $response[ 'custom_url' ] = $redirect_url;
464 break;
465 }
466 $response[ 'redirect_url' ] = '#';
467 break;
468 }
469 $response[ 'redirect_url' ] = '#';
470 break;
471 default:
472 $action_type = 'next_step';
473 $next_step = $funnel_id ? Wpfnl_functions::get_next_step( $funnel_id, $step_id ) : '';
474
475 if ( $next_step ) {
476 $redirect_url = sanitize_url( add_query_arg( $query_params, get_the_permalink( $next_step[ 'step_id' ] ) ) );
477 $response[ 'redirect_url' ] = $redirect_url;
478 $response[ 'custom_url' ] = $redirect_url;
479 }
480 else {
481 $response[ 'redirect_url' ] = '#';
482 }
483 $response[ 'redirect' ] = true;
484 $response[ 'confirmation_type' ] = 'to_a_custom_url';
485 }
486
487 return [
488 'response' => $response,
489 'next_step' => $next_step ?? [],
490 'action_type' => $action_type ?? ''
491 ];
492 }
493
494 /**
495 * Processes reCAPTCHA and sends an email after checking Google reCAPTCHA response.
496 *
497 * This function takes the post data, response, and user information, and processes reCAPTCHA
498 * by checking the Google reCAPTCHA response. It then sends an email with the provided user information.
499 *
500 * @param array $post_data The post data containing user inputs and reCAPTCHA details.
501 * @param array $response The current response data.
502 * @param array $user_info The user information to include in the email.
503 *
504 * @return array The updated response after processing reCAPTCHA and sending the email.
505 * @since 2.8.2
506 */
507 private function process_recaptcha( $post_data, $response, $user_info ) {
508 $admin_email = $post_data[ 'admin_email' ] ?? false;
509 $admin_email_subject = $post_data[ 'admin_email_subject' ] ?? 'Opt-in form Submission';
510 $allow_registration = $post_data[ 'optin_allow_registration' ] ?? '';
511 $token = $post_data[ 'wpfnl_optin_settings_token' ] ?? '';
512
513 // The recipient and subject are hidden inputs, so they come back as request
514 // data. Honour them only when they are still the ones this form was
515 // rendered with; otherwise there is no notification to send.
516 if ( ! Wpfnl_functions::is_valid_optin_settings_token( $token, (string) $admin_email, (string) $admin_email_subject, (string) $allow_registration ) ) {
517 $admin_email = false;
518 $admin_email_subject = false;
519 }
520
521 $recaptcha = $this->get_trusted_recaptcha_settings();
522 $recaptcha_response = $post_data[ 'wpf-optin-g-token' ] ?? '';
523
524 return $this->send_mail_after_checking_google_recaptcha_response( $recaptcha[ 'enabled' ], $recaptcha_response, $recaptcha[ 'secret' ], $admin_email, $admin_email_subject, $user_info, $response );
525 }
526
527 /**
528 * reCAPTCHA configuration as stored for the site.
529 *
530 * Never read the switch or the secret from a submission: both are rendered
531 * into the form, so a caller can omit the switch or substitute keys for a
532 * challenge they control.
533 *
534 * @return array
535 * @since 3.12.14
536 */
537 private function get_trusted_recaptcha_settings() {
538 $settings = Wpfnl_functions::get_recaptcha_settings();
539 $enabled = isset( $settings[ 'enable_recaptcha' ] ) ? $settings[ 'enable_recaptcha' ] : 'no';
540 $secret = isset( $settings[ 'recaptcha_site_secret' ] ) ? $settings[ 'recaptcha_site_secret' ] : '';
541
542 return array(
543 'enabled' => ( 'on' === $enabled && $secret ) ? 'on' : 'off',
544 'secret' => $secret,
545 );
546 }
547
548 /**
549 * Gutenberg opt-in form handling
550 *
551 * @return void
552 * @since 2.5.9
553 */
554 public function gutenberg_optin_form_submission() {
555 check_ajax_referer( 'optin_form_nonce', 'security' );
556 $step_id = isset( $_POST[ 'step_id' ] ) ? $_POST[ 'step_id' ] : '';
557 $postData = isset( $_POST[ 'postData' ] ) ? $_POST[ 'postData' ] : '';
558 $funnel_id = Wpfnl_functions::get_funnel_id_from_step( $step_id );
559 $post_data = array();
560 parse_str( $postData, $post_data );
561
562 if ( isset( $post_data[ 'email' ] ) ) {
563 $post_data[ 'email' ] = strtolower( $post_data[ 'email' ] );
564 }
565
566 $post_id = $step_id;
567 $post = get_post( $post_id );
568 $all_blocks = parse_blocks( $post->post_content );
569
570 $url = isset( $_POST[ 'url' ] ) ? $_POST[ 'url' ] : '';
571 $parts = parse_url( $url );
572 $query = [];
573 if ( isset( $parts[ 'query' ] ) ) {
574 parse_str( $parts[ 'query' ], $query );
575 }
576
577 $admin_email = '';
578 $admin_email_subject = '';
579 $post_action = '';
580 $block_attr = array();
581
582 $record = new Optin_Record( $post_data );
583 $fields = $record->get_fields();
584 $name = '';
585 if ( $fields ) {
586 foreach( $fields as $key => $value ) {
587 if ( 'email' === $key ) {
588 $name = strstr( $value, '@', true );
589 }
590 elseif ( 'last_name' === $key ) {
591 $name = $value;
592 }
593 elseif ( 'first_name' === $key ) {
594 $name = $value;
595 }
596 }
597 }
598
599 $response = array(
600 'success' => true,
601 'post_action' => 'notification',
602 'notification_text' => '',
603 'redirect_url' => '#'
604 );
605 $custom_url = '';
606 $blocks = $this->search_items_by_key( $all_blocks, 'blockName' );
607 foreach( $blocks as $block ) {
608 if ( $block[ 'blockName' ] == 'wpfunnels/optin-form' ) {
609 $block_attr = $block[ 'attrs' ];
610
611 $admin_email = isset( $block_attr[ 'adminEmail' ] ) ? $block_attr[ 'adminEmail' ] : '';
612 $admin_email_subject = isset( $block_attr[ 'emailSubject' ] ) ? $block_attr[ 'emailSubject' ] : 'Opt-in form Submission';
613
614 $post_action = isset( $block_attr[ 'postAction' ] ) ? $block_attr[ 'postAction' ] : 'notification';
615 $custom_url = isset( $block_attr[ 'redirect_url' ] ) ? $block_attr[ 'redirect_url' ] : '#';
616 }
617 }
618
619 $response[ 'notification_text' ] = isset( $block_attr[ 'notification' ] ) ? $block_attr[ 'notification' ] : '';
620 $next_step = [];
621 switch( $post_action ) {
622 case 'notification':
623 $action_type = 'notification';
624 $response[ 'redirect' ] = false;
625 break;
626 case 'redirect_to':
627 $action_type = 'redirect_to_url';
628 $response[ 'redirect' ] = true;
629 $response[ 'post_action' ] = $post_action;
630 if ( $custom_url ) {
631 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), $custom_url );
632 }
633 else {
634 $response[ 'redirect_url' ] = '#';
635 }
636 break;
637 case 'next_step':
638 $response[ 'post_action' ] = $post_action;
639 $action_type = 'next_step';
640 $next_step = Wpfnl_functions::get_next_step( $funnel_id, $step_id );
641
642 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), get_the_permalink( $next_step[ 'step_id' ] ) );
643 $response[ 'redirect' ] = true;
644 break;
645 default:
646 $action_type = 'next_step';
647 $next_step = Wpfnl_functions::get_next_step( $funnel_id, $step_id );
648 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), get_the_permalink( $next_step[ 'step_id' ] ) );
649 $response[ 'redirect' ] = true;
650 }
651 /**
652 * User registration
653 */
654 if ( !empty( $block_attr[ 'registration_checkbox' ] ) ) {
655
656 $this->create_user_optin_allow_registration( $name, $post_data );
657 }
658 /**
659 * Check google Recaptcha V3
660 */
661 $recaptcha = $this->get_trusted_recaptcha_settings();
662 $recaptcha_response = isset( $post_data[ 'wpf-optin-g-token' ] ) ? $post_data[ 'wpf-optin-g-token' ] : '';
663
664 $response = $this->send_mail_after_checking_google_recaptcha_response( $recaptcha[ 'enabled' ], $recaptcha_response, $recaptcha[ 'secret' ], $admin_email, $admin_email_subject, $post_data, $response );
665
666
667 $user_data = [
668 'first_name' => $post_data['first_name'] ?? '',
669 'last_name' => $post_data['last_name'] ?? '',
670 'email' => $post_data['email'] ?? '',
671 'phone' => $post_data['phone'] ?? '',
672 'web-url' => $post_data['web-url'] ?? '',
673 ];
674
675 if( \WPFunnels\Integrations\Helper::maybe_enabled() && !empty($post_data['enable_mm_contact']) && 'yes' === $post_data['enable_mm_contact'] ){
676
677 $lists = [];
678 $tags = [];
679 if ( !empty($post_data[ 'mm_lists' ]) ){
680 $data = \WPFunnels\Integrations\Helper::get_list_by_id($post_data[ 'mm_lists' ]);
681 if( isset($data['id'],$data['title'])){
682 $lists = [
683 [
684 'id' => $data['id'],
685 'title' => $data['title']
686 ]
687 ];
688 }
689 }
690 if ( !empty($post_data[ 'mm_tags' ]) ){
691 $data = \WPFunnels\Integrations\Helper::get_list_by_id($post_data[ 'mm_tags' ]);
692 if( isset($data['id'],$data['title'])){
693 $tags = [
694 [
695 'id' => $data['id'],
696 'title' => $data['title']
697 ]
698 ];
699 }
700 }
701
702 if ( !empty($post_data[ 'mm_contact_status' ]) ){
703 $user_data['status'] = $post_data[ 'mm_contact_status' ];
704 }
705
706 $user_data['meta_fields']['phone_number'] = isset( $user_data['phone'] ) ?$user_data['phone'] : '';
707
708 $mail_mint_object = new \WPFunnels\Integrations\MailMint( $user_data, $lists, $tags );
709 $mail_mint_object->create_or_update_contact();
710 $mail_mint_object->add_contact_to_lists();
711 $mail_mint_object->add_contact_to_tags();
712 }
713
714 ob_start();
715 do_action( 'wpfunnels/after_optin_submit', $step_id, $post_action, $action_type, $record, $post_data );
716 ob_get_clean();
717
718 if ( !empty( $next_step[ 'step_type' ] ) && 'conditional' == $next_step[ 'step_type' ] ) {
719 $next_step = $this->match_conditional_step( $next_step, $funnel_id, $step_id );
720 $response[ 'redirect_url' ] = add_query_arg( $this->prepare_query_param( $name, $query ), get_the_permalink( $next_step[ 'step_id' ] ) );
721 }
722
723 if ( isset( $next_step[ 'step_type' ] ) && 'thankyou' === $next_step[ 'step_type' ] ) {
724 $custom_url = Wpfnl_functions::custom_url_for_thankyou_page( $next_step[ 'step_id' ] );
725 if ( $custom_url ) {
726 $response[ 'redirect_url' ] = $custom_url;
727 }
728 }
729
730
731 echo json_encode( $response, true );
732 die();
733 }
734
735
736 /**
737 * Search array item by key
738 *
739 * @param Array $array
740 * @param String $key
741 *
742 * @return Array
743 * @since 2.5.9
744 */
745 private function search_items_by_key( $array, $key ) {
746 $results = array();
747
748 if ( is_array( $array ) ) {
749 if ( isset( $array[ $key ] ) && key( $array ) == $key )
750 if ( $array[ $key ] == 'wpfunnels/optin-form' ) {
751 $results[] = $array;
752 }
753
754 foreach( $array as $sub_array )
755 $results = array_merge( $results, $this->search_items_by_key( $sub_array, $key ) );
756 }
757
758 return $results;
759 }
760
761
762 /**
763 * Send email to admin
764 *
765 * @param String $email
766 * @param String $subject
767 * @param Array $user_info
768 *
769 * @return void
770 * @since 2.5.9
771 */
772 private function send_email_to_admin( $emails = '', $subject = '', $user_info = [] ) {
773 $email_array = explode( ",", $emails );
774
775 // Bound the fan-out and drop anything that is not an address, so a single
776 // submission cannot be turned into a mail relay.
777 $email_array = array_slice( array_filter( array_map( 'trim', $email_array ) ), 0, self::MAX_NOTIFICATION_RECIPIENTS );
778
779 if ( is_array( $email_array ) ) {
780 foreach( $email_array as $email ) {
781
782 if ( $email && is_email( $email ) ) {
783 $email = trim( $email );
784 $current_date = date( "d M Y" );
785 $time = new \DateTimeImmutable( 'now', wp_timezone() );
786 $current_time = $time->format( "h:i A" );
787 $poweredBy = __( 'WPFunnels', 'wpfnl' );
788 $info = '';
789 if ( isset( $user_info[ 'first_name' ] ) && $user_info[ 'first_name' ] ) {
790 $esc_first_name = esc_html( $user_info[ 'first_name' ] );
791 $info .= "First Name : {$esc_first_name}<br>";
792 }
793 if ( isset( $user_info[ 'last_name' ] ) && $user_info[ 'last_name' ] ) {
794 $esc_last_name = esc_html( $user_info[ 'last_name' ] );
795 $info .= "Last Name : {$esc_last_name}<br>";
796 }
797 if ( isset( $user_info[ 'email' ] ) && $user_info[ 'email' ] ) {
798 $esc_email = esc_html( $user_info[ 'email' ] );
799 $info .= "Email : {$esc_email}<br><br>";
800 }
801 if ( isset( $user_info[ 'phone' ] ) && $user_info[ 'phone' ] ) {
802 $esc_phone = esc_html( $user_info[ 'phone' ] );
803 $info .= "Phone : {$esc_phone}<br><br>";
804 }
805 if ( isset( $user_info[ 'web-url' ] ) && $user_info[ 'web-url' ] ) {
806 $esc_url = esc_url( $user_info[ 'web-url' ] );
807 $info .= "Website URL : {$esc_url}<br><br>";
808 }
809 if ( isset( $user_info[ 'message' ] ) && $user_info[ 'message' ] ) {
810 $esc_html = esc_html( $user_info[ 'message' ] );
811 $info .= "Message : {$esc_html}<br><br>";
812 }
813 $info .= "----<br><br>Date : {$current_date} <br>Time : {$current_time} <br>Powered by : {$poweredBy} <br>";
814
815 $email_body = apply_filters('wpfunnels/after_optin_submit_admin_email_body', $info );
816 if ( !$subject ) {
817 $subject = 'New Submission';
818 }
819 $headers = [ 'Content-Type: text/html; charset=UTF-8' ];
820 wp_mail( $email, $subject, $email_body, $headers );
821 }
822 }
823 }
824 }
825
826
827 /**
828 * Create User as a subscriber
829 * When allow the subscriber option for registration from builder
830 *
831 * Registration is refused unless the site itself allows it. Every caller
832 * routes through here - the Elementor and Gutenberg submission handlers as
833 * well as the after_optin_submit callback - so the site-wide switch is
834 * enforced at this one choke point rather than at each call site, and any
835 * future caller inherits it. On multisite, core filters
836 * option_users_can_register from the network registration setting, so this
837 * is the correct check there too.
838 *
839 * @param $name
840 * @param $post_data
841 *
842 * @since 2.5.9
843 */
844 public static function create_user_optin_allow_registration( $name, $post_data ) {
845 if ( ! get_option( 'users_can_register' ) ) {
846 return;
847 }
848
849 $exist_user_by_username = get_user_by( 'login', $name );
850 $exist_user_by_email = get_user_by( 'email', $post_data[ 'email' ] );
851
852 if ( empty( $exist_user_by_email ) || empty( $exist_user_by_username ) ) {
853 $data = array(
854 'user_login' => $name,
855 'user_email' => isset( $post_data[ 'email' ] ) ? $post_data[ 'email' ] : '',
856 'first_name' => isset( $post_data[ 'first_name' ] ) ? $post_data[ 'first_name' ] : '',
857 'last_name' => isset( $post_data[ 'last_name' ] ) ? $post_data[ 'last_name' ] : '',
858 'user_pass' => wp_generate_password( 6, false ),
859 'role' => 'subscriber',
860 );
861 if ( isset( $post_data[ 'web-url' ] ) ) {
862 $data[ 'user_url' ] = $post_data[ 'web-url' ];
863 }
864 $user_id = wp_insert_user( $data );
865 if ( isset( $post_data[ 'phone' ] ) ) {
866 update_user_meta( $user_id, 'phone', $post_data[ 'phone' ] );
867 }
868 if ( !is_wp_error( $user_id ) ) {
869 wp_send_new_user_notifications( $user_id, $notify = 'both' );
870 }
871 }
872 }
873
874
875 /**
876 * Check Google recaptcha Response and Send mail
877 *
878 * @param $is_recaptcha
879 * @param $recaptcha_site_key
880 * @param $recaptcha_site_secrect
881 *
882 * @since 2.5.9
883 */
884
885 private function send_mail_after_checking_google_recaptcha_response( $is_recaptcha, $recaptcha_site_key, $recaptcha_site_secrect, $admin_email, $admin_email_subject, $post_data, $response ) {
886 $recaptcha_response = [];
887 if ( $recaptcha_site_key && $recaptcha_site_secrect && 'on' === $is_recaptcha ) {
888 $recaptcha_response = Google_Recaptcha_Handler::get_response_recaptcha( $recaptcha_site_secrect, $recaptcha_site_key );
889 }
890 if ( 'on' === $is_recaptcha ) {
891 if ( $admin_email && $admin_email_subject && isset( $post_data[ 'email' ] ) && $post_data[ 'email' ] && isset( $recaptcha_response->success ) && $recaptcha_response->success ) {
892 $this->send_email_to_admin( $admin_email, $admin_email_subject, $post_data );
893 }
894 else {
895 $response[ 'notification_text' ] = __( "reCAPTCHA is not Correct", 'wpfnl' );
896 $response[ 'success' ] = false;
897 return $response;
898 }
899 }
900 else {
901 if ( $admin_email && $admin_email_subject && isset( $post_data[ 'email' ] ) && $post_data[ 'email' ] ) {
902 $this->send_email_to_admin( $admin_email, $admin_email_subject, $post_data );
903 }
904 }
905 return $response;
906 }
907
908
909 /**
910 * Match ption submit condition
911 *
912 * @param Array $next_step
913 * @param Number $funnel_id
914 *
915 * @return Array $next_step
916 * @since 2.5.7
917 */
918 public static function match_conditional_step( $next_step, $funnel_id, $step_id ) {
919 $condition = Wpfnl_Condition_Checker::getInstance();
920 $condition_identifier = strval( $next_step[ 'step_id' ] );
921 $data[ 'step_id' ] = $step_id;
922 $condition_matched = $condition->check_condition( $funnel_id, $data, $condition_identifier );
923 $next_node = Wpfnl_functions::get_next_step( $funnel_id, $condition_identifier, $condition_matched );
924 $next_node = apply_filters( 'wpfunnels/next_step_data', $next_node );
925 return $next_node;
926 }
927
928
929 }
930