PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0.14
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0.14
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 / models / FrmFieldFormHtml.php

FrmFieldFormHtml.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 5.0.14, at classes/models/FrmFieldFormHtml.php

455 lines 11.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 3.0
8 */
9
10 class FrmFieldFormHtml {
11
12 private $html;
13
14 private $html_id;
15
16 /**
17 * @var FrmFieldType
18 */
19 private $field_obj;
20
21 private $field_id;
22
23 private $form = array();
24
25 private $pass_args = array();
26
27 /**
28 * @since 3.0
29 *
30 * @param array $atts
31 */
32 public function __construct( $atts ) {
33 $this->_set( 'field_obj', $atts );
34 $this->set_field_id( $atts );
35 $this->_set( 'form', $atts );
36 $this->_set( 'html_id', $atts );
37 $this->set_html( $atts );
38 $this->set_pass_args( $atts );
39 }
40
41 /**
42 * @since 3.0
43 *
44 * @param string $param
45 * @param array $atts
46 */
47 private function _set( $param, $atts ) {
48 if ( isset( $atts[ $param ] ) ) {
49 $this->{$param} = $atts[ $param ];
50 }
51 }
52
53 /**
54 * @since 3.0
55 *
56 * @param array $atts
57 */
58 private function set_html( $atts ) {
59 $this->set_from_field(
60 $atts,
61 array(
62 'param' => 'html',
63 'default' => 'custom_html',
64 )
65 );
66 }
67
68 /**
69 * @since 3.0
70 *
71 * @param array $atts
72 */
73 private function set_field_id( $atts ) {
74 $this->set_from_field(
75 $atts,
76 array(
77 'param' => 'field_id',
78 'default' => 'id',
79 )
80 );
81 }
82
83 /**
84 * @since 3.0
85 *
86 * @param array $atts
87 */
88 private function set_pass_args( $atts ) {
89 $this->pass_args = $atts;
90
91 $exclude = array( 'field_obj', 'html' );
92 foreach ( $exclude as $ex ) {
93 if ( isset( $atts[ $ex ] ) ) {
94 unset( $this->pass_args[ $ex ] );
95 }
96 }
97 }
98
99 /**
100 * @since 3.0
101 *
102 * @param array $atts
103 * @param array $set
104 */
105 private function set_from_field( $atts, $set ) {
106 if ( isset( $atts[ $set['param'] ] ) ) {
107 $this->{$set['param']} = $atts[ $set['param'] ];
108 } else {
109 $this->{$set['param']} = $this->field_obj->get_field_column( $set['default'] );
110 }
111 }
112
113 public function get_html() {
114 $this->replace_shortcodes_before_input();
115 $this->replace_shortcodes_with_atts();
116 $this->replace_shortcodes_after_input();
117
118 return $this->html;
119 }
120
121 /**
122 * @since 3.0
123 */
124 private function replace_shortcodes_before_input() {
125 $this->html = apply_filters( 'frm_before_replace_shortcodes', $this->html, $this->field_obj->get_field(), $this->pass_args['errors'], $this->form );
126
127 $this->replace_field_values();
128
129 $this->replace_required_label_shortcode();
130 $this->replace_required_class();
131 $this->maybe_replace_description_shortcode( false );
132 $this->replace_error_shortcode();
133 $this->add_class_to_label();
134 $this->add_field_div_classes();
135
136 $this->replace_entry_key();
137 $this->replace_form_shortcodes();
138 $this->process_wp_shortcodes();
139 $this->maybe_replace_description_shortcode( true );
140 }
141
142 /**
143 * @since 3.0
144 */
145 private function replace_field_values() {
146 //replace [id]
147 $this->html = str_replace( '[id]', $this->field_id, $this->html );
148
149 // set the label for
150 $this->html = str_replace( 'field_[key]', $this->html_id, $this->html );
151
152 //replace [key]
153 $this->html = str_replace( '[key]', $this->field_obj->get_field_column( 'field_key' ), $this->html );
154
155 //replace [field_name]
156 $this->html = str_replace( '[field_name]', FrmAppHelper::maybe_kses( $this->field_obj->get_field_column( 'name' ) ), $this->html );
157 }
158
159 /**
160 * @since 3.0
161 */
162 private function replace_required_label_shortcode() {
163 $required = FrmField::is_required( $this->field_obj->get_field() ) ? $this->field_obj->get_field_column( 'required_indicator' ) : '';
164 FrmShortcodeHelper::remove_inline_conditions( ! empty( $required ), 'required_label', $required, $this->html );
165 }
166
167 /**
168 * If this is an HTML field, the values are included in the description.
169 * In this case, we don't want to run the wp shortcodes with the description included.
170 *
171 * @since 3.0
172 */
173 private function maybe_replace_description_shortcode( $wp_processed = false ) {
174 $is_html = 'html' === $this->field_obj->get_field_column( 'type' );
175 $should_replace = ( $is_html && $wp_processed ) || ( ! $is_html && ! $wp_processed );
176 if ( $should_replace ) {
177 $this->replace_description_shortcode();
178 }
179 }
180
181 /**
182 * @since 3.0
183 */
184 private function replace_description_shortcode() {
185 $this->maybe_add_description_id();
186 $description = FrmAppHelper::maybe_kses( $this->field_obj->get_field_column( 'description' ) );
187 FrmShortcodeHelper::remove_inline_conditions( ( $description && $description != '' ), 'description', $description, $this->html );
188 }
189
190 /**
191 * Add an ID to the description for aria-describedby.
192 * This ID was added to the HTML in v3.0.
193 *
194 * @since 3.0
195 */
196 private function maybe_add_description_id() {
197 $description = $this->field_obj->get_field_column( 'description' );
198 if ( $description != '' ) {
199 $this->add_element_id( 'description', 'desc' );
200 }
201 }
202
203 /**
204 * Insert an ID if it doesn't exist.
205 *
206 * @since 3.06.02
207 */
208 private function add_element_id( $param, $id ) {
209 preg_match_all( '/(\[if\s+' . $param . '\])(.*?)(\[\/if\s+' . $param . '\])/mis', $this->html, $inner_html );
210 if ( ! isset( $inner_html[2] ) ) {
211 return;
212 }
213
214 if ( ! is_string( $inner_html[2] ) && count( $inner_html[2] ) === 1 ) {
215 $inner_html[2] = $inner_html[2][0];
216 }
217
218 if ( is_string( $inner_html[2] ) ) {
219 $has_id = strpos( $inner_html[2], ' id=' );
220 if ( ! $has_id ) {
221 $id = 'frm_' . $id . '_' . $this->html_id;
222 $this->html = str_replace( 'class="frm_' . $param, 'id="' . esc_attr( $id ) . '" class="frm_' . esc_attr( $param ), $this->html );
223 }
224 }
225 }
226
227 /**
228 * @since 3.0
229 */
230 private function replace_error_shortcode() {
231 $this->maybe_add_error_id();
232 $error = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? $this->pass_args['errors'][ 'field' . $this->field_id ] : false;
233 FrmShortcodeHelper::remove_inline_conditions( ! empty( $error ), 'error', $error, $this->html );
234 }
235
236 /**
237 * Add an ID to the error message for aria-describedby.
238 * This ID was added to the HTML in v3.06.02.
239 *
240 * @since 3.06.02
241 */
242 private function maybe_add_error_id() {
243 if ( ! isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ) {
244 return;
245 }
246
247 $this->add_element_id( 'error', 'error' );
248 }
249
250 /**
251 * Replace [required_class]
252 *
253 * @since 3.0
254 */
255 private function replace_required_class() {
256 $required_class = FrmField::is_required( $this->field_obj->get_field() ) ? ' frm_required_field' : '';
257 $this->html = str_replace( '[required_class]', $required_class, $this->html );
258 }
259
260 /**
261 * @since 3.0
262 */
263 private function replace_form_shortcodes() {
264 if ( ! empty( $this->form ) ) {
265 $form = (array) $this->form;
266
267 //replace [form_key]
268 $this->html = str_replace( '[form_key]', $form['form_key'], $this->html );
269
270 //replace [form_name]
271 $this->html = str_replace( '[form_name]', $form['name'], $this->html );
272 }
273 }
274
275 /**
276 * @since 3.0
277 */
278 public function replace_shortcodes_after_input() {
279 $this->html .= "\n";
280
281 // Stop html filtering on confirmation field to prevent loop
282 if ( $this->field_obj->get_field_column( 'conf_field' ) != 'stop' ) {
283 $this->filter_for_more_shortcodes();
284 }
285 }
286
287 /**
288 * @since 3.0
289 */
290 private function filter_for_more_shortcodes() {
291 $atts = $this->pass_args;
292
293 //If field is not in repeating section
294 if ( empty( $atts['section_id'] ) ) {
295 $atts = array(
296 'errors' => $this->pass_args['errors'],
297 'form' => $this->form,
298 );
299 }
300 $this->html = apply_filters( 'frm_replace_shortcodes', $this->html, $this->field_obj->get_field(), $atts );
301 }
302
303 /**
304 * Remove [collapse_this] if it's still included after all processing
305 *
306 * @since 3.0
307 *
308 * @param string $html
309 */
310 public function remove_collapse_shortcode( &$html ) {
311 if ( strpos( $html, '[collapse_this]' ) ) {
312 $html = str_replace( '[collapse_this]', '', $html );
313 }
314 }
315
316 /**
317 * @since 3.0
318 */
319 private function replace_shortcodes_with_atts() {
320 preg_match_all( "/\[(input|deletelink)\b(.*?)(?:(\/))?\]/s", $this->html, $shortcodes, PREG_PATTERN_ORDER );
321
322 foreach ( $shortcodes[0] as $short_key => $tag ) {
323 $shortcode_atts = FrmShortcodeHelper::get_shortcode_attribute_array( $shortcodes[2][ $short_key ] );
324 $tag = FrmShortcodeHelper::get_shortcode_tag( $shortcodes, $short_key );
325
326 $replace_with = '';
327
328 if ( $tag == 'deletelink' && FrmAppHelper::pro_is_installed() ) {
329 $replace_with = FrmProEntriesController::entry_delete_link( $shortcode_atts );
330 } elseif ( $tag == 'input' ) {
331 $replace_with = $this->replace_input_shortcode( $shortcode_atts );
332 }
333
334 $this->html = str_replace( $shortcodes[0][ $short_key ], $replace_with, $this->html );
335 }
336 }
337
338 /**
339 * @param array $shortcode_atts
340 *
341 * @return string
342 */
343 private function replace_input_shortcode( $shortcode_atts ) {
344 $shortcode_atts = $this->prepare_input_shortcode_atts( $shortcode_atts );
345
346 return $this->field_obj->include_front_field_input( $this->pass_args, $shortcode_atts );
347 }
348
349 /**
350 * @param array $shortcode_atts
351 *
352 * @return array
353 */
354 private function prepare_input_shortcode_atts( $shortcode_atts ) {
355 if ( isset( $shortcode_atts['opt'] ) ) {
356 $shortcode_atts['opt'] --;
357 }
358
359 $field_class = isset( $shortcode_atts['class'] ) ? $shortcode_atts['class'] : '';
360 $this->field_obj->set_field_column( 'input_class', $field_class );
361
362 if ( isset( $shortcode_atts['class'] ) ) {
363 unset( $shortcode_atts['class'] );
364 }
365
366 $shortcode_atts['aria-invalid'] = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? 'true' : 'false';
367
368 $this->field_obj->set_field_column( 'shortcodes', $shortcode_atts );
369
370 return $shortcode_atts;
371 }
372
373 /**
374 * Add the label position class into the HTML
375 * If the label position is inside, add a class to show the label if the field has a value.
376 *
377 * @since 3.0
378 */
379 private function add_class_to_label() {
380 $label_class = $this->field_obj->get_label_class();
381 $this->html = str_replace( '[label_position]', $label_class, $this->html );
382 if ( $this->field_obj->get_field_column( 'label' ) == 'inside' && $this->field_obj->get_field_column( 'value' ) != '' ) {
383 $this->html = str_replace( 'frm_primary_label', 'frm_primary_label frm_visible', $this->html );
384 }
385 }
386
387 /**
388 * Replace [entry_key]
389 *
390 * @since 3.0
391 */
392 private function replace_entry_key() {
393 $entry_key = FrmAppHelper::simple_get( 'entry', 'sanitize_title' );
394 $this->html = str_replace( '[entry_key]', $entry_key, $this->html );
395 }
396
397 /**
398 * Add classes to a field div
399 *
400 * @since 3.0
401 */
402 private function add_field_div_classes() {
403 $classes = $this->get_field_div_classes();
404
405 if ( $this->field_obj->get_field_column( 'type' ) == 'html' && strpos( $this->html, '[error_class]' ) === false ) {
406 // there is no error_class shortcode for HTML fields
407 $this->html = str_replace( 'class="frm_form_field', 'class="frm_form_field ' . $classes, $this->html );
408 }
409 $this->html = str_replace( '[error_class]', $classes, $this->html );
410 }
411
412 /**
413 * Get the classes for a field div
414 *
415 * @since 3.0
416 *
417 * @return string $classes
418 */
419 private function get_field_div_classes() {
420 // Add error class
421 $classes = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? ' frm_blank_field' : '';
422
423 // Add label position class
424 $settings = $this->field_obj->display_field_settings();
425 if ( isset( $settings['label_position'] ) && $settings['label_position'] ) {
426 $classes .= ' frm_' . $this->field_obj->get_field_column( 'label' ) . '_container';
427 }
428
429 // Add CSS layout classes
430 $extra_classes = $this->field_obj->get_field_column( 'classes' );
431 if ( ! empty( $extra_classes ) ) {
432 if ( ! strpos( $this->html, 'frm_form_field ' ) ) {
433 $classes .= ' frm_form_field';
434 }
435 $classes .= ' ' . $extra_classes;
436 }
437
438 $classes .= $this->field_obj->get_container_class();
439
440 // Get additional classes
441 return apply_filters( 'frm_field_div_classes', $classes, $this->field_obj->get_field(), array( 'field_id' => $this->field_id ) );
442 }
443
444 /**
445 * This filters shortcodes in the field HTML
446 *
447 * @since 3.0
448 */
449 private function process_wp_shortcodes() {
450 if ( apply_filters( 'frm_do_html_shortcodes', true ) ) {
451 $this->html = do_shortcode( $this->html );
452 }
453 }
454 }
455