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

FrmStylesPreviewHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.26.1, at classes/helpers/FrmStylesPreviewHelper.php

410 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 /**
7 * @since 6.0
8 */
9 class FrmStylesPreviewHelper {
10
11 /**
12 * @var int
13 */
14 private $form_id;
15
16 /**
17 * This is tracked so we can show a note that the CAPTCHA was turned off.
18 *
19 * @var bool
20 */
21 private $form_includes_captcha = false;
22
23 /**
24 * Track the field ids with the default label position.
25 * A field with a default label position will have a frm-default-label-position class in the styler preview.
26 * Only fields with this class will change when you update the position setting in the styler.
27 *
28 * @since 6.0.1
29 *
30 * @var array
31 */
32 private $default_label_position_field_ids;
33
34 /**
35 * @param int|string $form_id
36 *
37 * @return void
38 */
39 public function __construct( $form_id ) {
40 $this->form_id = (int) $form_id;
41 $this->default_label_position_field_ids = array();
42 }
43
44 /**
45 * Modify form behaviours for the styler preview.
46 *
47 * @since 6.0
48 *
49 * @return void
50 */
51 public function adjust_form_for_preview() {
52 // Don't bother including the antispam token in the preview as the form isn't submitted.
53 add_filter( 'frm_run_antispam', '__return_false', 99 );
54
55 // We don't need the honeypot in the preview so leave it out.
56 add_filter( 'frm_run_honeypot', '__return_false' );
57 $this->hide_captcha_fields();
58 $this->disable_javascript_validation();
59 $this->add_a_div_class_for_default_label_positions();
60 }
61
62 /**
63 * Add a frm-default-label-position class to any field with a default label position.
64 * A field with a custom label position shouldn't ever change in the styler preview.
65 *
66 * @since 6.0.1
67 *
68 * @return void
69 */
70 private function add_a_div_class_for_default_label_positions() {
71 // Only fields with no label position set hit this filter, so track those for the frm_field_div_classes filter.
72 add_filter(
73 'frm_html_label_position',
74 /**
75 * @param string $position
76 * @param array|object $field
77 *
78 * @return string
79 */
80 function ( $position, $field ) {
81 if ( is_array( $field ) ) {
82 $this->default_label_position_field_ids[] = (int) $field['id'];
83 }
84 return $position;
85 },
86 10,
87 2
88 );
89
90 add_filter(
91 'frm_field_div_classes',
92 /**
93 * @param string $classes
94 * @param array|object $field
95 *
96 * @return string
97 */
98 function ( $classes, $field ) {
99 if ( is_array( $field ) && in_array( (int) $field['id'], $this->default_label_position_field_ids, true ) ) {
100 $classes .= ' frm-default-label-position';
101 }
102 return $classes;
103 },
104 10,
105 2
106 );
107 }
108
109 /**
110 * Captcha does not initialize in the preview. Hide it so we don't see the label either.
111 *
112 * @since 6.0
113 *
114 * @return void
115 */
116 private function hide_captcha_fields() {
117 add_filter(
118 'frm_show_normal_field_type',
119 /**
120 * @param bool $show
121 * @param string $field_type
122 * @param string $target_field_type
123 *
124 * @return bool
125 */
126 function ( $show, $field_type ) {
127 if ( 'captcha' === $field_type ) {
128 $show = false;
129 }
130 return $show;
131 },
132 10,
133 2
134 );
135 }
136
137 /**
138 * Turn off JavaScript validation for the preview.
139 * Without this we hit a "PHP Fatal error: Uncaught Error: Maximum function nesting level of '256' reached" error.
140 * This only happened with specific Look up fields when FrmProLookupFieldsController::get_independent_lookup_field_options is called in Pro.
141 *
142 * @since 6.0
143 *
144 * @return void
145 */
146 private function disable_javascript_validation() {
147 add_filter(
148 'frm_form_object',
149 /**
150 * @param stdClass|null $form
151 * @param int $form_id
152 *
153 * @return stdClass|null
154 */
155 function ( $form ) {
156 if ( is_object( $form ) && is_array( $form->options ) ) {
157 $form->options['js_validate'] = false;
158 }
159 return $form;
160 }
161 );
162 }
163
164 /**
165 * @since 6.0
166 *
167 * @return string
168 */
169 public function get_html_for_form_preview() {
170 // Force is_admin to false so the "Entry Key" field doesn't render in the preview.
171 add_filter( 'frm_is_admin', '__return_false' );
172
173 $target_form_preview_html = FrmFormsController::show_form( $this->form_id, '', 'auto', 'auto' );
174
175 $this->form_includes_captcha = wp_script_is( 'captcha-api', 'enqueued' );
176
177 if ( $this->form_includes_captcha ) {
178 // If a form includes a CAPTCHA field, don't try to load the CAPTCHA scripts for the visual styler preview.
179 wp_dequeue_script( 'captcha-api' );
180 }
181
182 // Return the is_admin status.
183 // Otherwise success messages won't use the proper mark up and will appear without the green background and padding.
184 remove_filter( 'frm_is_admin', '__return_false' );
185
186 return $target_form_preview_html;
187 }
188
189 /**
190 * @since 6.0
191 *
192 * @todo Only show the note once for a form per user per month or something.
193 *
194 * @return array<string>
195 */
196 public function get_notes_for_styler_preview() {
197 $notes = array();
198
199 $fallback_form_note = $this->get_fallback_form_note();
200
201 if ( is_string( $fallback_form_note ) ) {
202 $notes[] = $fallback_form_note;
203 }
204
205 $frm_settings = FrmAppHelper::get_settings();
206
207 if ( 'none' === $frm_settings->load_style ) {
208 $notes[] = function () {
209 printf(
210 // translators: %1$s: Anchor tag open, %2$s: Anchor tag close.
211 esc_html__( 'Formidable styles are disabled. This needs to be enabled in %1$sGlobal Settings%2$s.', 'formidable' ),
212 '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-settings' ) ) . '">',
213 '</a>'
214 );
215 };
216 }
217
218 if ( class_exists( 'FrmProStylesController' ) && ! class_exists( 'FrmProStylesPreviewHelper' ) ) {
219 $notes[] = __( 'You are using an outdated version of Formidable Pro. Please update to version 6.0 to get access to all styler features.', 'formidable' );
220 }
221
222 if ( is_callable( 'FrmProStylesController::get_notes_for_styler_preview' ) ) {
223 $notes = array_merge( $notes, FrmProStylesController::get_notes_for_styler_preview() );
224 }
225
226 $disabled_features_note = $this->get_disabled_features_note();
227
228 if ( is_string( $disabled_features_note ) ) {
229 $notes[] = $disabled_features_note;
230 }
231
232 return $notes;
233 }
234
235 /**
236 * @since 6.0
237 *
238 * @return string
239 */
240 private function get_disabled_features_note() {
241 return __( 'Not all JavaScript is loaded in this preview. Some features will appear differently on the front end.', 'formidable' );
242 }
243
244 /**
245 * @since 6.0
246 *
247 * @return false|string
248 */
249 private function get_fallback_form_note() {
250 if ( ! FrmAppHelper::simple_get( 'form', 'absint' ) ) {
251 return __( 'This form is being previewed because no form was selected. Use the form dropdown to select a new preview target.', 'formidable' );
252 }
253 return false;
254 }
255
256 /**
257 * Get all warnings to display above the visual styler preview.
258 *
259 * @since 6.0
260 *
261 * @param stdClass|WP_Post $style A new style is not a WP_Post object.
262 * @param WP_Post $default_style
263 * @param string $view Either 'list' or 'edit'.
264 *
265 * @return array<string>
266 */
267 public function get_warnings_for_styler_preview( $style, $default_style, $view ) {
268 $warnings = array();
269
270 if ( 'edit' === $view && $this->should_show_multiple_forms_warning( $style->ID, $default_style->ID ) ) {
271 $warnings[] = __( 'Changes that you will make to this style will apply to every form using this style.', 'formidable' );
272 }
273
274 return $warnings;
275 }
276
277 /**
278 * @since 6.0
279 *
280 * @param int $style_id
281 * @param int $default_style_id
282 *
283 * @return bool
284 */
285 private function should_show_multiple_forms_warning( $style_id, $default_style_id ) {
286 $is_default_style = $style_id === $default_style_id;
287
288 if ( ! $is_default_style ) {
289 // Also check for the conversational default.
290 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
291
292 if ( $conversational_style_id && (int) $conversational_style_id === $style_id ) {
293 $is_default_style = true;
294 }
295 }
296
297 $form_count = FrmStylesHelper::get_form_count_for_style( $style_id, $is_default_style );
298
299 if ( $form_count <= 1 ) {
300 return false;
301 }
302
303 // Only show the warning once per user per style.
304 $user_id = get_current_user_id();
305 $meta_key = 'frm_dismiss_multiple_forms_warning_' . $style_id;
306 $meta = get_user_meta( $user_id, $meta_key, true );
307
308 if ( $meta ) {
309 return false;
310 }
311
312 add_user_meta( $user_id, $meta_key, 1 );
313 return true;
314 }
315
316 /**
317 * @since 6.0
318 *
319 * @param WP_Styles $styles
320 *
321 * @return void
322 */
323 public static function disable_conflicting_wp_admin_css( $styles ) {
324 if ( ! is_callable( array( $styles, 'remove' ) ) || ! array_key_exists( 'wp-admin', $styles->registered ) ) {
325 return;
326 }
327
328 $styles->remove( 'edit' );
329
330 $wp_admin_dependencies = $styles->registered['wp-admin']->deps;
331 $edit_key = array_search( 'edit', $wp_admin_dependencies );
332
333 if ( false === $edit_key ) {
334 return;
335 }
336
337 // Remove the edit dependency from wp-admin so it still loads, just without edit.css.
338 self::remove_wp_admin_dependency( $styles, 'edit' );
339 }
340
341 /**
342 * Provides few fixes for style preview.
343 * Fix the "Width" from Fields Settings to get reflected on each style preview ajax update.
344 * Fix the Radio & Checkbox "Single Row" or "Multiple Row" to get reflected in style preview ajax update.
345 *
346 * @since 6.14
347 *
348 * @param array $settings The style options.
349 * @param bool $is_preview
350 *
351 * @return void
352 */
353 public static function get_additional_preview_style( $settings, $is_preview = false ) {
354 if ( ! $is_preview ) {
355 return;
356 }
357
358 $radio_display_type = 'inline' === $settings['radio_align'] ? 'inline-block' : 'block';
359 $check_display_type = 'inline' === $settings['check_align'] ? 'inline-block' : 'block';
360
361 $style = '#frm_style_preview .with_frm_style input[type=text],
362 #frm_style_preview .with_frm_style input[type=password],
363 #frm_style_preview .with_frm_style input[type=email],
364 #frm_style_preview .with_frm_style input[type=number],
365 #frm_style_preview .with_frm_style input[type=url],
366 #frm_style_preview .with_frm_style input[type=tel],
367 #frm_style_preview .with_frm_style input[type=phone],
368 #frm_style_preview .with_frm_style input[type=search],
369 #frm_style_preview .with_frm_style textarea,
370 #frm_style_preview .frm_form_fields_style,
371 #frm_style_preview .with_frm_style .frm_scroll_box .frm_opt_container,
372 #frm_style_preview .frm_form_fields_active_style,
373 #frm_style_preview .frm_form_fields_error_style,
374 #frm_style_preview .with_frm_style .frm-card-element.StripeElement,
375 #frm_style_preview .with_frm_style .frm_slimselect.ss-main {
376 width: var(--field-width);
377 }
378 #frm_style_preview .with_frm_style .frm_radio {
379 display:' . $radio_display_type . ';
380 }
381 #frm_style_preview .with_frm_style .frm_checkbox {
382 display:' . $check_display_type . ';
383 }';
384
385 echo esc_html( $style );
386 }
387
388 /**
389 * @since 6.0
390 *
391 * @param WP_Styles $styles
392 * @param string $key
393 *
394 * @return void
395 */
396 private static function remove_wp_admin_dependency( $styles, $key ) {
397 $dependencies = $styles->registered['wp-admin']->deps;
398 $index = array_search( $key, $dependencies );
399
400 if ( false === $index ) {
401 return;
402 }
403
404 unset( $dependencies[ $index ] );
405 $dependencies = array_values( $dependencies );
406
407 $styles->registered['wp-admin']->deps = $dependencies;
408 }
409 }
410