PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 3.06.06
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v3.06.06
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 +350 -1229 6.293.06.06 View file →
@@ -1,232 +1,130 @@
1 1 <?php
2 -if ( ! defined( 'ABSPATH' ) ) {
3 - die( 'You are not allowed to call this page directly.' );
4 -}
5 2
6 3 class FrmStylesController {
4 + public static $post_type = 'frm_styles';
5 + public static $screen = 'formidable_page_formidable-styles';
7 6
8 - /**
9 - * @var string
10 - */
11 - public static $post_type = 'frm_styles';
7 + public static function load_pro_hooks() {
8 + if ( FrmAppHelper::pro_is_installed() ) {
9 + FrmProStylesController::load_pro_hooks();
10 + }
11 + }
12 12
13 - /**
14 - * @var string
15 - */
16 - public static $screen = 'formidable_page_formidable-styles';
17 -
18 - /**
19 - * @var string|null
20 - */
21 - private static $message;
22 -
23 - /**
24 - * @return void
25 - */
26 - public static function load_pro_hooks() {
27 - if ( FrmAppHelper::pro_is_installed() ) {
28 - FrmProStylesController::load_pro_hooks();
29 - }
30 - }
31 -
32 - /**
33 - * @return void
34 - */
35 - public static function register_post_types() {
13 + public static function register_post_types() {
36 14 register_post_type(
37 15 self::$post_type,
38 16 array(
39 - 'label' => __( 'Styles', 'formidable' ),
40 - 'public' => false,
41 - 'show_ui' => false,
17 + 'label' => __( 'Styles', 'formidable' ),
18 + 'public' => false,
19 + 'show_ui' => false,
42 20 'capability_type' => 'page',
43 - 'capabilities' => array(
44 - 'edit_post' => 'frm_change_settings',
45 - 'edit_posts' => 'frm_change_settings',
46 - 'edit_others_posts' => 'frm_change_settings',
47 - 'publish_posts' => 'frm_change_settings',
48 - 'delete_post' => 'frm_change_settings',
49 - 'delete_posts' => 'frm_change_settings',
21 + 'capabilities' => array(
22 + 'edit_post' => 'frm_change_settings',
23 + 'edit_posts' => 'frm_change_settings',
24 + 'edit_others_posts' => 'frm_change_settings',
25 + 'publish_posts' => 'frm_change_settings',
26 + 'delete_post' => 'frm_change_settings',
27 + 'delete_posts' => 'frm_change_settings',
50 28 'read_private_posts' => 'read_private_posts',
51 29 ),
52 - 'supports' => array(
30 + 'supports' => array(
53 31 'title',
54 32 ),
55 - 'has_archive' => false,
56 - 'labels' => array(
57 - 'name' => __( 'Styles', 'formidable' ),
33 + 'has_archive' => false,
34 + 'labels' => array(
35 + 'name' => __( 'Styles', 'formidable' ),
58 36 'singular_name' => __( 'Style', 'formidable' ),
59 - 'menu_name' => __( 'Style', 'formidable' ),
60 - 'edit' => __( 'Edit', 'formidable' ),
61 - 'add_new_item' => __( 'Create a New Style', 'formidable' ),
62 - 'edit_item' => __( 'Edit Style', 'formidable' ),
37 + 'menu_name' => __( 'Style', 'formidable' ),
38 + 'edit' => __( 'Edit', 'formidable' ),
39 + 'add_new_item' => __( 'Create a New Style', 'formidable' ),
40 + 'edit_item' => __( 'Edit Style', 'formidable' ),
63 41 ),
64 42 )
65 43 );
66 - }
44 + }
67 45
68 - /**
69 - * Add two links for the visual styler.
70 - * There's a "Styles" submenu in the Formidable menu.
71 - * There's a second alternative "Forms" submenu in the Appearance menu.
72 - * This submenu links to a page to edit a form with the default style.
73 - *
74 - * @return void
75 - */
76 - public static function menu() {
77 - add_submenu_page( 'formidable', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Styles', 'formidable' ), 'frm_change_settings', 'formidable-styles', 'FrmStylesController::route' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
78 - add_submenu_page( 'themes.php', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Forms', 'formidable' ), 'frm_change_settings', 'formidable-styles2', 'FrmStylesController::route' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
79 - }
46 + public static function menu() {
47 + add_submenu_page( 'formidable', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Styles', 'formidable' ), 'frm_change_settings', 'formidable-styles', 'FrmStylesController::route' );
48 + }
80 49
81 - /**
82 - * Remove filters for the visual styler preview.
83 - * This triggers earlier than self::admin_init which is called too late.
84 - *
85 - * @return void
86 - */
87 - public static function plugins_loaded() {
88 - if ( ! FrmAppHelper::is_style_editor_page() ) {
50 + public static function admin_init() {
51 + if ( ! FrmAppHelper::is_admin_page( 'formidable-styles' ) ) {
89 52 return;
90 53 }
91 54
92 - self::disable_form_css();
93 - self::prevent_form_scripts_from_loading();
94 - }
55 + self::load_pro_hooks();
95 56
96 - /**
97 - * Avoid loading CSS the normal way with the preview in the styler.
98 - * It gets loaded instead with the frmpro_css action set to the #frm-custom-theme-css element.
99 - *
100 - * @since 6.0
101 - *
102 - * @return void
103 - */
104 - private static function disable_form_css() {
105 - add_filter( 'get_frm_stylesheet', '__return_empty_array' );
106 - }
107 -
108 - /**
109 - * Removing this action prevents front end JavaScript from loading.
110 - *
111 - * @since 6.0
112 - *
113 - * @return void
114 - */
115 - private static function prevent_form_scripts_from_loading() {
116 - remove_action( 'init', 'FrmFormsController::front_head' );
117 - }
118 -
119 - /**
120 - * @return void
121 - */
122 - public static function admin_init() {
123 - self::maybe_hook_into_global_settings_save();
124 -
125 - if ( ! FrmAppHelper::is_style_editor_page() ) {
57 + $style_tab = FrmAppHelper::get_param( 'frm_action', '', 'get', 'sanitize_title' );
58 + if ( $style_tab == 'manage' || $style_tab == 'custom_css' ) {
59 + // we only need to load these styles/scripts on the styler page
126 60 return;
127 61 }
128 62
129 - FrmStyleComponent::register_assets();
130 - self::load_pro_hooks();
131 -
132 63 $version = FrmAppHelper::plugin_version();
133 -
134 - if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
135 - wp_enqueue_style( 'wp-color-picker' );
136 - }
137 -
64 + wp_enqueue_script( 'jquery-ui-datepicker' );
65 + wp_enqueue_style( 'wp-color-picker' );
138 66 wp_enqueue_style( 'frm-custom-theme', admin_url( 'admin-ajax.php?action=frmpro_css' ), array(), $version );
139 67
140 68 $style = apply_filters( 'frm_style_head', false );
69 + if ( $style ) {
70 + wp_enqueue_style( 'frm-single-custom-theme', admin_url( 'admin-ajax.php?action=frmpro_load_css&flat=1' ) . '&' . http_build_query( $style->post_content ), array(), $version );
71 + }
72 + }
141 73
142 - if ( $style ) {
143 - wp_enqueue_style( 'frm-single-custom-theme', admin_url( 'admin-ajax.php?action=frmpro_load_css&flat=1' ) . '&' . http_build_query( $style->post_content ), array(), $version ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
144 - }
145 - }
146 -
147 74 /**
148 - * @since 6.0
149 - *
150 - * @return void
151 - */
152 - private static function maybe_hook_into_global_settings_save() {
153 - if ( empty( $_POST ) || ! isset( $_POST['style'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
154 - // Avoid changing any style data if the style array is not sent in the request.
155 - return;
156 - }
157 -
158 - add_action(
159 - 'frm_update_settings',
160 - /**
161 - * Update the form data on the "Manage Styles" tab after global settings are saved.
162 - */
163 - function () {
164 - self::manage_styles();
165 - }
166 - );
167 - }
168 -
169 - /**
170 75 * @param string $register Either 'enqueue' or 'register'.
171 76 * @param bool $force True to enqueue/register the style if a form has not been loaded.
172 - *
173 - * @return void
174 77 */
175 78 public static function enqueue_css( $register = 'enqueue', $force = false ) {
176 79 global $frm_vars;
177 80
178 - $register_css = $register === 'register';
179 - $should_load = $force || ( ( $frm_vars['load_css'] || $register_css ) && ! FrmAppHelper::is_admin() );
81 + $register_css = ( $register == 'register' );
82 + $should_load = $force || ( ( $frm_vars['load_css'] || $register_css ) && ! FrmAppHelper::is_admin() );
180 83
181 - if ( ! $should_load ) {
182 - return;
183 - }
84 + if ( $should_load ) {
184 85
185 - $frm_settings = FrmAppHelper::get_settings();
86 + $frm_settings = FrmAppHelper::get_settings();
87 + if ( $frm_settings->load_style == 'none' ) {
88 + return;
89 + }
186 90
187 - if ( $frm_settings->load_style === 'none' ) {
188 - return;
189 - }
91 + $css = apply_filters( 'get_frm_stylesheet', self::custom_stylesheet() );
190 92
191 - $css = apply_filters( 'get_frm_stylesheet', self::custom_stylesheet() );
93 + if ( ! empty( $css ) ) {
94 + $css = (array) $css;
192 95
193 - if ( $css ) {
194 - $css = (array) $css;
195 - $version = FrmAppHelper::plugin_version();
96 + $version = FrmAppHelper::plugin_version();
196 97
197 - foreach ( $css as $css_key => $file ) {
198 - if ( $register_css ) {
199 - $this_version = self::get_css_version( $css_key, $version );
200 - wp_register_style( $css_key, $file, array(), $this_version );
98 + foreach ( $css as $css_key => $file ) {
99 + if ( $register_css ) {
100 + $this_version = self::get_css_version( $css_key, $version );
101 + wp_register_style( $css_key, $file, array(), $this_version );
102 + }
103 +
104 + $load_on_all = ! FrmAppHelper::is_admin() && 'all' == $frm_settings->load_style;
105 + if ( $load_on_all || $register != 'register' ) {
106 + wp_enqueue_style( $css_key );
107 + }
108 + unset( $css_key, $file );
201 109 }
202 110
203 - $load_on_all = ! FrmAppHelper::is_admin() && 'all' === $frm_settings->load_style;
204 -
205 - if ( $load_on_all || $register !== 'register' ) {
206 - wp_enqueue_style( $css_key );
111 + if ( $frm_settings->load_style == 'all' ) {
112 + $frm_vars['css_loaded'] = true;
207 113 }
208 - unset( $css_key, $file );
209 114 }
115 + unset( $css );
210 116
211 - if ( $frm_settings->load_style === 'all' ) {
212 - $frm_vars['css_loaded'] = true;
213 - }
214 - }//end if
215 - unset( $css );
216 -
217 - add_filter( 'style_loader_tag', 'FrmStylesController::add_tags_to_css', 10, 2 );
117 + add_filter( 'style_loader_tag', 'FrmStylesController::add_tags_to_css', 10, 2 );
118 + }
218 119 }
219 120
220 - /**
221 - * @return array<string,string>
222 - */
223 121 public static function custom_stylesheet() {
224 122 global $frm_vars;
225 123 $stylesheet_urls = array();
226 124
227 - if ( empty( $frm_vars['css_loaded'] ) ) {
228 - // Include css in head.
125 + if ( ! isset( $frm_vars['css_loaded'] ) || ! $frm_vars['css_loaded'] ) {
126 + //include css in head
229 127 self::get_url_to_custom_style( $stylesheet_urls );
230 128 }
231 129
232 130 return $stylesheet_urls;
@@ -231,22 +129,15 @@
231 129
232 130 return $stylesheet_urls;
233 131 }
234 132
235 - /**
236 - * @param array $stylesheet_urls
237 - *
238 - * @return void
239 - */
240 133 private static function get_url_to_custom_style( &$stylesheet_urls ) {
241 134 $file_name = '/css/' . self::get_file_name();
242 -
243 135 if ( is_readable( FrmAppHelper::plugin_path() . $file_name ) ) {
244 136 $url = FrmAppHelper::plugin_url() . $file_name;
245 137 } else {
246 138 $url = admin_url( 'admin-ajax.php?action=frmpro_css' );
247 139 }
248 -
249 140 $stylesheet_urls['formidable'] = $url;
250 141 }
251 142
252 143 /**
@@ -252,818 +143,257 @@
252 143 /**
253 144 * Use a different stylesheet per site in a multisite install
254 145 *
255 146 * @since 3.0.03
256 - *
257 - * @return string
258 147 */
259 148 public static function get_file_name() {
260 149 if ( is_multisite() ) {
261 150 $blog_id = get_current_blog_id();
262 - return 'formidableforms' . absint( $blog_id ) . '.css';
151 + $name = 'formidableforms' . absint( $blog_id ) . '.css';
152 + } else {
153 + $name = 'formidableforms.css';
263 154 }
264 -
265 - return 'formidableforms.css';
155 + return $name;
266 156 }
267 157
268 - /**
269 - * @param string $css_key
270 - * @param string $version
271 - *
272 - * @return string
273 - */
274 158 private static function get_css_version( $css_key, $version ) {
275 - if ( 'formidable' !== $css_key ) {
276 - return $version;
159 + if ( 'formidable' == $css_key ) {
160 + $this_version = get_option( 'frm_last_style_update' );
161 + if ( ! $this_version ) {
162 + $this_version = $version;
163 + }
164 + } else {
165 + $this_version = $version;
277 166 }
278 -
279 - $this_version = get_option( 'frm_last_style_update' );
280 -
281 - return $this_version ? $this_version : $version;
167 + return $this_version;
282 168 }
283 169
284 - /**
285 - * @param string $tag
286 - * @param string $handle
287 - *
288 - * @return string
289 - */
290 170 public static function add_tags_to_css( $tag, $handle ) {
291 - if ( ( 'formidable' === $handle || 'jquery-theme' === $handle ) && ! str_contains( $tag, ' property=' ) ) {
292 - return str_replace( ' type="', ' property="stylesheet" type="', $tag );
171 + if ( ( 'formidable' == $handle || 'jquery-theme' == $handle ) && strpos( $tag, ' property=' ) === false ) {
172 + $frm_settings = FrmAppHelper::get_settings();
173 + if ( $frm_settings->use_html ) {
174 + $tag = str_replace( ' type="', ' property="stylesheet" type="', $tag );
175 + }
293 176 }
294 -
295 177 return $tag;
296 178 }
297 179
298 - /**
299 - * Route the edit route to the style function.
300 - *
301 - * @since 6.0 this function no longer has any parameter values.
302 - *
303 - * @return void
304 - */
305 - public static function edit() {
306 - self::load_styler();
180 + public static function new_style( $return = '' ) {
181 + self::load_styler( 'default' );
307 182 }
308 183
309 - /**
310 - * 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.
311 - *
312 - * @return void
313 - */
314 - public static function new_style() {
315 - self::load_styler();
316 - }
317 -
318 - /**
319 - * 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.
320 - *
321 - * @return void
322 - */
323 184 public static function duplicate() {
324 - self::load_styler();
185 + self::load_styler( 'default' );
325 186 }
326 187
327 - /**
328 - * Render the style page for a form for assigning a style to a form, and for updating a target style.
329 - *
330 - * @since 6.0 this function no longer takes parameters.
331 - *
332 - * @return void
333 - */
334 - public static function load_styler() {
335 - if ( 'assign_style' === FrmAppHelper::get_post_param( 'frm_action' ) ) {
336 - self::save_form_style();
337 - }
338 -
339 - self::setup_styles_and_scripts_for_styler();
340 -
341 - $style_id = self::get_style_id_for_styler();
342 -
188 + public static function edit( $style_id = false, $message = '' ) {
343 189 if ( ! $style_id ) {
344 - $error_args = array(
345 - 'title' => __( 'No styles', 'formidable' ),
346 - 'body' => __( 'You must have a style to use the Visual Styler.', 'formidable' ),
347 - 'cancel_url' => admin_url( 'admin.php?page=formidable' ),
348 - );
349 - FrmAppController::show_error_modal( $error_args );
350 - return;
351 - }
352 -
353 - $form_id = FrmAppHelper::simple_get( 'form', 'absint', 0 );
354 -
355 - if ( ! $form_id ) {
356 - $form_id = self::get_form_id_for_style( $style_id );
357 - }
358 -
359 - $form = FrmForm::getOne( $form_id );
360 -
361 - if ( ! is_object( $form ) ) {
362 - $error_args = array(
363 - 'title' => __( 'No forms', 'formidable' ),
364 - 'body' => __( 'You must have a form to use the Visual Styler.', 'formidable' ),
365 - 'cancel_url' => admin_url( 'admin.php?page=formidable' ),
366 - );
367 - FrmAppController::show_error_modal( $error_args );
368 - return;
369 - }
370 -
371 - $frm_style = new FrmStyle( $style_id );
372 - $active_style = $frm_style->get_one();
373 - $default_style = self::get_default_style();
374 -
375 - self::disable_admin_page_styling_on_submit_buttons();
376 -
377 - /**
378 - * @since 6.0
379 - *
380 - * @param array{form:\stdClass} $data
381 - */
382 - do_action( 'frm_before_render_style_page', compact( 'form' ) );
383 -
384 - self::render_style_page( $active_style, $form, $default_style );
385 - }
386 -
387 - /**
388 - * @since 6.0
389 - *
390 - * @return int
391 - */
392 - private static function get_style_id_for_styler() {
393 - $action = FrmAppHelper::simple_get( 'frm_action' );
394 -
395 - if ( 'duplicate' === $action ) {
396 - // The duplicate action uses style_id instead of id for better backward compatibility.
397 - return FrmAppHelper::simple_get( 'style_id', 'absint', 0 );
398 - }
399 -
400 - $style_id = FrmAppHelper::simple_get( 'id', 'absint', 0 );
401 -
402 - if ( $style_id ) {
403 - // Always use the style ID from the URL if one is specified.
404 - return $style_id;
405 - }
406 -
407 - $request_form_id = FrmAppHelper::simple_get( 'form', 'absint', 0 );
408 -
409 - if ( $request_form_id && is_callable( 'FrmProStylesController::get_active_style_for_form' ) ) {
410 - return FrmProStylesController::get_active_style_for_form( $request_form_id )->ID;
411 - }
412 -
413 - return self::get_default_style()->ID;
414 - }
415 -
416 - /**
417 - * If a form ID is not being passed in the URL, try to get the best match.
418 - *
419 - * @since 6.0
420 - *
421 - * @param int $style_id
422 - *
423 - * @return int
424 - */
425 - private static function get_form_id_for_style( $style_id ) {
426 - $check = serialize( array( 'custom_style' => (string) $style_id ) );
427 - $check = substr( $check, 5, -1 );
428 - $form_id = FrmDb::get_var(
429 - 'frm_forms',
430 - array(
431 - 'options LIKE' => $check,
432 - 'status' => 'published',
433 - )
434 - );
435 -
436 - if ( ! $form_id ) {
437 - // Fallback to any form.
438 - $where = array(
439 - 'status' => 'published',
440 - // Make sure it's not a repeater.
441 - 'parent_form_id' => array( null, 0 ),
442 - );
443 - $form_id = FrmDb::get_var( 'frm_forms', $where, 'id' );
444 - }
445 -
446 - return $form_id;
447 - }
448 -
449 - /**
450 - * Add a frm_no_style_button class to all buttons to avoid some style rules like border-radius: 30px.
451 - *
452 - * @return void
453 - */
454 - private static function disable_admin_page_styling_on_submit_buttons() {
455 - add_filter(
456 - 'frm_submit_button_class',
457 - function ( $classes ) {
458 - $classes[] = 'frm_no_style_button';
459 - return $classes;
190 + $style_id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
191 + if ( empty( $style_id ) ) {
192 + $style_id = 'default';
460 193 }
461 - );
462 - }
463 -
464 - /**
465 - * @since 6.0
466 - *
467 - * @return WP_Post
468 - */
469 - private static function get_default_style() {
470 - $frm_style = new FrmStyle( 'default' );
471 - return $frm_style->get_one();
472 - }
473 -
474 - /**
475 - * Save style for form (from Styler list page) via a POST action.
476 - *
477 - * @since 6.0
478 - *
479 - * @return void
480 - */
481 - private static function save_form_style() {
482 - $permission_error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'frm_save_form_style', 'frm_save_form_style_nonce' );
483 -
484 - if ( $permission_error !== false ) {
485 - wp_die( 'Unable to save form', '', 403 );
486 194 }
487 195
488 - $style_id = FrmAppHelper::get_post_param( 'style_id', 0, 'absint' );
489 -
490 - if ( $style_id && ! self::confirm_style_exists_before_setting( $style_id ) ) {
491 - wp_die( esc_html__( 'Invalid target style', 'formidable' ), esc_html__( 'Invalid target style', 'formidable' ), 400 );
492 - return;
196 + if ( 'default' == $style_id ) {
197 + $style = 'default';
198 + } else {
199 + $frm_style = new FrmStyle( $style_id );
200 + $style = $frm_style->get_one();
201 + $style = $style->ID;
493 202 }
494 203
495 - /**
496 - * Hook into the saved style ID so Pro can import a style template by its key and return a new style ID.
497 - *
498 - * @since 6.0
499 - *
500 - * @param int $style_id
501 - */
502 - $style_id = apply_filters( 'frm_saved_form_style_id', $style_id );
503 -
504 - if ( ! $style_id && '0' !== FrmAppHelper::get_post_param( 'style_id', '', 'sanitize_text_field' ) ) {
505 - // "0" is a special value used for the enable/disable toggle.
506 - wp_die( esc_html__( 'Invalid style value', 'formidable' ), esc_html__( 'Invalid style value', 'formidable' ), 400 );
507 - return;
508 - }
509 -
510 - $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
511 -
512 - if ( ! $form_id ) {
513 - wp_die( esc_html__( 'No form specified', 'formidable' ), esc_html__( 'No form specified', 'formidable' ), 400 );
514 - return;
515 - }
516 -
517 - $form = FrmForm::getOne( $form_id );
518 -
519 - if ( ! $form ) {
520 - wp_die( esc_html__( 'Form does not exist', 'formidable' ), esc_html__( 'Form does not exist', 'formidable' ), 400 );
521 - return;
522 - }
523 -
524 - $previous_style_id = $form->options['custom_style'];
525 -
526 - // If the default style is selected, use the "Always use default" legacy option instead of the default style.
527 - // There's also a check here for conversational forms.
528 - // Without the check it isn't possible to select "Default" because "Always use default" will convert to "Lines" dynamically.
529 - $default_style = self::get_default_style();
530 -
531 - if ( $style_id === $default_style->ID && empty( $form->options['chat'] ) ) {
532 - $style_id = 1;
533 - }
534 -
535 - // We want to save a string for consistency. FrmStylesHelper::get_form_count_for_style expects the custom style ID is a string.
536 - $form->options['custom_style'] = (string) $style_id;
537 -
538 - if ( $previous_style_id === $form->options['custom_style'] ) {
539 - // Exit early before updating DB if nothing actually changed.
540 - self::$message = __( 'Successfully updated style.', 'formidable' );
541 - return;
542 - }
543 -
544 - global $wpdb;
545 - $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $form->options ) ), array( 'id' => $form->id ) );
546 -
547 - FrmForm::clear_form_cache();
548 -
549 - /**
550 - * @since 6.25.1
551 - *
552 - * @param int $form_id
553 - * @param int $style_id
554 - */
555 - do_action( 'frm_after_changed_form_style', absint( $form_id ), absint( $style_id ) );
556 -
557 - self::$message = __( 'Successfully updated style.', 'formidable' );
204 + self::load_styler( $style, $message );
558 205 }
559 206
560 - /**
561 - * Validate that we're assigning a form to a style that actually exists before assigning it to a form.
562 - *
563 - * @param int $style_id
564 - *
565 - * @return bool True if the style actually exists.
566 - */
567 - private static function confirm_style_exists_before_setting( $style_id ) {
568 - global $wpdb;
569 - $post_type = FrmDb::get_var( $wpdb->posts, array( 'ID' => $style_id ), 'post_type' );
570 - return self::$post_type === $post_type;
571 - }
207 + public static function save() {
208 + $frm_style = new FrmStyle();
209 + $message = '';
210 + $post_id = FrmAppHelper::get_post_param( 'ID', false, 'sanitize_title' );
211 + $style_nonce = FrmAppHelper::get_post_param( 'frm_style', '', 'sanitize_text_field' );
572 212
573 - /**
574 - * Register and enqueue styles and scripts for the style tab page.
575 - *
576 - * @since 6.0
577 - *
578 - * @return void
579 - */
580 - private static function setup_styles_and_scripts_for_styler() {
581 - $plugin_url = FrmAppHelper::plugin_url();
582 - $version = FrmAppHelper::plugin_version();
583 - $js_dependencies = array( 'wp-i18n', 'wp-hooks', 'formidable_dom' );
584 -
585 - if ( FrmAppHelper::pro_is_installed() && is_callable( 'FrmProAppHelper::use_jquery_datepicker' ) && FrmProAppHelper::use_jquery_datepicker() ) {
586 - $js_dependencies[] = 'jquery-ui-datepicker';
587 - }
588 -
589 - wp_register_script( 'formidable_style', $plugin_url . '/js/admin/style.js', $js_dependencies, $version );
590 - wp_register_style( 'formidable_style', $plugin_url . '/css/admin/style.css', array(), $version );
591 - wp_print_styles( 'formidable_style' );
592 -
593 - wp_print_styles( 'formidable' );
594 - wp_enqueue_script( 'formidable_style' );
595 - wp_set_script_translations( 'formidable_style', 'formidable' );
596 - }
597 -
598 - /**
599 - * Render the style page (with a more limited and typed scope than calling it from self::style directly).
600 - *
601 - * @since 6.0
602 - *
603 - * @param stdClass|WP_Post $active_style
604 - * @param stdClass $form
605 - * @param WP_Post $default_style
606 - *
607 - * @return void
608 - */
609 - private static function render_style_page( $active_style, $form, $default_style ) {
610 - $style_views_path = self::get_views_path();
611 - // Edit, list (default), new_style.
612 - $view = FrmAppHelper::simple_get( 'frm_action', 'sanitize_text_field', 'list' );
613 - $frm_style = new FrmStyle( $active_style->ID );
614 -
615 - if ( 'new_style' !== $view && ! FrmAppHelper::simple_get( 'form' ) && ! FrmAppHelper::simple_get( 'style_id' ) ) {
616 - // Have the Appearance > Forms link fallback to the edit view. Otherwise we want to use 'list' as the default.
617 - $view = 'edit';
618 - }
619 -
620 - if ( in_array( $view, array( 'edit', 'new_style', 'duplicate' ), true ) ) {
621 - self::add_meta_boxes();
622 - }
623 -
624 - switch ( $view ) {
625 - case 'edit':
626 - $style = $active_style;
627 - break;
628 -
629 - case 'duplicate':
630 - $style = clone $active_style;
631 - $new_style = $frm_style->get_new();
632 - $style->ID = $new_style->ID;
633 - $style->post_name = $new_style->post_name;
634 - unset( $new_style );
635 - break;
636 -
637 - case 'new_style':
638 - $style = $frm_style->get_new();
639 - break;
640 - }
641 -
642 - if ( in_array( $view, array( 'duplicate', 'new_style' ), true ) ) {
643 - $style->post_title = FrmAppHelper::simple_get( 'style_name' );
644 - $style->menu_order = 0;
645 - }
646 -
647 - if ( ! isset( $style ) ) {
648 - $style = $active_style;
649 - }
650 -
651 - self::force_form_style( $style );
652 -
653 - if ( isset( self::$message ) ) {
654 - $message = self::$message;
655 - }
656 -
657 - $preview_helper = new FrmStylesPreviewHelper( $form->id );
658 - $preview_helper->adjust_form_for_preview();
659 -
660 - // Get form HTML before displaying warnings and notes so we can check global $frm_vars data without adding extra database calls.
661 - $target_form_preview_html = $preview_helper->get_html_for_form_preview();
662 - $warnings = $preview_helper->get_warnings_for_styler_preview( $style, $default_style, $view );
663 - $notes = $preview_helper->get_notes_for_styler_preview();
664 -
665 - include $style_views_path . 'show.php';
666 - }
667 -
668 - /**
669 - * @since 6.0
670 - *
671 - * @return string
672 - */
673 - private static function get_views_path() {
674 - return FrmAppHelper::plugin_path() . '/classes/views/styles/';
675 - }
676 -
677 - /**
678 - * Filter form classes so the form uses the preview style, not the form's active style.
679 - *
680 - * @since 6.0
681 - *
682 - * @param stdClass|WP_Post $style A new style is not a WP_Post object.
683 - *
684 - * @return void
685 - */
686 - private static function force_form_style( $style ) {
687 - add_filter(
688 - 'frm_add_form_style_class',
689 - function ( $class ) use ( $style ) {
690 - $split = array_filter(
691 - explode( ' ', $class ),
692 - /**
693 - * @param string $class
694 - */
695 - function ( $class ) {
696 - return $class && ! str_starts_with( $class, 'frm_style_' );
697 - }
698 - );
699 - $split[] = 'frm_style_' . $style->post_name;
700 - return implode( ' ', $split );
213 + if ( $post_id !== false && wp_verify_nonce( $style_nonce, 'frm_style_nonce' ) ) {
214 + $id = $frm_style->update( $post_id );
215 + if ( empty( $post_id ) && ! empty( $id ) ) {
216 + // set the post id to the new style so it will be loaded for editing
217 + $post_id = reset( $id );
701 218 }
702 - );
703 - }
704 -
705 - /**
706 - * Save style post object via a POST request submitted from the Visual styler "edit" page.
707 - *
708 - * @since 6.0
709 - *
710 - * @return void
711 - */
712 - public static function save_style() {
713 - FrmAppHelper::permission_check( 'frm_change_settings' );
714 -
715 - $frm_style = new FrmStyle();
716 - $post_id = FrmAppHelper::get_post_param( 'ID', false, 'sanitize_title' );
717 - $style_nonce = FrmAppHelper::get_post_param( 'frm_style', '', 'sanitize_text_field' );
718 -
719 - if ( $post_id === false || ! wp_verify_nonce( $style_nonce, 'frm_style_nonce' ) ) {
720 - // Exit early if the request isn't valid.
721 - // Since we're not dying, it should just reload the visual styler without any message.
722 - return;
219 + // include the CSS that includes this style
220 + echo '<link href="' . esc_url( admin_url( 'admin-ajax.php?action=frmpro_css' ) ) . '" type="text/css" rel="Stylesheet" class="frm-custom-theme" />';
221 + $message = __( 'Your styling settings have been saved.', 'formidable' );
723 222 }
724 223
725 - $id = $frm_style->update( $post_id );
726 -
727 - if ( ! $post_id && $id ) {
728 - self::maybe_redirect_after_save( $id );
729 - // Set the post id to the new style so it will be loaded for editing.
730 - $post_id = reset( $id );
731 - }
732 -
733 - /**
734 - * @since 6.25.1
735 - *
736 - * @param int $post_id
737 - */
738 - do_action( 'frm_after_saved_style', absint( $post_id ) );
739 -
740 - self::$message = __( 'Your styling settings have been saved.', 'formidable' );
224 + return self::edit( $post_id, $message );
741 225 }
742 226
743 - /**
744 - * Show the edit view after saving.
745 - * The save event is triggered earlier, on admin init where self::save_style is called.
746 - * This happens earlier because there is a possible redirect (to adjust the URL for a new or duplicated style).
747 - *
748 - * @return void
749 - */
750 - public static function save() {
751 - self::edit();
752 - }
227 + public static function load_styler( $style, $message = '' ) {
228 + global $frm_settings;
753 229
754 - /**
755 - * Force a redirect after duplicating or creating a new style to avoid an old stale URL that could result in more styles than intended.
756 - *
757 - * @since 6.0
758 - *
759 - * @param array $ids
760 - *
761 - * @return void
762 - */
763 - private static function maybe_redirect_after_save( $ids ) {
764 - $referer = FrmAppHelper::get_server_value( 'HTTP_REFERER' );
765 - $parsed = parse_url( $referer );
766 - $query = $parsed['query'];
767 - $current_action = false;
768 - $actions_to_redirect = array( 'duplicate', 'new_style' );
230 + $frm_style = new FrmStyle();
231 + $styles = $frm_style->get_all();
769 232
770 - foreach ( $actions_to_redirect as $action ) {
771 - if ( str_contains( $query, 'frm_action=' . $action ) ) {
772 - $current_action = $action;
773 - break;
774 - }
233 + if ( is_numeric( $style ) ) {
234 + $style = $styles[ $style ];
235 + } elseif ( 'default' == $style ) {
236 + $style = $frm_style->get_default_style( $styles );
775 237 }
776 238
777 - if ( false === $current_action ) {
778 - // Do not redirect as the referer URL did not match $actions_to_redirect.
779 - return;
780 - }
239 + self::add_meta_boxes();
781 240
782 - parse_str( $query, $parsed_query );
783 - $form_id = ! empty( $parsed_query['form'] ) ? absint( $parsed_query['form'] ) : 0;
784 - $style = new stdClass();
785 - $style->ID = end( $ids );
786 - wp_safe_redirect( esc_url_raw( FrmStylesHelper::get_edit_url( $style, $form_id ) ) );
787 - die();
788 - }
241 + include( FrmAppHelper::plugin_path() . '/classes/views/styles/show.php' );
242 + }
789 243
790 244 /**
791 - * @since 6.0
792 - *
793 - * @param string $message
245 + * @param string $message
794 246 * @param array|object $forms
795 - *
796 - * @return void
797 247 */
798 - public static function manage( $message = '', $forms = array() ) {
799 - $frm_style = new FrmStyle();
800 - $styles = $frm_style->get_all();
248 + private static function manage( $message = '', $forms = array() ) {
249 + $frm_style = new FrmStyle();
250 + $styles = $frm_style->get_all();
801 251 $default_style = $frm_style->get_default_style( $styles );
802 - $frm_settings = FrmAppHelper::get_settings();
803 252
804 - if ( ! $forms ) {
253 + if ( empty( $forms ) ) {
805 254 $forms = FrmForm::get_published_forms();
806 255 }
807 256
808 - include FrmAppHelper::plugin_path() . '/classes/views/styles/manage.php';
257 + include( FrmAppHelper::plugin_path() . '/classes/views/styles/manage.php' );
809 258 }
810 259
811 - /**
812 - * Handle saving for the page rendered in self::manage which is included in Global Settings in the "Manage Styles" tab.
813 - * This gets called from the frm_update_settings hook which is called after saving Global settings.
814 - *
815 - * @return void
816 - */
817 - private static function manage_styles() {
818 - global $wpdb;
260 + private static function manage_styles() {
261 + $style_nonce = FrmAppHelper::get_post_param( 'frm_manage_style', '', 'sanitize_text_field' );
262 + if ( ! $_POST || ! isset( $_POST['style'] ) || ! wp_verify_nonce( $style_nonce, 'frm_manage_style_nonce' ) ) {
263 + return self::manage();
264 + }
819 265
266 + global $wpdb;
267 +
820 268 $forms = FrmForm::get_published_forms();
269 + foreach ( $forms as $form ) {
270 + if ( $_POST['style'][ $form->id ] == $_POST['prev_style'][ $form->id ] ) {
271 + continue;
272 + }
821 273
822 - foreach ( $forms as $form ) {
823 - if ( ! isset( $_POST['style'] ) || ! isset( $_POST['style'][ $form->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
824 - continue;
825 - }
274 + $form->options['custom_style'] = $_POST['style'][ $form->id ];
826 275
827 - $new_style = sanitize_text_field( wp_unslash( $_POST['style'][ $form->id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
828 -
829 - $form->options['custom_style'] = $new_style;
830 276 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $form->options ) ), array( 'id' => $form->id ) );
831 277 unset( $form );
832 - }
833 - }
278 + }
834 279
835 - /**
836 - * Echo content for the Custom CSS page.
837 - *
838 - * @param string $message
839 - * @param array $extra_args An array of extra arguments.
840 - *
841 - * @return void
842 - */
843 - public static function custom_css( $message = '', $extra_args = array() ) {
844 - $id = $extra_args['id'] ?? 'frm_codemirror_box';
845 - $settings = self::enqueue_codemirror( $id, $extra_args['placeholder'] ?? '' );
846 - $id = $settings ? $id : 'frm_custom_css_box';
847 - $show_errors = $extra_args['show_errors'] ?? true;
848 - $custom_css = $extra_args['custom_css'] ?? self::get_custom_css();
849 - $heading = $extra_args['heading'] ?? __( 'You can add custom css here or in your theme style.css. Any CSS added here will be used anywhere the Formidable CSS is loaded.', 'formidable' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
850 - $textarea_params = ! empty( $extra_args['textarea_params'] ) ? $extra_args['textarea_params'] : array(
851 - 'name' => 'frm_custom_css',
852 - 'id' => $id,
853 - );
280 + $message = __( 'Your form styles have been saved.', 'formidable' );
281 + return self::manage( $message, $forms );
282 + }
854 283
855 - if ( $settings ) {
856 - $textarea_params['class'] = 'hide-if-js';
284 + public static function custom_css( $message = '', $style = null ) {
285 + if ( function_exists( 'wp_enqueue_code_editor' ) ) {
286 + $id = 'frm_codemirror_box';
287 + $settings = wp_enqueue_code_editor(
288 + array(
289 + 'type' => 'text/css',
290 + 'codemirror' => array(
291 + 'indentUnit' => 2,
292 + 'tabSize' => 2,
293 + ),
294 + )
295 + );
296 + } else {
297 + $id = 'frm_custom_css_box';
298 + $settings = array();
299 + $codemirror = '4.7';
300 + wp_enqueue_style( 'codemirror', FrmAppHelper::plugin_url() . '/css/codemirror.css', array(), $codemirror );
301 + wp_enqueue_script( 'codemirror', FrmAppHelper::plugin_url() . '/js/codemirror/codemirror.js', array(), $codemirror );
302 + wp_enqueue_script( 'codemirror-css', FrmAppHelper::plugin_url() . '/js/codemirror/css.js', array( 'codemirror' ), $codemirror );
857 303 }
858 304
859 - include FrmAppHelper::plugin_path() . '/classes/views/styles/custom_css.php';
860 - }
861 -
862 - /**
863 - * Get custom CSS code entered in the Custom CSS page.
864 - *
865 - * @since 6.0
866 - *
867 - * @param array|null $single_style_settings The single style settings.
868 - *
869 - * @return string
870 - */
871 - public static function get_custom_css( $single_style_settings = null ) {
872 - if ( $single_style_settings ) {
873 - // If the single style settings are passed, return the custom CSS from the single style settings.
874 - if ( ! empty( $single_style_settings['single_style_custom_css'] ) && ! empty( $single_style_settings['enable_style_custom_css'] ) ) {
875 - return $single_style_settings['single_style_custom_css'];
876 - }
877 -
878 - return '';
305 + if ( ! isset( $style ) ) {
306 + $frm_style = new FrmStyle();
307 + $style = $frm_style->get_default_style();
879 308 }
880 309
881 - $settings = FrmAppHelper::get_settings();
310 + include( FrmAppHelper::plugin_path() . '/classes/views/styles/custom_css.php' );
311 + }
882 312
883 - if ( is_string( $settings->custom_css ) ) {
884 - return $settings->custom_css;
885 - }
886 -
887 - // If it does not exist, check the default style as a fallback.
313 + public static function save_css() {
888 314 $frm_style = new FrmStyle();
889 - $style = $frm_style->get_default_style();
890 315
891 - return $style->post_content['custom_css'];
892 - }
893 -
894 - /**
895 - * Enqueue assets for codemirror, built into WordPress since 4.9.
896 - * The Custom CSS page uses codemirror.
897 - *
898 - * @since 6.0 Previously this code was embedded in self::custom_css.
899 - *
900 - * @param string $id The ID of the codemirror box.
901 - * @param string $placeholder The placeholder text for the codemirror box.
902 - *
903 - * @return array|false
904 - */
905 - private static function enqueue_codemirror( $id = 'frm_codemirror_box', $placeholder = '' ) {
906 - if ( ! function_exists( 'wp_enqueue_code_editor' ) ) {
907 - // The WordPress version is likely older than 4.9.
908 - return false;
316 + $message = '';
317 + $post_id = FrmAppHelper::get_post_param( 'ID', false, 'sanitize_text_field' );
318 + $nonce = FrmAppHelper::get_post_param( 'frm_custom_css', '', 'sanitize_text_field' );
319 + if ( wp_verify_nonce( $nonce, 'frm_custom_css_nonce' ) ) {
320 + $frm_style->update( $post_id );
321 + $message = __( 'Your styling settings have been saved.', 'formidable' );
909 322 }
910 323
911 - $settings = wp_enqueue_code_editor(
912 - array(
913 - 'type' => 'text/css',
914 - 'codemirror' => array(
915 - 'indentUnit' => 2,
916 - 'tabSize' => 2,
917 - // As the codemirror box only appears once you click into the Custom CSS tab, we need to auto-refresh.
918 - // Otherwise the line numbers all end up with a 1px width causing overlap issues with the text in the content.
919 - 'autoRefresh' => true,
920 - 'placeholder' => $placeholder,
921 - ),
922 - )
923 - );
924 -
925 - if ( $settings ) {
926 - wp_add_inline_script(
927 - 'code-editor',
928 - sprintf(
929 - 'jQuery( function() { window.%s_wp_editor = wp.codeEditor.initialize( \'%s\', %s ); } );',
930 - $id,
931 - $id,
932 - wp_json_encode( $settings )
933 - )
934 - );
935 - }
936 -
937 - return $settings;
324 + return self::custom_css( $message );
938 325 }
939 326
940 - /**
941 - * Handling routing for the visual styler.
942 - *
943 - * @return void
944 - */
945 - public static function route() {
327 + public static function route() {
946 328 $action = FrmAppHelper::get_param( 'frm_action', '', 'get', 'sanitize_title' );
947 - FrmAppHelper::include_svg();
948 329
949 - switch ( $action ) {
950 - case 'edit':
951 - case 'save':
952 - self::$action();
953 - return;
954 - default:
955 - do_action( 'frm_style_action_route', $action );
330 + switch ( $action ) {
331 + case 'edit':
332 + case 'save':
333 + case 'manage':
334 + case 'manage_styles':
335 + case 'custom_css':
336 + case 'save_css':
337 + return self::$action();
338 + default:
339 + do_action( 'frm_style_action_route', $action );
340 + if ( apply_filters( 'frm_style_stop_action_route', false, $action ) ) {
341 + return;
342 + }
956 343
957 - if ( apply_filters( 'frm_style_stop_action_route', false, $action ) ) {
958 - return;
959 - }
344 + if ( 'new_style' == $action || 'duplicate' == $action ) {
345 + return self::$action();
346 + }
960 347
961 - if ( in_array( $action, array( 'new_style', 'duplicate' ), true ) ) {
962 - self::$action();
963 - return;
964 - }
348 + return self::edit();
349 + }
350 + }
965 351
966 - self::edit();
967 - return;
968 - }
969 - }
970 -
971 - /**
972 - * Handle AJAX routing for frm_settings_reset for resetting styles to the default settings.
973 - * From the edit view, it will return default styles and not actually update the style.
974 - * 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.
975 - *
976 - * @since 6.0 When a style_id is passed to this action, the style will actually be reset.
977 - *
978 - * @return void
979 - */
980 - public static function reset_styling() {
352 + public static function reset_styling() {
981 353 FrmAppHelper::permission_check( 'frm_change_settings' );
982 - check_ajax_referer( 'frm_ajax', 'nonce' );
354 + check_ajax_referer( 'frm_ajax', 'nonce' );
983 355
984 - $style_id = FrmAppHelper::get_post_param( 'style_id', '', 'absint' );
356 + $frm_style = new FrmStyle();
357 + $defaults = $frm_style->get_defaults();
985 358
986 - if ( ! $style_id ) {
987 - // A style ID is not sent when resetting on the edit page.
988 - // Instead of resetting the style, send the defaults back so the inputs can be updated with JavaScript.
989 - $frm_style = new FrmStyle();
990 - $defaults = $frm_style->get_defaults();
991 - echo json_encode( $defaults );
992 - wp_die();
993 - }
359 + echo json_encode( $defaults );
360 + wp_die();
361 + }
994 362
995 - $frm_style = new FrmStyle();
996 - $default_template_style = $frm_style->get_default_template_style( $style_id );
997 - $where = array(
998 - 'ID' => $style_id,
999 - 'post_type' => self::$post_type,
1000 - );
1001 -
1002 - $style_object = $frm_style->get_new();
1003 - $style_object->post_content = json_decode( $default_template_style, true );
1004 -
1005 - global $wpdb;
1006 - $wpdb->update( $wpdb->posts, array( 'post_content' => $default_template_style ), $where );
1007 -
1008 - // Save the settings after resetting to default or the old style will still appear.
1009 - $frm_style->save_settings();
1010 -
1011 - $data = array(
1012 - 'style' => FrmStylesCardHelper::get_style_param_for_card( $style_object ),
1013 - );
1014 - wp_send_json_success( $data );
1015 - wp_die();
1016 - }
1017 -
1018 - /**
1019 - * Handle routing for the frm_change_styling AJAX action.
1020 - * This doesn't actually change styling. It just handles the events when someone changes a style.
1021 - * It responds with the new CSS required for the updated styler preview in the edit page.
1022 - *
1023 - * @return void
1024 - */
1025 363 public static function change_styling() {
1026 - FrmAppHelper::permission_check( 'frm_change_settings' );
1027 364 check_ajax_referer( 'frm_ajax', 'nonce' );
1028 365
1029 - $is_loaded_via_ajax = true;
1030 - $frm_style = new FrmStyle();
366 + $frm_style = new FrmStyle();
367 + $defaults = $frm_style->get_defaults();
368 + $style = '';
1031 369
1032 - // Intentionally avoid defaults here so nothing gets removed from our style.
1033 - $defaults = array();
1034 - $style = '';
1035 -
1036 370 echo '<style type="text/css">';
1037 - include FrmAppHelper::plugin_path() . '/css/_single_theme.css.php';
371 + include( FrmAppHelper::plugin_path() . '/css/_single_theme.css.php' );
1038 372 echo '</style>';
1039 373 wp_die();
1040 374 }
1041 375
1042 - /**
1043 - * @return void
1044 - */
1045 - public static function add_meta_boxes() {
1046 - // Setup meta boxes
1047 - $meta_boxes = array(
1048 - 'general' => __( 'General', 'formidable' ),
1049 - 'form-title' => __( 'Form Title', 'formidable' ),
1050 - 'form-description' => __( 'Form Description', 'formidable' ),
1051 - 'field-labels' => __( 'Field Labels', 'formidable' ),
1052 - 'field-description' => __( 'Field Description', 'formidable' ),
1053 - 'field-colors' => __( 'Field Colors', 'formidable' ),
1054 - 'field-sizes' => __( 'Field Settings', 'formidable' ),
1055 - 'check-box-radio-fields' => __( 'Check Box & Radio Fields', 'formidable' ),
1056 - 'buttons' => __( 'Buttons', 'formidable' ),
1057 - 'form-messages' => __( 'Form Messages', 'formidable' ),
1058 - );
376 + private static function add_meta_boxes() {
1059 377
378 + // setup meta boxes
379 + $meta_boxes = array(
380 + 'general' => __( 'General', 'formidable' ),
381 + 'form-title' => __( 'Form Title', 'formidable' ),
382 + 'form-description' => __( 'Form Description', 'formidable' ),
383 + 'field-labels' => __( 'Field Labels', 'formidable' ),
384 + 'field-description' => __( 'Field Description', 'formidable' ),
385 + 'field-colors' => __( 'Field Colors', 'formidable' ),
386 + 'field-sizes' => __( 'Field Settings', 'formidable' ),
387 + 'check-box-radio-fields' => __( 'Check Box & Radio Fields', 'formidable' ),
388 + 'buttons' => __( 'Buttons', 'formidable' ),
389 + 'form-messages' => __( 'Form Messages', 'formidable' ),
390 + );
391 +
1060 392 /**
1061 393 * Add custom boxes to the styling settings
1062 394 *
1063 395 * @since 2.3
1064 - *
1065 - * @param array $meta_boxes
1066 396 */
1067 397 $meta_boxes = apply_filters( 'frm_style_boxes', $meta_boxes );
1068 398
1069 399 foreach ( $meta_boxes as $nicename => $name ) {
@@ -1071,21 +401,15 @@
1071 401 unset( $nicename, $name );
1072 402 }
1073 403 }
1074 404
1075 - /**
1076 - * @param array $atts
1077 - * @param array $sec
1078 - *
1079 - * @return void
1080 - */
1081 405 public static function include_style_section( $atts, $sec ) {
1082 - extract( $atts ); // phpcs:ignore WordPress.PHP.DontExtract
406 + extract( $atts );
1083 407 $style = $atts['style'];
1084 408 FrmStylesHelper::prepare_color_output( $style->post_content, false );
1085 409
1086 410 $current_tab = FrmAppHelper::simple_get( 'page-tab', 'sanitize_title', 'default' );
1087 - $file_name = FrmAppHelper::plugin_path() . '/classes/views/styles/_' . $sec['args'] . '.php';
411 + $file_name = FrmAppHelper::plugin_path() . '/classes/views/styles/_' . $sec['args'] . '.php';
1088 412
1089 413 /**
1090 414 * Set the location of custom styling settings right before
1091 415 * loading onto the page. If your style box was named "progress",
@@ -1094,162 +418,80 @@
1094 418 * @since 2.3
1095 419 */
1096 420 $file_name = apply_filters( 'frm_style_settings_' . $sec['args'], $file_name );
1097 421
1098 - echo '<div class="frm_grid_container">';
1099 - include $file_name;
1100 - echo '</div>';
1101 - }
422 + include( $file_name );
423 + }
1102 424
1103 - public static function load_css() {
425 + public static function load_css() {
1104 426 header( 'Content-type: text/css' );
1105 427
1106 - $frm_style = new FrmStyle();
1107 - $defaults = $frm_style->get_defaults();
1108 - $style = '';
428 + $frm_style = new FrmStyle();
429 + $defaults = $frm_style->get_defaults();
430 + $style = '';
1109 431
1110 - include FrmAppHelper::plugin_path() . '/css/_single_theme.css.php';
1111 - wp_die();
1112 - }
432 + include( FrmAppHelper::plugin_path() . '/css/_single_theme.css.php' );
433 + wp_die();
434 + }
1113 435
1114 - /**
1115 - * @return void
1116 - */
1117 436 public static function load_saved_css() {
1118 437 $css = get_transient( 'frmpro_css' );
1119 438
1120 - ob_start();
1121 - include FrmAppHelper::plugin_path() . '/css/custom_theme.css.php';
1122 - $output = ob_get_clean();
1123 - $output = self::replace_relative_url( $output );
1124 -
1125 - /**
1126 - * The API needs to load font icons through a custom URL.
1127 - *
1128 - * @since 5.2
1129 - *
1130 - * @param string $output
1131 - */
1132 - $output = apply_filters( 'frm_saved_css', $output );
1133 -
1134 - echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1135 -
1136 - self::maybe_hide_sample_form_error_message();
1137 -
439 + include( FrmAppHelper::plugin_path() . '/css/custom_theme.css.php' );
1138 440 wp_die();
1139 441 }
1140 442
1141 - /**
1142 - * Add an extra style rule to hide a broken style warning.
1143 - * To avoid cluttering the front end with any unnecessary styles this is only added when the referer URL matches the styler.
443 + /**
444 + * Check if the Formidable styling should be loaded,
445 + * then enqueue it for the footer
1144 446 *
1145 - * @since 6.2.3
1146 - *
1147 - * @return void
1148 - */
1149 - public static function maybe_hide_sample_form_error_message() {
1150 - $referer = FrmAppHelper::get_server_value( 'HTTP_REFERER' );
447 + * @since 2.0
448 + */
449 + public static function enqueue_style() {
450 + global $frm_vars;
1151 451
1152 - if ( str_contains( $referer, 'admin.php?page=formidable-styles' ) ) {
1153 - echo '#frm_broken_styles_warning { display: none; }';
1154 - }
1155 - }
452 + if ( isset( $frm_vars['css_loaded'] ) && $frm_vars['css_loaded'] ) {
453 + // the CSS has already been loaded
454 + return;
455 + }
1156 456
1157 - /**
1158 - * Replaces relative URL with absolute URL.
1159 - *
1160 - * @since 4.11.03
1161 - *
1162 - * @param string $css CSS content.
1163 - *
1164 - * @return string
1165 - */
1166 - public static function replace_relative_url( $css ) {
1167 - $plugin_url = trailingslashit( FrmAppHelper::plugin_url() );
1168 - return str_replace(
1169 - array(
1170 - 'url(../',
1171 - "url('../",
1172 - 'url("../',
1173 - ),
1174 - array(
1175 - 'url(' . $plugin_url,
1176 - "url('" . $plugin_url,
1177 - 'url("' . $plugin_url,
1178 - ),
1179 - $css
1180 - );
1181 - }
457 + $frm_settings = FrmAppHelper::get_settings();
458 + if ( $frm_settings->load_style != 'none' ) {
459 + wp_enqueue_style( 'formidable' );
460 + $frm_vars['css_loaded'] = true;
461 + }
462 + }
1182 463
1183 - /**
1184 - * Check if the Formidable styling should be loaded,
1185 - * then enqueue it for the footer
1186 - *
1187 - * @since 2.0
1188 - *
1189 - * @return void
1190 - */
1191 - public static function enqueue_style() {
1192 - global $frm_vars;
464 + // Get the stylesheets for the form settings page
465 + public static function get_style_opts() {
466 + $frm_style = new FrmStyle();
467 + $styles = $frm_style->get_all();
1193 468
1194 - if ( ! empty( $frm_vars['css_loaded'] ) ) {
1195 - // The CSS has already been loaded.
1196 - return;
1197 - }
469 + return $styles;
470 + }
1198 471
1199 - $frm_settings = FrmAppHelper::get_settings();
472 + public static function get_form_style( $form = 'default' ) {
473 + $style = FrmFormsHelper::get_form_style( $form );
1200 474
1201 - if ( $frm_settings->load_style === 'none' ) {
1202 - return;
1203 - }
475 + if ( empty( $style ) || 1 == $style ) {
476 + $style = 'default';
477 + }
1204 478
1205 - wp_enqueue_style( 'formidable' );
1206 - $frm_vars['css_loaded'] = true;
1207 - }
479 + $frm_style = new FrmStyle( $style );
480 + return $frm_style->get_one();
481 + }
1208 482
1209 - /**
1210 - * Get the stylesheets for the form settings page
1211 - *
1212 - * @return array<WP_Post>
1213 - */
1214 - public static function get_style_opts() {
1215 - $frm_style = new FrmStyle();
1216 - return $frm_style->get_all();
1217 - }
1218 -
1219 - /**
1220 - * Get the style post object for a target form.
1221 - *
1222 - * @param bool|object|string $form
1223 - *
1224 - * @return WP_Post|null
1225 - */
1226 - public static function get_form_style( $form = 'default' ) {
1227 - $style = FrmFormsHelper::get_form_style( $form );
1228 -
1229 - // phpcs:ignore Universal.Operators.StrictComparisons
1230 - if ( ! $style || 1 == $style ) {
1231 - $style = 'default';
1232 - }
1233 -
1234 - $frm_style = new FrmStyle( $style );
1235 - return $frm_style->get_one();
1236 - }
1237 -
1238 - /**
1239 - * @param string $class
1240 - * @param string $style
1241 - *
1242 - * @return string
1243 - */
483 + /**
484 + * @param string $class
485 + * @param string $style
486 + */
1244 487 public static function get_form_style_class( $class, $style ) {
1245 - // phpcs:ignore Universal.Operators.StrictComparisons
1246 488 if ( 1 == $style ) {
1247 489 $style = 'default';
1248 490 }
1249 491
1250 492 $frm_style = new FrmStyle( $style );
1251 - $style = $frm_style->get_one();
493 + $style = $frm_style->get_one();
1252 494
1253 495 if ( $style ) {
1254 496 $class .= ' frm_style_' . $style->post_name;
1255 497 self::maybe_add_rtl_class( $style, $class );
@@ -1258,235 +500,114 @@
1258 500 return $class;
1259 501 }
1260 502
1261 503 /**
1262 - * @since 3.0
1263 - *
1264 504 * @param object $style
1265 505 * @param string $class
1266 506 *
1267 - * @return void
507 + * @since 3.0
1268 508 */
1269 509 private static function maybe_add_rtl_class( $style, &$class ) {
1270 510 $is_rtl = isset( $style->post_content['direction'] ) && 'rtl' === $style->post_content['direction'];
1271 -
1272 511 if ( $is_rtl ) {
1273 512 $class .= ' frm_rtl';
1274 513 }
1275 514 }
1276 515
1277 - /**
1278 - * @param string $val Style setting key.
1279 - * @param int|string $form Form ID or 'default'.
1280 - *
1281 - * @return mixed
1282 - */
516 + /**
517 + * @param string $val
518 + */
1283 519 public static function get_style_val( $val, $form = 'default' ) {
1284 520 $style = self::get_form_style( $form );
1285 -
1286 521 if ( $style && isset( $style->post_content[ $val ] ) ) {
1287 522 return $style->post_content[ $val ];
1288 523 }
1289 -
1290 - return null;
1291 524 }
1292 525
1293 - /**
1294 - * @param array $default_styles
1295 - *
1296 - * @return array
1297 - */
1298 526 public static function show_entry_styles( $default_styles ) {
1299 527 $frm_style = new FrmStyle( 'default' );
1300 - $style = $frm_style->get_one();
528 + $style = $frm_style->get_one();
1301 529
1302 - if ( ! $style ) {
1303 - return $default_styles;
1304 - }
530 + if ( ! $style ) {
531 + return $default_styles;
532 + }
1305 533
1306 - foreach ( $default_styles as $name => $val ) {
1307 - $setting = $name;
1308 -
1309 - if ( 'border_width' === $name ) {
1310 - $setting = 'field_border_width';
1311 - } elseif ( 'alt_bg_color' === $name ) {
1312 - $setting = 'bg_color_active';
1313 - }
1314 -
1315 - $default_styles[ $name ] = $style->post_content[ $setting ];
534 + foreach ( $default_styles as $name => $val ) {
535 + $setting = $name;
536 + if ( 'border_width' == $name ) {
537 + $setting = 'field_border_width';
538 + } else if ( 'alt_bg_color' == $name ) {
539 + $setting = 'bg_color_active';
540 + }
541 + $default_styles[ $name ] = $style->post_content[ $setting ];
1316 542 unset( $name, $val );
1317 - }
543 + }
1318 544
1319 - return $default_styles;
1320 - }
545 + return $default_styles;
546 + }
1321 547
1322 - /**
1323 - * @param string $important
1324 - * @param array $field
1325 - *
1326 - * @return string
1327 - */
1328 - public static function important_style( $important, $field ) {
1329 - return self::get_style_val( 'important_style', $field['form_id'] );
1330 - }
548 + public static function &important_style( $important, $field ) {
549 + $important = self::get_style_val( 'important_style', $field['form_id'] );
550 + return $important;
551 + }
1331 552
1332 - /**
1333 - * Duplicate of WordPress do_accordion_section function, it adds an additional svg icon support.
1334 - *
1335 - * @since 6.8.3
1336 - *
1337 - * @param string|WP_Screen $screen Screen ID or screen object.
1338 - * @param string $context Meta box context.
1339 - * @param mixed $data_object Data object passed to callbacks.
1340 - *
1341 - * @return int
1342 - */
1343 - public static function do_accordion_sections( $screen, $context, $data_object ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
1344 - global $wp_meta_boxes;
553 + /**
554 + * Fallback for WP < 3.6
555 + */
556 + public static function do_accordion_sections( $screen, $context, $object ) {
557 + if ( function_exists( 'do_accordion_sections' ) ) {
558 + return do_accordion_sections( $screen, $context, $object );
559 + }
1345 560
1346 - // The symbol id from icons.svg
1347 - $icon_ids = array(
1348 - 'ranking-fields-style' => 'frm_chart_bar_icon',
1349 - 'section-fields-style' => 'frm-form-title-style',
1350 - );
561 + global $wp_meta_boxes;
1351 562
1352 - wp_enqueue_script( 'accordion' );
563 + $screen = 'formidable_page_formidable-styles';
564 + $screen = convert_to_screen( $screen );
1353 565
1354 - if ( ! $screen ) {
1355 - $screen = get_current_screen();
1356 - } elseif ( is_string( $screen ) ) {
1357 - $screen = convert_to_screen( $screen );
1358 - }
566 + $page = $screen->id;
1359 567
1360 - $page = $screen->id;
568 + $hidden = get_hidden_meta_boxes( $screen );
569 + ?>
570 + <div id="side-sortables" class="accordion-container">
571 + <?php
572 + $i = 0;
573 + $first_open = false;
574 + do {
575 + if ( ! isset( $wp_meta_boxes ) || ! isset( $wp_meta_boxes[ $page ] ) || ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
576 + break;
577 + }
1361 578
1362 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1363 - ?>
1364 - <div id="side-sortables" class="accordion-container">
1365 - <ul class="outer-border">
1366 - <?php
1367 - $i = 0;
1368 - $first_open = false;
579 + foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
580 + if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
581 + foreach ( $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
582 + if ( false == $box || ! $box['title'] ) {
583 + continue;
584 + }
1369 585
1370 - if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
1371 - foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
1372 - if ( ! isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
1373 - continue;
1374 - }
586 + $i++;
587 + $hidden_class = in_array( $box['id'], $hidden ) ? 'hide-if-js' : '';
1375 588
1376 - foreach ( $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
1377 - if ( false === $box || ! $box['title'] ) {
1378 - continue;
1379 - }
589 + if ( ! $first_open && empty( $hidden_class ) ) {
590 + $first_open = true;
591 + }
1380 592
1381 - ++$i;
1382 - $icon_id = array_key_exists( $box['id'], $icon_ids ) ? $icon_ids[ $box['id'] ] : 'frm-' . $box['id'];
1383 - $open_class = '';
1384 -
1385 - if ( ! $first_open ) {
1386 - $first_open = true;
1387 - $open_class = 'open';
1388 - }
1389 -
1390 - $accordion_content_id = 'frm_style_section_' . $box['id'];
1391 - ?>
1392 - <li class="control-section accordion-section <?php echo esc_attr( $open_class ); ?> <?php echo esc_attr( $box['id'] ); ?>" id="<?php echo esc_attr( $box['id'] ); ?>"><?php // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong ?>
1393 - <h3 class="accordion-section-title hndle">
1394 - <?php
1395 - FrmAppHelper::icon_by_class( 'frmfont ' . $icon_id . ' frm_svg24' );
1396 - echo esc_html( $box['title'] );
1397 - ?>
1398 - <button type="button" aria-expanded="<?php echo esc_attr( 'open' === $open_class ? 'true' : 'false' ); ?>" aria-controls="<?php echo esc_attr( $accordion_content_id ); ?>" aria-label="<?php echo esc_attr( $box['title'] ); ?>"><?php // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong ?>
1399 - <?php FrmAppHelper::icon_by_class( 'frmfont frm_arrowdown8_icon' ); ?>
1400 - </button>
1401 - </h3>
1402 - <div class="accordion-section-content <?php postbox_classes( $box['id'], $page ); ?>" id="<?php echo esc_attr( $accordion_content_id ); ?>">
1403 - <div class="inside">
1404 - <?php call_user_func( $box['callback'], $data_object, $box ); ?>
1405 - </div><!-- .inside -->
1406 - </div><!-- .accordion-section-content -->
1407 - </li><!-- .accordion-section -->
1408 - <?php
1409 - }//end foreach
1410 - }//end foreach
1411 - }//end if
1412 - ?>
1413 - </ul><!-- .outer-border -->
1414 - </div><!-- .accordion-container -->
1415 - <?php
1416 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
1417 - return $i;
1418 - }
1419 -
1420 - /**
1421 - * Rename a style via an AJAX action.
1422 - *
1423 - * @since 6.0
1424 - *
1425 - * @return void
1426 - */
1427 - public static function rename_style() {
1428 - $permission_error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'nonce', 'frm_ajax' );
1429 -
1430 - if ( $permission_error !== false ) {
1431 - $data = array(
1432 - 'message' => __( 'Unable to rename style', 'formidable' ),
1433 - );
1434 - wp_send_json_error( $data, 403 );
1435 - die();
1436 - }
1437 -
1438 - $style_id = FrmAppHelper::get_post_param( 'style_id', 0, 'absint' );
1439 - $style_name = FrmAppHelper::get_post_param( 'style_name', '', 'sanitize_text_field' );
1440 -
1441 - if ( ! $style_id || ! $style_name ) {
1442 - $data = array(
1443 - 'message' => __( 'Invalid route', 'formidable' ),
1444 - );
1445 - wp_send_json_error( $data, 400 );
1446 - die();
1447 - }
1448 -
1449 - $post = get_post( $style_id );
1450 -
1451 - if ( ! $post || $post->post_type !== self::$post_type ) {
1452 - $data = array(
1453 - 'message' => __( 'The style you are renaming either does not exist or it is not a style', 'formidable' ),
1454 - );
1455 - wp_send_json_error( $data, 404 );
1456 - die();
1457 - }
1458 -
1459 - global $wpdb;
1460 - $wpdb->update( $wpdb->posts, array( 'post_title' => $style_name ), array( 'ID' => $post->ID ) );
1461 -
1462 - $data = array();
1463 - wp_send_json_success( $data );
1464 - }
1465 -
1466 - /**
1467 - * Prevent the WordPress edit.css file from loading on the visual styler page.
1468 - * This way .form-field elements do not have border styles applied to them.
1469 - *
1470 - * @since 6.0
1471 - *
1472 - * @param WP_Styles $styles
1473 - *
1474 - * @return void
1475 - */
1476 - public static function disable_conflicting_wp_admin_css( $styles ) {
1477 - if ( ! FrmAppHelper::is_style_editor_page() ) {
1478 - return;
1479 - }
1480 -
1481 - FrmStylesPreviewHelper::disable_conflicting_wp_admin_css( $styles );
1482 - }
1483 -
1484 - /**
1485 - * @deprecated 6.1 Saving custom CSS has been moved into Global Settings.
1486 - *
1487 - * @return void
1488 - */
1489 - public static function save_css() {
1490 - _deprecated_function( __METHOD__, '6.1' );
1491 - }
593 + ?>
594 + <div class="postbox <?php echo esc_attr( $box['id'] ); ?>">
595 + <div class="handlediv" title="<?php esc_attr_e( 'Click to toggle', 'formidable' ); ?>"><br/></div>
596 + <h3 class='hndle'><span><?php echo esc_html( $box['title'] ); ?></span></h3>
597 + <div class="accordion-section-content <?php postbox_classes( $box['id'], $page ); ?>">
598 + <div class="inside">
599 + <?php call_user_func( $box['callback'], $object, $box ); ?>
600 + </div><!-- .inside -->
601 + </div><!-- .accordion-section-content -->
602 + </div><!-- .postbox -->
603 + <?php
604 + }
605 + }
606 + }
607 + } while ( 0 );
608 + ?>
609 + </div><!-- .accordion-container -->
610 + <?php
611 + return $i;
612 + }
1492 613 }