PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.6
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.6
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 / FrmAppController.php

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

1,207 lines 33.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmAppController {
7
8 /**
9 * @return void
10 */
11 public static function menu() {
12 FrmAppHelper::maybe_add_permissions();
13 if ( ! current_user_can( 'frm_view_forms' ) ) {
14 return;
15 }
16
17 $menu_name = FrmAppHelper::get_menu_name();
18 add_menu_page( 'Formidable', $menu_name, 'frm_view_forms', 'formidable', 'FrmFormsController::route', self::menu_icon(), self::get_menu_position() );
19 }
20
21 /**
22 * @return int
23 */
24 private static function get_menu_position() {
25 return (int) apply_filters( 'frm_menu_position', 29 );
26 }
27
28 /**
29 * @since 3.05
30 */
31 private static function menu_icon() {
32 $icon = FrmAppHelper::svg_logo(
33 array(
34 'fill' => '#a0a5aa',
35 'orange' => '#a0a5aa',
36 )
37 );
38 $icon = 'data:image/svg+xml;base64,' . base64_encode( $icon );
39
40 return apply_filters( 'frm_icon', $icon );
41 }
42
43 /**
44 * @since 3.0
45 */
46 public static function add_admin_class( $classes ) {
47 if ( self::is_white_page() ) {
48 $classes .= ' frm-white-body ';
49 $classes .= self::get_os();
50
51 $page = str_replace( 'formidable-', '', FrmAppHelper::simple_get( 'page', 'sanitize_title' ) );
52 if ( empty( $page ) || $page === 'formidable' ) {
53 $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
54 if ( in_array( $action, array( 'settings', 'edit', 'list' ) ) ) {
55 $page .= $action;
56 } else {
57 $page = $action;
58 }
59 }
60 if ( ! empty( $page ) ) {
61 $classes .= ' frm-admin-page-' . $page;
62 }
63 }
64
65 if ( FrmAppHelper::is_full_screen() ) {
66 $full_screen_on = self::get_full_screen_setting();
67 $add_class = '';
68 if ( $full_screen_on ) {
69 $add_class = ' frm-full-screen is-fullscreen-mode';
70 wp_enqueue_style( 'wp-edit-post' ); // Load the CSS for .is-fullscreen-mode.
71 }
72 $classes .= apply_filters( 'frm_admin_full_screen_class', $add_class );
73 }
74
75 if ( ! FrmAppHelper::pro_is_installed() ) {
76 $classes .= ' frm-lite ';
77 }
78
79 return $classes;
80 }
81
82 /**
83 * Get the full screen mode setting from the block editor.
84 *
85 * @since 6.1
86 *
87 * @return bool
88 */
89 private static function get_full_screen_setting() {
90 global $wpdb;
91 $meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences';
92
93 $prefs = get_user_meta( get_current_user_id(), $meta_key, true );
94 if ( $prefs && isset( $prefs['core/edit-post']['fullscreenMode'] ) ) {
95 return $prefs['core/edit-post']['fullscreenMode'];
96 }
97
98 return true;
99 }
100
101 /**
102 * @since 4.0
103 *
104 * @return string
105 */
106 private static function get_os() {
107 $agent = strtolower( FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ) );
108 $os = '';
109 if ( strpos( $agent, 'mac' ) !== false ) {
110 $os = ' osx';
111 } elseif ( strpos( $agent, 'linux' ) !== false ) {
112 $os = ' linux';
113 } elseif ( strpos( $agent, 'windows' ) !== false ) {
114 $os = ' windows';
115 }
116 return $os;
117 }
118
119 /**
120 * @since 3.0
121 */
122 private static function is_white_page() {
123 $white_pages = array(
124 'formidable',
125 'formidable-entries',
126 'formidable-views',
127 'formidable-views-editor',
128 'formidable-pro-upgrade',
129 'formidable-addons',
130 'formidable-import',
131 'formidable-settings',
132 'formidable-styles',
133 'formidable-styles2',
134 'formidable-inbox',
135 'formidable-welcome',
136 'formidable-applications',
137 );
138
139 if ( ! class_exists( 'FrmTransHooksController', false ) && ! FrmTransLiteAppHelper::should_fallback_to_paypal() ) {
140 // Only consider the payments page as a "white page" when the Payments submodule is off.
141 // Otherwise this causes a lot of styling issues when the Stripe add-on (or Authorize.Net) is active.
142
143 // Add an extra check to avoid white page styling on the PayPal "edit" action.
144 // We fallback to the PayPal add on for the "edit" action since Stripe Lite does not have an edit view.
145 if ( ! in_array( FrmAppHelper::simple_get( 'action' ), array( 'edit', 'new' ), true ) || ! is_callable( 'FrmPaymentsController::route' ) ) {
146 $white_pages[] = 'formidable-payments';
147 }
148 }
149
150 $get_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
151 $is_white_page = in_array( $get_page, $white_pages, true );
152
153 if ( ! $is_white_page ) {
154 $screen = get_current_screen();
155 $is_white_page = ( $screen && strpos( $screen->id, 'frm_display' ) !== false );
156 }
157
158 /**
159 * Allow another add on to style a page as a Formidable "white page", which adds a white background color.
160 *
161 * @since 5.3
162 *
163 * @param bool $is_white_page
164 */
165 $is_white_page = apply_filters( 'frm_is_white_page', $is_white_page );
166
167 return $is_white_page;
168 }
169
170 /**
171 * @return void
172 */
173 public static function load_wp_admin_style() {
174 FrmAppHelper::load_font_style();
175 }
176
177 /**
178 * @param bool $show_nav
179 * @param string $title
180 *
181 * @psalm-param 'hide'|'show' $title
182 *
183 * @return void
184 */
185 public static function get_form_nav( $form, $show_nav = false, $title = 'show' ) {
186 $show_nav = FrmAppHelper::get_param( 'show_nav', $show_nav, 'get', 'absint' );
187 if ( empty( $show_nav ) || ! $form ) {
188 return;
189 }
190
191 FrmForm::maybe_get_form( $form );
192 if ( ! is_object( $form ) ) {
193 return;
194 }
195
196 $id = $form->id;
197 $current_page = self::get_current_page();
198 $nav_items = self::get_form_nav_items( $form );
199
200 include( FrmAppHelper::plugin_path() . '/classes/views/shared/form-nav.php' );
201 }
202
203 /**
204 * @return string
205 */
206 private static function get_current_page() {
207 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
208 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title', 'None' );
209 $current_page = isset( $_GET['page'] ) ? $page : $post_type;
210
211 if ( FrmAppHelper::is_view_builder_page() ) {
212 $current_page = 'frm_display';
213 }
214
215 return $current_page;
216 }
217
218 /**
219 * @param object $form
220 * @return array
221 */
222 private static function get_form_nav_items( $form ) {
223 $id = $form->parent_form_id ? $form->parent_form_id : $form->id;
224
225 $nav_items = array(
226 array(
227 'link' => FrmForm::get_edit_link( $id ),
228 'label' => __( 'Build', 'formidable' ),
229 'current' => array( 'edit', 'new', 'duplicate' ),
230 'page' => 'formidable',
231 'permission' => 'frm_edit_forms',
232 ),
233 array(
234 'link' => FrmStylesHelper::get_list_url( $id ),
235 'label' => __( 'Style', 'formidable' ),
236 'current' => array(),
237 'page' => 'formidable-styles',
238 'permission' => 'frm_edit_forms',
239 ),
240 array(
241 'link' => admin_url( 'admin.php?page=formidable&frm_action=settings&id=' . absint( $id ) ),
242 'label' => __( 'Settings', 'formidable' ),
243 'current' => array( 'settings' ),
244 'page' => 'formidable',
245 'permission' => 'frm_edit_forms',
246 ),
247 array(
248 'link' => admin_url( 'admin.php?page=formidable-entries&frm_action=list&form=' . absint( $id ) ),
249 'label' => __( 'Entries', 'formidable' ),
250 'current' => array(),
251 'page' => 'formidable-entries',
252 'permission' => 'frm_view_entries',
253 ),
254 );
255
256 $views_installed = is_callable( 'FrmProAppHelper::views_is_installed' ) ? FrmProAppHelper::views_is_installed() : FrmAppHelper::pro_is_installed();
257
258 if ( ! $views_installed ) {
259 $nav_items[] = array(
260 'link' => admin_url( 'admin.php?page=formidable-views&form=' . absint( $id ) ),
261 'label' => __( 'Views', 'formidable' ),
262 'current' => array(),
263 'page' => 'formidable-views',
264 'permission' => 'frm_view_entries',
265 'atts' => array(
266 'class' => 'frm_noallow',
267 ),
268 );
269 }
270
271 // Let people know reports and views exist.
272 if ( ! FrmAppHelper::pro_is_installed() ) {
273 $nav_items[] = array(
274 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&form=' . absint( $id ) ),
275 'label' => __( 'Reports', 'formidable' ),
276 'current' => array( 'reports' ),
277 'page' => 'formidable',
278 'permission' => 'frm_view_entries',
279 'atts' => array(
280 'class' => 'frm_noallow',
281 ),
282 );
283 }
284
285 $nav_args = array(
286 'form_id' => $id,
287 'form' => $form,
288 );
289
290 return (array) apply_filters( 'frm_form_nav_list', $nav_items, $nav_args );
291 }
292
293 // Adds a settings link to the plugins page
294 /**
295 * @return array
296 */
297 public static function settings_link( $links ) {
298 $settings = array();
299
300 if ( ! FrmAppHelper::pro_is_installed() ) {
301 $label = FrmAddonsController::is_license_expired() ? __( 'Renew', 'formidable' ) : __( 'Upgrade to Pro', 'formidable' );
302 $settings[] = '<a href="' . esc_url( FrmAppHelper::admin_upgrade_link( 'plugin-row' ) ) . '" target="_blank" rel="noopener"><b style="color:#1da867;font-weight:700;">' . esc_html( $label ) . '</b></a>';
303 }
304
305 $settings[] = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable' ) ) . '">' . __( 'Build a Form', 'formidable' ) . '</a>';
306
307 return array_merge( $settings, $links );
308 }
309
310 /**
311 * @return void
312 */
313 public static function pro_get_started_headline() {
314 self::review_request();
315 FrmAppHelper::min_pro_version_notice( '4.0' );
316 }
317
318 /**
319 * Add admin notices as needed for reviews
320 *
321 * @since 3.04.03
322 *
323 * @return void
324 */
325 private static function review_request() {
326 $reviews = new FrmReviews();
327 $reviews->review_request();
328 }
329
330 /**
331 * Save the request to hide the review
332 *
333 * @since 3.04.03
334 *
335 * @return void
336 */
337 public static function dismiss_review() {
338 FrmAppHelper::permission_check( 'frm_change_settings' );
339 check_ajax_referer( 'frm_ajax', 'nonce' );
340
341 $reviews = new FrmReviews();
342 $reviews->dismiss_review();
343 }
344
345 /**
346 * @since 3.04.02
347 *
348 * @return void
349 */
350 public static function include_upgrade_overlay() {
351 self::enqueue_dialog_assets();
352 add_action( 'admin_footer', 'FrmAppController::upgrade_overlay_html' );
353 }
354
355 /**
356 * Enqueue scripts and styles required for modals.
357 *
358 * @since 5.3
359 *
360 * @return void
361 */
362 public static function enqueue_dialog_assets() {
363 wp_enqueue_script( 'jquery-ui-dialog' );
364 wp_enqueue_style( 'jquery-ui-dialog' );
365 }
366
367 /**
368 * @since 3.06.03
369 *
370 * @return void
371 */
372 public static function upgrade_overlay_html() {
373 $is_pro = FrmAppHelper::pro_is_installed();
374 $upgrade_link = array(
375 'medium' => 'builder',
376 'content' => 'upgrade',
377 );
378 $default_link = FrmAppHelper::admin_upgrade_link( $upgrade_link );
379 $plugin_path = FrmAppHelper::plugin_path();
380 $shared_path = $plugin_path . '/classes/views/shared/';
381
382 include $shared_path . 'upgrade_overlay.php';
383 include $shared_path . 'confirm-overlay.php';
384
385 if ( FrmAppHelper::is_admin_page( 'formidable-welcome' ) || FrmAppHelper::on_form_listing_page() ) {
386 self::new_form_overlay_html();
387 }
388 }
389
390 /**
391 * @return void
392 */
393 private static function new_form_overlay_html() {
394 FrmFormsController::before_list_templates();
395
396 $plugin_path = FrmAppHelper::plugin_path();
397 $path = $plugin_path . '/classes/views/frm-forms/';
398 $expired = FrmFormsController::expired();
399 $expiring = FrmAddonsController::is_license_expiring();
400 $user = wp_get_current_user(); // $user used in leave-email.php to determine a default value for field
401 $view_path = $path . 'new-form-overlay/';
402 $modal_class = '';
403 $upgrade_link = FrmAppHelper::admin_upgrade_link(
404 array(
405 'medium' => 'new-template',
406 'content' => 'upgrade',
407 )
408 );
409 $renew_link = FrmAppHelper::admin_upgrade_link(
410 array(
411 'medium' => 'new-template',
412 'content' => 'renew',
413 )
414 );
415 $blocks_to_render = array();
416
417 if ( ! FrmAppHelper::pro_is_installed() ) {
418 // avoid rendering the email and code blocks for users who have upgraded or have a free license already
419 $api = new FrmFormTemplateApi();
420 if ( ! $api->has_free_access() ) {
421 array_push( $blocks_to_render, 'email', 'code' );
422 }
423 }
424
425 // avoid rendering the upgrade block for users with elite
426 if ( 'elite' !== FrmAddonsController::license_type() ) {
427 $blocks_to_render[] = 'upgrade';
428 }
429
430 // avoid rendering the renew block for users who are not currently expired
431 if ( $expired ) {
432 $blocks_to_render[] = 'renew';
433 $modal_class = 'frm-expired';
434 } elseif ( $expiring ) {
435 $modal_class = 'frm-expiring';
436 }
437
438 include $path . 'new-form-overlay.php';
439 }
440
441 /**
442 * Create a basic form with an email field.
443 *
444 * @param string $form_key
445 * @param string $title
446 * @param string $description
447 * @return void
448 */
449 public static function api_email_form( $form_key, $title, $description ) {
450 $url = 'https://sandbox.formidableforms.com/api/wp-json/frm/v2/forms/' . $form_key . '?return=html&exclude_script=jquery&exclude_style=formidable-css';
451 $view_path = FrmAppHelper::plugin_path() . '/classes/views/frm-forms/new-form-overlay/';
452 $user = wp_get_current_user();
453 require $view_path . 'leave-email.php';
454 }
455
456 /**
457 * @return void
458 */
459 public static function include_info_overlay() {
460 self::enqueue_dialog_assets();
461 add_action( 'admin_footer', 'FrmAppController::info_overlay_html' );
462 }
463
464 /**
465 * @return void
466 */
467 public static function info_overlay_html() {
468 include FrmAppHelper::plugin_path() . '/classes/views/shared/info-overlay.php';
469 }
470
471 /**
472 * @since 3.04.02
473 *
474 * @return void
475 */
476 public static function remove_upsells() {
477 remove_action( 'frm_before_settings', 'FrmSettingsController::license_box' );
478 remove_action( 'frm_after_settings', 'FrmSettingsController::settings_cta' );
479 remove_action( 'frm_add_form_style_tab_options', 'FrmFormsController::add_form_style_tab_options' );
480 remove_action( 'frm_after_field_options', 'FrmFormsController::logic_tip' );
481 }
482
483 /**
484 * If there are CURL problems on this server, wp_remote_post won't work for installing
485 * Use a javascript fallback instead.
486 *
487 * @since 2.0.3
488 *
489 * @return void
490 */
491 public static function install_js_fallback() {
492 FrmAppHelper::load_admin_wide_js();
493 ?>
494 <div id="frm_install_message"></div>
495 <script>jQuery(document).ready( frm_install_now );</script>
496 <?php
497 }
498
499 /**
500 * Check if the database is outdated
501 *
502 * @since 2.0.1
503 * @return boolean
504 */
505 public static function needs_update() {
506 $needs_upgrade = self::compare_for_update(
507 array(
508 'option' => 'frm_db_version',
509 'new_db_version' => FrmAppHelper::$db_version,
510 'new_plugin_version' => FrmAppHelper::plugin_version(),
511 )
512 );
513
514 if ( ! $needs_upgrade ) {
515 $needs_upgrade = apply_filters( 'frm_db_needs_upgrade', $needs_upgrade );
516 }
517
518 return $needs_upgrade;
519 }
520
521 /**
522 * Check both version number and DB number for changes
523 *
524 * @since 3.0.04
525 *
526 * @param array $atts
527 * @return bool
528 */
529 public static function compare_for_update( $atts ) {
530 $db_version = get_option( $atts['option'] );
531
532 if ( strpos( $db_version, '-' ) === false ) {
533 $needs_upgrade = true;
534 } else {
535 $last_upgrade = explode( '-', $db_version );
536 $needs_db_upgrade = (int) $last_upgrade[1] < (int) $atts['new_db_version'];
537 $new_version = version_compare( $last_upgrade[0], $atts['new_plugin_version'], '<' );
538 $needs_upgrade = $needs_db_upgrade || $new_version;
539 }
540
541 return $needs_upgrade;
542 }
543
544 /**
545 * Check for database update and trigger js loading
546 *
547 * @since 2.0.1
548 *
549 * @return void
550 */
551 public static function admin_init() {
552 if ( FrmAppHelper::is_admin_page( 'formidable' ) && 'duplicate' === FrmAppHelper::get_param( 'frm_action' ) ) {
553 FrmFormsController::duplicate();
554 }
555
556 if ( FrmAppHelper::is_style_editor_page() && 'save' === FrmAppHelper::get_param( 'frm_action' ) ) {
557 // Hook in earlier than FrmStylesController::route so we can redirect before the headers have been sent.
558 FrmStylesController::save_style();
559 }
560
561 new FrmPersonalData(); // register personal data hooks
562
563 if ( ! FrmAppHelper::doing_ajax() && self::needs_update() ) {
564 self::network_upgrade_site();
565 }
566
567 if ( ! FrmAppHelper::doing_ajax() ) {
568 // don't continue during ajax calls
569 self::admin_js();
570 }
571
572 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
573 $action = FrmAppHelper::get_param( 'frm_action' );
574
575 if ( in_array( $action, array( 'add_new', 'list_templates' ), true ) ) {
576 wp_safe_redirect( admin_url( 'admin.php?page=formidable&triggerNewFormModal=1' ) );
577 exit;
578 }
579
580 FrmInbox::maybe_disable_screen_options();
581 }
582
583 self::maybe_add_ip_warning();
584 }
585
586 /**
587 * Show a warning for the IP address setting if it hasn't been set.
588 *
589 * @since 6.1
590 *
591 * @return void
592 */
593 private static function maybe_add_ip_warning() {
594 $settings = FrmAppHelper::get_settings();
595 if ( false !== $settings->custom_header_ip ) {
596 // The setting has been changed from the false default (to either 1 or 0), so stop showing the message.
597 return;
598 }
599
600 if ( ! self::is_behind_proxy() ) {
601 // This message is only applicable when using a reverse proxy.
602 return;
603 }
604
605 if ( FrmAppHelper::get_post_param( 'frm_action', '', 'sanitize_text_field' ) ) {
606 // Avoid the message on a POST action. We don't want to show the message if we're saving global settings.
607 return;
608 }
609
610 $global_settings_link = admin_url( 'admin.php?page=formidable-settings' ) . '#frm_custom_header_ip';
611 $message = sprintf(
612 // Translators: 1: Global Settings Link
613 __( 'IP addresses in form submissions may no longer be accurate! If you are experiencing issues, we recommend going to %1$s and enabling the "Use custom headers when retrieving IPs with form submissions." setting.', 'formidable' ),
614 '<a href="' . esc_url( $global_settings_link ) . '">Global Settings</a>'
615 );
616 $option_name = 'frm_dismiss_ip_address_notice';
617 FrmAppHelper::add_dismissable_warning_message( $message, $option_name );
618 }
619
620 /**
621 * Check if any reverse proxy headers are set.
622 *
623 * @since 6.1
624 *
625 * @return bool
626 */
627 private static function is_behind_proxy() {
628 $custom_headers = FrmAppHelper::get_custom_header_keys_for_ip();
629 foreach ( $custom_headers as $header ) {
630 if ( 'REMOTE_ADDR' === $header ) {
631 // We want to check every key but REMOTE_ADDR. REMOTE_ATTR is not unique to reverse proxy servers.
632 continue;
633 }
634
635 $ip = trim( FrmAppHelper::get_server_value( $header ) );
636 // Return true for anything that isn't empty but ignoring values like ::1.
637 if ( $ip && 0 !== strpos( $ip, '::' ) ) {
638 return true;
639 }
640 }
641
642 return false;
643 }
644
645 /**
646 * @return void
647 */
648 public static function admin_js() {
649 $plugin_url = FrmAppHelper::plugin_url();
650 $version = FrmAppHelper::plugin_version();
651
652 FrmAppHelper::load_admin_wide_js();
653
654 if ( class_exists( 'FrmOverlayController' ) ) {
655 // This should always exist.
656 // But it may not have loaded properly when updating the plugin.
657 FrmOverlayController::register_assets();
658 }
659
660 wp_register_style( 'formidable_admin_global', $plugin_url . '/css/admin/frm_admin_global.css', array(), $version );
661 wp_enqueue_style( 'formidable_admin_global' );
662
663 wp_register_style( 'formidable-admin', $plugin_url . '/css/frm_admin.css', array(), $version );
664 wp_register_style( 'formidable-grids', $plugin_url . '/css/frm_grids.css', array(), $version );
665
666 wp_register_script( 'formidable_dom', $plugin_url . '/js/admin/dom.js', array( 'jquery', 'jquery-ui-dialog', 'wp-i18n' ), $version, true );
667 wp_register_script( 'formidable_embed', $plugin_url . '/js/admin/embed.js', array( 'formidable_dom', 'jquery-ui-autocomplete' ), $version, true );
668 self::register_popper1();
669 wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '4.6.1', true );
670 wp_register_script( 'formidable_settings', $plugin_url . '/js/admin/settings.js', array(), $version, true );
671
672 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
673
674 // Enqueue Floating Links.
675 $is_valid_page =
676 FrmAppHelper::is_formidable_admin() &&
677 ! FrmAppHelper::is_style_editor_page() &&
678 ! FrmAppHelper::is_admin_page( 'formidable-views-editor' ) &&
679 ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
680 if ( $is_valid_page && FrmAppHelper::is_formidable_branding() ) {
681 self::enqueue_floating_links( $plugin_url, $version );
682 }
683 unset( $is_valid_page );
684
685 if ( 'formidable-applications' === $page ) {
686 FrmApplicationsController::load_assets();
687 return;
688 }
689
690 $dependencies = array(
691 'formidable_admin_global',
692 'jquery',
693 'jquery-ui-core',
694 'jquery-ui-draggable',
695 'jquery-ui-sortable',
696 'bootstrap_tooltip',
697 'bootstrap-multiselect',
698 'wp-i18n',
699 'wp-hooks', // Required in WP versions older than 5.7
700 'formidable_dom',
701 'formidable_embed',
702 );
703
704 if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
705 // We only need to load the color picker when editing styles.
706 $dependencies[] = 'wp-color-picker';
707 }
708
709 wp_register_script( 'formidable_admin', $plugin_url . '/js/formidable_admin.js', $dependencies, $version, true );
710
711 if ( FrmAppHelper::on_form_listing_page() ) {
712 // For the existing page dropdown in the Form embed modal.
713 wp_enqueue_script( 'jquery-ui-autocomplete' );
714 }
715
716 wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '1.1.1', true );
717
718 if ( ! class_exists( 'FrmTransHooksController', false ) ) {
719 /**
720 * Gateway fields are included for add-on compatibility but we do not want it to be visible.
721 * They do however need to be visible when the payments submodule is active.
722 */
723 wp_add_inline_style(
724 'formidable-admin',
725 '#frm_builder_page li[data-ftype="gateway"] { display: none; }'
726 );
727 }
728
729 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
730
731 global $pagenow;
732 if ( strpos( $page, 'formidable' ) === 0 || ( $pagenow === 'edit.php' && $post_type === 'frm_display' ) ) {
733
734 wp_enqueue_script( 'admin-widgets' );
735 wp_enqueue_style( 'widgets' );
736 self::maybe_deregister_popper2();
737 wp_enqueue_script( 'formidable_admin' );
738 wp_enqueue_script( 'formidable_embed' );
739 FrmAppHelper::localize_script( 'admin' );
740
741 wp_enqueue_style( 'formidable-admin' );
742 if ( 'formidable-styles' !== $page && 'formidable-styles2' !== $page ) {
743 wp_enqueue_style( 'formidable-grids' );
744 wp_enqueue_style( 'formidable-dropzone' );
745 } else {
746 wp_enqueue_style( 'formidable-grids' );
747 }
748
749 if ( 'formidable-entries' === $page ) {
750 // Load front end js for entries.
751 wp_enqueue_script( 'formidable' );
752 }
753
754 do_action( 'frm_enqueue_builder_scripts' );
755 self::include_upgrade_overlay();
756 self::include_info_overlay();
757 } elseif ( FrmAppHelper::is_view_builder_page() ) {
758 if ( isset( $_REQUEST['post_type'] ) ) {
759 $post_type = sanitize_title( wp_unslash( $_REQUEST['post_type'] ) );
760 } elseif ( isset( $_REQUEST['post'] ) && absint( $_REQUEST['post'] ) ) {
761 $post = get_post( absint( wp_unslash( $_REQUEST['post'] ) ) );
762 if ( ! $post ) {
763 return;
764 }
765 $post_type = $post->post_type;
766 } else {
767 return;
768 }
769
770 if ( $post_type === 'frm_display' ) {
771 self::enqueue_legacy_views_assets();
772 }
773 }
774
775 }
776
777 /**
778 * @since 6.3.2
779 *
780 * @return void
781 */
782 public static function admin_enqueue_scripts() {
783 self::load_wp_admin_style();
784 self::maybe_force_formidable_block_on_gutenberg_page();
785 }
786
787 /**
788 * Enqueue required assets for the Legacy Views editor (Views v4.x).
789 *
790 * @since 6.1.2
791 *
792 * @return void
793 */
794 private static function enqueue_legacy_views_assets() {
795 wp_enqueue_style( 'formidable-grids' );
796 wp_enqueue_script( 'jquery-ui-draggable' );
797 self::maybe_deregister_popper2();
798 wp_enqueue_script( 'formidable_admin' );
799 wp_add_inline_style(
800 'formidable-admin',
801 '
802 .frm-white-body.post-type-frm_display .columns-2 {
803 display: block;
804 overflow: visible;
805 }
806
807 .frm-white-body.post-type-frm_display .columns-2 > div {
808 overflow-y: hidden;
809 }
810
811 .frm-white-body.post-type-frm_display #titlediv #title-prompt-text {
812 padding: 3px 0 0 10px;
813 }
814
815 .post-type-frm_display #field-search-input,
816 .post-type-frm_display #advanced-search-input {
817 flex: 1;
818 }
819 '
820 );
821 wp_enqueue_style( 'formidable-admin' );
822 FrmAppHelper::localize_script( 'admin' );
823 self::include_info_overlay();
824 }
825
826 /**
827 * Fix a Duplicator Pro conflict because it uses Popper 2. See issue #3459.
828 *
829 * @since 5.2.02.01
830 *
831 * @return void
832 */
833 private static function maybe_deregister_popper2() {
834 global $wp_scripts;
835
836 if ( ! array_key_exists( 'popper', $wp_scripts->registered ) ) {
837 return;
838 }
839
840 $popper = $wp_scripts->registered['popper'];
841 if ( version_compare( $popper->ver, '2.0', '>=' ) ) {
842 wp_deregister_script( 'popper' );
843 self::register_popper1();
844 }
845 }
846
847 /**
848 * Register Popper required for Bootstrap 4.
849 *
850 * @since 5.2.02.01
851 *
852 * @return void
853 */
854 private static function register_popper1() {
855 wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array( 'jquery' ), '1.16.0', true );
856 }
857
858 /**
859 * Automatically insert a Formidable block when loading Gutenberg when $_GET['frmForm' is set.
860 *
861 * @since 5.2
862 *
863 * @return void
864 */
865 private static function maybe_force_formidable_block_on_gutenberg_page() {
866 global $pagenow;
867 if ( 'post.php' !== $pagenow ) {
868 return;
869 }
870
871 $form_id = FrmAppHelper::simple_get( 'frmForm', 'absint' );
872 if ( ! $form_id ) {
873 return;
874 }
875
876 self::add_js_to_inject_gutenberg_block( 'formidable/simple-form', 'formId', $form_id );
877 }
878
879 /**
880 * @since 5.3
881 *
882 * @param string $block_name
883 * @param string $object_key
884 * @param array|string $object_id
885 *
886 * @return void
887 */
888 public static function add_js_to_inject_gutenberg_block( $block_name, $object_key, $object_id ) {
889 require FrmAppHelper::plugin_path() . '/classes/views/shared/edit-page-js.php';
890 }
891
892 /**
893 * @return void
894 */
895 public static function load_lang() {
896 load_plugin_textdomain( 'formidable', false, FrmAppHelper::plugin_folder() . '/languages/' );
897 }
898
899 /**
900 * Check if the styles are updated when a form is loaded on the front-end
901 *
902 * @since 3.0.1
903 *
904 * @return void
905 */
906 public static function maybe_update_styles() {
907 if ( self::needs_update() ) {
908 self::network_upgrade_site();
909 }
910 }
911
912 /**
913 * @since 3.0
914 *
915 * @return void
916 */
917 public static function create_rest_routes() {
918 $args = array(
919 'methods' => 'GET',
920 'callback' => 'FrmAppController::api_install',
921 'permission_callback' => __CLASS__ . '::can_update_db',
922 );
923
924 register_rest_route( 'frm-admin/v1', '/install', $args );
925
926 $args = array(
927 'methods' => 'GET',
928 'callback' => 'FrmAddonsController::install_addon_api',
929 'permission_callback' => 'FrmAddonsController::can_install_addon_api',
930 );
931
932 register_rest_route( 'frm-admin/v1', '/install-addon', $args );
933 }
934
935 /**
936 * Make sure the install is only being run when we tell it to.
937 * We don't want to run manually by people calling the API.
938 *
939 * @since 4.06.02
940 */
941 public static function can_update_db() {
942 return get_transient( 'frm_updating_api' );
943 }
944
945 /**
946 * Run silent upgrade on each site in the network during a network upgrade.
947 * Update database settings for all sites in a network during network upgrade process.
948 *
949 * @since 2.0.1
950 *
951 * @param int $blog_id Blog ID.
952 *
953 * @return void
954 */
955 public static function network_upgrade_site( $blog_id = 0 ) {
956 // Flag to check if install is happening as intended.
957 set_transient( 'frm_updating_api', true, MINUTE_IN_SECONDS );
958 $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
959
960 self::maybe_add_wp_site_health();
961
962 if ( $blog_id ) {
963 switch_to_blog( $blog_id );
964 $response = rest_do_request( $request );
965 restore_current_blog();
966 } else {
967 $response = rest_do_request( $request );
968 }
969
970 if ( $response->is_error() ) {
971 // if the remove post fails, use javascript instead
972 add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
973 }
974 }
975
976 /**
977 * Make sure WP_Site_Health has been included because it is required when calling rest_do_request.
978 * Check first that the file exists because WP_Site_Health was only introduced in WordPress 5.2.
979 *
980 * @return void
981 */
982 private static function maybe_add_wp_site_health() {
983 if ( ! class_exists( 'WP_Site_Health' ) ) {
984 $wp_site_health_path = ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
985 if ( file_exists( $wp_site_health_path ) ) {
986 require_once $wp_site_health_path;
987 }
988 }
989 }
990
991 /**
992 * @since 3.0
993 *
994 * @return true
995 */
996 public static function api_install() {
997 delete_transient( 'frm_updating_api' );
998 if ( self::needs_update() ) {
999 $running = get_option( 'frm_install_running' );
1000 if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
1001 update_option( 'frm_install_running', time(), 'no' );
1002 self::install();
1003 delete_option( 'frm_install_running' );
1004 }
1005 }
1006
1007 return true;
1008 }
1009
1010 /**
1011 * Silent database upgrade (no redirect).
1012 * Called via ajax request during network upgrade process.
1013 *
1014 * @since 2.0.1
1015 *
1016 * @return void
1017 */
1018 public static function ajax_install() {
1019 FrmAppHelper::permission_check( 'frm_change_settings' );
1020 check_ajax_referer( 'frm_ajax', 'nonce' );
1021 self::api_install();
1022 wp_die();
1023 }
1024
1025 /**
1026 * @return void
1027 */
1028 public static function install() {
1029 $frmdb = new FrmMigrate();
1030 $frmdb->upgrade();
1031 }
1032
1033 /**
1034 * @return void
1035 */
1036 public static function uninstall() {
1037 FrmAppHelper::permission_check( 'administrator' );
1038 check_ajax_referer( 'frm_ajax', 'nonce' );
1039
1040 $frmdb = new FrmMigrate();
1041 $frmdb->uninstall();
1042
1043 //disable the plugin and redirect after uninstall so the tables don't get added right back
1044 $plugins = array( FrmAppHelper::plugin_folder() . '/formidable.php', 'formidable-pro/formidable-pro.php' );
1045 deactivate_plugins( $plugins, false, false );
1046 echo esc_url_raw( admin_url( 'plugins.php?deactivate=true' ) );
1047
1048 wp_die();
1049 }
1050
1051 public static function drop_tables( $tables ) {
1052 global $wpdb;
1053 $tables[] = $wpdb->prefix . 'frm_fields';
1054 $tables[] = $wpdb->prefix . 'frm_forms';
1055 $tables[] = $wpdb->prefix . 'frm_items';
1056 $tables[] = $wpdb->prefix . 'frm_item_metas';
1057
1058 return $tables;
1059 }
1060
1061 /**
1062 * @return void
1063 */
1064 public static function deauthorize() {
1065 FrmAppHelper::permission_check( 'frm_change_settings' );
1066 check_ajax_referer( 'frm_ajax', 'nonce' );
1067
1068 delete_option( 'frmpro-credentials' );
1069 delete_option( 'frmpro-authorized' );
1070 delete_site_option( 'frmpro-credentials' );
1071 delete_site_option( 'frmpro-authorized' );
1072 wp_die();
1073 }
1074
1075 /**
1076 * This is triggered when Formidable is activated.
1077 *
1078 * @return void
1079 */
1080 public static function handle_activation() {
1081 self::maybe_activate_payment_cron();
1082 }
1083
1084 /**
1085 * The payment cron is unscheduled when Formidable is deactivated.
1086 * We need to add it back again on activation if Stripe is configured.
1087 *
1088 * @since 6.5
1089 *
1090 * @return void
1091 */
1092 private static function maybe_activate_payment_cron() {
1093 if ( ! FrmStrpLiteConnectHelper::stripe_connect_is_setup() ) {
1094 return;
1095 }
1096
1097 FrmTransLiteAppController::maybe_schedule_cron();
1098 }
1099
1100 public static function set_footer_text( $text ) {
1101 if ( FrmAppHelper::is_formidable_admin() ) {
1102 $text = '';
1103 }
1104
1105 return $text;
1106 }
1107
1108 /**
1109 * Add admin footer links.
1110 *
1111 * @since 6.4.1
1112 *
1113 * @return void
1114 */
1115 public static function add_admin_footer_links() {
1116 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1117
1118 // Check admin privileges, screen mode, and branding
1119 $is_not_admin = ! FrmAppHelper::is_formidable_admin() && $post_type !== 'frm_logs';
1120 $is_full_screen = FrmAppHelper::is_full_screen();
1121 $is_not_formidable_branding = ! FrmAppHelper::is_formidable_branding();
1122
1123 // Exit if any of the above conditions are met
1124 if ( $is_not_admin || $is_full_screen || $is_not_formidable_branding ) {
1125 return;
1126 }
1127
1128 include FrmAppHelper::plugin_path() . '/classes/views/shared/admin-footer-links.php';
1129 }
1130
1131 /**
1132 * @deprecated 3.0.04
1133 *
1134 * @codeCoverageIgnore
1135 *
1136 * @return void
1137 */
1138 public static function activation_install() {
1139 FrmDeprecated::activation_install();
1140 }
1141
1142 /**
1143 * @deprecated 3.0
1144 * @codeCoverageIgnore
1145 */
1146 public static function page_route( $content ) {
1147 return FrmDeprecated::page_route( $content );
1148 }
1149
1150 /**
1151 * Include icons on page for Embed Form modal.
1152 *
1153 * @since 5.2
1154 *
1155 * @return void
1156 */
1157 public static function include_embed_form_icons() {
1158 _deprecated_function( __METHOD__, '5.3' );
1159 }
1160
1161 /**
1162 * @deprecated 1.07.05 This is still referenced in the API add on as of v1.13.
1163 * @codeCoverageIgnore
1164 *
1165 * @param array $atts
1166 * @return string
1167 */
1168 public static function get_form_shortcode( $atts ) {
1169 _deprecated_function( __FUNCTION__, '1.07.05', 'FrmFormsController::get_form_shortcode' );
1170 return FrmFormsController::get_form_shortcode( $atts );
1171 }
1172
1173 /**
1174 * Handles Floating Links' scripts and styles enqueueing.
1175 *
1176 * @since 6.4
1177 *
1178 * @param string $plugin_url URL of the plugin.
1179 * @param string $version Current version of the plugin.
1180 * @return void
1181 */
1182 private static function enqueue_floating_links( $plugin_url, $version ) {
1183 if ( ! $plugin_url || ! $version ) {
1184 // If any required parameters are missing, exit early.
1185 return;
1186 }
1187
1188 // Enqueue the Floating Links styles.
1189 wp_enqueue_style( 's11-floating-links', $plugin_url . '/css/packages/s11-floating-links.css', array(), $version );
1190
1191 // Enqueue the Floating Links script.
1192 wp_enqueue_script( 's11-floating-links', $plugin_url . '/js/packages/floating-links/s11-floating-links.js', array(), $version, true );
1193
1194 // Enqueue the config script.
1195 wp_enqueue_script( 's11-floating-links-config', $plugin_url . '/js/packages/floating-links/config.js', array( 'wp-i18n' ), $version, true );
1196
1197 if ( function_exists( 'wp_set_script_translations' ) ) {
1198 wp_set_script_translations( 's11-floating-links-config', 's11-' );
1199 }
1200
1201 $floating_links_data = array(
1202 'proIsInstalled' => FrmAppHelper::pro_is_installed(),
1203 );
1204 wp_localize_script( 's11-floating-links-config', 's11FloatingLinksData', $floating_links_data );
1205 }
1206 }
1207