PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.11.2
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.11.2
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / controllers / FrmOnboardingWizardController.php

FrmOnboardingWizardController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.11.2, at classes/controllers/FrmOnboardingWizardController.php

665 lines 19.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Onboarding Wizard Controller class.
4 *
5 * @package Formidable
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 die( 'You are not allowed to call this page directly.' );
10 }
11
12 /**
13 * Handles the Onboarding Wizard page in the admin area.
14 *
15 * @since 6.9
16 */
17 class FrmOnboardingWizardController {
18
19 /**
20 * The slug of the Onboarding Wizard page.
21 *
22 * @var string
23 */
24 const PAGE_SLUG = 'formidable-onboarding-wizard';
25
26 /**
27 * The script handle.
28 *
29 * @var string
30 */
31 const SCRIPT_HANDLE = 'frm-onboarding-wizard';
32
33 /**
34 * The required user capability to view the Onboarding Wizard page.
35 *
36 * @var string
37 */
38 const REQUIRED_CAPABILITY = 'frm_view_forms';
39
40 /**
41 * Transient name used for managing redirection to the Onboarding Wizard page.
42 *
43 * @var string
44 */
45 const TRANSIENT_NAME = 'frm_activation_redirect';
46
47 /**
48 * Transient value associated with the redirection to the Onboarding Wizard page.
49 *
50 * @var string
51 */
52 const TRANSIENT_VALUE = 'formidable-welcome';
53
54 /**
55 * Option name for storing the redirect status for the Onboarding Wizard page.
56 *
57 * @var string
58 */
59 const REDIRECT_STATUS_OPTION = 'frm_welcome_redirect';
60
61 /**
62 * Option name for tracking if the onboarding wizard was skipped.
63 *
64 * @var string
65 */
66 const ONBOARDING_SKIPPED_OPTION = 'frm_onboarding_skipped';
67
68 /**
69 * Defines the initial step for redirection within the application flow.
70 *
71 * @var string
72 */
73 const INITIAL_STEP = 'welcome';
74
75 /**
76 * Option name to store usage data.
77 *
78 * @var string
79 */
80 const USAGE_DATA_OPTION = 'frm_onboarding_usage_data';
81
82 /**
83 * Holds the URL to access the Onboarding Wizard's page.
84 *
85 * @var string
86 */
87 private static $page_url = '';
88
89 /**
90 * Holds a list of add-ons available for installation.
91 *
92 * @var array
93 */
94 private static $available_addons = array();
95
96 /**
97 * Path to views.
98 *
99 * @var string
100 */
101 private static $view_path = '';
102
103 /**
104 * Upgrade URL.
105 *
106 * @var string
107 */
108 private static $upgrade_link = '';
109
110 /**
111 * Initialize hooks for template page only.
112 *
113 * @since 6.9
114 */
115 public static function load_admin_hooks() {
116 self::set_page_url();
117 add_action( 'admin_init', __CLASS__ . '::do_admin_redirects' );
118
119 if ( self::has_onboarding_been_skipped() ) {
120 add_filter( 'option_frm_inbox', __CLASS__ . '::add_wizard_to_floating_links' );
121 }
122
123 // Load page if admin page is Onboarding Wizard.
124 self::maybe_load_page();
125 }
126
127 /**
128 * Performs a safe redirect to the welcome screen when the plugin is activated.
129 *
130 * @return void
131 */
132 public static function do_admin_redirects() {
133 $current_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
134
135 // Prevent endless loop.
136 if ( $current_page === self::PAGE_SLUG ) {
137 return;
138 }
139
140 // Only do this for single site installs.
141 if ( is_network_admin() ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
142 self::mark_onboarding_as_skipped();
143 return;
144 }
145
146 // Check if we should consider redirection.
147 if ( ! FrmAppHelper::is_formidable_admin() || ! self::is_onboarding_wizard_displayed() || self::has_onboarding_been_skipped() || FrmAppHelper::pro_is_connected() ) {
148 return;
149 }
150
151 set_transient( self::TRANSIENT_NAME, 'no', 60 );
152
153 // Prevent redirect with every activation.
154 if ( self::has_already_redirected() ) {
155 return;
156 }
157
158 // Redirect to the onboarding wizard's initial step.
159 $page_url = add_query_arg( 'step', self::INITIAL_STEP, self::$page_url );
160 if ( wp_safe_redirect( esc_url_raw( $page_url ) ) ) {
161 exit;
162 }
163 }
164
165 /**
166 * Initializes the Onboarding Wizard setup if on its designated admin page.
167 *
168 * @since 6.9
169 *
170 * @return void
171 */
172 public static function maybe_load_page() {
173 if ( self::is_onboarding_wizard_page() ) {
174 add_action( 'admin_menu', __CLASS__ . '::menu', 99 );
175 add_action( 'admin_init', __CLASS__ . '::assign_properties' );
176 add_action( 'admin_enqueue_scripts', __CLASS__ . '::enqueue_assets', 15 );
177 add_action( 'admin_head', __CLASS__ . '::remove_menu' );
178
179 add_filter( 'admin_body_class', __CLASS__ . '::add_admin_body_classes', 999 );
180 add_filter( 'frm_show_footer_links', '__return_false' );
181 }
182 }
183
184 /**
185 * Initializes class properties with essential values for operation.
186 *
187 * @since 6.9
188 *
189 * @return void
190 */
191 public static function assign_properties() {
192 self::$view_path = FrmAppHelper::plugin_path() . '/classes/views/onboarding-wizard/';
193
194 self::$upgrade_link = FrmAppHelper::admin_upgrade_link(
195 array(
196 'medium' => 'onboarding-wizard',
197 'content' => 'upgrade',
198 )
199 );
200
201 self::set_available_addons();
202 }
203
204 /**
205 * Add Onboarding Wizard menu item to sidebar and define index page.
206 *
207 * @since 6.9
208 *
209 * @return void
210 */
211 public static function menu() {
212 if ( ! current_user_can( 'activate_plugins' ) ) {
213 return;
214 }
215
216 $label = __( 'Onboarding Wizard', 'formidable' );
217
218 add_submenu_page(
219 'formidable',
220 'Formidable | ' . $label,
221 $label,
222 self::REQUIRED_CAPABILITY,
223 self::PAGE_SLUG,
224 array( __CLASS__, 'render' )
225 );
226 }
227
228 /**
229 * Renders the Onboarding Wizard page in the WordPress admin area.
230 *
231 * @since 6.9
232 *
233 * @return void
234 */
235 public static function render() {
236 if ( self::has_onboarding_been_skipped() ) {
237 delete_option( self::ONBOARDING_SKIPPED_OPTION );
238 self::has_already_redirected();
239 }
240
241 // Include SVG images for icons.
242 FrmAppHelper::include_svg();
243
244 $view_path = self::get_view_path();
245 $available_addons = self::get_available_addons();
246 $upgrade_link = self::get_upgrade_link();
247 $addons_count = FrmAddonsController::get_addons_count();
248 $license_key = base64_decode( rawurldecode( FrmAppHelper::get_param( 'key', '', 'request', 'sanitize_text_field' ) ) );
249 $pro_is_installed = FrmAppHelper::pro_is_installed();
250
251 // Note: Add step parts in order.
252 $step_parts = array(
253 'welcome' => 'steps/welcome-step.php',
254 'install-formidable-pro' => 'steps/install-formidable-pro-step.php',
255 'license-management' => 'steps/license-management-step.php',
256 'default-email-address' => 'steps/default-email-address-step.php',
257 'install-addons' => 'steps/install-addons-step.php',
258 'success' => 'steps/success-step.php',
259 );
260
261 include $view_path . 'index.php';
262 }
263
264 /**
265 * Handle AJAX request to setup the "Default Email Address" step.
266 *
267 * @since 6.9
268 *
269 * @return void
270 */
271 public static function ajax_setup_email_step() {
272 // Check permission and nonce.
273 FrmAppHelper::permission_check( self::REQUIRED_CAPABILITY );
274 check_ajax_referer( 'frm_ajax', 'nonce' );
275
276 // Get posted data.
277 $default_email = FrmAppHelper::get_post_param( 'default_email', '', 'sanitize_text_field' );
278 $allows_tracking = FrmAppHelper::get_post_param( 'allows_tracking', '', 'rest_sanitize_boolean' );
279 $summary_emails = FrmAppHelper::get_post_param( 'summary_emails', '', 'rest_sanitize_boolean' );
280
281 // Update Settings.
282 $frm_settings = FrmAppHelper::get_settings();
283 $frm_settings->update_setting( 'default_email', $default_email, 'sanitize_text_field' );
284 $frm_settings->update_setting( 'tracking', $allows_tracking, 'rest_sanitize_boolean' );
285 $frm_settings->update_setting( 'summary_emails', $summary_emails, 'rest_sanitize_boolean' );
286 // Remove the 'FrmProSettingsController::store' action to avoid PHP errors during AJAX call.
287 remove_action( 'frm_store_settings', 'FrmProSettingsController::store' );
288 $frm_settings->store();
289
290 // Send response.
291 wp_send_json_success();
292 }
293
294 /**
295 * Handle AJAX request to set up usage data for the Onboarding Wizard.
296 *
297 * @since 6.9
298 *
299 * @return void
300 */
301 public static function setup_usage_data() {
302 // Check permission and nonce.
303 FrmAppHelper::permission_check( self::REQUIRED_CAPABILITY );
304 check_ajax_referer( 'frm_ajax', 'nonce' );
305
306 // Retrieve the current usage data.
307 $usage_data = self::get_usage_data();
308
309 $fields_to_update = array(
310 'default_email' => 'sanitize_email',
311 'is_subscribed' => 'rest_sanitize_boolean',
312 'allows_tracking' => 'rest_sanitize_boolean',
313 'summary_emails' => 'rest_sanitize_boolean',
314 'installed_addons' => 'sanitize_text_field',
315 'processed_steps' => 'sanitize_text_field',
316 'completed_steps' => 'rest_sanitize_boolean',
317 );
318
319 foreach ( $fields_to_update as $field => $sanitize_callback ) {
320 if ( isset( $_POST[ $field ] ) ) {
321 $usage_data[ $field ] = FrmAppHelper::get_post_param( $field, '', $sanitize_callback );
322 }
323 }
324
325 update_option( self::USAGE_DATA_OPTION, $usage_data );
326 wp_send_json_success();
327 }
328
329 /**
330 * Enqueues the Onboarding Wizard page scripts and styles.
331 *
332 * @since 6.9
333 *
334 * @return void
335 */
336 public static function enqueue_assets() {
337 $plugin_url = FrmAppHelper::plugin_url();
338 $version = FrmAppHelper::plugin_version();
339 $js_dependencies = array(
340 'wp-i18n',
341 // This prevents a console error "wp.hooks is undefined" in WP versions older than 5.7.
342 'wp-hooks',
343 'formidable_dom',
344 );
345
346 // Enqueue styles that needed.
347 wp_enqueue_style( 'formidable-admin' );
348 wp_enqueue_style( 'formidable-grids' );
349
350 // Register and enqueue Onboarding Wizard style.
351 wp_register_style( self::SCRIPT_HANDLE, $plugin_url . '/css/admin/onboarding-wizard.css', array(), $version );
352 wp_enqueue_style( self::SCRIPT_HANDLE );
353
354 // Register and enqueue Onboarding Wizard script.
355 wp_register_script( self::SCRIPT_HANDLE, $plugin_url . '/js/onboarding-wizard.js', $js_dependencies, $version, true );
356 wp_localize_script( self::SCRIPT_HANDLE, 'frmOnboardingWizardVars', self::get_js_variables() );
357 wp_enqueue_script( self::SCRIPT_HANDLE );
358
359 /**
360 * Fires after the Onboarding Wizard enqueue assets.
361 *
362 * @since 6.9
363 */
364 do_action( 'frm_onboarding_wizard_enqueue_assets' );
365
366 FrmAppHelper::dequeue_extra_global_scripts();
367 }
368
369 /**
370 * Get the Onboarding Wizard JS variables as an array.
371 *
372 * @since 6.9
373 *
374 * @return array
375 */
376 private static function get_js_variables() {
377 return array(
378 'INITIAL_STEP' => self::INITIAL_STEP,
379 'proIsIncluded' => FrmAppHelper::pro_is_included(),
380 );
381 }
382
383 /**
384 * Remove the Onboarding Wizard submenu page from the formidable parent menu
385 * since it is not necessary to show that link there.
386 *
387 * @since 6.9
388 *
389 * @return void
390 */
391 public static function remove_menu() {
392 remove_submenu_page( 'formidable', self::PAGE_SLUG );
393 }
394
395 /**
396 * Adds custom classes to the existing string of admin body classes.
397 *
398 * The function appends a custom class to the existing admin body classes, enabling full-screen mode for the admin interface.
399 *
400 * @since 6.9
401 *
402 * @param string $classes Existing body classes.
403 * @return string Updated list of body classes, including the newly added classes.
404 */
405 public static function add_admin_body_classes( $classes ) {
406 return $classes . ' frm-admin-full-screen';
407 }
408
409 /**
410 * Checks if the Onboarding Wizard was skipped during the plugin's installation.
411 *
412 * @since 6.9
413 * @return bool True if the Onboarding Wizard was skipped, false otherwise.
414 */
415 public static function has_onboarding_been_skipped() {
416 return get_option( self::ONBOARDING_SKIPPED_OPTION, false );
417 }
418
419 /**
420 * Marks the Onboarding Wizard as skipped to prevent automatic redirects to the wizard.
421 *
422 * @since 6.9
423 * @return void
424 */
425 public static function mark_onboarding_as_skipped() {
426 update_option( self::ONBOARDING_SKIPPED_OPTION, true, 'no' );
427 }
428
429 /**
430 * Adds an Onboarding Wizard welcome message to the floating notifications.
431 *
432 * @since 6.9
433 *
434 * @param array $inbox_messages The array of existing inbox messages.
435 * @return array Configuration for the onboarding wizard slide-in notification.
436 */
437 public static function add_wizard_to_floating_links( $inbox_messages ) {
438 $message = __( 'Welcome to Formidable Forms! Click here to run the Onboarding Wizard and it will guide you through the basic settings and get you started in 2 minutes.', 'formidable' );
439
440 return array(
441 'onboarding_wizard' => array(
442 'subject' => esc_html__( 'Begin With Ease!', 'formidable' ),
443 'message' => esc_html( $message ),
444 'slidein' => esc_html( $message ),
445 'cta' => '<a href="' . esc_url( self::$page_url ) . '" class="button-primary frm-button-primary" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Begin Setup', 'formidable' ) . '</a>',
446 'created' => time(),
447 'key' => 'onboarding_wizard',
448 ),
449 );
450 }
451
452 /**
453 * Check if the current page is the Onboarding Wizard page.
454 *
455 * @since 6.9
456 *
457 * @return bool True if the current page is the Onboarding Wizard page, false otherwise.
458 */
459 public static function is_onboarding_wizard_page() {
460 return FrmAppHelper::is_admin_page( self::PAGE_SLUG );
461 }
462
463 /**
464 * Validates if the Onboarding Wizard page is being displayed.
465 *
466 * @since 6.9
467 *
468 * @return bool True if the Onboarding Wizard page is displayed, false otherwise.
469 */
470 public static function is_onboarding_wizard_displayed() {
471 return get_transient( self::TRANSIENT_NAME ) === self::TRANSIENT_VALUE;
472 }
473
474 /**
475 * Checks if the plugin has already performed a redirect to avoid repeated redirections.
476 *
477 * @return bool Returns true if already redirected, otherwise false.
478 */
479 private static function has_already_redirected() {
480 if ( get_option( self::REDIRECT_STATUS_OPTION ) ) {
481 return true;
482 }
483
484 update_option( self::REDIRECT_STATUS_OPTION, FrmAppHelper::plugin_version(), 'no' );
485 return false;
486 }
487
488 /**
489 * Get the path to the Onboarding Wizard views.
490 *
491 * @since 6.9
492 *
493 * @return string Path to views.
494 */
495 public static function get_page_url() {
496 return self::$page_url;
497 }
498
499 /**
500 * Set the URL to access the Onboarding Wizard's page.
501 *
502 * @return void
503 */
504 private static function set_page_url() {
505 self::$page_url = admin_url( 'admin.php?page=' . self::PAGE_SLUG );
506 }
507
508 /**
509 * Get the list of add-ons available for installation.
510 *
511 * @since 6.9
512 *
513 * @return array A list of add-ons.
514 */
515 public static function get_available_addons() {
516 return self::$available_addons;
517 }
518
519 /**
520 * Set the list of add-ons available for installation.
521 *
522 * @since 6.9
523 *
524 * @return void
525 */
526 private static function set_available_addons() {
527 $pro_is_installed = FrmAppHelper::pro_is_installed();
528
529 self::$available_addons['spam-protection'] = array(
530 'title' => esc_html__( 'Spam Protection', 'formidable' ),
531 'is-checked' => true,
532 'is-disabled' => true,
533 'help-text' => esc_html__( 'Get anti-spam options like reCAPTCHA, hCaptcha, Akismet, Turnstile and the blocklist.', 'formidable' ),
534 );
535 self::$available_addons['stripe-payments'] = array(
536 'title' => esc_html__( 'Stripe Payments', 'formidable' ),
537 'is-checked' => true,
538 'is-disabled' => true,
539 'help-text' => esc_html__( 'Collect donations and payments with your forms. Offer physical products, digital goods, services, and more.', 'formidable' ),
540 );
541 if ( ! $pro_is_installed ) {
542 self::$available_addons['visual-styler'] = array(
543 'title' => esc_html__( 'Visual Styler', 'formidable' ),
544 'is-checked' => true,
545 'is-disabled' => true,
546 'help-text' => esc_html__( 'Customize form appearance with an intuitive styling interface.', 'formidable' ),
547 );
548 self::$available_addons['save-entries'] = array(
549 'title' => esc_html__( 'Save Entries', 'formidable' ),
550 'is-checked' => true,
551 'is-disabled' => true,
552 'help-text' => esc_html__( 'Save form submissions to your database for future reference and analysis.', 'formidable' ),
553 );
554 }
555 if ( ! function_exists( 'wp_mail_smtp' ) ) {
556 self::$available_addons['wp-mail-smtp'] = array(
557 'title' => esc_html__( 'SMTP', 'formidable' ),
558 'rel' => 'wp-mail-smtp',
559 'is-checked' => false,
560 'is-vendor' => true,
561 'help-text' => esc_html__( 'Improve email deliverability by routing WordPress emails through SMTP.', 'formidable' ),
562 );
563 }
564 if ( $pro_is_installed ) {
565 $views_addon = FrmAddonsController::get_addon( 'views' );
566 $mailchimp_addon = FrmAddonsController::get_addon( 'mailchimp' );
567 $registration_addon = FrmAddonsController::get_addon( 'registration' );
568 $api_addon = FrmAddonsController::get_addon( 'api' );
569 $acf_addon = FrmAddonsController::get_addon( 'acf' );
570 $signature_addon = FrmAddonsController::get_addon( 'signature' );
571
572 if ( ! is_plugin_active( 'formidable-views/formidable-views.php' ) && isset( $views_addon['url'] ) ) {
573 self::$available_addons['formidable-views'] = array(
574 'title' => esc_html__( 'Views', 'formidable' ),
575 'rel' => $views_addon['url'],
576 'is-checked' => false,
577 'help-text' => $views_addon['excerpt'],
578 );
579 }
580 if ( ! is_plugin_active( 'formidable-mailchimp/formidable-mailchimp.php' ) && isset( $mailchimp_addon['url'] ) ) {
581 self::$available_addons['formidable-mailchimp'] = array(
582 'title' => esc_html__( 'Mailchimp', 'formidable' ),
583 'rel' => $mailchimp_addon['url'],
584 'is-checked' => false,
585 'help-text' => $mailchimp_addon['excerpt'],
586 );
587 }
588 if ( ! is_plugin_active( 'formidable-registration/formidable-registration.php' ) && isset( $registration_addon['url'] ) ) {
589 self::$available_addons['formidable-registration'] = array(
590 'title' => esc_html__( 'User Registration', 'formidable' ),
591 'rel' => $registration_addon['url'],
592 'is-checked' => false,
593 'help-text' => $registration_addon['excerpt'],
594 );
595 }
596 if ( ! is_plugin_active( 'formidable-api/formidable-api.php' ) && isset( $api_addon['url'] ) ) {
597 self::$available_addons['formidable-api'] = array(
598 'title' => esc_html__( 'Form Rest API', 'formidable' ),
599 'rel' => $api_addon['url'],
600 'is-checked' => false,
601 'help-text' => $api_addon['excerpt'],
602 );
603 }
604 if ( class_exists( 'ACF' ) && ! is_plugin_active( 'formidable-acf/formidable-acf.php' ) && isset( $acf_addon['url'] ) ) {
605 self::$available_addons['formidable-acf'] = array(
606 'title' => esc_html__( 'ACF Forms', 'formidable' ),
607 'rel' => $acf_addon['url'],
608 'is-checked' => false,
609 'help-text' => $acf_addon['excerpt'],
610 );
611 }
612 if ( ! is_plugin_active( 'formidable-signature/signature.php' ) && isset( $signature_addon['url'] ) ) {
613 self::$available_addons['formidable-signature'] = array(
614 'title' => esc_html__( 'Signature Forms', 'formidable' ),
615 'rel' => $signature_addon['url'],
616 'is-checked' => false,
617 'help-text' => $signature_addon['excerpt'],
618 );
619 }
620 }//end if
621 if ( class_exists( 'GFForms' ) && ! is_plugin_active( 'formidable-gravity-forms-importer/formidable-gravity-forms-importer.php' ) ) {
622 self::$available_addons['formidable-gravity-forms-importer'] = array(
623 'title' => esc_html__( 'Gravity Forms Migrator', 'formidable' ),
624 'rel' => 'formidable-gravity-forms-importer',
625 'is-checked' => false,
626 'is-vendor' => true,
627 'help-text' => esc_html__( 'Easily migrate your forms from Gravity Forms to Formidable.', 'formidable' ),
628 );
629 }
630 }
631
632 /**
633 * Get the path to the Onboarding Wizard views.
634 *
635 * @since 6.9
636 *
637 * @return string Path to views.
638 */
639 public static function get_view_path() {
640 return self::$view_path;
641 }
642
643 /**
644 * Get the upgrade link.
645 *
646 * @since 6.9
647 *
648 * @return string URL for upgrading accounts.
649 */
650 public static function get_upgrade_link() {
651 return self::$upgrade_link;
652 }
653
654 /**
655 * Retrieves the current Onboarding Wizard usage data, returning an empty array if none exists.
656 *
657 * @since 6.9
658 *
659 * @return array Current usage data.
660 */
661 public static function get_usage_data() {
662 return get_option( self::USAGE_DATA_OPTION, array() );
663 }
664 }
665