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

356 lines 9.5 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 $form_id
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 string|int $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 object|array $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 object|array $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 function( $form ) {
145 $form->options['js_validate'] = false;
146 return $form;
147 }
148 );
149 }
150
151 /**
152 * @since 6.0
153 *
154 * @return string
155 */
156 public function get_html_for_form_preview() {
157 // Force is_admin to false so the "Entry Key" field doesn't render in the preview.
158 add_filter( 'frm_is_admin', '__return_false' );
159
160 $target_form_preview_html = FrmFormsController::show_form( $this->form_id, '', 'auto', 'auto' );
161
162 $this->form_includes_captcha = wp_script_is( 'captcha-api', 'enqueued' );
163 if ( $this->form_includes_captcha ) {
164 // If a form includes a CAPTCHA field, don't try to load the CAPTCHA scripts for the visual styler preview.
165 wp_dequeue_script( 'captcha-api' );
166 }
167
168 // Return the is_admin status.
169 // Otherwise success messages won't use the proper mark up and will appear without the green background and padding.
170 remove_filter( 'frm_is_admin', '__return_false' );
171
172 return $target_form_preview_html;
173 }
174
175 /**
176 * @since 6.0
177 *
178 * @todo Only show the note once for a form per user per month or something.
179 *
180 * @return array<string>
181 */
182 public function get_notes_for_styler_preview() {
183 $notes = array();
184
185 $fallback_form_note = $this->get_fallback_form_note();
186 if ( is_string( $fallback_form_note ) ) {
187 $notes[] = $fallback_form_note;
188 }
189
190 $frm_settings = FrmAppHelper::get_settings();
191 if ( 'none' === $frm_settings->load_style ) {
192 $notes[] = function() {
193 printf(
194 // translators: %1$s: Anchor tag open, %2$s: Anchor tag close.
195 esc_html__( 'Formidable styles are disabled. This needs to be enabled in %1$sGlobal Settings%2$s.', 'formidable' ),
196 '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-settings' ) ) . '">',
197 '</a>'
198 );
199 };
200 }
201
202 if ( class_exists( 'FrmProStylesController' ) && ! class_exists( 'FrmProStylesPreviewHelper' ) ) {
203 $notes[] = __( 'You are using an outdated version of Formidable Pro. Please update to version 6.0 to get access to all styler features.', 'formidable' );
204 }
205
206 if ( is_callable( 'FrmProStylesController::get_notes_for_styler_preview' ) ) {
207 $notes = array_merge( $notes, FrmProStylesController::get_notes_for_styler_preview() );
208 }
209
210 $disabled_features_note = $this->get_disabled_features_note();
211 if ( is_string( $disabled_features_note ) ) {
212 $notes[] = $disabled_features_note;
213 }
214
215 return $notes;
216 }
217
218 /**
219 * @since 6.0
220 *
221 * @return string|false
222 */
223 private function get_disabled_features_note() {
224 $disabled_features = array();
225
226 if ( $this->form_includes_captcha ) {
227 $disabled_features[] = __( 'Captcha fields are hidden.', 'formidable' );
228 }
229
230 if ( is_callable( 'FrmProStylesController::get_disabled_javascript_features' ) ) {
231 $disabled_pro_features = FrmProStylesController::get_disabled_javascript_features();
232 if ( is_string( $disabled_pro_features ) ) {
233 $disabled_features[] = $disabled_pro_features;
234 }
235 }
236
237 if ( $disabled_features ) {
238 return __( 'Not all JavaScript is loaded in this preview.', 'formidable' ) . ' ' . implode( ' ', $disabled_features );
239 }
240
241 return false;
242 }
243
244 /**
245 * @since 6.0
246 *
247 * @return string|false
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 WP_Post|stdClass $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 * @return array<string>
265 */
266 public function get_warnings_for_styler_preview( $style, $default_style, $view ) {
267 $warnings = array();
268
269 if ( 'edit' === $view && $this->should_show_multiple_forms_warning( $style->ID, $default_style->ID ) ) {
270 $warnings[] = __( 'Changes that you will make to this style will apply to every form using this style.', 'formidable' );
271 }
272
273 return $warnings;
274 }
275
276 /**
277 * @since 6.0
278 *
279 * @param int $style_id
280 * @param int $default_style_id
281 * @return bool
282 */
283 private function should_show_multiple_forms_warning( $style_id, $default_style_id ) {
284 $is_default_style = $style_id === $default_style_id;
285
286 if ( ! $is_default_style ) {
287 // Also check for the conversational default.
288 $conversational_style_id = FrmDb::get_var( 'posts', array( 'post_name' => 'lines-no-boxes' ), 'ID' );
289 if ( $conversational_style_id && (int) $conversational_style_id === $style_id ) {
290 $is_default_style = true;
291 }
292 }
293
294 $form_count = FrmStylesHelper::get_form_count_for_style( $style_id, $is_default_style );
295
296 if ( $form_count <= 1 ) {
297 return false;
298 }
299
300 // Only show the warning once per user per style.
301 $user_id = get_current_user_id();
302 $meta_key = 'frm_dismiss_multiple_forms_warning_' . $style_id;
303 $meta = get_user_meta( $user_id, $meta_key, true );
304
305 if ( $meta ) {
306 return false;
307 }
308
309 add_user_meta( $user_id, $meta_key, 1 );
310 return true;
311 }
312
313 /**
314 * @since 6.0
315 *
316 * @param WP_Styles $styles
317 * @return void
318 */
319 public static function disable_conflicting_wp_admin_css( $styles ) {
320 if ( ! is_callable( array( $styles, 'remove' ) ) || ! array_key_exists( 'wp-admin', $styles->registered ) ) {
321 return;
322 }
323
324 $styles->remove( 'edit' );
325
326 $wp_admin_dependencies = $styles->registered['wp-admin']->deps;
327 $edit_key = array_search( 'edit', $wp_admin_dependencies );
328 if ( false === $edit_key ) {
329 return;
330 }
331
332 // Remove the edit dependency from wp-admin so it still loads, just without edit.css.
333 self::remove_wp_admin_dependency( $styles, 'edit' );
334 }
335
336 /**
337 * @since 6.0
338 *
339 * @param WP_Styles $styles
340 * @param string $key
341 * @return void
342 */
343 private static function remove_wp_admin_dependency( $styles, $key ) {
344 $dependencies = $styles->registered['wp-admin']->deps;
345 $index = array_search( $key, $dependencies );
346 if ( false === $index ) {
347 return;
348 }
349
350 unset( $dependencies[ $index ] );
351 $dependencies = array_values( $dependencies );
352
353 $styles->registered['wp-admin']->deps = $dependencies;
354 }
355 }
356