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

363 lines 9.7 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 * @return void
37 */
38 public function __construct( $form_id ) {
39 $this->form_id = (int) $form_id;
40 $this->default_label_position_field_ids = array();
41 }
42
43 /**
44 * Modify form behaviours for the styler preview.
45 *
46 * @since 6.0
47 *
48 * @return void
49 */
50 public function adjust_form_for_preview() {
51 // Don't bother including the antispam token in the preview as the form isn't submitted.
52 add_filter( 'frm_run_antispam', '__return_false', 99 );
53
54 // We don't need the honeypot in the preview so leave it out.
55 add_filter( 'frm_run_honeypot', '__return_false' );
56 $this->hide_captcha_fields();
57 $this->disable_javascript_validation();
58 $this->add_a_div_class_for_default_label_positions();
59 }
60
61 /**
62 * Add a frm-default-label-position class to any field with a default label position.
63 * A field with a custom label position shouldn't ever change in the styler preview.
64 *
65 * @since 6.0.1
66 * @return void
67 */
68 private function add_a_div_class_for_default_label_positions() {
69 // Only fields with no label position set hit this filter, so track those for the frm_field_div_classes filter.
70 add_filter(
71 'frm_html_label_position',
72 /**
73 * @param string $position
74 * @param array|object $field
75 * @return string
76 */
77 function ( $position, $field ) {
78 if ( is_array( $field ) ) {
79 $this->default_label_position_field_ids[] = (int) $field['id'];
80 }
81 return $position;
82 },
83 10,
84 2
85 );
86
87 add_filter(
88 'frm_field_div_classes',
89 /**
90 * @param string $classes
91 * @param array|object $field
92 * @return string
93 */
94 function ( $classes, $field ) {
95 if ( is_array( $field ) && in_array( (int) $field['id'], $this->default_label_position_field_ids, true ) ) {
96 $classes .= ' frm-default-label-position';
97 }
98 return $classes;
99 },
100 10,
101 2
102 );
103 }
104
105 /**
106 * Captcha does not initialize in the preview. Hide it so we don't see the label either.
107 *
108 * @since 6.0
109 *
110 * @return void
111 */
112 private function hide_captcha_fields() {
113 add_filter(
114 'frm_show_normal_field_type',
115 /**
116 * @param bool $show
117 * @param string $field_type
118 * @param string $target_field_type
119 * @return bool
120 */
121 function ( $show, $field_type ) {
122 if ( 'captcha' === $field_type ) {
123 $show = false;
124 }
125 return $show;
126 },
127 10,
128 2
129 );
130 }
131
132 /**
133 * Turn off JavaScript validation for the preview.
134 * Without this we hit a "PHP Fatal error: Uncaught Error: Maximum function nesting level of '256' reached" error.
135 * This only happened with specific Look up fields when FrmProLookupFieldsController::get_independent_lookup_field_options is called in Pro.
136 *
137 * @since 6.0
138 *
139 * @return void
140 */
141 private function disable_javascript_validation() {
142 add_filter(
143 'frm_form_object',
144 /**
145 * @param stdClass|null $form
146 * @param int $form_id
147 * @return stdClass|null
148 */
149 function ( $form ) {
150 if ( is_object( $form ) && is_array( $form->options ) ) {
151 $form->options['js_validate'] = false;
152 }
153 return $form;
154 }
155 );
156 }
157
158 /**
159 * @since 6.0
160 *
161 * @return string
162 */
163 public function get_html_for_form_preview() {
164 // Force is_admin to false so the "Entry Key" field doesn't render in the preview.
165 add_filter( 'frm_is_admin', '__return_false' );
166
167 $target_form_preview_html = FrmFormsController::show_form( $this->form_id, '', 'auto', 'auto' );
168
169 $this->form_includes_captcha = wp_script_is( 'captcha-api', 'enqueued' );
170 if ( $this->form_includes_captcha ) {
171 // If a form includes a CAPTCHA field, don't try to load the CAPTCHA scripts for the visual styler preview.
172 wp_dequeue_script( 'captcha-api' );
173 }
174
175 // Return the is_admin status.
176 // Otherwise success messages won't use the proper mark up and will appear without the green background and padding.
177 remove_filter( 'frm_is_admin', '__return_false' );
178
179 return $target_form_preview_html;
180 }
181
182 /**
183 * @since 6.0
184 *
185 * @todo Only show the note once for a form per user per month or something.
186 *
187 * @return array<string>
188 */
189 public function get_notes_for_styler_preview() {
190 $notes = array();
191
192 $fallback_form_note = $this->get_fallback_form_note();
193 if ( is_string( $fallback_form_note ) ) {
194 $notes[] = $fallback_form_note;
195 }
196
197 $frm_settings = FrmAppHelper::get_settings();
198 if ( 'none' === $frm_settings->load_style ) {
199 $notes[] = function () {
200 printf(
201 // translators: %1$s: Anchor tag open, %2$s: Anchor tag close.
202 esc_html__( 'Formidable styles are disabled. This needs to be enabled in %1$sGlobal Settings%2$s.', 'formidable' ),
203 '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-settings' ) ) . '">',
204 '</a>'
205 );
206 };
207 }
208
209 if ( class_exists( 'FrmProStylesController' ) && ! class_exists( 'FrmProStylesPreviewHelper' ) ) {
210 $notes[] = __( 'You are using an outdated version of Formidable Pro. Please update to version 6.0 to get access to all styler features.', 'formidable' );
211 }
212
213 if ( is_callable( 'FrmProStylesController::get_notes_for_styler_preview' ) ) {
214 $notes = array_merge( $notes, FrmProStylesController::get_notes_for_styler_preview() );
215 }
216
217 $disabled_features_note = $this->get_disabled_features_note();
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 false|string
229 */
230 private function get_disabled_features_note() {
231 $disabled_features = array();
232
233 if ( $this->form_includes_captcha ) {
234 $disabled_features[] = __( 'Captcha fields are hidden.', 'formidable' );
235 }
236
237 if ( is_callable( 'FrmProStylesController::get_disabled_javascript_features' ) ) {
238 $disabled_pro_features = FrmProStylesController::get_disabled_javascript_features();
239 if ( is_string( $disabled_pro_features ) ) {
240 $disabled_features[] = $disabled_pro_features;
241 }
242 }
243
244 if ( $disabled_features ) {
245 return __( 'Not all JavaScript is loaded in this preview.', 'formidable' ) . ' ' . implode( ' ', $disabled_features );
246 }
247
248 return false;
249 }
250
251 /**
252 * @since 6.0
253 *
254 * @return false|string
255 */
256 private function get_fallback_form_note() {
257 if ( ! FrmAppHelper::simple_get( 'form', 'absint' ) ) {
258 return __( 'This form is being previewed because no form was selected. Use the form dropdown to select a new preview target.', 'formidable' );
259 }
260 return false;
261 }
262
263 /**
264 * Get all warnings to display above the visual styler preview.
265 *
266 * @since 6.0
267 *
268 * @param stdClass|WP_Post $style A new style is not a WP_Post object.
269 * @param WP_Post $default_style
270 * @param string $view Either 'list' or 'edit'.
271 * @return array<string>
272 */
273 public function get_warnings_for_styler_preview( $style, $default_style, $view ) {
274 $warnings = array();
275
276 if ( 'edit' === $view && $this->should_show_multiple_forms_warning( $style->ID, $default_style->ID ) ) {
277 $warnings[] = __( 'Changes that you will make to this style will apply to every form using this style.', 'formidable' );
278 }
279
280 return $warnings;
281 }
282
283 /**
284 * @since 6.0
285 *
286 * @param int $style_id
287 * @param int $default_style_id
288 * @return bool
289 */
290 private function should_show_multiple_forms_warning( $style_id, $default_style_id ) {
291 $is_default_style = $style_id === $default_style_id;
292
293 if ( ! $is_default_style ) {
294 // Also check for the conversational default.
295 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
296 if ( $conversational_style_id && (int) $conversational_style_id === $style_id ) {
297 $is_default_style = true;
298 }
299 }
300
301 $form_count = FrmStylesHelper::get_form_count_for_style( $style_id, $is_default_style );
302
303 if ( $form_count <= 1 ) {
304 return false;
305 }
306
307 // Only show the warning once per user per style.
308 $user_id = get_current_user_id();
309 $meta_key = 'frm_dismiss_multiple_forms_warning_' . $style_id;
310 $meta = get_user_meta( $user_id, $meta_key, true );
311
312 if ( $meta ) {
313 return false;
314 }
315
316 add_user_meta( $user_id, $meta_key, 1 );
317 return true;
318 }
319
320 /**
321 * @since 6.0
322 *
323 * @param WP_Styles $styles
324 * @return void
325 */
326 public static function disable_conflicting_wp_admin_css( $styles ) {
327 if ( ! is_callable( array( $styles, 'remove' ) ) || ! array_key_exists( 'wp-admin', $styles->registered ) ) {
328 return;
329 }
330
331 $styles->remove( 'edit' );
332
333 $wp_admin_dependencies = $styles->registered['wp-admin']->deps;
334 $edit_key = array_search( 'edit', $wp_admin_dependencies );
335 if ( false === $edit_key ) {
336 return;
337 }
338
339 // Remove the edit dependency from wp-admin so it still loads, just without edit.css.
340 self::remove_wp_admin_dependency( $styles, 'edit' );
341 }
342
343 /**
344 * @since 6.0
345 *
346 * @param WP_Styles $styles
347 * @param string $key
348 * @return void
349 */
350 private static function remove_wp_admin_dependency( $styles, $key ) {
351 $dependencies = $styles->registered['wp-admin']->deps;
352 $index = array_search( $key, $dependencies );
353 if ( false === $index ) {
354 return;
355 }
356
357 unset( $dependencies[ $index ] );
358 $dependencies = array_values( $dependencies );
359
360 $styles->registered['wp-admin']->deps = $dependencies;
361 }
362 }
363