PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.28
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.28
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.28, at classes/helpers/FrmStylesPreviewHelper.php

401 lines 10.8 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 return 'captcha' === $field_type ? false : $show;
128 },
129 10,
130 2
131 );
132 }
133
134 /**
135 * Turn off JavaScript validation for the preview.
136 * Without this we hit a "PHP Fatal error: Uncaught Error: Maximum function nesting level of '256' reached" error.
137 * This only happened with specific Look up fields when FrmProLookupFieldsController::get_independent_lookup_field_options is called in Pro.
138 *
139 * @since 6.0
140 *
141 * @return void
142 */
143 private function disable_javascript_validation() {
144 add_filter(
145 'frm_form_object',
146 /**
147 * @param stdClass|null $form
148 * @param int $form_id
149 *
150 * @return stdClass|null
151 */
152 function ( $form ) {
153 if ( is_object( $form ) && is_array( $form->options ) ) {
154 $form->options['js_validate'] = false;
155 }
156 return $form;
157 }
158 );
159 }
160
161 /**
162 * @since 6.0
163 *
164 * @return string
165 */
166 public function get_html_for_form_preview() {
167 // Force is_admin to false so the "Entry Key" field doesn't render in the preview.
168 add_filter( 'frm_is_admin', '__return_false' );
169
170 $target_form_preview_html = FrmFormsController::show_form( $this->form_id, '', 'auto', 'auto' );
171
172 $this->form_includes_captcha = wp_script_is( 'captcha-api', 'enqueued' );
173
174 if ( $this->form_includes_captcha ) {
175 // If a form includes a CAPTCHA field, don't try to load the CAPTCHA scripts for the visual styler preview.
176 wp_dequeue_script( 'captcha-api' );
177 }
178
179 // Return the is_admin status.
180 // Otherwise success messages won't use the proper mark up and will appear without the green background and padding.
181 remove_filter( 'frm_is_admin', '__return_false' );
182
183 return $target_form_preview_html;
184 }
185
186 /**
187 * @since 6.0
188 *
189 * @return array<string>
190 */
191 public function get_notes_for_styler_preview() {
192 $notes = array();
193 $fallback_form_note = $this->get_fallback_form_note();
194
195 if ( is_string( $fallback_form_note ) ) {
196 $notes[] = $fallback_form_note;
197 }
198
199 $frm_settings = FrmAppHelper::get_settings();
200
201 if ( 'none' === $frm_settings->load_style ) {
202 $notes[] = function () {
203 printf(
204 // translators: %1$s: Anchor tag open, %2$s: Anchor tag close.
205 esc_html__( 'Formidable styles are disabled. This needs to be enabled in %1$sGlobal Settings%2$s.', 'formidable' ),
206 '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-settings' ) ) . '">',
207 '</a>'
208 );
209 };
210 }
211
212 if ( is_callable( 'FrmProStylesController::get_notes_for_styler_preview' ) ) {
213 $notes = array_merge( $notes, FrmProStylesController::get_notes_for_styler_preview() );
214 }
215
216 $disabled_features_note = $this->get_disabled_features_note();
217
218 if ( is_string( $disabled_features_note ) ) {
219 $notes[] = $disabled_features_note;
220 }
221
222 return $notes;
223 }
224
225 /**
226 * @since 6.0
227 *
228 * @return string
229 */
230 private function get_disabled_features_note() {
231 return __( 'Not all JavaScript is loaded in this preview. Some features will appear differently on the front end.', 'formidable' );
232 }
233
234 /**
235 * @since 6.0
236 *
237 * @return false|string
238 */
239 private function get_fallback_form_note() {
240 if ( ! FrmAppHelper::simple_get( 'form', 'absint' ) ) {
241 return __( 'This form is being previewed because no form was selected. Use the form dropdown to select a new preview target.', 'formidable' );
242 }
243 return false;
244 }
245
246 /**
247 * Get all warnings to display above the visual styler preview.
248 *
249 * @since 6.0
250 *
251 * @param stdClass|WP_Post $style A new style is not a WP_Post object.
252 * @param WP_Post $default_style
253 * @param string $view Either 'list' or 'edit'.
254 *
255 * @return array<string>
256 */
257 public function get_warnings_for_styler_preview( $style, $default_style, $view ) {
258 $warnings = array();
259
260 if ( 'edit' === $view && $this->should_show_multiple_forms_warning( $style->ID, $default_style->ID ) ) {
261 $warnings[] = __( 'Changes that you will make to this style will apply to every form using this style.', 'formidable' );
262 }
263
264 return $warnings;
265 }
266
267 /**
268 * @since 6.0
269 *
270 * @param int $style_id
271 * @param int $default_style_id
272 *
273 * @return bool
274 */
275 private function should_show_multiple_forms_warning( $style_id, $default_style_id ) {
276 $is_default_style = $style_id === $default_style_id;
277
278 if ( ! $is_default_style ) {
279 // Also check for the conversational default.
280 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
281
282 if ( $conversational_style_id && (int) $conversational_style_id === $style_id ) {
283 $is_default_style = true;
284 }
285 }
286
287 $form_count = FrmStylesHelper::get_form_count_for_style( $style_id, $is_default_style );
288
289 if ( $form_count <= 1 ) {
290 return false;
291 }
292
293 // Only show the warning once per user per style.
294 $user_id = get_current_user_id();
295 $meta_key = 'frm_dismiss_multiple_forms_warning_' . $style_id;
296 $meta = get_user_meta( $user_id, $meta_key, true );
297
298 if ( $meta ) {
299 return false;
300 }
301
302 add_user_meta( $user_id, $meta_key, 1 );
303 return true;
304 }
305
306 /**
307 * @since 6.0
308 *
309 * @param WP_Styles $styles
310 *
311 * @return void
312 */
313 public static function disable_conflicting_wp_admin_css( $styles ) {
314 if ( ! is_callable( array( $styles, 'remove' ) ) || ! array_key_exists( 'wp-admin', $styles->registered ) ) {
315 return;
316 }
317
318 $styles->remove( 'edit' );
319
320 $wp_admin_dependencies = $styles->registered['wp-admin']->deps;
321 $edit_key = array_search( 'edit', $wp_admin_dependencies, true );
322
323 if ( false === $edit_key ) {
324 return;
325 }
326
327 // Remove the edit dependency from wp-admin so it still loads, just without edit.css.
328 self::remove_wp_admin_dependency( $styles, 'edit' );
329 }
330
331 /**
332 * Provides few fixes for style preview.
333 * Fix the "Width" from Fields Settings to get reflected on each style preview ajax update.
334 * Fix the Radio & Checkbox "Single Row" or "Multiple Row" to get reflected in style preview ajax update.
335 *
336 * @since 6.14
337 *
338 * @param array $settings The style options.
339 * @param bool $is_preview
340 *
341 * @return void
342 */
343 public static function get_additional_preview_style( $settings, $is_preview = false ) {
344 if ( ! $is_preview ) {
345 return;
346 }
347
348 $radio_display_type = 'inline' === $settings['radio_align'] ? 'inline-block' : 'block';
349 $check_display_type = 'inline' === $settings['check_align'] ? 'inline-block' : 'block';
350
351 $style = '#frm_style_preview .with_frm_style input[type=text],
352 #frm_style_preview .with_frm_style input[type=password],
353 #frm_style_preview .with_frm_style input[type=email],
354 #frm_style_preview .with_frm_style input[type=number],
355 #frm_style_preview .with_frm_style input[type=url],
356 #frm_style_preview .with_frm_style input[type=tel],
357 #frm_style_preview .with_frm_style input[type=phone],
358 #frm_style_preview .with_frm_style input[type=search],
359 #frm_style_preview .with_frm_style textarea,
360 #frm_style_preview .frm_form_fields_style,
361 #frm_style_preview .with_frm_style .frm_scroll_box .frm_opt_container,
362 #frm_style_preview .frm_form_fields_active_style,
363 #frm_style_preview .frm_form_fields_error_style,
364 #frm_style_preview .with_frm_style .frm-card-element.StripeElement,
365 #frm_style_preview .with_frm_style .frm_slimselect.ss-main {
366 width: var(--field-width);
367 }
368 #frm_style_preview .with_frm_style .frm_radio {
369 display:' . $radio_display_type . ';
370 }
371 #frm_style_preview .with_frm_style .frm_checkbox {
372 display:' . $check_display_type . ';
373 }';
374
375 echo esc_html( $style );
376 }
377
378 /**
379 * @since 6.0
380 *
381 * @param WP_Styles $styles
382 * @param string $key
383 *
384 * @return void
385 */
386 private static function remove_wp_admin_dependency( $styles, $key ) {
387 $dependencies = $styles->registered['wp-admin']->deps;
388 // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
389 $index = array_search( $key, $dependencies );
390
391 if ( false === $index ) {
392 return;
393 }
394
395 unset( $dependencies[ $index ] );
396 $dependencies = array_values( $dependencies );
397
398 $styles->registered['wp-admin']->deps = $dependencies;
399 }
400 }
401