PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.4
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.4
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/FrmStylesController.php +119 -756 6.35.4 View file →
@@ -3,24 +3,11 @@
3 3 die( 'You are not allowed to call this page directly.' );
4 4 }
5 5
6 6 class FrmStylesController {
7 -
8 - /**
9 - * @var string $post_type
10 - */
11 7 public static $post_type = 'frm_styles';
12 -
13 - /**
14 - * @var string $screen
15 - */
16 8 public static $screen = 'formidable_page_formidable-styles';
17 9
18 - /**
19 - * @var string|null $message
20 - */
21 - private static $message;
22 -
23 10 public static function load_pro_hooks() {
24 11 if ( FrmAppHelper::pro_is_installed() ) {
25 12 FrmProStylesController::load_pro_hooks();
26 13 }
@@ -58,78 +45,29 @@
58 45 )
59 46 );
60 47 }
61 48
62 - /**
63 - * Add two links for the visual styler.
64 - * There's a "Styles" submenu in the Formidable menu.
65 - * There's a second alternative "Forms" submenu in the Appearance menu.
66 - * This submenu links to a page to edit a form with the default style.
67 - *
68 - * @return void
69 - */
70 49 public static function menu() {
71 50 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Styles', 'formidable' ), 'frm_change_settings', 'formidable-styles', 'FrmStylesController::route' );
72 51 add_submenu_page( 'themes.php', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Forms', 'formidable' ), 'frm_change_settings', 'formidable-styles2', 'FrmStylesController::route' );
73 52 }
74 53
75 - /**
76 - * Remove filters for the visual styler preview.
77 - * This triggers earlier than self::admin_init which is called too late.
78 - *
79 - * @return void
80 - */
81 - public static function plugins_loaded() {
82 - if ( ! FrmAppHelper::is_style_editor_page() ) {
54 + public static function admin_init() {
55 + if ( ! FrmAppHelper::is_admin_page( 'formidable-styles' ) && ! FrmAppHelper::is_admin_page( 'formidable-styles2' ) ) {
83 56 return;
84 57 }
85 58
86 - self::disable_form_css();
87 - self::prevent_form_scripts_from_loading();
88 - }
59 + self::load_pro_hooks();
89 60
90 - /**
91 - * Avoid loading CSS the normal way with the preview in the styler.
92 - * It gets loaded instead with the frmpro_css action set to the #frm-custom-theme-css element.
93 - *
94 - * @since 6.0
95 - *
96 - * @return void
97 - */
98 - private static function disable_form_css() {
99 - add_filter( 'get_frm_stylesheet', '__return_false' );
100 - }
101 -
102 - /**
103 - * Removing this action prevents front end JavaScript from loading.
104 - *
105 - * @since 6.0
106 - *
107 - * @return void
108 - */
109 - private static function prevent_form_scripts_from_loading() {
110 - remove_action( 'init', 'FrmFormsController::front_head' );
111 - }
112 -
113 - /**
114 - * @return void
115 - */
116 - public static function admin_init() {
117 - self::maybe_hook_into_global_settings_save();
118 -
119 - if ( ! FrmAppHelper::is_style_editor_page() ) {
61 + $style_tab = FrmAppHelper::get_param( 'frm_action', '', 'get', 'sanitize_title' );
62 + if ( $style_tab === 'manage' || $style_tab === 'custom_css' ) {
63 + // we only need to load these styles/scripts on the styler page
120 64 return;
121 65 }
122 66
123 - self::load_pro_hooks();
124 -
125 67 $version = FrmAppHelper::plugin_version();
126 68 wp_enqueue_script( 'jquery-ui-datepicker' );
127 -
128 - if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
129 - wp_enqueue_style( 'wp-color-picker' );
130 - }
131 -
69 + wp_enqueue_style( 'wp-color-picker' );
132 70 wp_enqueue_style( 'frm-custom-theme', admin_url( 'admin-ajax.php?action=frmpro_css' ), array(), $version );
133 71
134 72 $style = apply_filters( 'frm_style_head', false );
135 73 if ( $style ) {
@@ -137,38 +75,15 @@
137 75 }
138 76 }
139 77
140 78 /**
141 - * @since 6.0
142 - *
143 - * @return void
144 - */
145 - private static function maybe_hook_into_global_settings_save() {
146 - if ( empty( $_POST ) || ! isset( $_POST['style'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
147 - // Avoid changing any style data if the style array is not sent in the request.
148 - return;
149 - }
150 -
151 - add_action(
152 - 'frm_update_settings',
153 - /**
154 - * Update the form data on the "Manage Styles" tab after global settings are saved.
155 - */
156 - function() {
157 - self::manage_styles();
158 - }
159 - );
160 - }
161 -
162 - /**
163 79 * @param string $register Either 'enqueue' or 'register'.
164 80 * @param bool $force True to enqueue/register the style if a form has not been loaded.
165 - * @return void
166 81 */
167 82 public static function enqueue_css( $register = 'enqueue', $force = false ) {
168 83 global $frm_vars;
169 84
170 - $register_css = $register === 'register';
85 + $register_css = ( $register == 'register' );
171 86 $should_load = $force || ( ( $frm_vars['load_css'] || $register_css ) && ! FrmAppHelper::is_admin() );
172 87
173 88 if ( ! $should_load ) {
174 89 return;
@@ -174,16 +89,17 @@
174 89 return;
175 90 }
176 91
177 92 $frm_settings = FrmAppHelper::get_settings();
178 - if ( $frm_settings->load_style === 'none' ) {
93 + if ( $frm_settings->load_style == 'none' ) {
179 94 return;
180 95 }
181 96
182 97 $css = apply_filters( 'get_frm_stylesheet', self::custom_stylesheet() );
183 98
184 - if ( $css ) {
185 - $css = (array) $css;
99 + if ( ! empty( $css ) ) {
100 + $css = (array) $css;
101 +
186 102 $version = FrmAppHelper::plugin_version();
187 103
188 104 foreach ( $css as $css_key => $file ) {
189 105 if ( $register_css ) {
@@ -190,9 +106,9 @@
190 106 $this_version = self::get_css_version( $css_key, $version );
191 107 wp_register_style( $css_key, $file, array(), $this_version );
192 108 }
193 109
194 - $load_on_all = ! FrmAppHelper::is_admin() && 'all' === $frm_settings->load_style;
110 + $load_on_all = ! FrmAppHelper::is_admin() && 'all' == $frm_settings->load_style;
195 111 if ( $load_on_all || $register != 'register' ) {
196 112 wp_enqueue_style( $css_key );
197 113 }
198 114 unset( $css_key, $file );
@@ -197,9 +113,9 @@
197 113 }
198 114 unset( $css_key, $file );
199 115 }
200 116
201 - if ( $frm_settings->load_style === 'all' ) {
117 + if ( $frm_settings->load_style == 'all' ) {
202 118 $frm_vars['css_loaded'] = true;
203 119 }
204 120 }
205 121 unset( $css );
@@ -206,17 +122,14 @@
206 122
207 123 add_filter( 'style_loader_tag', 'FrmStylesController::add_tags_to_css', 10, 2 );
208 124 }
209 125
210 - /**
211 - * @return array<string,string>
212 - */
213 126 public static function custom_stylesheet() {
214 127 global $frm_vars;
215 128 $stylesheet_urls = array();
216 129
217 - if ( empty( $frm_vars['css_loaded'] ) ) {
218 - // Include css in head.
130 + if ( ! isset( $frm_vars['css_loaded'] ) || ! $frm_vars['css_loaded'] ) {
131 + //include css in head
219 132 self::get_url_to_custom_style( $stylesheet_urls );
220 133 }
221 134
222 135 return $stylesheet_urls;
@@ -221,12 +134,8 @@
221 134
222 135 return $stylesheet_urls;
223 136 }
224 137
225 - /**
226 - * @param array $stylesheet_urls
227 - * @return void
228 - */
229 138 private static function get_url_to_custom_style( &$stylesheet_urls ) {
230 139 $file_name = '/css/' . self::get_file_name();
231 140 if ( is_readable( FrmAppHelper::plugin_path() . $file_name ) ) {
232 141 $url = FrmAppHelper::plugin_url() . $file_name;
@@ -275,569 +184,166 @@
275 184
276 185 return $tag;
277 186 }
278 187
279 - /**
280 - * Route the edit route to the style function.
281 - *
282 - * @since 6.0 this function no longer has any parameter values.
283 - *
284 - * @return void
285 - */
286 - public static function edit() {
287 - self::load_styler();
188 + public static function new_style( $return = '' ) {
189 + self::load_styler( 'default' );
288 190 }
289 191
290 - /**
291 - * When a new style route is hit, show a new style with the defaults. There is no ID yet, it is created after the first save event.
292 - *
293 - * @return void
294 - */
295 - public static function new_style() {
296 - self::load_styler();
297 - }
298 -
299 - /**
300 - * When the duplicate route is hit, it just shows the visual styler with a copy of the target style. There is no ID yet, it is created after the first save event.
301 - *
302 - * @return void
303 - */
304 192 public static function duplicate() {
305 - self::load_styler();
193 + self::load_styler( 'default' );
306 194 }
307 195
308 - /**
309 - * Render the style page for a form for assigning a style to a form, and for updating a target style.
310 - *
311 - * @since 6.0 this function no longer takes parameters.
312 - *
313 - * @return void
314 - */
315 - public static function load_styler() {
316 - if ( 'assign_style' === FrmAppHelper::get_post_param( 'frm_action' ) ) {
317 - self::save_form_style();
318 - }
319 -
320 - self::setup_styles_and_scripts_for_styler();
321 -
322 - $style_id = self::get_style_id_for_styler();
196 + public static function edit( $style_id = false, $message = '' ) {
323 197 if ( ! $style_id ) {
324 - wp_die( esc_html__( 'Invalid route', 'formidable' ), esc_html__( 'Invalid route', 'formidable' ), 400 );
325 - }
326 -
327 - $form_id = FrmAppHelper::simple_get( 'form', 'absint', 0 );
328 - if ( ! $form_id ) {
329 - $form_id = self::get_form_id_for_style( $style_id );
330 - }
331 -
332 - $form = FrmForm::getOne( $form_id );
333 - if ( ! is_object( $form ) ) {
334 - wp_die( esc_html__( 'Invalid route', 'formidable' ), esc_html__( 'Invalid route', 'formidable' ), 400 );
335 - }
336 -
337 - $frm_style = new FrmStyle( $style_id );
338 - $active_style = $frm_style->get_one();
339 - $default_style = self::get_default_style();
340 -
341 - self::disable_admin_page_styling_on_submit_buttons();
342 -
343 - /**
344 - * @since 6.0
345 - *
346 - * @param array {
347 - * @type stdClass $form
348 - * }
349 - */
350 - do_action( 'frm_before_render_style_page', compact( 'form' ) );
351 -
352 - self::render_style_page( $active_style, $form, $default_style );
353 - }
354 -
355 - /**
356 - * @since 6.0
357 - *
358 - * @return int
359 - */
360 - private static function get_style_id_for_styler() {
361 - $action = FrmAppHelper::simple_get( 'frm_action' );
362 - if ( 'duplicate' === $action ) {
363 - // The duplicate action uses style_id instead of id for better backward compatibility.
364 - return FrmAppHelper::simple_get( 'style_id', 'absint', 0 );
365 - }
366 -
367 - $style_id = FrmAppHelper::simple_get( 'id', 'absint', 0 );
368 - if ( $style_id ) {
369 - // Always use the style ID from the URL if one is specified.
370 - return $style_id;
371 - }
372 -
373 - $request_form_id = FrmAppHelper::simple_get( 'form', 'absint', 0 );
374 - if ( $request_form_id && is_callable( 'FrmProStylesController::get_active_style_for_form' ) ) {
375 - return FrmProStylesController::get_active_style_for_form( $request_form_id )->ID;
376 - }
377 -
378 - return self::get_default_style()->ID;
379 - }
380 -
381 - /**
382 - * If a form ID is not being passed in the URL, try to get the best match.
383 - *
384 - * @since 6.0
385 - *
386 - * @param int $style_id
387 - * @return int
388 - */
389 - private static function get_form_id_for_style( $style_id ) {
390 - $check = serialize( array( 'custom_style' => (string) $style_id ) );
391 - $check = substr( $check, 5, -1 );
392 - $form_id = FrmDb::get_var(
393 - 'frm_forms',
394 - array(
395 - 'options LIKE' => $check,
396 - 'status' => 'published',
397 - )
398 - );
399 -
400 - if ( ! $form_id ) {
401 - // TODO: Show a message why a random form is being shown (because no form is assigned to the style).
402 - // Fallback to any form.
403 - $where = array(
404 - 'status' => 'published',
405 - 'parent_form_id' => array( null, 0 ), // Make sure it's not a repeater.
406 - );
407 - $form_id = FrmDb::get_var( 'frm_forms', $where, 'id' );
408 - }
409 -
410 - return $form_id;
411 - }
412 -
413 - /**
414 - * Add a frm_no_style_button class to all buttons to avoid some style rules like border-radius: 30px.
415 - *
416 - * @return void
417 - */
418 - private static function disable_admin_page_styling_on_submit_buttons() {
419 - add_filter(
420 - 'frm_submit_button_class',
421 - function( $classes ) {
422 - $classes[] = 'frm_no_style_button';
423 - return $classes;
198 + $style_id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
199 + if ( empty( $style_id ) ) {
200 + $style_id = 'default';
424 201 }
425 - );
426 - }
427 -
428 - /**
429 - * @since 6.0
430 - *
431 - * @return WP_Post
432 - */
433 - private static function get_default_style() {
434 - $frm_style = new FrmStyle( 'default' );
435 - $default_style = $frm_style->get_one();
436 - return $default_style;
437 - }
438 -
439 - /**
440 - * Save style for form (from Styler list page) via a POST action.
441 - *
442 - * @since 6.0
443 - *
444 - * @return void
445 - */
446 - private static function save_form_style() {
447 - $permission_error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'frm_save_form_style', 'frm_save_form_style_nonce' );
448 - if ( $permission_error !== false ) {
449 - wp_die( 'Unable to save form', '', 403 );
450 202 }
451 203
452 - $style_id = FrmAppHelper::get_post_param( 'style_id', 0, 'absint' );
453 - if ( $style_id && ! self::confirm_style_exists_before_setting( $style_id ) ) {
454 - wp_die( esc_html__( 'Invalid target style', 'formidable' ), esc_html__( 'Invalid target style', 'formidable' ), 400 );
455 - return;
204 + if ( 'default' == $style_id ) {
205 + $style = 'default';
206 + } else {
207 + $frm_style = new FrmStyle( $style_id );
208 + $style = $frm_style->get_one();
209 + $style = $style->ID;
456 210 }
457 211
458 - /**
459 - * Hook into the saved style ID so Pro can import a style template by its key and return a new style ID.
460 - *
461 - * @since 6.0
462 - *
463 - * @param int $style_id
464 - */
465 - $style_id = apply_filters( 'frm_saved_form_style_id', $style_id );
466 -
467 - if ( ! $style_id && '0' !== FrmAppHelper::get_post_param( 'style_id', 'sanitize_text_field', '' ) ) {
468 - // "0" is a special value used for the enable/disable toggle.
469 - wp_die( esc_html__( 'Invalid style value', 'formidable' ), esc_html__( 'Invalid style value', 'formidable' ), 400 );
470 - return;
471 - }
472 -
473 - $form_id = FrmAppHelper::get_post_param( 'form_id', 'absint', 0 );
474 - if ( ! $form_id ) {
475 - wp_die( esc_html__( 'No form specified', 'formidable' ), esc_html__( 'No form specified', 'formidable' ), 400 );
476 - return;
477 - }
478 -
479 - $form = FrmForm::getOne( $form_id );
480 - if ( ! $form ) {
481 - wp_die( esc_html__( 'Form does not exist', 'formidable' ), esc_html__( 'Form does not exist', 'formidable' ), 400 );
482 - return;
483 - }
484 -
485 - // If the default style is selected, use the "Always use default" legacy option instead of the default style.
486 - // There's also a check here for conversational forms.
487 - // Without the check it isn't possible to select "Default" because "Always use default" will convert to "Lines" dynamically.
488 - $default_style = self::get_default_style();
489 - if ( $style_id === $default_style->ID && empty( $form->options['chat'] ) ) {
490 - $style_id = 1;
491 - }
492 -
493 - $form->options['custom_style'] = (string) $style_id; // We want to save a string for consistency. FrmStylesHelper::get_form_count_for_style expects the custom style ID is a string.
494 -
495 - global $wpdb;
496 - $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $form->options ) ), array( 'id' => $form->id ) );
497 -
498 - FrmForm::clear_form_cache();
499 -
500 - self::$message = __( 'Successfully updated style.', 'formidable' );
212 + self::load_styler( $style, $message );
501 213 }
502 214
503 - /**
504 - * Validate that we're assigning a form to a style that actually exists before assigning it to a form.
505 - *
506 - * @param int $style_id
507 - * @return bool True if the style actually exists.
508 - */
509 - private static function confirm_style_exists_before_setting( $style_id ) {
510 - global $wpdb;
511 - $post_type = FrmDb::get_var( $wpdb->posts, array( 'ID' => $style_id ), 'post_type' );
512 - return self::$post_type === $post_type;
513 - }
514 -
515 - /**
516 - * Register and enqueue styles and scripts for the style tab page.
517 - *
518 - * @since 6.0
519 - *
520 - * @return void
521 - */
522 - private static function setup_styles_and_scripts_for_styler() {
523 - $plugin_url = FrmAppHelper::plugin_url();
524 - $version = FrmAppHelper::plugin_version();
525 - $js_dependencies = array( 'wp-i18n', 'wp-hooks', 'formidable_dom' );
526 -
527 - if ( FrmAppHelper::pro_is_installed() ) {
528 - $js_dependencies[] = 'jquery-ui-datepicker';
529 - }
530 -
531 - wp_register_script( 'formidable_style', $plugin_url . '/js/admin/style.js', $js_dependencies, $version );
532 - wp_register_style( 'formidable_style', $plugin_url . '/css/admin/style.css', array(), $version );
533 - wp_print_styles( 'formidable_style' );
534 -
535 - wp_print_styles( 'formidable' );
536 - wp_enqueue_script( 'formidable_style' );
537 - }
538 -
539 - /**
540 - * Render the style page (with a more limited and typed scope than calling it from self::style directly).
541 - *
542 - * @since 6.0
543 - *
544 - * @param stdClass|WP_Post $active_style
545 - * @param array<WP_Post> $styles
546 - * @param stdClass $form
547 - * @param WP_Post $default_style
548 - * @return void
549 - */
550 - private static function render_style_page( $active_style, $form, $default_style ) {
551 - $style_views_path = self::get_views_path();
552 - $view = FrmAppHelper::simple_get( 'frm_action', 'sanitize_text_field', 'list' ); // edit, list (default), new_style.
553 - $frm_style = new FrmStyle( $active_style->ID );
554 -
555 - if ( 'new_style' !== $view && ! FrmAppHelper::simple_get( 'form' ) && ! FrmAppHelper::simple_get( 'style_id' ) ) {
556 - $view = 'edit'; // Have the Appearance > Forms link fallback to the edit view. Otherwise we want to use 'list' as the default.
557 - }
558 -
559 - if ( in_array( $view, array( 'edit', 'new_style', 'duplicate' ), true ) ) {
560 - self::add_meta_boxes();
561 - }
562 -
563 - switch ( $view ) {
564 - case 'edit':
565 - $style = $active_style;
566 - break;
567 -
568 - case 'duplicate':
569 - $style = clone $active_style;
570 - $new_style = $frm_style->get_new();
571 - $style->ID = $new_style->ID;
572 - $style->post_name = $new_style->post_name;
573 - unset( $new_style );
574 - break;
575 -
576 - case 'new_style':
577 - $style = $frm_style->get_new();
578 - break;
579 - }
580 -
581 - if ( in_array( $view, array( 'duplicate', 'new_style' ), true ) ) {
582 - $style->post_title = FrmAppHelper::simple_get( 'style_name' );
583 - $style->menu_order = 0;
584 - }
585 -
586 - if ( ! isset( $style ) ) {
587 - $style = $active_style;
588 - }
589 -
590 - self::force_form_style( $style );
591 -
592 - if ( isset( self::$message ) ) {
593 - $message = self::$message;
594 - }
595 -
596 - $preview_helper = new FrmStylesPreviewHelper( $form->id );
597 - $preview_helper->adjust_form_for_preview();
598 -
599 - // Get form HTML before displaying warnings and notes so we can check global $frm_vars data without adding extra database calls.
600 - $target_form_preview_html = $preview_helper->get_html_for_form_preview();
601 - $warnings = $preview_helper->get_warnings_for_styler_preview( $style, $default_style, $view );
602 - $notes = $preview_helper->get_notes_for_styler_preview();
603 -
604 - include $style_views_path . 'show.php';
605 - }
606 -
607 - /**
608 - * @since 6.0
609 - *
610 - * @return string
611 - */
612 - private static function get_views_path() {
613 - return FrmAppHelper::plugin_path() . '/classes/views/styles/';
614 - }
615 -
616 - /**
617 - * Filter form classes so the form uses the preview style, not the form's active style.
618 - *
619 - * @since 6.0
620 - *
621 - * @param WP_Post|stdClass $style A new style is not a WP_Post object.
622 - * @return void
623 - */
624 - private static function force_form_style( $style ) {
625 - add_filter(
626 - 'frm_add_form_style_class',
627 - function( $class ) use ( $style ) {
628 - $split = array_filter(
629 - explode( ' ', $class ),
630 - /**
631 - * @param string $class
632 - */
633 - function( $class ) {
634 - return $class && 0 !== strpos( $class, 'frm_style_' );
635 - }
636 - );
637 - $split[] = 'frm_style_' . $style->post_name;
638 - return implode( ' ', $split );
639 - }
640 - );
641 - }
642 -
643 - /**
644 - * Save style post object via a POST request submitted from the Visual styler "edit" page.
645 - *
646 - * @since 6.0
647 - *
648 - * @return void
649 - */
650 - public static function save_style() {
215 + public static function save() {
651 216 $frm_style = new FrmStyle();
652 217 $message = '';
653 218 $post_id = FrmAppHelper::get_post_param( 'ID', false, 'sanitize_title' );
654 219 $style_nonce = FrmAppHelper::get_post_param( 'frm_style', '', 'sanitize_text_field' );
655 220
656 - if ( $post_id === false || ! wp_verify_nonce( $style_nonce, 'frm_style_nonce' ) ) {
657 - // Exit early if the request isn't valid.
658 - // Since we're not dying, it should just reload the visual styler without any message.
659 - return;
221 + if ( $post_id !== false && wp_verify_nonce( $style_nonce, 'frm_style_nonce' ) ) {
222 + $id = $frm_style->update( $post_id );
223 + if ( empty( $post_id ) && ! empty( $id ) ) {
224 + // set the post id to the new style so it will be loaded for editing
225 + $post_id = reset( $id );
226 + }
227 + // include the CSS that includes this style
228 + echo '<link href="' . esc_url( admin_url( 'admin-ajax.php?action=frmpro_css' ) ) . '" type="text/css" rel="Stylesheet" class="frm-custom-theme" />';
229 + $message = __( 'Your styling settings have been saved.', 'formidable' );
660 230 }
661 231
662 - $id = $frm_style->update( $post_id );
663 - if ( ! $post_id && $id ) {
664 - self::maybe_redirect_after_save( $id );
665 - $post_id = reset( $id ); // Set the post id to the new style so it will be loaded for editing.
666 - }
667 -
668 - self::$message = __( 'Your styling settings have been saved.', 'formidable' );
232 + return self::edit( $post_id, $message );
669 233 }
670 234
671 - /**
672 - * Show the edit view after saving.
673 - * The save event is triggered earlier, on admin init where self::save_style is called.
674 - * This happens earlier because there is a possible redirect (to adjust the URL for a new or duplicated style).
675 - *
676 - * @return void
677 - */
678 - public static function save() {
679 - self::edit();
680 - }
235 + public static function load_styler( $style, $message = '' ) {
236 + global $frm_settings;
681 237
682 - /**
683 - * Force a redirect after duplicating or creating a new style to avoid an old stale URL that could result in more styles than intended.
684 - *
685 - * @since 6.0
686 - *
687 - * @param array $ids
688 - * @return void
689 - */
690 - private static function maybe_redirect_after_save( $ids ) {
691 - $referer = FrmAppHelper::get_server_value( 'HTTP_REFERER' );
692 - $parsed = parse_url( $referer );
693 - $query = $parsed['query'];
238 + $frm_style = new FrmStyle();
239 + $styles = $frm_style->get_all();
694 240
695 - $current_action = false;
696 - $actions_to_redirect = array( 'duplicate', 'new_style' );
697 - foreach ( $actions_to_redirect as $action ) {
698 - if ( false !== strpos( $query, 'frm_action=' . $action ) ) {
699 - $current_action = $action;
700 - break;
701 - }
241 + if ( is_numeric( $style ) ) {
242 + $style = $styles[ $style ];
243 + } elseif ( 'default' == $style ) {
244 + $style = $frm_style->get_default_style( $styles );
702 245 }
703 246
704 - if ( false === $current_action ) {
705 - // Do not redirect as the referer URL did not match $actions_to_redirect.
706 - return;
707 - }
247 + self::add_meta_boxes();
708 248
709 - parse_str( $query, $parsed_query );
710 - $form_id = ! empty( $parsed_query['form'] ) ? absint( $parsed_query['form'] ) : 0;
711 -
712 - $style = new stdClass();
713 - $style->ID = end( $ids );
714 - wp_safe_redirect( esc_url_raw( FrmStylesHelper::get_edit_url( $style, $form_id ) ) );
715 - die();
249 + include( FrmAppHelper::plugin_path() . '/classes/views/styles/show.php' );
716 250 }
717 251
718 252 /**
719 - * @since 6.0
720 - *
721 - * @param string $message
253 + * @param string $message
722 254 * @param array|object $forms
723 - * @return void
724 255 */
725 - public static function manage( $message = '', $forms = array() ) {
256 + private static function manage( $message = '', $forms = array() ) {
726 257 $frm_style = new FrmStyle();
727 258 $styles = $frm_style->get_all();
728 259 $default_style = $frm_style->get_default_style( $styles );
729 260
730 - if ( ! $forms ) {
261 + if ( empty( $forms ) ) {
731 262 $forms = FrmForm::get_published_forms();
732 263 }
733 264
734 - include FrmAppHelper::plugin_path() . '/classes/views/styles/manage.php';
265 + include( FrmAppHelper::plugin_path() . '/classes/views/styles/manage.php' );
735 266 }
736 267
737 - /**
738 - * Handle saving for the page rendered in self::manage which is included in Global Settings in the "Manage Styles" tab.
739 - * This gets called from the frm_update_settings hook which is called after saving Global settings.
740 - *
741 - * @return void
742 - */
743 268 private static function manage_styles() {
269 + $style_nonce = FrmAppHelper::get_post_param( 'frm_manage_style', '', 'sanitize_text_field' );
270 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
271 + if ( ! $_POST || ! isset( $_POST['style'] ) || ! wp_verify_nonce( $style_nonce, 'frm_manage_style_nonce' ) ) {
272 + return self::manage();
273 + }
274 +
744 275 global $wpdb;
745 276
746 277 $forms = FrmForm::get_published_forms();
747 278 foreach ( $forms as $form ) {
748 - $new_style = ( isset( $_POST['style'] ) && isset( $_POST['style'][ $form->id ] ) ) ? sanitize_text_field( wp_unslash( $_POST['style'][ $form->id ] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
749 - $previous_style = ( isset( $_POST['prev_style'] ) && isset( $_POST['prev_style'][ $form->id ] ) ) ? sanitize_text_field( wp_unslash( $_POST['prev_style'][ $form->id ] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
279 + $new_style = ( isset( $_POST['style'] ) && isset( $_POST['style'][ $form->id ] ) ) ? sanitize_text_field( wp_unslash( $_POST['style'][ $form->id ] ) ) : '';
280 + $previous_style = ( isset( $_POST['prev_style'] ) && isset( $_POST['prev_style'][ $form->id ] ) ) ? sanitize_text_field( wp_unslash( $_POST['prev_style'][ $form->id ] ) ) : '';
750 281 if ( $new_style == $previous_style ) {
751 282 continue;
752 283 }
753 284
754 285 $form->options['custom_style'] = $new_style;
286 +
755 287 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $form->options ) ), array( 'id' => $form->id ) );
756 288 unset( $form );
757 289 }
290 +
291 + $message = __( 'Your form styles have been saved.', 'formidable' );
292 +
293 + return self::manage( $message, $forms );
758 294 }
759 295
760 296 /**
761 - * Echo content for the Custom CSS page.
762 - *
763 - * @param string $message
297 + * @param string $message
298 + * @param FrmStyle|null $style
764 299 * @return void
765 300 */
766 - public static function custom_css( $message = '' ) {
767 - $settings = self::enqueue_codemirror();
768 - $id = $settings ? 'frm_codemirror_box' : 'frm_custom_css_box';
769 - $custom_css = self::get_custom_css();
301 + public static function custom_css( $message = '', $style = null ) {
302 + if ( function_exists( 'wp_enqueue_code_editor' ) ) {
303 + $id = 'frm_codemirror_box';
304 + $settings = wp_enqueue_code_editor(
305 + array(
306 + 'type' => 'text/css',
307 + 'codemirror' => array(
308 + 'indentUnit' => 2,
309 + 'tabSize' => 2,
310 + ),
311 + )
312 + );
313 + } else {
314 + $settings = false;
315 + }
770 316
771 - include FrmAppHelper::plugin_path() . '/classes/views/styles/custom_css.php';
772 - }
317 + if ( empty( $settings ) ) {
318 + $id = 'frm_custom_css_box';
319 + }
773 320
774 - /**
775 - * Get custom CSS code entered in the Custom CSS page.
776 - *
777 - * @since 6.0
778 - *
779 - * @return string
780 - */
781 - public static function get_custom_css() {
782 - $settings = FrmAppHelper::get_settings();
783 - if ( is_string( $settings->custom_css ) ) {
784 - return $settings->custom_css;
321 + if ( ! isset( $style ) ) {
322 + $frm_style = new FrmStyle();
323 + $style = $frm_style->get_default_style();
785 324 }
786 325
787 - // If it does not exist, check the default style as a fallback.
788 - $frm_style = new FrmStyle();
789 - $style = $frm_style->get_default_style();
790 - $custom_css = $style->post_content['custom_css'];
791 -
792 - return $custom_css;
326 + include FrmAppHelper::plugin_path() . '/classes/views/styles/custom_css.php';
793 327 }
794 328
795 329 /**
796 - * Enqueue assets for codemirror, built into WordPress since 4.9.
797 - * The Custom CSS page uses codemirror.
798 - *
799 - * @since 6.0 Previously this code was embedded in self::custom_css.
800 - *
801 - * @return array|false
330 + * @return void
802 331 */
803 - private static function enqueue_codemirror() {
804 - if ( ! function_exists( 'wp_enqueue_code_editor' ) ) {
805 - // The WordPress version is likely older than 4.9.
806 - return false;
807 - }
332 + public static function save_css() {
333 + $frm_style = new FrmStyle();
808 334
809 - $settings = wp_enqueue_code_editor(
810 - array(
811 - 'type' => 'text/css',
812 - 'codemirror' => array(
813 - 'indentUnit' => 2,
814 - 'tabSize' => 2,
815 - // As the codemirror box only appears once you click into the Custom CSS tab, we need to auto-refresh.
816 - // Otherwise the line numbers all end up with a 1px width causing overlap issues with the text in the content.
817 - 'autoRefresh' => true,
818 - ),
819 - )
820 - );
821 -
822 - if ( $settings ) {
823 - wp_add_inline_script(
824 - 'code-editor',
825 - sprintf(
826 - 'jQuery( function() { wp.codeEditor.initialize( \'frm_codemirror_box\', %s ); } );',
827 - wp_json_encode( $settings )
828 - )
829 - );
335 + $message = '';
336 + $post_id = FrmAppHelper::get_post_param( 'ID', false, 'sanitize_text_field' );
337 + $nonce = FrmAppHelper::get_post_param( 'frm_custom_css', '', 'sanitize_text_field' );
338 + if ( wp_verify_nonce( $nonce, 'frm_custom_css_nonce' ) ) {
339 + $frm_style->update( $post_id );
340 + $message = __( 'Your styling settings have been saved.', 'formidable' );
830 341 }
831 342
832 - return $settings;
343 + self::custom_css( $message );
833 344 }
834 345
835 - /**
836 - * Handling routing for the visual styler.
837 - *
838 - * @return void
839 - */
840 346 public static function route() {
841 347 $action = FrmAppHelper::get_param( 'frm_action', '', 'get', 'sanitize_title' );
842 348 FrmAppHelper::include_svg();
843 349
@@ -843,94 +349,53 @@
843 349
844 350 switch ( $action ) {
845 351 case 'edit':
846 352 case 'save':
847 - self::$action();
848 - return;
353 + case 'manage':
354 + case 'manage_styles':
355 + case 'custom_css':
356 + case 'save_css':
357 + return self::$action();
849 358 default:
850 359 do_action( 'frm_style_action_route', $action );
851 -
852 360 if ( apply_filters( 'frm_style_stop_action_route', false, $action ) ) {
853 361 return;
854 362 }
855 363
856 - if ( in_array( $action, array( 'new_style', 'duplicate' ), true ) ) {
857 - self::$action();
858 - return;
364 + if ( 'new_style' == $action || 'duplicate' == $action ) {
365 + return self::$action();
859 366 }
860 367
861 - self::edit();
862 - return;
368 + return self::edit();
863 369 }
864 370 }
865 371
866 - /**
867 - * Handle AJAX routing for frm_settings_reset for resetting styles to the default settings.
868 - * From the edit view, it will return default styles and not actually update the style.
869 - * On the list view, it does update the style immediately, and returns the default card style attributes so the style card can be reset as well.
870 - *
871 - * @since 6.0 When a style_id is passed to this action, the style will actually be reset.
872 - *
873 - * @return void
874 - */
875 372 public static function reset_styling() {
876 373 FrmAppHelper::permission_check( 'frm_change_settings' );
877 374 check_ajax_referer( 'frm_ajax', 'nonce' );
878 375
879 - $style_id = FrmAppHelper::get_post_param( 'style_id', '', 'absint' );
880 - if ( ! $style_id ) {
881 - // A style ID is not sent when resetting on the edit page.
882 - // Instead of resetting the style, send the defaults back so the inputs can be updated with JavaScript.
883 - $frm_style = new FrmStyle();
884 - $defaults = $frm_style->get_defaults();
885 - echo json_encode( $defaults );
886 - wp_die();
887 - }
376 + $frm_style = new FrmStyle();
377 + $defaults = $frm_style->get_defaults();
888 378
889 - $frm_style = new FrmStyle();
890 - $defaults = $frm_style->get_defaults();
891 - $default_post_content = FrmAppHelper::prepare_and_encode( $defaults );
892 - $where = array(
893 - 'ID' => $style_id,
894 - 'post_type' => self::$post_type,
895 - );
896 - global $wpdb;
897 - $wpdb->update( $wpdb->posts, array( 'post_content' => $default_post_content ), $where );
898 -
899 - $frm_style->save_settings(); // Save the settings after resetting to default or the old style will still appear.
900 -
901 - $data = array(
902 - 'style' => FrmStylesCardHelper::get_style_param_for_card( $frm_style->get_new() ),
903 - );
904 - wp_send_json_success( $data );
379 + echo json_encode( $defaults );
905 380 wp_die();
906 381 }
907 382
908 - /**
909 - * Handle routing for the frm_change_styling AJAX action.
910 - * This doesn't actually change styling. It just handles the events when someone changes a style.
911 - * It responds with the new CSS required for the updated styler preview in the edit page.
912 - *
913 - * @return void
914 - */
915 383 public static function change_styling() {
916 - FrmAppHelper::permission_check( 'frm_change_settings' );
917 384 check_ajax_referer( 'frm_ajax', 'nonce' );
918 385
919 386 $frm_style = new FrmStyle();
920 - $defaults = false; // Intentionally avoid defaults here so nothing gets removed from our style.
387 + $defaults = $frm_style->get_defaults();
921 388 $style = '';
922 389
923 390 echo '<style type="text/css">';
924 - include FrmAppHelper::plugin_path() . '/css/_single_theme.css.php';
391 + include( FrmAppHelper::plugin_path() . '/css/_single_theme.css.php' );
925 392 echo '</style>';
926 393 wp_die();
927 394 }
928 395
929 - /**
930 - * @return void
931 - */
932 - public static function add_meta_boxes() {
396 + private static function add_meta_boxes() {
397 +
933 398 // setup meta boxes
934 399 $meta_boxes = array(
935 400 'general' => __( 'General', 'formidable' ),
936 401 'form-title' => __( 'Form Title', 'formidable' ),
@@ -947,10 +412,8 @@
947 412 /**
948 413 * Add custom boxes to the styling settings
949 414 *
950 415 * @since 2.3
951 - *
952 - * @param array $meta_boxes
953 416 */
954 417 $meta_boxes = apply_filters( 'frm_style_boxes', $meta_boxes );
955 418
956 419 foreach ( $meta_boxes as $nicename => $name ) {
@@ -958,13 +421,8 @@
958 421 unset( $nicename, $name );
959 422 }
960 423 }
961 424
962 - /**
963 - * @param array $atts
964 - * @param array $sec
965 - * @return void
966 - */
967 425 public static function include_style_section( $atts, $sec ) {
968 426 extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
969 427 $style = $atts['style'];
970 428 FrmStylesHelper::prepare_color_output( $style->post_content, false );
@@ -981,9 +439,9 @@
981 439 */
982 440 $file_name = apply_filters( 'frm_style_settings_' . $sec['args'], $file_name );
983 441
984 442 echo '<div class="frm_grid_container">';
985 - include $file_name;
443 + include( $file_name );
986 444 echo '</div>';
987 445 }
988 446
989 447 public static function load_css() {
@@ -1017,30 +475,12 @@
1017 475 */
1018 476 $output = apply_filters( 'frm_saved_css', $output );
1019 477
1020 478 echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1021 -
1022 - self::maybe_hide_sample_form_error_message();
1023 -
1024 479 wp_die();
1025 480 }
1026 481
1027 482 /**
1028 - * Add an extra style rule to hide a broken style warning.
1029 - * To avoid cluttering the front end with any unecessary styles this is only added when the referer URL matches the styler.
1030 - *
1031 - * @since 6.2.3
1032 - *
1033 - * @return void
1034 - */
1035 - public static function maybe_hide_sample_form_error_message() {
1036 - $referer = FrmAppHelper::get_server_value( 'HTTP_REFERER' );
1037 - if ( false !== strpos( $referer, 'admin.php?page=formidable-styles' ) ) {
1038 - echo '#frm_broken_styles_warning { display: none; }';
1039 - }
1040 - }
1041 -
1042 - /**
1043 483 * Replaces relative URL with absolute URL.
1044 484 *
1045 485 * @since 4.11.03
1046 486 *
@@ -1086,10 +526,8 @@
1086 526 }
1087 527
1088 528 /**
1089 529 * Get the stylesheets for the form settings page
1090 - *
1091 - * @return array<WP_Post>
1092 530 */
1093 531 public static function get_style_opts() {
1094 532 $frm_style = new FrmStyle();
1095 533 $styles = $frm_style->get_all();
@@ -1096,14 +534,8 @@
1096 534
1097 535 return $styles;
1098 536 }
1099 537
1100 - /**
1101 - * Get the style post object for a target form.
1102 - *
1103 - * @param object|string|boolean $form
1104 - * @return WP_Post|null
1105 - */
1106 538 public static function get_form_style( $form = 'default' ) {
1107 539 $style = FrmFormsHelper::get_form_style( $form );
1108 540
1109 541 if ( empty( $style ) || 1 == $style ) {
@@ -1110,8 +542,9 @@
1110 542 $style = 'default';
1111 543 }
1112 544
1113 545 $frm_style = new FrmStyle( $style );
546 +
1114 547 return $frm_style->get_one();
1115 548 }
1116 549
1117 550 /**
@@ -1186,76 +619,6 @@
1186 619 }
1187 620
1188 621 public static function do_accordion_sections( $screen, $context, $object ) {
1189 622 return do_accordion_sections( $screen, $context, $object );
1190 - }
1191 -
1192 - /**
1193 - * Rename a style via an AJAX action.
1194 - *
1195 - * @since 6.0
1196 - *
1197 - * @return void
1198 - */
1199 - public static function rename_style() {
1200 - $permission_error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'nonce', 'frm_ajax' );
1201 - if ( $permission_error !== false ) {
1202 - $data = array(
1203 - 'message' => __( 'Unable to rename style', 'formidable' ),
1204 - );
1205 - wp_send_json_error( $data, 403 );
1206 - die();
1207 - }
1208 -
1209 - $style_id = FrmAppHelper::get_post_param( 'style_id', 0, 'absint' );
1210 - $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_text_field' );
1211 -
1212 - if ( ! $style_id || ! $style_name ) {
1213 - $data = array(
1214 - 'message' => __( 'Invalid route', 'formidable' ),
1215 - );
1216 - wp_send_json_error( $data, 400 );
1217 - die();
1218 - }
1219 -
1220 - $post = get_post( $style_id );
1221 - if ( ! $post || $post->post_type !== self::$post_type ) {
1222 - $data = array(
1223 - 'message' => __( 'The style you are renaming either does not exist or it is not a style', 'formidable' ),
1224 - );
1225 - wp_send_json_error( $data, 404 );
1226 - die();
1227 - }
1228 -
1229 - global $wpdb;
1230 - $wpdb->update( $wpdb->posts, array( 'post_title' => $style_name ), array( 'ID' => $post->ID ) );
1231 -
1232 - $data = array();
1233 - wp_send_json_success( $data );
1234 - }
1235 -
1236 - /**
1237 - * Prevent the WordPress edit.css file from loading on the visual styler page.
1238 - * This way .form-field elements do not have border styles applied to them.
1239 - *
1240 - * @since 6.0
1241 - *
1242 - * @param WP_Styles $styles
1243 - * @return void
1244 - */
1245 - public static function disable_conflicting_wp_admin_css( $styles ) {
1246 - if ( ! FrmAppHelper::is_style_editor_page() ) {
1247 - return;
1248 - }
1249 -
1250 - FrmStylesPreviewHelper::disable_conflicting_wp_admin_css( $styles );
1251 - }
1252 -
1253 - /**
1254 - * @deprecated 6.1 Saving custom CSS has been moved into Global Settings.
1255 - *
1256 - * @return void
1257 - */
1258 - public static function save_css() {
1259 - _deprecated_function( __METHOD__, '6.1' );
1260 623 }
1261 624 }