PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.32
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.32
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
← All changes | classes/controllers/FrmAppController.php +923 -241 6.36.32 View file →
@@ -9,13 +9,19 @@
9 9 * @return void
10 10 */
11 11 public static function menu() {
12 12 FrmAppHelper::maybe_add_permissions();
13 +
13 14 if ( ! current_user_can( 'frm_view_forms' ) ) {
14 15 return;
15 16 }
16 17
17 18 $menu_name = FrmAppHelper::get_menu_name();
19 +
20 + if ( in_array( $menu_name, array( 'Formidable', 'Forms' ), true ) ) {
21 + $menu_name .= wp_kses_post( FrmInboxController::get_notice_count() );
22 + }
23 +
18 24 add_menu_page( 'Formidable', $menu_name, 'frm_view_forms', 'formidable', 'FrmFormsController::route', self::menu_icon(), self::get_menu_position() );
19 25 }
20 26
21 27 /**
@@ -26,8 +32,10 @@
26 32 }
27 33
28 34 /**
29 35 * @since 3.05
36 + *
37 + * @return string
30 38 */
31 39 private static function menu_icon() {
32 40 $icon = FrmAppHelper::svg_logo(
33 41 array(
@@ -41,8 +49,12 @@
41 49 }
42 50
43 51 /**
44 52 * @since 3.0
53 + *
54 + * @param string $classes
55 + *
56 + * @return string
45 57 */
46 58 public static function add_admin_class( $classes ) {
47 59 if ( self::is_white_page() ) {
48 60 $classes .= ' frm-white-body ';
@@ -48,28 +60,38 @@
48 60 $classes .= ' frm-white-body ';
49 61 $classes .= self::get_os();
50 62
51 63 $page = str_replace( 'formidable-', '', FrmAppHelper::simple_get( 'page', 'sanitize_title' ) );
52 - if ( empty( $page ) || $page === 'formidable' ) {
64 +
65 + if ( ! $page || $page === 'formidable' ) {
53 66 $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
54 - if ( in_array( $action, array( 'settings', 'edit', 'list' ) ) ) {
67 +
68 + if ( in_array( $action, array( 'settings', 'edit', 'list' ), true ) ) {
55 69 $page .= $action;
56 70 } else {
57 71 $page = $action;
58 72 }
59 73 }
60 - if ( ! empty( $page ) ) {
74 +
75 + if ( $page ) {
61 76 $classes .= ' frm-admin-page-' . $page;
62 77 }
63 78 }
64 79
80 + if ( self::is_grey_page() ) {
81 + $classes .= ' frm-grey-body ';
82 + }
83 +
65 84 if ( FrmAppHelper::is_full_screen() ) {
66 - $full_screen_on = self::get_full_screen_setting();
67 85 $add_class = '';
68 - if ( $full_screen_on ) {
86 +
87 + if ( self::get_full_screen_setting() ) {
69 88 $add_class = ' frm-full-screen is-fullscreen-mode';
70 - wp_enqueue_style( 'wp-edit-post' ); // Load the CSS for .is-fullscreen-mode.
89 +
90 + // Load the CSS for .is-fullscreen-mode.
91 + wp_enqueue_style( 'wp-edit-post' );
71 92 }
93 +
72 94 $classes .= apply_filters( 'frm_admin_full_screen_class', $add_class );
73 95 }
74 96
75 97 if ( ! FrmAppHelper::pro_is_installed() ) {
@@ -75,8 +97,12 @@
75 97 if ( ! FrmAppHelper::pro_is_installed() ) {
76 98 $classes .= ' frm-lite ';
77 99 }
78 100
101 + if ( get_user_setting( 'unfold' ) && 'f' !== get_user_setting( 'mfold' ) ) {
102 + $classes .= ' frm-unfold ';
103 + }
104 +
79 105 return $classes;
80 106 }
81 107
82 108 /**
@@ -88,10 +114,10 @@
88 114 */
89 115 private static function get_full_screen_setting() {
90 116 global $wpdb;
91 117 $meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences';
118 + $prefs = get_user_meta( get_current_user_id(), $meta_key, true );
92 119
93 - $prefs = get_user_meta( get_current_user_id(), $meta_key, true );
94 120 if ( $prefs && isset( $prefs['core/edit-post']['fullscreenMode'] ) ) {
95 121 return $prefs['core/edit-post']['fullscreenMode'];
96 122 }
97 123
@@ -105,20 +131,24 @@
105 131 */
106 132 private static function get_os() {
107 133 $agent = strtolower( FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ) );
108 134 $os = '';
109 - if ( strpos( $agent, 'mac' ) !== false ) {
135 +
136 + if ( str_contains( $agent, 'mac' ) ) {
110 137 $os = ' osx';
111 - } elseif ( strpos( $agent, 'linux' ) !== false ) {
138 + } elseif ( str_contains( $agent, 'linux' ) ) {
112 139 $os = ' linux';
113 - } elseif ( strpos( $agent, 'windows' ) !== false ) {
140 + } elseif ( str_contains( $agent, 'windows' ) ) {
114 141 $os = ' windows';
115 142 }
143 +
116 144 return $os;
117 145 }
118 146
119 147 /**
120 148 * @since 3.0
149 + *
150 + * @return bool
121 151 */
122 152 private static function is_white_page() {
123 153 $white_pages = array(
124 154 'formidable',
@@ -124,9 +154,8 @@
124 154 'formidable',
125 155 'formidable-entries',
126 156 'formidable-views',
127 157 'formidable-views-editor',
128 - 'formidable-pro-upgrade',
129 158 'formidable-addons',
130 159 'formidable-import',
131 160 'formidable-settings',
132 161 'formidable-styles',
@@ -131,19 +160,17 @@
131 160 'formidable-settings',
132 161 'formidable-styles',
133 162 'formidable-styles2',
134 163 'formidable-inbox',
135 - 'formidable-welcome',
136 - 'formidable-applications',
164 + FrmFormTemplatesController::PAGE_SLUG,
165 + FrmOnboardingWizardController::PAGE_SLUG,
137 166 );
138 167
139 - $get_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
140 - $is_white_page = in_array( $get_page, $white_pages, true );
168 + if ( self::is_white_payments_page() ) {
169 + $white_pages[] = 'formidable-payments';
170 + }
141 171
142 - if ( ! $is_white_page ) {
143 - $screen = get_current_screen();
144 - $is_white_page = ( $screen && strpos( $screen->id, 'frm_display' ) !== false );
145 - }
172 + $is_white_page = self::is_page_in_list( $white_pages ) || self::is_grey_page() || FrmAppHelper::is_view_builder_page();
146 173
147 174 /**
148 175 * Allow another add on to style a page as a Formidable "white page", which adds a white background color.
149 176 *
@@ -150,14 +177,68 @@
150 177 * @since 5.3
151 178 *
152 179 * @param bool $is_white_page
153 180 */
154 - $is_white_page = apply_filters( 'frm_is_white_page', $is_white_page );
181 + return apply_filters( 'frm_is_white_page', $is_white_page );
182 + }
155 183
156 - return $is_white_page;
184 + /**
185 + * Check if the payments page should be styled as a white page.
186 + * Fallback to the Stripe, Authorize.Net, or PayPal add on for the "edit" action since
187 + * Stripe Lite does not have an edit view. Also fallback for bulk deleting, since that
188 + * isn't built into Lite. The pages we fall back to should not be styled as white pages.
189 + *
190 + * @since 6.27
191 + *
192 + * @return bool
193 + */
194 + private static function is_white_payments_page() {
195 + $action = FrmAppHelper::simple_get( 'action', 'sanitize_title' );
196 + $on_edit_page = in_array( $action, array( 'edit', 'new' ), true );
197 + return ! $on_edit_page && 'bulk_delete' !== $action;
157 198 }
158 199
159 200 /**
201 + * Add a grey bg instead of white.
202 + *
203 + * @since 6.8
204 + *
205 + * @return bool
206 + */
207 + private static function is_grey_page() {
208 + $grey_pages = array(
209 + 'formidable-applications',
210 + 'formidable-dashboard',
211 + 'formidable-views',
212 + );
213 +
214 + $is_grey_page = self::is_page_in_list( $grey_pages );
215 +
216 + /**
217 + * Filter to change FF wrapper background to grey.
218 + *
219 + * @since 6.8
220 + *
221 + * @param bool $is_grey_page
222 + *
223 + * @return bool
224 + */
225 + return apply_filters( 'frm_is_grey_page', $is_grey_page );
226 + }
227 +
228 + /**
229 + * @since 6.8
230 + *
231 + * @param array $pages A list of page names to check.
232 + *
233 + * @return bool
234 + */
235 + private static function is_page_in_list( $pages ) {
236 + $get_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
237 + return in_array( $get_page, $pages, true );
238 + }
239 +
240 + /**
160 241 * @return void
161 242 */
162 243 public static function load_wp_admin_style() {
163 244 FrmAppHelper::load_font_style();
@@ -163,10 +244,11 @@
163 244 FrmAppHelper::load_font_style();
164 245 }
165 246
166 247 /**
167 - * @param bool $show_nav
168 - * @param string $title
248 + * @param int|object $form
249 + * @param bool $show_nav
250 + * @param string $title
169 251 *
170 252 * @psalm-param 'hide'|'show' $title
171 253 *
172 254 * @return void
@@ -172,13 +254,15 @@
172 254 * @return void
173 255 */
174 256 public static function get_form_nav( $form, $show_nav = false, $title = 'show' ) {
175 257 $show_nav = FrmAppHelper::get_param( 'show_nav', $show_nav, 'get', 'absint' );
176 - if ( empty( $show_nav ) || ! $form ) {
258 +
259 + if ( ! $show_nav || ! $form ) {
177 260 return;
178 261 }
179 262
180 263 FrmForm::maybe_get_form( $form );
264 +
181 265 if ( ! is_object( $form ) ) {
182 266 return;
183 267 }
184 268
@@ -185,9 +269,9 @@
185 269 $id = $form->id;
186 270 $current_page = self::get_current_page();
187 271 $nav_items = self::get_form_nav_items( $form );
188 272
189 - include( FrmAppHelper::plugin_path() . '/classes/views/shared/form-nav.php' );
273 + include FrmAppHelper::plugin_path() . '/classes/views/shared/form-nav.php';
190 274 }
191 275
192 276 /**
193 277 * @return string
@@ -192,21 +276,21 @@
192 276 /**
193 277 * @return string
194 278 */
195 279 private static function get_current_page() {
196 - $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
197 - $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title', 'None' );
198 - $current_page = isset( $_GET['page'] ) ? $page : $post_type;
199 -
200 280 if ( FrmAppHelper::is_view_builder_page() ) {
201 - $current_page = 'frm_display';
281 + return 'frm_display';
202 282 }
203 283
204 - return $current_page;
284 + $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
285 + $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title', 'None' );
286 +
287 + return isset( $_GET['page'] ) ? $page : $post_type;
205 288 }
206 289
207 290 /**
208 291 * @param object $form
292 + *
209 293 * @return array
210 294 */
211 295 private static function get_form_nav_items( $form ) {
212 296 $id = $form->parent_form_id ? $form->parent_form_id : $form->id;
@@ -241,18 +325,18 @@
241 325 'permission' => 'frm_view_entries',
242 326 ),
243 327 );
244 328
245 - $views_installed = is_callable( 'FrmProAppHelper::views_is_installed' ) ? FrmProAppHelper::views_is_installed() : FrmAppHelper::pro_is_installed();
329 + $views_installed = is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed();
246 330
247 331 if ( ! $views_installed ) {
248 332 $nav_items[] = array(
249 - 'link' => admin_url( 'admin.php?page=formidable-views&form=' . absint( $id ) ),
250 - 'label' => __( 'Views', 'formidable' ),
251 - 'current' => array(),
252 - 'page' => 'formidable-views',
333 + 'link' => admin_url( 'admin.php?page=formidable-views&form=' . absint( $id ) ),
334 + 'label' => __( 'Views', 'formidable' ),
335 + 'current' => array(),
336 + 'page' => 'formidable-views',
253 337 'permission' => 'frm_view_entries',
254 - 'atts' => array(
338 + 'atts' => array(
255 339 'class' => 'frm_noallow',
256 340 ),
257 341 );
258 342 }
@@ -259,14 +343,14 @@
259 343
260 344 // Let people know reports and views exist.
261 345 if ( ! FrmAppHelper::pro_is_installed() ) {
262 346 $nav_items[] = array(
263 - 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&form=' . absint( $id ) ),
264 - 'label' => __( 'Reports', 'formidable' ),
265 - 'current' => array( 'reports' ),
266 - 'page' => 'formidable',
347 + 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&form=' . absint( $id ) ),
348 + 'label' => __( 'Reports', 'formidable' ),
349 + 'current' => array( 'reports' ),
350 + 'page' => 'formidable',
267 351 'permission' => 'frm_view_entries',
268 - 'atts' => array(
352 + 'atts' => array(
269 353 'class' => 'frm_noallow',
270 354 ),
271 355 );
272 356 }
@@ -278,10 +362,13 @@
278 362
279 363 return (array) apply_filters( 'frm_form_nav_list', $nav_items, $nav_args );
280 364 }
281 365
282 - // Adds a settings link to the plugins page
283 366 /**
367 + * Adds a settings link to the plugins page
368 + *
369 + * @param array $links
370 + *
284 371 * @return array
285 372 */
286 373 public static function settings_link( $links ) {
287 374 $settings = array();
@@ -286,13 +373,39 @@
286 373 public static function settings_link( $links ) {
287 374 $settings = array();
288 375
289 376 if ( ! FrmAppHelper::pro_is_installed() ) {
290 - $settings[] = '<a href="' . esc_url( FrmAppHelper::admin_upgrade_link( 'plugin-row' ) ) . '" target="_blank" rel="noopener"><b>' . esc_html__( 'Upgrade to Pro', 'formidable' ) . '</b></a>';
291 - }
377 + $is_expired = FrmAddonsController::is_license_expired();
292 378
293 - $settings[] = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable' ) ) . '">' . __( 'Build a Form', 'formidable' ) . '</a>';
379 + if ( $is_expired ) {
380 + $label = __( 'Renew', 'formidable' );
381 + } else {
382 + $label = FrmSalesApi::get_best_sale_value( 'plugin_page_cta_text' );
294 383
384 + if ( ! $label ) {
385 + $label = __( 'Upgrade to Pro', 'formidable' );
386 + }
387 + }
388 +
389 + $upgrade_content = $is_expired ? 'renew' : 'upgrade';
390 + $upgrade_link = FrmSalesApi::get_best_sale_value( 'plugin_page_cta_link' );
391 +
392 + $utm = array(
393 + 'campaign' => 'plugin-row',
394 + 'content' => $upgrade_content,
395 + );
396 +
397 + if ( $upgrade_link ) {
398 + $upgrade_link = FrmAppHelper::maybe_add_missing_utm( $upgrade_link, $utm );
399 + } else {
400 + $upgrade_link = FrmAppHelper::admin_upgrade_link( $utm );
401 + }
402 +
403 + $settings[] = '<a href="' . esc_url( $upgrade_link ) . '" target="_blank" rel="noopener"><b style="color:#1da867;font-weight:700;">' . esc_html( $label ) . '</b></a>';
404 + }//end if
405 +
406 + $settings[] = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable' ) ) . '">' . esc_html__( 'Build a Form', 'formidable' ) . '</a>';
407 +
295 408 return array_merge( $settings, $links );
296 409 }
297 410
298 411 /**
@@ -299,9 +412,9 @@
299 412 * @return void
300 413 */
301 414 public static function pro_get_started_headline() {
302 415 self::review_request();
303 - FrmAppHelper::min_pro_version_notice( '4.0' );
416 + FrmAppHelper::min_pro_version_notice( '6.20' );
304 417 }
305 418
306 419 /**
307 420 * Add admin notices as needed for reviews
@@ -368,63 +481,27 @@
368 481 $shared_path = $plugin_path . '/classes/views/shared/';
369 482
370 483 include $shared_path . 'upgrade_overlay.php';
371 484 include $shared_path . 'confirm-overlay.php';
372 -
373 - if ( FrmAppHelper::is_admin_page( 'formidable-welcome' ) || FrmAppHelper::on_form_listing_page() ) {
374 - self::new_form_overlay_html();
375 - }
376 485 }
377 486
378 487 /**
488 + * Create a basic form with an email field.
489 + *
490 + * @param string $form_key
491 + * @param string $title
492 + * @param string $description
493 + *
379 494 * @return void
380 495 */
381 - private static function new_form_overlay_html() {
382 - FrmFormsController::before_list_templates();
383 -
384 - $plugin_path = FrmAppHelper::plugin_path();
385 - $path = $plugin_path . '/classes/views/frm-forms/';
386 - $expired = FrmFormsController::expired();
387 - $expiring = FrmAddonsController::is_license_expiring();
388 - $user = wp_get_current_user(); // $user used in leave-email.php to determine a default value for field
389 - $view_path = $path . 'new-form-overlay/';
390 - $modal_class = '';
391 - $upgrade_link = FrmAppHelper::admin_upgrade_link(
392 - array(
393 - 'medium' => 'new-template',
394 - 'content' => 'upgrade',
395 - )
496 + public static function api_email_form( $form_key, $title = '', $description = '' ) {
497 + $user = wp_get_current_user();
498 + $args = array(
499 + 'api_url' => 'https://sandbox.formidableforms.com/api/wp-json/frm/v2/forms/' . $form_key . '?return=html&exclude_script=jquery&exclude_style=formidable-css',
500 + 'title' => $title,
501 + 'description' => $description,
396 502 );
397 - $renew_link = FrmAppHelper::admin_upgrade_link(
398 - array(
399 - 'medium' => 'new-template',
400 - 'content' => 'renew',
401 - )
402 - );
403 - $blocks_to_render = array();
404 -
405 - if ( ! FrmAppHelper::pro_is_installed() ) {
406 - // avoid rendering the email and code blocks for users who have upgraded or have a free license already
407 - $api = new FrmFormTemplateApi();
408 - if ( ! $api->has_free_access() ) {
409 - array_push( $blocks_to_render, 'email', 'code' );
410 - }
411 - }
412 -
413 - // avoid rendering the upgrade block for users with elite
414 - if ( 'elite' !== FrmAddonsController::license_type() ) {
415 - $blocks_to_render[] = 'upgrade';
416 - }
417 -
418 - // avoid rendering the renew block for users who are not currently expired
419 - if ( $expired ) {
420 - $blocks_to_render[] = 'renew';
421 - $modal_class = 'frm-expired';
422 - } elseif ( $expiring ) {
423 - $modal_class = 'frm-expiring';
424 - }
425 -
426 - include $path . 'new-form-overlay.php';
503 + require FrmAppHelper::plugin_path() . '/classes/views/form-templates/modals/leave-email-modal.php';
427 504 }
428 505
429 506 /**
430 507 * @return void
@@ -447,10 +524,9 @@
447 524 * @return void
448 525 */
449 526 public static function remove_upsells() {
450 527 remove_action( 'frm_before_settings', 'FrmSettingsController::license_box' );
451 - remove_action( 'frm_after_settings', 'FrmSettingsController::settings_cta' );
452 - remove_action( 'frm_add_form_style_tab_options', 'FrmFormsController::add_form_style_tab_options' );
528 + remove_action( 'frm_after_settings_tabs', 'FrmSettingsController::settings_cta' );
453 529 remove_action( 'frm_after_field_options', 'FrmFormsController::logic_tip' );
454 530 }
455 531
456 532 /**
@@ -462,12 +538,14 @@
462 538 * @return void
463 539 */
464 540 public static function install_js_fallback() {
465 541 FrmAppHelper::load_admin_wide_js();
542 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
466 543 ?>
467 544 <div id="frm_install_message"></div>
468 545 <script>jQuery(document).ready( frm_install_now );</script>
469 546 <?php
547 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
470 548 }
471 549
472 550 /**
473 551 * Check if the database is outdated
@@ -472,9 +550,10 @@
472 550 /**
473 551 * Check if the database is outdated
474 552 *
475 553 * @since 2.0.1
476 - * @return boolean
554 + *
555 + * @return bool
477 556 */
478 557 public static function needs_update() {
479 558 $needs_upgrade = self::compare_for_update(
480 559 array(
@@ -484,9 +563,9 @@
484 563 )
485 564 );
486 565
487 566 if ( ! $needs_upgrade ) {
488 - $needs_upgrade = apply_filters( 'frm_db_needs_upgrade', $needs_upgrade );
567 + return apply_filters( 'frm_db_needs_upgrade', $needs_upgrade );
489 568 }
490 569
491 570 return $needs_upgrade;
492 571 }
@@ -496,23 +575,27 @@
496 575 *
497 576 * @since 3.0.04
498 577 *
499 578 * @param array $atts
579 + *
500 580 * @return bool
501 581 */
502 582 public static function compare_for_update( $atts ) {
503 583 $db_version = get_option( $atts['option'] );
504 584
505 - if ( strpos( $db_version, '-' ) === false ) {
506 - $needs_upgrade = true;
507 - } else {
508 - $last_upgrade = explode( '-', $db_version );
509 - $needs_db_upgrade = (int) $last_upgrade[1] < (int) $atts['new_db_version'];
510 - $new_version = version_compare( $last_upgrade[0], $atts['new_plugin_version'], '<' );
511 - $needs_upgrade = $needs_db_upgrade || $new_version;
585 + if ( ! str_contains( $db_version, '-' ) ) {
586 + return true;
512 587 }
513 588
514 - return $needs_upgrade;
589 + $last_upgrade = explode( '-', $db_version );
590 + $needs_db_upgrade = (int) $last_upgrade[1] < (int) $atts['new_db_version'];
591 +
592 + if ( $needs_db_upgrade ) {
593 + return true;
594 + }
595 +
596 + // New plugin version.
597 + return version_compare( $last_upgrade[0], $atts['new_plugin_version'], '<' );
515 598 }
516 599
517 600 /**
518 601 * Check for database update and trigger js loading
@@ -521,99 +604,95 @@
521 604 *
522 605 * @return void
523 606 */
524 607 public static function admin_init() {
608 + if ( FrmAppHelper::get_param( 'delete_all' ) && FrmAppHelper::is_admin_page( 'formidable' ) && 'trash' === FrmAppHelper::get_param( 'form_type' ) ) {
609 + FrmFormsController::delete_all();
610 + }
611 +
525 612 if ( FrmAppHelper::is_admin_page( 'formidable' ) && 'duplicate' === FrmAppHelper::get_param( 'frm_action' ) ) {
526 613 FrmFormsController::duplicate();
527 614 }
528 615
616 + if ( FrmAppHelper::is_admin_page( 'formidable' ) && FrmAppHelper::simple_get( 'frm_add_tables' ) ) {
617 + self::add_missing_tables();
618 + }
619 +
529 620 if ( FrmAppHelper::is_style_editor_page() && 'save' === FrmAppHelper::get_param( 'frm_action' ) ) {
530 621 // Hook in earlier than FrmStylesController::route so we can redirect before the headers have been sent.
531 622 FrmStylesController::save_style();
532 623 }
533 624
534 - new FrmPersonalData(); // register personal data hooks
625 + if ( 'formidable-pro-upgrade' === FrmAppHelper::get_param( 'page' ) && ! FrmAppHelper::pro_is_installed() && current_user_can( 'frm_view_forms' ) ) {
626 + $redirect = FrmSalesApi::get_best_sale_value( 'menu_cta_link' );
627 + $utm = array(
628 + 'campaign' => 'upgrade',
629 + 'content' => 'submenu-upgrade',
630 + );
535 631
632 + $redirect = $redirect ? FrmAppHelper::maybe_add_missing_utm( $redirect, $utm ) : FrmAppHelper::admin_upgrade_link( $utm );
633 +
634 + wp_redirect( $redirect );
635 + die();
636 + }
637 +
638 + // Register personal data hooks.
639 + new FrmPersonalData();
640 +
536 641 if ( ! FrmAppHelper::doing_ajax() && self::needs_update() ) {
537 642 self::network_upgrade_site();
538 643 }
539 644
540 645 if ( ! FrmAppHelper::doing_ajax() ) {
541 - // don't continue during ajax calls
646 + // Don't continue during ajax calls
542 647 self::admin_js();
543 648 }
544 649
545 - if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
546 - $action = FrmAppHelper::get_param( 'frm_action' );
650 + self::trigger_page_load_hooks();
547 651
548 - if ( in_array( $action, array( 'add_new', 'list_templates' ), true ) ) {
549 - wp_safe_redirect( admin_url( 'admin.php?page=formidable&triggerNewFormModal=1' ) );
550 - exit;
551 - }
652 + if ( ! FrmAppHelper::is_admin_page( 'formidable' ) ) {
653 + return;
654 + }
552 655
553 - FrmInbox::maybe_disable_screen_options();
656 + // Redirect to the "Form Templates" page if the 'frm_action' parameter matches specific actions.
657 + // This provides backward compatibility for old addons that use legacy modal templates.
658 + $action = FrmAppHelper::get_param( 'frm_action' );
659 + $trigger_name_modal = FrmAppHelper::get_param( 'triggerNewFormModal' );
660 +
661 + if ( $trigger_name_modal || in_array( $action, array( 'add_new', 'list_templates' ), true ) ) {
662 + $application_id = FrmAppHelper::simple_get( 'applicationId', 'absint' );
663 + $url_param = $application_id ? '&applicationId=' . $application_id : '';
664 +
665 + wp_safe_redirect( admin_url( 'admin.php?page=' . FrmFormTemplatesController::PAGE_SLUG . $url_param ) );
666 + exit;
554 667 }
555 668
556 - self::maybe_add_ip_warning();
669 + FrmInbox::maybe_disable_screen_options();
557 670 }
558 671
559 672 /**
560 - * Show a warning for the IP address setting if it hasn't been set.
673 + * Get the current page and check for a possible function to trigger.
674 + * If a class name matches the page name, and the class has a load_page() method, trigger it.
561 675 *
562 - * @since 6.1
676 + * @since 6.8
563 677 *
564 678 * @return void
565 679 */
566 - private static function maybe_add_ip_warning() {
567 - $settings = FrmAppHelper::get_settings();
568 - if ( false !== $settings->custom_header_ip ) {
569 - // The setting has been changed from the false default (to either 1 or 0), so stop showing the message.
570 - return;
571 - }
680 + private static function trigger_page_load_hooks() {
681 + $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
572 682
573 - if ( ! self::is_behind_proxy() ) {
574 - // This message is only applicable when using a reverse proxy.
683 + if ( ! str_starts_with( $page, 'formidable-' ) ) {
684 + // Only trigger hooks on Formidable pages.
575 685 return;
576 686 }
577 687
578 - if ( FrmAppHelper::get_post_param( 'frm_action', '', 'sanitize_text_field' ) ) {
579 - // Avoid the message on a POST action. We don't want to show the message if we're saving global settings.
580 - return;
581 - }
688 + $page = str_replace( array( 'formidable-', '-' ), array( '', ' ' ), $page );
689 + $page = str_replace( ' ', '', ucwords( $page ) );
690 + $class = 'Frm' . $page . 'Controller';
582 691
583 - $global_settings_link = admin_url( 'admin.php?page=formidable-settings' ) . '#frm_custom_header_ip';
584 - $message = sprintf(
585 - // Translators: 1: Global Settings Link
586 - __( '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' ),
587 - '<a href="' . esc_url( $global_settings_link ) . '">Global Settings</a>'
588 - );
589 - $option_name = 'frm_dismiss_ip_address_notice';
590 - FrmAppHelper::add_dismissable_warning_message( $message, $option_name );
591 - }
592 -
593 - /**
594 - * Check if any reverse proxy headers are set.
595 - *
596 - * @since 6.1
597 - *
598 - * @return bool
599 - */
600 - private static function is_behind_proxy() {
601 - $custom_headers = FrmAppHelper::get_custom_header_keys_for_ip();
602 - foreach ( $custom_headers as $header ) {
603 - if ( 'REMOTE_ADDR' === $header ) {
604 - // We want to check every key but REMOTE_ADDR. REMOTE_ATTR is not unique to reverse proxy servers.
605 - continue;
606 - }
607 -
608 - $ip = trim( FrmAppHelper::get_server_value( $header ) );
609 - // Return true for anything that isn't empty but ignoring values like ::1.
610 - if ( $ip && 0 !== strpos( $ip, '::' ) ) {
611 - return true;
612 - }
692 + if ( class_exists( $class ) && method_exists( $class, 'load_page' ) ) {
693 + call_user_func( array( $class, 'load_page' ) );
613 694 }
614 -
615 - return false;
616 695 }
617 696
618 697 /**
619 698 * @return void
@@ -618,13 +697,23 @@
618 697 /**
619 698 * @return void
620 699 */
621 700 public static function admin_js() {
622 - $plugin_url = FrmAppHelper::plugin_url();
623 - $version = FrmAppHelper::plugin_version();
701 + $plugin_url = FrmAppHelper::plugin_url();
702 + $version = FrmAppHelper::plugin_version();
703 + $is_pro_min_v6_28 = FrmAppHelper::pro_is_installed() && FrmAppHelper::meets_min_pro_version( '6.28' );
704 + $frm_components_dependencies = $is_pro_min_v6_28 ? array( 'formidable_admin', 'formidable-pro-web-components' ) : array( 'formidable_admin' );
624 705
625 706 FrmAppHelper::load_admin_wide_js();
707 + // Register component assets early to ensure they can be enqueued later in controllers.
708 + wp_register_style( 'formidable-animations', $plugin_url . '/css/admin/animations.css', array(), $version );
626 709
710 + if ( class_exists( 'FrmOverlayController' ) ) {
711 + // This should always exist.
712 + // But it may not have loaded properly when updating the plugin.
713 + FrmOverlayController::register_assets();
714 + }
715 +
627 716 wp_register_style( 'formidable_admin_global', $plugin_url . '/css/admin/frm_admin_global.css', array(), $version );
628 717 wp_enqueue_style( 'formidable_admin_global' );
629 718
630 719 wp_register_style( 'formidable-admin', $plugin_url . '/css/frm_admin.css', array(), $version );
@@ -631,63 +720,69 @@
631 720 wp_register_style( 'formidable-grids', $plugin_url . '/css/frm_grids.css', array(), $version );
632 721
633 722 wp_register_script( 'formidable_dom', $plugin_url . '/js/admin/dom.js', array( 'jquery', 'jquery-ui-dialog', 'wp-i18n' ), $version, true );
634 723 wp_register_script( 'formidable_embed', $plugin_url . '/js/admin/embed.js', array( 'formidable_dom', 'jquery-ui-autocomplete' ), $version, true );
635 - self::register_popper1();
636 - wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '4.6.1', true );
724 + self::register_popper2();
725 + wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '5.0.2', true );
726 +
727 + $settings_js_vars = array(
728 + 'currencies' => FrmCurrencyHelper::get_currencies(),
729 + );
637 730 wp_register_script( 'formidable_settings', $plugin_url . '/js/admin/settings.js', array(), $version, true );
731 + wp_localize_script( 'formidable_settings', 'frmSettings', $settings_js_vars );
732 + wp_register_script( 'formidable-web-components', $plugin_url . '/js/formidable-web-components.js', $frm_components_dependencies, $version, true );
638 733
639 - $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
734 + if ( self::should_show_floating_links() ) {
735 + self::enqueue_floating_links( $plugin_url, $version );
736 + }
640 737
641 - if ( 'formidable-applications' === $page ) {
642 - FrmApplicationsController::load_assets();
643 - return;
644 - }
738 + wp_register_script( 'formidable_admin', $plugin_url . '/js/formidable_admin.js', self::get_admin_js_dependencies(), $version, true );
645 739
646 - $dependencies = array(
647 - 'formidable_admin_global',
648 - 'jquery',
649 - 'jquery-ui-core',
650 - 'jquery-ui-draggable',
651 - 'jquery-ui-sortable',
652 - 'bootstrap_tooltip',
653 - 'bootstrap-multiselect',
654 - 'wp-i18n',
655 - 'wp-hooks', // Required in WP versions older than 5.7
656 - 'formidable_dom',
657 - 'formidable_embed',
740 + wp_register_script(
741 + 'formidable_forms_list',
742 + $plugin_url . '/js/admin/forms-list.js',
743 + array(
744 + 'formidable_dom',
745 + ),
746 + $version,
747 + true
658 748 );
659 749
660 - if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
661 - // We only need to load the color picker when editing styles.
662 - $dependencies[] = 'wp-color-picker';
663 - }
664 -
665 - wp_register_script( 'formidable_admin', $plugin_url . '/js/formidable_admin.js', $dependencies, $version, true );
666 -
667 750 if ( FrmAppHelper::on_form_listing_page() ) {
668 751 // For the existing page dropdown in the Form embed modal.
669 752 wp_enqueue_script( 'jquery-ui-autocomplete' );
753 + wp_enqueue_script( 'formidable_forms_list' );
670 754 }
671 755
672 - wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '1.1.1', true );
756 + wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '2.0', true );
673 757
758 + if ( ! class_exists( 'FrmTransHooksController', false ) ) {
759 + FrmTransLiteAppController::hide_gateway_fields_in_builder();
760 + }
761 +
762 + $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
674 763 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
675 764
676 765 global $pagenow;
677 - if ( strpos( $page, 'formidable' ) === 0 || ( $pagenow === 'edit.php' && $post_type === 'frm_display' ) ) {
678 766
767 + if ( str_starts_with( $page, 'formidable' ) || ( $pagenow === 'edit.php' && $post_type === 'frm_display' ) ) {
768 + self::enqueue_global_settings_scripts( $page );
769 +
679 770 wp_enqueue_script( 'admin-widgets' );
680 771 wp_enqueue_style( 'widgets' );
681 - self::maybe_deregister_popper2();
772 + self::maybe_deregister_popper1();
682 773 wp_enqueue_script( 'formidable_admin' );
774 + wp_set_script_translations( 'formidable_admin', 'formidable' );
683 775 wp_enqueue_script( 'formidable_embed' );
776 + wp_set_script_translations( 'formidable_embed', 'formidable' );
684 777 FrmAppHelper::localize_script( 'admin' );
685 778
779 + wp_enqueue_style( 'formidable-animations' );
686 780 wp_enqueue_style( 'formidable-admin' );
781 +
687 782 if ( 'formidable-styles' !== $page && 'formidable-styles2' !== $page ) {
688 783 wp_enqueue_style( 'formidable-grids' );
689 - wp_enqueue_style( 'formidable-dropzone' );
784 + self::maybe_enqueue_dropzone_css( $page );
690 785 } else {
691 786 wp_enqueue_style( 'formidable-grids' );
692 787 }
693 788
@@ -693,11 +788,16 @@
693 788
694 789 if ( 'formidable-entries' === $page ) {
695 790 // Load front end js for entries.
696 791 wp_enqueue_script( 'formidable' );
792 +
793 + // Registers and enqueues the entries page scripts.
794 + wp_register_script( 'formidable_entries', $plugin_url . '/js/admin/entries.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
795 + wp_enqueue_script( 'formidable_entries' );
697 796 }
698 797
699 798 do_action( 'frm_enqueue_builder_scripts' );
799 + self::maybe_enqueue_legacy_paypal_assets();
700 800 self::include_upgrade_overlay();
701 801 self::include_info_overlay();
702 802 } elseif ( FrmAppHelper::is_view_builder_page() ) {
703 803 if ( isset( $_REQUEST['post_type'] ) ) {
@@ -703,11 +803,13 @@
703 803 if ( isset( $_REQUEST['post_type'] ) ) {
704 804 $post_type = sanitize_title( wp_unslash( $_REQUEST['post_type'] ) );
705 805 } elseif ( isset( $_REQUEST['post'] ) && absint( $_REQUEST['post'] ) ) {
706 806 $post = get_post( absint( wp_unslash( $_REQUEST['post'] ) ) );
807 +
707 808 if ( ! $post ) {
708 809 return;
709 810 }
811 +
710 812 $post_type = $post->post_type;
711 813 } else {
712 814 return;
713 815 }
@@ -714,14 +816,169 @@
714 816
715 817 if ( $post_type === 'frm_display' ) {
716 818 self::enqueue_legacy_views_assets();
717 819 }
820 + }//end if
821 +
822 + if ( 'formidable-addons' === $page ) {
823 + wp_register_script( 'formidable_addons', $plugin_url . '/js/admin/addons.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
824 + wp_enqueue_script( 'formidable_addons' );
718 825 }
719 826
827 + self::enqueue_builder_assets( $plugin_url, $version );
828 + }
829 +
830 + /**
831 + * @since 6.27
832 + *
833 + * @return array
834 + */
835 + private static function get_admin_js_dependencies() {
836 + $dependencies = array(
837 + 'formidable_admin_global',
838 + 'jquery',
839 + 'jquery-ui-core',
840 + 'jquery-ui-draggable',
841 + 'jquery-ui-sortable',
842 + 'bootstrap_tooltip',
843 + 'bootstrap-multiselect',
844 + 'wp-i18n',
845 + // Required in WP versions older than 5.7
846 + 'wp-hooks',
847 + 'formidable_dom',
848 + 'formidable_embed',
849 + );
850 +
851 + if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
852 + // We only need to load the color picker when editing styles.
853 + $dependencies[] = 'wp-color-picker';
854 + }
855 +
856 + return $dependencies;
857 + }
858 +
859 + /**
860 + * Enqueue the Form Builder assets.
861 + *
862 + * @since 6.24
863 + *
864 + * @param string $plugin_url The plugin URL.
865 + * @param string $version The plugin version.
866 + *
867 + * @return void
868 + */
869 + private static function enqueue_builder_assets( $plugin_url, $version ) {
870 + wp_register_style( 'formidable-settings-components', $plugin_url . '/css/admin/frm-settings-components.css', array( 'formidable-admin', 'formidable-grids' ), $version );
871 + wp_register_script( 'formidable-settings-components', $plugin_url . '/js/formidable-settings-components.js', array( 'formidable_admin' ), $version, true );
872 +
873 + if ( ! FrmAppHelper::is_form_builder_page() ) {
874 + return;
875 + }
876 +
877 + wp_enqueue_style( 'formidable-settings-components' );
878 + wp_enqueue_script( 'formidable-settings-components' );
879 + }
880 +
881 + /**
882 + * Enqueues global settings scripts.
883 + *
884 + * @param string $page The `page` param in URL.
885 + *
886 + * @return void
887 + */
888 + private static function enqueue_global_settings_scripts( $page ) {
889 + if ( 'formidable-settings' !== $page ) {
890 + return;
891 + }
892 +
893 + wp_enqueue_style( 'wp-color-picker' );
894 + wp_enqueue_script( 'formidable_settings' );
895 + }
896 +
897 + /**
898 + * Avoid loading dropzone CSS on the form list page. It isn't required there.
899 + *
900 + * @since 6.11
901 + *
902 + * @param string $page
903 + *
904 + * @return void
905 + */
906 + private static function maybe_enqueue_dropzone_css( $page ) {
907 + if ( ! FrmAppHelper::pro_is_installed() ) {
908 + return;
909 + }
910 +
911 + $should_avoid_loading_dropzone = 'formidable' === $page && ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
912 +
913 + if ( ! $should_avoid_loading_dropzone ) {
914 + wp_enqueue_style( 'formidable-dropzone' );
915 + }
916 + }
917 +
918 + /**
919 + * The floating links are not shown on every page.
920 + * They are also not shown if white labeling is being used.
921 + *
922 + * @since 6.8.4
923 + *
924 + * @return bool
925 + */
926 + private static function should_show_floating_links() {
927 + if ( ! FrmAppHelper::is_formidable_branding() ) {
928 + return false;
929 + }
930 +
931 + $should_show = FrmAppHelper::is_formidable_admin() && ! FrmAppHelper::is_style_editor_page() && ! FrmAppHelper::is_admin_page( 'formidable-views-editor' ) && ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
932 +
933 + /**
934 + * Filters whether the floating links should be displayed.
935 + *
936 + * @since 6.25.1
937 + *
938 + * @param bool $should_show Whether the floating links should be shown.
939 + */
940 + return apply_filters( 'frm_should_show_floating_links', $should_show );
941 + }
942 +
943 + /**
944 + * @since 6.3.2
945 + *
946 + * @return void
947 + */
948 + public static function admin_enqueue_scripts() {
949 + self::load_wp_admin_style();
720 950 self::maybe_force_formidable_block_on_gutenberg_page();
951 +
952 + if ( FrmAppHelper::is_admin_page( 'formidable-settings' ) ) {
953 + wp_enqueue_style( FrmDashboardController::PAGE_SLUG, FrmAppHelper::plugin_url() . '/css/admin/dashboard.css', array(), FrmAppHelper::plugin_version() );
954 + }
955 +
956 + FrmUsageController::load_scripts();
721 957 }
722 958
723 959 /**
960 + * Enqueue legacy PayPal action settings styles when the PayPal add-on is active.
961 + *
962 + * @since 6.31
963 + *
964 + * @return void
965 + */
966 + private static function maybe_enqueue_legacy_paypal_assets() {
967 + if ( ! FrmAppHelper::is_form_builder_page() || ! class_exists( 'FrmPaymentsController' ) ) {
968 + return;
969 + }
970 +
971 + wp_register_style(
972 + 'formidable-legacy-paypal',
973 + FrmAppHelper::plugin_url() . '/css/admin/frm-legacy-paypal.css',
974 + array( 'formidable-admin' ),
975 + FrmAppHelper::plugin_version()
976 + );
977 + wp_enqueue_style( 'formidable-legacy-paypal' );
978 + }
979 +
980 + /**
724 981 * Enqueue required assets for the Legacy Views editor (Views v4.x).
725 982 *
726 983 * @since 6.1.2
727 984 *
@@ -729,9 +986,9 @@
729 986 */
730 987 private static function enqueue_legacy_views_assets() {
731 988 wp_enqueue_style( 'formidable-grids' );
732 989 wp_enqueue_script( 'jquery-ui-draggable' );
733 - self::maybe_deregister_popper2();
990 + self::maybe_deregister_popper1();
734 991 wp_enqueue_script( 'formidable_admin' );
735 992 wp_add_inline_style(
736 993 'formidable-admin',
737 994 '
@@ -754,20 +1011,21 @@
754 1011 }
755 1012 '
756 1013 );
757 1014 wp_enqueue_style( 'formidable-admin' );
1015 + wp_enqueue_script( 'formidable_legacy_views', FrmAppHelper::plugin_url() . '/js/admin/legacy-views.js', array( 'jquery', 'formidable_admin' ), FrmAppHelper::plugin_version() ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
758 1016 FrmAppHelper::localize_script( 'admin' );
759 1017 self::include_info_overlay();
760 1018 }
761 1019
762 1020 /**
763 - * Fix a Duplicator Pro conflict because it uses Popper 2. See issue #3459.
1021 + * Unregister Popper if the registered version is outdated.
764 1022 *
765 - * @since 5.2.02.01
1023 + * @since 6.26
766 1024 *
767 1025 * @return void
768 1026 */
769 - private static function maybe_deregister_popper2() {
1027 + private static function maybe_deregister_popper1() {
770 1028 global $wp_scripts;
771 1029
772 1030 if ( ! array_key_exists( 'popper', $wp_scripts->registered ) ) {
773 1031 return;
@@ -773,26 +1031,65 @@
773 1031 return;
774 1032 }
775 1033
776 1034 $popper = $wp_scripts->registered['popper'];
777 - if ( version_compare( $popper->ver, '2.0', '>=' ) ) {
778 - wp_deregister_script( 'popper' );
779 - self::register_popper1();
1035 +
1036 + if ( ! version_compare( $popper->ver, '2.0', '<' ) ) {
1037 + return;
780 1038 }
1039 +
1040 + wp_deregister_script( 'popper' );
1041 + self::register_popper2();
781 1042 }
782 1043
783 1044 /**
784 - * Register Popper required for Bootstrap 4.
1045 + * Register Popper required for Bootstrap 5.
785 1046 *
786 - * @since 5.2.02.01
1047 + * @since 6.26
787 1048 *
788 1049 * @return void
789 1050 */
790 - private static function register_popper1() {
791 - wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array( 'jquery' ), '1.16.0', true );
1051 + private static function register_popper2() {
1052 + if ( ! self::should_register_popper() ) {
1053 + return;
1054 + }
1055 + wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array(), '2.11.8', true );
792 1056 }
793 1057
794 1058 /**
1059 + * Only register popper on Formidable pages.
1060 + * This helps to avoid popper conflicts on other plugin pages, including the WP Bakery page editor.
1061 + *
1062 + * @since 6.11.1
1063 + *
1064 + * @return bool
1065 + */
1066 + private static function should_register_popper() {
1067 + global $pagenow;
1068 +
1069 + $post_id = FrmAppHelper::simple_get( 'post', 'absint' );
1070 +
1071 + if ( 'post.php' === $pagenow && $post_id && 'frm_display' === get_post_type( $post_id ) ) {
1072 + return true;
1073 + }
1074 +
1075 + $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1076 + $is_views_post_type = 'frm_display' === $post_type;
1077 +
1078 + if ( in_array( $pagenow, array( 'post-new.php', 'edit.php' ), true ) && $is_views_post_type ) {
1079 + return true;
1080 + }
1081 +
1082 + $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
1083 +
1084 + if ( str_starts_with( $page, 'formidable' ) ) {
1085 + return true;
1086 + }
1087 +
1088 + return in_array( $pagenow, array( 'term.php', 'edit-tags.php' ), true ) && FrmAppHelper::simple_get( 'taxonomy' ) === 'frm_application';
1089 + }
1090 +
1091 + /**
795 1092 * Automatically insert a Formidable block when loading Gutenberg when $_GET['frmForm' is set.
796 1093 *
797 1094 * @since 5.2
798 1095 *
@@ -799,13 +1096,15 @@
799 1096 * @return void
800 1097 */
801 1098 private static function maybe_force_formidable_block_on_gutenberg_page() {
802 1099 global $pagenow;
1100 +
803 1101 if ( 'post.php' !== $pagenow ) {
804 1102 return;
805 1103 }
806 1104
807 1105 $form_id = FrmAppHelper::simple_get( 'frmForm', 'absint' );
1106 +
808 1107 if ( ! $form_id ) {
809 1108 return;
810 1109 }
811 1110
@@ -851,18 +1150,18 @@
851 1150 * @return void
852 1151 */
853 1152 public static function create_rest_routes() {
854 1153 $args = array(
855 - 'methods' => 'GET',
856 - 'callback' => 'FrmAppController::api_install',
857 - 'permission_callback' => __CLASS__ . '::can_update_db',
1154 + 'methods' => 'GET',
1155 + 'callback' => 'FrmAppController::api_install',
1156 + 'permission_callback' => self::class . '::can_update_db',
858 1157 );
859 1158
860 1159 register_rest_route( 'frm-admin/v1', '/install', $args );
861 1160
862 1161 $args = array(
863 - 'methods' => 'GET',
864 - 'callback' => 'FrmAddonsController::install_addon_api',
1162 + 'methods' => 'GET',
1163 + 'callback' => 'FrmAddonsController::install_addon_api',
865 1164 'permission_callback' => 'FrmAddonsController::can_install_addon_api',
866 1165 );
867 1166
868 1167 register_rest_route( 'frm-admin/v1', '/install-addon', $args );
@@ -872,8 +1171,10 @@
872 1171 * Make sure the install is only being run when we tell it to.
873 1172 * We don't want to run manually by people calling the API.
874 1173 *
875 1174 * @since 4.06.02
1175 + *
1176 + * @return bool
876 1177 */
877 1178 public static function can_update_db() {
878 1179 return get_transient( 'frm_updating_api' );
879 1180 }
@@ -903,9 +1204,9 @@
903 1204 $response = rest_do_request( $request );
904 1205 }
905 1206
906 1207 if ( $response->is_error() ) {
907 - // if the remove post fails, use javascript instead
1208 + // If the remove post fails, use javascript instead
908 1209 add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
909 1210 }
910 1211 }
911 1212
@@ -915,14 +1216,17 @@
915 1216 *
916 1217 * @return void
917 1218 */
918 1219 private static function maybe_add_wp_site_health() {
919 - if ( ! class_exists( 'WP_Site_Health' ) ) {
920 - $wp_site_health_path = ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
921 - if ( file_exists( $wp_site_health_path ) ) {
922 - require_once $wp_site_health_path;
923 - }
1220 + if ( class_exists( 'WP_Site_Health' ) ) {
1221 + return;
924 1222 }
1223 +
1224 + $wp_site_health_path = ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
1225 +
1226 + if ( file_exists( $wp_site_health_path ) ) {
1227 + require_once $wp_site_health_path;
1228 + }
925 1229 }
926 1230
927 1231 /**
928 1232 * @since 3.0
@@ -930,12 +1234,14 @@
930 1234 * @return true
931 1235 */
932 1236 public static function api_install() {
933 1237 delete_transient( 'frm_updating_api' );
1238 +
934 1239 if ( self::needs_update() ) {
935 1240 $running = get_option( 'frm_install_running' );
1241 +
936 1242 if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
937 - update_option( 'frm_install_running', time(), 'no' );
1243 + update_option( 'frm_install_running', time(), false );
938 1244 self::install();
939 1245 delete_option( 'frm_install_running' );
940 1246 }
941 1247 }
@@ -975,9 +1281,9 @@
975 1281
976 1282 $frmdb = new FrmMigrate();
977 1283 $frmdb->uninstall();
978 1284
979 - //disable the plugin and redirect after uninstall so the tables don't get added right back
1285 + // Disable the plugin and redirect after uninstall so the tables don't get added right back.
980 1286 $plugins = array( FrmAppHelper::plugin_folder() . '/formidable.php', 'formidable-pro/formidable-pro.php' );
981 1287 deactivate_plugins( $plugins, false, false );
982 1288 echo esc_url_raw( admin_url( 'plugins.php?deactivate=true' ) );
983 1289
@@ -983,8 +1289,13 @@
983 1289
984 1290 wp_die();
985 1291 }
986 1292
1293 + /**
1294 + * @param array $tables
1295 + *
1296 + * @return array
1297 + */
987 1298 public static function drop_tables( $tables ) {
988 1299 global $wpdb;
989 1300 $tables[] = $wpdb->prefix . 'frm_fields';
990 1301 $tables[] = $wpdb->prefix . 'frm_forms';
@@ -1007,54 +1318,425 @@
1007 1318 delete_site_option( 'frmpro-authorized' );
1008 1319 wp_die();
1009 1320 }
1010 1321
1322 + /**
1323 + * This is triggered when Formidable is activated.
1324 + *
1325 + * @return void
1326 + */
1327 + public static function handle_activation() {
1328 + self::maybe_activate_payment_cron();
1329 + }
1330 +
1331 + /**
1332 + * The payment cron is unscheduled when Formidable is deactivated.
1333 + * We need to add it back again on activation if Stripe is configured.
1334 + *
1335 + * @since 6.5
1336 + *
1337 + * @return void
1338 + */
1339 + private static function maybe_activate_payment_cron() {
1340 + if ( ! FrmStrpLiteConnectHelper::stripe_connect_is_setup() ) {
1341 + return;
1342 + }
1343 +
1344 + FrmTransLiteAppController::maybe_schedule_cron();
1345 + }
1346 +
1347 + /**
1348 + * @param string $text
1349 + *
1350 + * @return string
1351 + */
1011 1352 public static function set_footer_text( $text ) {
1353 + return FrmAppHelper::is_formidable_admin() ? '' : $text;
1354 + }
1355 +
1356 + /**
1357 + * Add admin footer links.
1358 + *
1359 + * @since 6.4.1
1360 + *
1361 + * @return void
1362 + */
1363 + public static function add_admin_footer_links() {
1364 + FrmFormsController::include_device_too_small_message();
1365 +
1366 + if ( self::should_show_footer_links() ) {
1367 + include FrmAppHelper::plugin_path() . '/classes/views/shared/admin-footer-links.php';
1368 + }
1369 + }
1370 +
1371 + /**
1372 + * Check if the footer links should be shown.
1373 + *
1374 + * @since 6.7
1375 + *
1376 + * @return bool
1377 + */
1378 + private static function should_show_footer_links() {
1379 + $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1380 + $is_formidable_page = FrmAppHelper::is_formidable_admin() || 'frm_logs' === $post_type;
1381 + $show_footer_links = $is_formidable_page;
1382 +
1383 + if ( FrmAppHelper::is_full_screen() || ! FrmAppHelper::is_formidable_branding() ) {
1384 + $show_footer_links = false;
1385 + }
1386 +
1387 + /**
1388 + * Filter whether to show the Formidable footer links.
1389 + *
1390 + * @since 6.7
1391 + *
1392 + * @param bool $show_footer_links
1393 + *
1394 + * @return bool
1395 + */
1396 + return apply_filters( 'frm_show_footer_links', $show_footer_links );
1397 + }
1398 +
1399 + /**
1400 + * Show an error modal and terminate the script execution.
1401 + *
1402 + * @since 6.7
1403 + *
1404 + * @param array $error_args Arguments that control the behavior of the error modal.
1405 + *
1406 + * @return void
1407 + */
1408 + public static function show_error_modal( $error_args ) {
1409 + add_filter( 'frm_show_footer_links', '__return_false' );
1410 +
1411 + $defaults = array(
1412 + 'title' => '',
1413 + 'body' => '',
1414 + 'cancel_url' => '',
1415 + 'cancel_classes' => '',
1416 + 'continue_url' => '',
1417 + 'continue_classes' => '',
1418 + 'icon' => 'frm_lock_simple',
1419 + );
1420 +
1421 + $error_args = wp_parse_args( $error_args, $defaults );
1422 +
1423 + if ( ! isset( $error_args['cancel_text'] ) && ! empty( $error_args['cancel_url'] ) ) {
1424 + $error_args['cancel_text'] = __( 'Cancel', 'formidable' );
1425 + }
1426 +
1427 + if ( ! isset( $error_args['continue_text'] ) && ! empty( $error_args['continue_url'] ) ) {
1428 + $error_args['continue_text'] = __( 'Continue', 'formidable' );
1429 + }
1430 +
1431 + include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/error-modal.php';
1432 + }
1433 +
1434 + /**
1435 + * Handles Floating Links' scripts and styles enqueueing.
1436 + *
1437 + * @since 6.4
1438 + *
1439 + * @param string $plugin_url URL of the plugin.
1440 + * @param string $version Current version of the plugin.
1441 + *
1442 + * @return void
1443 + */
1444 + private static function enqueue_floating_links( $plugin_url, $version ) {
1445 + if ( ! $plugin_url || ! $version ) {
1446 + // If any required parameters are missing, exit early.
1447 + return;
1448 + }
1449 +
1450 + // Enqueue the Floating Links styles.
1451 + wp_enqueue_style( 's11-floating-links', $plugin_url . '/css/packages/s11-floating-links.css', array(), $version );
1452 +
1453 + // Enqueue the Floating Links script.
1454 + wp_enqueue_script( 's11-floating-links', $plugin_url . '/js/packages/floating-links/s11-floating-links.js', array( 'formidable_admin' ), $version, true );
1455 +
1456 + // Enqueue the config script.
1457 + wp_enqueue_script( 's11-floating-links-config', $plugin_url . '/js/packages/floating-links/config.js', array( 'wp-i18n' ), $version, true );
1458 +
1459 + if ( function_exists( 'wp_set_script_translations' ) ) {
1460 + wp_set_script_translations( 's11-floating-links-config', 's11-' );
1461 + }
1462 +
1463 + $upgrade_utm = array(
1464 + 'campaign' => 'floating-links',
1465 + 'content' => 'floating-links-upgrade',
1466 + );
1467 + $docs_utm = array(
1468 + 'campaign' => 'floating-links',
1469 + 'content' => 'floating-links-docs',
1470 + );
1471 + $floating_links_data = array(
1472 + 'proIsInstalled' => FrmAppHelper::pro_is_installed(),
1473 + 'upgradeUrl' => FrmAppHelper::admin_upgrade_link( $upgrade_utm ),
1474 + 'documentationUrl' => FrmAppHelper::admin_upgrade_link( $docs_utm, 'knowledgebase/' ),
1475 + );
1476 + wp_localize_script( 's11-floating-links-config', 's11FloatingLinksData', $floating_links_data );
1477 +
1478 + /**
1479 + * Prompt Pro to load additional floating links scripts.
1480 + * This is used to include images in the Inbox SlideIn when Pro is active.
1481 + *
1482 + * @since 6.8.4
1483 + */
1484 + do_action( 'frm_enqueue_floating_links' );
1485 + }
1486 +
1487 + /**
1488 + * Check if we are in our admin pages.
1489 + *
1490 + * @return bool
1491 + */
1492 + private static function in_our_pages() {
1493 + global $current_screen, $pagenow;
1494 +
1012 1495 if ( FrmAppHelper::is_formidable_admin() ) {
1013 - $text = '';
1496 + return true;
1014 1497 }
1015 1498
1016 - return $text;
1499 + if ( ! empty( $current_screen->post_type ) && 'frm_logs' === $current_screen->post_type ) {
1500 + return true;
1501 + }
1502 +
1503 + return in_array( $pagenow, array( 'term.php', 'edit-tags.php' ), true ) && 'frm_application' === FrmAppHelper::simple_get( 'taxonomy' );
1017 1504 }
1018 1505
1019 1506 /**
1020 - * @deprecated 3.0.04
1507 + * Handles actions related to the current screen.
1021 1508 *
1022 - * @codeCoverageIgnore
1509 + * @since 6.19
1023 1510 *
1024 1511 * @return void
1025 1512 */
1026 - public static function activation_install() {
1027 - FrmDeprecated::activation_install();
1513 + public static function handle_current_screen() {
1514 + if ( ! self::in_our_pages() ) {
1515 + return;
1516 + }
1517 +
1518 + self::filter_admin_notices();
1519 + self::remember_custom_sort();
1028 1520 }
1029 1521
1030 1522 /**
1031 - * @deprecated 3.0
1032 - * @codeCoverageIgnore
1523 + * Hide all third-parties admin notices only in our admin pages.
1524 + *
1525 + * @return void
1033 1526 */
1034 - public static function page_route( $content ) {
1035 - return FrmDeprecated::page_route( $content );
1527 + public static function filter_admin_notices() {
1528 + $actions = array(
1529 + 'admin_notices',
1530 + 'network_admin_notices',
1531 + 'user_admin_notices',
1532 + 'all_admin_notices',
1533 + );
1534 +
1535 + global $wp_filter;
1536 +
1537 + foreach ( $actions as $action ) {
1538 + if ( empty( $wp_filter[ $action ]->callbacks ) ) {
1539 + continue;
1540 + }
1541 +
1542 + foreach ( $wp_filter[ $action ]->callbacks as $priority => $callbacks ) {
1543 + foreach ( $callbacks as $callback_name => $callback ) {
1544 + if ( self::is_our_callback_string( $callback_name ) || self::is_our_callback_array( $callback ) ) {
1545 + continue;
1546 + }
1547 + unset( $wp_filter[ $action ]->callbacks[ $priority ][ $callback_name ] );
1548 + }
1549 + }
1550 + }
1036 1551 }
1037 1552
1038 1553 /**
1039 - * Include icons on page for Embed Form modal.
1554 + * Remembers and applies user-specific sorting preferences.
1040 1555 *
1041 - * @since 5.2
1556 + * @return void
1557 + */
1558 + private static function remember_custom_sort() {
1559 + $meta_key = self::get_sort_pref_user_meta_key();
1560 +
1561 + if ( false === $meta_key ) {
1562 + return;
1563 + }
1564 +
1565 + $is_form_list = FrmAppHelper::is_admin_list_page();
1566 + $is_entry_list = FrmAppHelper::is_admin_list_page( 'formidable-entries' );
1567 +
1568 + if ( ! $is_form_list && ! $is_entry_list ) {
1569 + return;
1570 + }
1571 +
1572 + $orderby = FrmAppHelper::get_param( 'orderby' );
1573 +
1574 + if ( ! $orderby ) {
1575 + return;
1576 + }
1577 +
1578 + $user_id = get_current_user_id();
1579 + $order = FrmAppHelper::get_param( 'order' );
1580 + $new_sort = array(
1581 + 'orderby' => $orderby,
1582 + 'order' => $order,
1583 + );
1584 + $previous_meta = get_user_meta( $user_id, $meta_key, true );
1585 + $current_sort = $previous_meta;
1586 + $form_id = $is_entry_list ? FrmAppHelper::simple_get( 'form', 'absint' ) : 0;
1587 +
1588 + if ( is_array( $current_sort ) && $form_id && is_int( $form_id ) && isset( $current_sort[ $form_id ] ) ) {
1589 + $current_sort = $current_sort[ $form_id ];
1590 + }
1591 +
1592 + if ( $new_sort === $current_sort ) {
1593 + return;
1594 + }
1595 +
1596 + $new_meta = $new_sort;
1597 +
1598 + if ( $is_entry_list && $form_id && is_int( $form_id ) ) {
1599 + // Index meta by form ID.
1600 + $temp_meta = is_array( $previous_meta ) ? $previous_meta : array();
1601 + $temp_meta[ $form_id ] = $new_meta;
1602 + $new_meta = $temp_meta;
1603 + unset( $temp_meta );
1604 + }
1605 +
1606 + update_user_meta( $user_id, $meta_key, $new_meta );
1607 + }
1608 +
1609 + /**
1610 + * Retrieve and apply any saved sorting preferences for the current screen.
1042 1611 *
1612 + * @since 6.19
1613 + *
1614 + * @param string $orderby Reference to the current 'orderby' parameter.
1615 + * @param string $order Reference to the current 'order' parameter.
1616 + *
1043 1617 * @return void
1044 1618 */
1045 - public static function include_embed_form_icons() {
1046 - _deprecated_function( __METHOD__, '5.3' );
1619 + public static function apply_saved_sort_preference( &$orderby, &$order ) {
1620 + $meta_key = self::get_sort_pref_user_meta_key();
1621 +
1622 + if ( false === $meta_key ) {
1623 + return;
1624 + }
1625 +
1626 + $preferred_list_sort = get_user_meta( get_current_user_id(), $meta_key, true );
1627 + $form_id = FrmAppHelper::simple_get( 'form', 'absint' );
1628 +
1629 + if ( is_array( $preferred_list_sort ) && $form_id && is_int( $form_id ) && isset( $preferred_list_sort[ $form_id ] ) ) {
1630 + $preferred_list_sort = $preferred_list_sort[ $form_id ];
1631 + }
1632 +
1633 + if ( ! is_array( $preferred_list_sort ) || empty( $preferred_list_sort['orderby'] ) ) {
1634 + return;
1635 + }
1636 +
1637 + $orderby = $preferred_list_sort['orderby'];
1638 +
1639 + if ( ! empty( $preferred_list_sort['order'] ) ) {
1640 + $order = $preferred_list_sort['order'];
1641 + }
1047 1642 }
1048 1643
1049 1644 /**
1050 - * @deprecated 1.07.05 This is still referenced in the API add on as of v1.13.
1051 - * @codeCoverageIgnore
1645 + * Get a simple user meta key that only includes the screen ID.
1052 1646 *
1053 - * @param array $atts
1054 - * @return string
1647 + * @since 6.25.1
1648 + *
1649 + * @return false|string
1055 1650 */
1056 - public static function get_form_shortcode( $atts ) {
1057 - _deprecated_function( __FUNCTION__, '1.07.05', 'FrmFormsController::get_form_shortcode' );
1058 - return FrmFormsController::get_form_shortcode( $atts );
1651 + private static function get_sort_pref_user_meta_key() {
1652 + if ( ! function_exists( 'get_current_screen' ) ) {
1653 + return false;
1654 + }
1655 +
1656 + $screen = get_current_screen();
1657 + return $screen ? 'frm_preferred_list_sort_' . $screen->id : false;
1658 + }
1659 +
1660 + /**
1661 + * Validate that the callback name is ours not from third-party.
1662 + *
1663 + * @param string $callback_name WordPress callback name.
1664 + *
1665 + * @return bool
1666 + */
1667 + private static function is_our_callback_string( $callback_name ) {
1668 + return 0 === stripos( $callback_name, 'frm' );
1669 + }
1670 +
1671 + /**
1672 + * Validate that the callback array is ours not from third-party.
1673 + *
1674 + * @param array $callback WordPress callback array.
1675 + *
1676 + * @return bool
1677 + */
1678 + private static function is_our_callback_array( $callback ) {
1679 + return ! empty( $callback['function'] ) && is_array( $callback['function'] ) && ! empty( $callback['function'][0] ) && self::is_our_callback_string( is_object( $callback['function'][0] ) ? get_class( $callback['function'][0] ) : $callback['function'][0] ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
1680 + }
1681 +
1682 + /**
1683 + * In some cases, the DB tables may fail to install.
1684 + * This function tries to add them again when the user clicks the link to try again
1685 + * from the given inbox notice.
1686 + *
1687 + * @since 6.19
1688 + */
1689 + private static function add_missing_tables() {
1690 + FrmAppHelper::permission_check( 'frm_view_forms' );
1691 +
1692 + $error = FrmInbox::check_for_error();
1693 +
1694 + if ( ! $error || 'failed-to-create-tables' !== $error['key'] ) {
1695 + // Confirm the inbox item with this CTA exists.
1696 + wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1697 + exit;
1698 + }
1699 +
1700 + global $wpdb;
1701 + $exists = $wpdb->get_results( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->prefix . 'frm_forms' ) );
1702 +
1703 + if ( $exists ) {
1704 + // Exit early if the table already exists.
1705 + wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1706 + exit;
1707 + }
1708 +
1709 + delete_option( 'frm_db_version' );
1710 + wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1711 + exit;
1712 + }
1713 +
1714 + /**
1715 + * Handles the small screen proceed action.
1716 + *
1717 + * @since 6.21
1718 + *
1719 + * @return void
1720 + */
1721 + public static function small_screen_proceed() {
1722 + FrmAppHelper::permission_check( 'frm_view_forms' );
1723 + check_ajax_referer( 'frm_ajax', 'nonce' );
1724 + update_user_option( get_current_user_id(), 'frm_ignore_small_screen_warning', true );
1725 + wp_send_json_success();
1726 + }
1727 +
1728 + /**
1729 + * Enqueue the components scripts.
1730 + *
1731 + * @since 6.28
1732 + *
1733 + * @return void
1734 + */
1735 + public static function enqueue_components_scripts() {
1736 + if ( is_callable( array( 'FrmProFormsController', 'enqueue_pro_web_components_script' ) ) ) {
1737 + FrmProFormsController::enqueue_pro_web_components_script();
1738 + }
1739 +
1740 + wp_enqueue_script( 'formidable-web-components' );
1059 1741 }
1060 1742 }