PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 4.01.02
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v4.01.02
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 / FrmFormsHelper.php

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

1,233 lines 37.0 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 class FrmFormsHelper {
7
8 /**
9 * @since 2.2.10
10 */
11 public static function form_error_class() {
12 return apply_filters( 'frm_form_error_class', 'frm_error_style' );
13 }
14
15 public static function get_direct_link( $key, $form = false ) {
16 $target_url = esc_url( admin_url( 'admin-ajax.php?action=frm_forms_preview&form=' . $key ) );
17 $target_url = apply_filters( 'frm_direct_link', $target_url, $key, $form );
18
19 return $target_url;
20 }
21
22 public static function forms_dropdown( $field_name, $field_value = '', $args = array() ) {
23 $defaults = array(
24 'blank' => true,
25 'field_id' => false,
26 'onchange' => false,
27 'exclude' => false,
28 'class' => '',
29 'inc_children' => 'exclude',
30 );
31 $args = wp_parse_args( $args, $defaults );
32
33 if ( ! $args['field_id'] ) {
34 $args['field_id'] = $field_name;
35 }
36
37 $query = array();
38 if ( $args['exclude'] ) {
39 $query['id !'] = $args['exclude'];
40 }
41
42 $where = apply_filters( 'frm_forms_dropdown', $query, $field_name );
43 $forms = FrmForm::get_published_forms( $where, 999, $args['inc_children'] );
44 $add_html = array();
45 self::add_html_attr( $args['onchange'], 'onchange', $add_html );
46 self::add_html_attr( $args['class'], 'class', $add_html );
47
48 ?>
49 <select name="<?php echo esc_attr( $field_name ); ?>"
50 id="<?php echo esc_attr( $args['field_id'] ); ?>"
51 <?php echo wp_strip_all_tags( implode( ' ', $add_html ) ); // WPCS: XSS ok. ?>>
52 <?php if ( $args['blank'] ) { ?>
53 <option value=""><?php echo ( $args['blank'] == 1 ) ? ' ' : '- ' . esc_attr( $args['blank'] ) . ' -'; ?></option>
54 <?php } ?>
55 <?php foreach ( $forms as $form ) { ?>
56 <option value="<?php echo esc_attr( $form->id ); ?>" <?php selected( $field_value, $form->id ); ?>>
57 <?php echo esc_html( '' === $form->name ? __( '(no title)', 'formidable' ) : FrmAppHelper::truncate( $form->name, 50 ) . ( $form->parent_form_id ? __( ' (child)', 'formidable' ) : '' ) ); ?>
58 </option>
59 <?php } ?>
60 </select>
61 <?php
62 }
63
64 /**
65 * @param string $class
66 * @param string $param
67 * @param array $add_html
68 *
69 * @since 2.0.6
70 */
71 public static function add_html_attr( $class, $param, &$add_html ) {
72 if ( ! empty( $class ) ) {
73 $add_html[ $param ] = sanitize_title( $param ) . '="' . esc_attr( trim( sanitize_text_field( $class ) ) ) . '"';
74 }
75 }
76
77 /**
78 * @param string|object $selected - The label for the placeholder, or the form object.
79 */
80 public static function form_switcher( $selected = false ) {
81 $where = apply_filters( 'frm_forms_dropdown', array(), '' );
82 $forms = FrmForm::get_published_forms( $where );
83
84 $args = array(
85 'id' => 0,
86 'form' => 0,
87 );
88 if ( isset( $_GET['id'] ) && ! isset( $_GET['form'] ) ) {
89 unset( $args['form'] );
90 } elseif ( isset( $_GET['form'] ) && ! isset( $_GET['id'] ) ) {
91 unset( $args['id'] );
92 }
93
94 $frm_action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
95 if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) && in_array( $frm_action, array( 'edit', 'show', 'destroy_all' ) ) ) {
96 $args['frm_action'] = 'list';
97 $args['form'] = 0;
98 } elseif ( FrmAppHelper::is_admin_page( 'formidable' ) && in_array( $frm_action, array( 'new', 'duplicate' ) ) ) {
99 $args['frm_action'] = 'edit';
100 } elseif ( isset( $_GET['post'] ) ) {
101 $args['form'] = 0;
102 $base = admin_url( 'edit.php?post_type=frm_display' );
103 }
104
105 $form_id = 0;
106 if ( is_object( $selected ) ) {
107 $form_id = $selected->id;
108 $selected = $selected->name;
109 }
110
111 $name = ( $selected === false ) ? __( 'Switch Form', 'formidable' ) : $selected;
112 $name = '' === $name ? __( '(no title)', 'formidable' ) : strip_tags( $name );
113 $truncated_name = FrmAppHelper::truncate( $name, 25 );
114
115 ?>
116 <div id="frm_bs_dropdown" class="dropdown <?php echo esc_attr( is_rtl() ? 'pull-right' : 'pull-left' ); ?>">
117 <a href="#" id="frm-navbarDrop" class="frm-dropdown-toggle" data-toggle="dropdown">
118 <h1>
119 <span class="frm_bstooltip" title="<?php echo esc_attr( $truncated_name === $name ? '' : $name ); ?>" data-placement="right">
120 <?php echo esc_html( $name ); ?>
121 </span>
122 <?php FrmAppHelper::icon_by_class( 'frmfont frm_arrowdown4_icon', array( 'aria-hidden' => 'true' ) ); ?>
123 </h1>
124 </a>
125 <ul class="frm-dropdown-menu frm-on-top frm-inline-modal frm_code_list frm-full-hover" role="menu" aria-labelledby="frm-navbarDrop">
126 <?php if ( count( $forms ) > 8 ) { ?>
127 <li class="frm-with-search">
128 <?php
129 FrmAppHelper::show_search_box(
130 array(
131 'input_id' => 'dropform',
132 'placeholder' => __( 'Search Forms', 'formidable' ),
133 'tosearch' => 'frm-dropdown-form',
134 )
135 );
136 ?>
137 </li>
138 <?php } ?>
139 <?php
140 foreach ( $forms as $form ) {
141 if ( $form->id === $form_id ) {
142 // Don't include the selected form in the switcher since it does nothing.
143 continue;
144 }
145
146 if ( isset( $args['id'] ) ) {
147 $args['id'] = $form->id;
148 }
149 if ( isset( $args['form'] ) ) {
150 $args['form'] = $form->id;
151 }
152
153 $url = isset( $base ) ? add_query_arg( $args, $base ) : add_query_arg( $args );
154 $form_name = empty( $form->name ) ? __( '(no title)', 'formidable' ) : $form->name;
155 ?>
156 <li class="frm-dropdown-form">
157 <a href="<?php echo esc_url( $url ); ?>" tabindex="-1">
158 <span class="frm-sub-label">
159 <?php
160 printf(
161 /* translators: %d: Form ID */
162 esc_html__( '(ID %d)', 'formidable' ),
163 esc_attr( $form->id )
164 );
165 ?>
166 </span>
167 <?php echo esc_html( $form_name ); ?>
168 <span class="frm_hidden"><?php echo esc_html( $form->form_key ); ?></span>
169 </a>
170 </li>
171 <?php
172 unset( $form );
173 }
174 ?>
175 </ul>
176 </div>
177 <?php
178 }
179
180 /**
181 * @since 3.05
182 * @deprecated 4.0
183 *
184 * @param array $values - The form array
185 */
186 public static function builder_submit_button( $values ) {
187 FrmDeprecated::builder_submit_button( $values );
188 }
189
190 public static function get_sortable_classes( $col, $sort_col, $sort_dir ) {
191 echo ( $sort_col == $col ) ? 'sorted' : 'sortable';
192 echo ( $sort_col == $col && $sort_dir == 'desc' ) ? ' asc' : ' desc';
193 }
194
195 /**
196 * @since 3.0
197 */
198 public static function get_field_link_name( $field_type ) {
199 if ( is_array( $field_type ) ) {
200 $field_label = $field_type['name'];
201 } else {
202 $field_label = $field_type;
203 }
204
205 return $field_label;
206 }
207
208 /**
209 * @since 3.0
210 */
211 public static function get_field_link_icon( $field_type ) {
212 if ( is_array( $field_type ) && isset( $field_type['icon'] ) ) {
213 $icon = $field_type['icon'];
214 } else {
215 $icon = 'frm_icon_font frm_pencil_icon';
216 }
217
218 return $icon;
219 }
220
221 /**
222 * Get the invalid form error message
223 *
224 * @since 2.02.07
225 *
226 * @param array $args
227 *
228 * @return string
229 */
230 public static function get_invalid_error_message( $args ) {
231 $settings_args = $args;
232 if ( isset( $args['form'] ) ) {
233 $settings_args['current_form'] = $args['form']->id;
234 }
235
236 $frm_settings = FrmAppHelper::get_settings( $settings_args );
237 $invalid_msg = do_shortcode( $frm_settings->invalid_msg );
238 return apply_filters( 'frm_invalid_error_message', $invalid_msg, $args );
239 }
240
241 public static function get_success_message( $atts ) {
242 $message = apply_filters( 'frm_content', $atts['message'], $atts['form'], $atts['entry_id'] );
243 $message = FrmAppHelper::use_wpautop( do_shortcode( $message ) );
244 $message = '<div class="' . esc_attr( $atts['class'] ) . '">' . $message . '</div>';
245
246 return $message;
247 }
248
249 /**
250 * Used when a form is created
251 */
252 public static function setup_new_vars( $values = array() ) {
253 global $wpdb;
254
255 if ( ! empty( $values ) ) {
256 $post_values = $values;
257 } else {
258 $values = array();
259 $post_values = isset( $_POST ) ? $_POST : array();
260 }
261
262 $defaults = array(
263 'name' => '',
264 'description' => '',
265 );
266 foreach ( $defaults as $var => $default ) {
267 if ( ! isset( $values[ $var ] ) ) {
268 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
269 }
270 }
271
272 $values['description'] = FrmAppHelper::use_wpautop( $values['description'] );
273
274 $defaults = array(
275 'form_id' => '',
276 'logged_in' => '',
277 'editable' => '',
278 'is_template' => 0,
279 'status' => 'published',
280 'parent_form_id' => 0,
281 );
282 foreach ( $defaults as $var => $default ) {
283 if ( ! isset( $values[ $var ] ) ) {
284 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
285 }
286 }
287 unset( $defaults );
288
289 if ( ! isset( $values['form_key'] ) ) {
290 $values['form_key'] = ( $post_values && isset( $post_values['form_key'] ) ) ? $post_values['form_key'] : FrmAppHelper::get_unique_key( '', $wpdb->prefix . 'frm_forms', 'form_key' );
291 }
292
293 $values = self::fill_default_opts( $values, false, $post_values );
294 $values['custom_style'] = FrmAppHelper::custom_style_value( $post_values );
295
296 return apply_filters( 'frm_setup_new_form_vars', $values );
297 }
298
299 /**
300 * Used when editing a form
301 */
302 public static function setup_edit_vars( $values, $record, $post_values = array() ) {
303 if ( empty( $post_values ) ) {
304 $post_values = wp_unslash( $_POST );
305 }
306
307 $values['form_key'] = isset( $post_values['form_key'] ) ? $post_values['form_key'] : $record->form_key;
308 $values['is_template'] = isset( $post_values['is_template'] ) ? $post_values['is_template'] : $record->is_template;
309 $values['status'] = $record->status;
310
311 $values = self::fill_default_opts( $values, $record, $post_values );
312
313 return apply_filters( 'frm_setup_edit_form_vars', $values );
314 }
315
316 public static function fill_default_opts( $values, $record, $post_values ) {
317
318 $defaults = self::get_default_opts();
319 foreach ( $defaults as $var => $default ) {
320 if ( is_array( $default ) ) {
321 if ( ! isset( $values[ $var ] ) ) {
322 $values[ $var ] = ( $record && isset( $record->options[ $var ] ) ) ? $record->options[ $var ] : array();
323 }
324
325 foreach ( $default as $k => $v ) {
326 $values[ $var ][ $k ] = ( $post_values && isset( $post_values[ $var ][ $k ] ) ) ? $post_values[ $var ][ $k ] : ( ( $record && isset( $record->options[ $var ] ) && isset( $record->options[ $var ][ $k ] ) ) ? $record->options[ $var ][ $k ] : $v );
327
328 if ( is_array( $v ) ) {
329 foreach ( $v as $k1 => $v1 ) {
330 $values[ $var ][ $k ][ $k1 ] = ( $post_values && isset( $post_values[ $var ][ $k ][ $k1 ] ) ) ? $post_values[ $var ][ $k ][ $k1 ] : ( ( $record && isset( $record->options[ $var ] ) && isset( $record->options[ $var ][ $k ] ) && isset( $record->options[ $var ][ $k ][ $k1 ] ) ) ? $record->options[ $var ][ $k ][ $k1 ] : $v1 );
331 unset( $k1, $v1 );
332 }
333 }
334
335 unset( $k, $v );
336 }
337 } else {
338 $values[ $var ] = ( $post_values && isset( $post_values['options'][ $var ] ) ) ? $post_values['options'][ $var ] : ( ( $record && isset( $record->options[ $var ] ) ) ? $record->options[ $var ] : $default );
339 }
340
341 unset( $var, $default );
342 }
343
344 return $values;
345 }
346
347 public static function get_default_opts() {
348 $frm_settings = FrmAppHelper::get_settings();
349
350 return array(
351 'submit_value' => $frm_settings->submit_value,
352 'success_action' => 'message',
353 'success_msg' => $frm_settings->success_msg,
354 'show_form' => 0,
355 'akismet' => '',
356 'no_save' => 0,
357 'ajax_load' => 0,
358 'js_validate' => 0,
359 'form_class' => '',
360 'custom_style' => 1,
361 'before_html' => self::get_default_html( 'before' ),
362 'after_html' => '',
363 'submit_html' => self::get_default_html( 'submit' ),
364 );
365 }
366
367 /**
368 * @param array $options
369 * @param array $values
370 *
371 * @since 2.0.6
372 */
373 public static function fill_form_options( &$options, $values ) {
374 $defaults = self::get_default_opts();
375 foreach ( $defaults as $var => $default ) {
376 $options[ $var ] = isset( $values['options'][ $var ] ) ? $values['options'][ $var ] : $default;
377 unset( $var, $default );
378 }
379 }
380
381 /**
382 * @param string $loc
383 */
384 public static function get_default_html( $loc ) {
385 if ( $loc == 'submit' ) {
386 $draft_link = self::get_draft_link();
387 $default_html = <<<SUBMIT_HTML
388 <div class="frm_submit">
389 [if back_button]<button type="submit" name="frm_prev_page" formnovalidate="formnovalidate" class="frm_prev_page" [back_hook]>[back_label]</button>[/if back_button]
390 <button class="frm_button_submit" type="submit" [button_action]>[button_label]</button>
391 $draft_link
392 </div>
393 SUBMIT_HTML;
394 } elseif ( $loc == 'before' ) {
395 $default_html = <<<BEFORE_HTML
396 <legend class="frm_screen_reader">[form_name]</legend>
397 [if form_name]<h3 class="frm_form_title">[form_name]</h3>[/if form_name]
398 [if form_description]<div class="frm_description">[form_description]</div>[/if form_description]
399 BEFORE_HTML;
400 } else {
401 $default_html = '';
402 }
403
404 return $default_html;
405 }
406
407 public static function get_draft_link() {
408 $link = '[if save_draft]<a href="#" tabindex="0" class="frm_save_draft" [draft_hook]>[draft_label]</a>[/if save_draft]';
409
410 return $link;
411 }
412
413 public static function get_custom_submit( $html, $form, $submit, $form_action, $values ) {
414 $button = self::replace_shortcodes( $html, $form, $submit, $form_action, $values );
415 if ( ! strpos( $button, '[button_action]' ) ) {
416 echo $button; // WPCS: XSS ok.
417
418 return;
419 }
420
421 $button_parts = explode( '[button_action]', $button );
422
423 $classes = apply_filters( 'frm_submit_button_class', array(), $form );
424 if ( ! empty( $classes ) ) {
425 $classes = implode( ' ', $classes );
426 $button_class = ' class="frm_button_submit';
427 if ( strpos( $button_parts[0], $button_class ) !== false ) {
428 $button_parts[0] = str_replace( $button_class, $button_class . ' ' . esc_attr( $classes ), $button_parts[0] );
429 } else {
430 $button_parts[0] .= ' class="' . esc_attr( $classes ) . '"';
431 }
432 }
433
434 echo $button_parts[0]; // WPCS: XSS ok.
435 do_action( 'frm_submit_button_action', $form, $form_action );
436 echo $button_parts[1]; // WPCS: XSS ok.
437 }
438
439 /**
440 * @since 4.0
441 */
442 public static function html_shortcodes() {
443 $codes = array(
444 'id' => array(
445 'label' => __( 'Field ID', 'formidable' ),
446 'class' => 'show_field_custom_html',
447 ),
448 'key' => array(
449 'label' => __( 'Field Key', 'formidable' ),
450 'class' => 'show_field_custom_html',
451 ),
452 'field_name' => array(
453 'label' => __( 'Field Name', 'formidable' ),
454 'class' => 'show_field_custom_html',
455 ),
456 'description' => array(
457 'label' => __( 'Field Description', 'formidable' ),
458 'class' => 'show_field_custom_html',
459 ),
460 'label_position' => array(
461 'label' => __( 'Label Position', 'formidable' ),
462 'class' => 'show_field_custom_html',
463 ),
464 'required_label' => array(
465 'label' => __( 'Required Label', 'formidable' ),
466 'class' => 'show_field_custom_html',
467 ),
468 'input' => array(
469 'label' => __( 'Input Field', 'formidable' ),
470 'class' => 'show_field_custom_html',
471 ),
472 'input opt=1' => array(
473 'label' => __( 'Single Option', 'formidable' ),
474 'title' => __( 'Show a single radio or checkbox option by replacing 1 with the order of the option', 'formidable' ),
475 'class' => 'show_field_custom_html',
476 ),
477 'input label=0' => array(
478 'label' => __( 'Hide Option Label', 'formidable' ),
479 'class' => 'show_field_custom_html',
480 ),
481 'required_class' => array(
482 'label' => __( 'Required Class', 'formidable' ),
483 'title' => __( 'Add class name if field is required', 'formidable' ),
484 'class' => 'show_field_custom_html',
485 ),
486 'error_class' => array(
487 'label' => __( 'Error Class', 'formidable' ),
488 'title' => __( 'Add class name if field has an error on form submit', 'formidable' ),
489 'class' => 'show_field_custom_html',
490 ),
491
492 'form_name' => array(
493 'label' => __( 'Form Name', 'formidable' ),
494 'class' => 'show_before_html show_after_html',
495 ),
496 'form_description' => array(
497 'label' => __( 'Form Description', 'formidable' ),
498 'class' => 'show_before_html show_after_html',
499 ),
500 'form_key' => array(
501 'label' => __( 'Form Key', 'formidable' ),
502 'class' => 'show_before_html show_after_html',
503 ),
504 'deletelink' => array(
505 'label' => __( 'Delete Entry Link', 'formidable' ),
506 'class' => 'show_before_html show_after_html',
507 ),
508
509 'button_label' => array(
510 'label' => __( 'Button Label', 'formidable' ),
511 'class' => 'show_submit_html',
512 ),
513 'button_action' => array(
514 'label' => __( 'Button Hook', 'formidable' ),
515 'class' => 'show_submit_html',
516 ),
517 );
518
519 /**
520 * @since 4.0
521 */
522 return apply_filters( 'frm_html_codes', $codes );
523 }
524
525 /**
526 * @since 4.0
527 * @param array $args
528 */
529 public static function insert_opt_html( $args ) {
530 $class = isset( $args['class'] ) ? $args['class'] : '';
531 $fields = FrmField::all_field_selection();
532 $field = isset( $fields[ $args['type'] ] ) ? $fields[ $args['type'] ] : array();
533
534 self::prepare_field_type( $field );
535
536 if ( ! isset( $field['icon'] ) ) {
537 $field['icon'] = 'frmfont frm_pencil_icon';
538 }
539
540 $possible_email_field = FrmFieldFactory::field_has_property( $args['type'], 'holds_email_values' );
541 if ( $possible_email_field ) {
542 $class .= ' show_frm_not_email_to';
543 }
544 ?>
545 <li class="<?php echo esc_attr( $class ); ?>">
546 <a href="javascript:void(0)" class="frmids frm_insert_code"
547 data-code="<?php echo esc_attr( $args['id'] ); ?>">
548 <span>[<?php echo esc_attr( isset( $args['id_label'] ) ? $args['id_label'] : $args['id'] ); ?>]</span>
549 <?php FrmAppHelper::icon_by_class( $field['icon'], array( 'aria-hidden' => 'true' ) ); ?>
550 <?php echo esc_attr( FrmAppHelper::truncate( $args['name'], 60 ) ); ?>
551 </a>
552 <a href="javascript:void(0)" class="frmkeys frm_insert_code frm_hidden"
553 data-code="<?php echo esc_attr( $args['key'] ); ?>">
554 <span>[<?php echo esc_attr( FrmAppHelper::truncate( isset( $args['key_label'] ) ? $args['key_label'] : $args['key'], 7 ) ); ?>]</span>
555 <?php if ( isset( $field['icon'] ) ) { ?>
556 <?php FrmAppHelper::icon_by_class( $field['icon'], array( 'aria-hidden' => 'true' ) ); ?>
557 <?php } ?>
558 <?php echo esc_attr( FrmAppHelper::truncate( $args['name'], 60 ) ); ?>
559 </a>
560 </li>
561 <?php
562 }
563
564 /**
565 * @since 4.0
566 * @param array $args
567 */
568 public static function insert_code_html( $args ) {
569 $defaults = array(
570 'class' => '',
571 'code' => '',
572 'label' => '',
573 'title' => '',
574 );
575
576 $args = array_merge( $defaults, $args );
577 $has_tooltip = ! empty( $args['title'] );
578
579 ?>
580 <li class="<?php echo esc_attr( $args['class'] ); ?>">
581 <a href="javascript:void(0)" class="frm_insert_code <?php echo $has_tooltip ? 'frm_help' : ''; ?>"
582 <?php echo $has_tooltip ? 'title="' . esc_attr( $args['title'] ) . '"' : ''; ?>
583 data-code="<?php echo esc_attr( $args['code'] ); ?>">
584 <span>
585 [<?php echo esc_attr( FrmAppHelper::truncate( $args['code'], 10 ) ); ?>]
586 </span>
587 <?php echo esc_attr( FrmAppHelper::truncate( $args['label'], 60 ) ); ?>
588 </a>
589 </li>
590 <?php
591 }
592
593 /**
594 * Some field types in add-ons may have been added with only
595 * a field type and name.
596 *
597 * @since 4.0
598 */
599 public static function prepare_field_type( &$field ) {
600 if ( ! is_array( $field ) ) {
601 $field = array(
602 'name' => $field,
603 'icon' => 'frm_icon_font frm_pencil_icon',
604 );
605 }
606 }
607
608 /**
609 * Automatically add end section fields if they don't exist (2.0 migration)
610 *
611 * @since 2.0
612 *
613 * @param boolean $reset_fields
614 */
615 public static function auto_add_end_section_fields( $form, $fields, &$reset_fields ) {
616 if ( empty( $fields ) ) {
617 return;
618 }
619
620 $end_section_values = apply_filters( 'frm_before_field_created', FrmFieldsHelper::setup_new_vars( 'end_divider', $form->id ) );
621 $open = false;
622 $prev_order = false;
623 $add_order = 0;
624 $last_field = false;
625 foreach ( $fields as $field ) {
626 if ( $prev_order === $field->field_order ) {
627 $add_order ++;
628 }
629
630 if ( $add_order ) {
631 $reset_fields = true;
632 $field->field_order = $field->field_order + $add_order;
633 FrmField::update( $field->id, array( 'field_order' => $field->field_order ) );
634 }
635
636 switch ( $field->type ) {
637 case 'divider':
638 // Create an end section if open.
639 self::maybe_create_end_section( $open, $reset_fields, $add_order, $end_section_values, $field, 'move' );
640
641 // Mark it open for the next end section.
642 $open = true;
643 break;
644 case 'break':
645 self::maybe_create_end_section( $open, $reset_fields, $add_order, $end_section_values, $field, 'move' );
646 break;
647 case 'end_divider':
648 if ( ! $open ) {
649 // The section isn't open, so this is an extra field that needs to be removed.
650 FrmField::destroy( $field->id );
651 $reset_fields = true;
652 }
653
654 // There is already an end section here, so there is no need to create one.
655 $open = false;
656 }
657 $prev_order = $field->field_order;
658
659 $last_field = $field;
660 unset( $field );
661 }
662
663 self::maybe_create_end_section( $open, $reset_fields, $add_order, $end_section_values, $last_field );
664 }
665
666 /**
667 * Create end section field if it doesn't exist. This is for migration from < 2.0
668 * Fix any ordering that may be messed up
669 */
670 public static function maybe_create_end_section( &$open, &$reset_fields, &$add_order, $end_section_values, $field, $move = 'no' ) {
671 if ( ! $open ) {
672 return;
673 }
674
675 $end_section_values['field_order'] = $field->field_order + 1;
676
677 FrmField::create( $end_section_values );
678
679 if ( $move == 'move' ) {
680 // bump the order of current field unless we're at the end of the form
681 FrmField::update( $field->id, array( 'field_order' => $field->field_order + 2 ) );
682 }
683
684 $add_order += 2;
685 $open = false;
686 $reset_fields = true;
687 }
688
689 public static function replace_shortcodes( $html, $form, $title = false, $description = false, $values = array() ) {
690 $codes = array(
691 'form_name' => $title,
692 'form_description' => $description,
693 'entry_key' => true,
694 );
695 foreach ( $codes as $code => $show ) {
696 if ( $code == 'form_name' ) {
697 $replace_with = $form->name;
698 } elseif ( $code == 'form_description' ) {
699 $replace_with = FrmAppHelper::use_wpautop( $form->description );
700 } elseif ( $code == 'entry_key' && isset( $_GET ) && isset( $_GET['entry'] ) ) {
701 $replace_with = FrmAppHelper::simple_get( 'entry' );
702 } else {
703 $replace_with = '';
704 }
705
706 FrmShortcodeHelper::remove_inline_conditions( ( FrmAppHelper::is_true( $show ) && $replace_with != '' ), $code, $replace_with, $html );
707 }
708
709 //replace [form_key]
710 $html = str_replace( '[form_key]', $form->form_key, $html );
711
712 //replace [frmurl]
713 $html = str_replace( '[frmurl]', FrmFieldsHelper::dynamic_default_values( 'frmurl' ), $html );
714
715 if ( strpos( $html, '[button_label]' ) ) {
716 add_filter( 'frm_submit_button', 'FrmFormsHelper::submit_button_label', 1 );
717 $submit_label = apply_filters( 'frm_submit_button', $title, $form );
718 $submit_label = esc_attr( do_shortcode( $submit_label ) );
719 $html = str_replace( '[button_label]', $submit_label, $html );
720 }
721
722 $html = apply_filters( 'frm_form_replace_shortcodes', $html, $form, $values );
723
724 if ( strpos( $html, '[if back_button]' ) ) {
725 $html = preg_replace( '/(\[if\s+back_button\])(.*?)(\[\/if\s+back_button\])/mis', '', $html );
726 }
727
728 if ( strpos( $html, '[if save_draft]' ) ) {
729 $html = preg_replace( '/(\[if\s+save_draft\])(.*?)(\[\/if\s+save_draft\])/mis', '', $html );
730 }
731
732 if ( apply_filters( 'frm_do_html_shortcodes', true ) ) {
733 $html = do_shortcode( $html );
734 }
735
736 return $html;
737 }
738
739 public static function submit_button_label( $submit ) {
740 if ( ! $submit || empty( $submit ) ) {
741 $frm_settings = FrmAppHelper::get_settings();
742 $submit = $frm_settings->submit_value;
743 }
744
745 return $submit;
746 }
747
748 /**
749 * If the Formidable styling isn't being loaded,
750 * use inline styling to hide the element
751 *
752 * @since 2.03.05
753 */
754 public static function maybe_hide_inline() {
755 $frm_settings = FrmAppHelper::get_settings();
756 if ( $frm_settings->load_style == 'none' ) {
757 echo ' style="display:none;"';
758 } elseif ( $frm_settings->load_style == 'dynamic' ) {
759 FrmStylesController::enqueue_style();
760 }
761 }
762
763 public static function get_form_style_class( $form = false ) {
764 $style = self::get_form_style( $form );
765 $class = ' with_frm_style';
766
767 if ( empty( $style ) ) {
768 if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) ) {
769 return $class;
770 } else {
771 return;
772 }
773 }
774
775 // If submit button needs to be inline or centered.
776 if ( is_object( $form ) ) {
777 $form = $form->options;
778 }
779
780 $submit_align = isset( $form['submit_align'] ) ? $form['submit_align'] : '';
781
782 if ( 'inline' === $submit_align ) {
783 $class .= ' frm_inline_form';
784 $class .= self::maybe_align_fields_top( $form );
785 } elseif ( 'center' === $submit_align ) {
786 $class .= ' frm_center_submit';
787 }
788
789 $class = apply_filters( 'frm_add_form_style_class', $class, $style );
790
791 return $class;
792 }
793
794 /**
795 * Returns appropriate class if form has top labels
796 *
797 * @param $form
798 *
799 * @return string
800 */
801 private static function maybe_align_fields_top( $form ) {
802 return self::form_has_top_labels( $form ) ? ' frm_inline_top' : '';
803 }
804
805 /**
806 * Determine if a form has fields with top labels so submit button can be aligned properly
807 *
808 * @param $form
809 *
810 * @return bool
811 */
812 private static function form_has_top_labels( $form ) {
813 if ( ! isset( $form['fields'] ) ) {
814 return false;
815 }
816
817 $fields = $form['fields'];
818 if ( count( $fields ) <= 0 ) {
819 return false;
820 }
821
822 $fields = array_reverse( $fields ); // start from the fields closest to the submit button
823 foreach ( $fields as $field ) {
824 $type = isset( $field['original_type'] ) ? $field['original_type'] : $field['type'];
825 $has_input = FrmFieldFactory::field_has_property( $type, 'has_input' );
826 if ( $has_input ) {
827 return self::field_has_top_label( $field, $form );
828 }
829 }
830
831 return false;
832 }
833
834 /**
835 * Check if a field's label position is set to "top"
836 *
837 * @param $field
838 * @param $form
839 *
840 * @return bool
841 */
842 private static function field_has_top_label( $field, $form ) {
843 $label_position = FrmFieldsHelper::label_position( $field['label'], $field, $form );
844
845 return in_array( $label_position, array( 'top', 'inside', 'hidden' ) );
846 }
847
848 /**
849 * @param object|string|boolean $form
850 *
851 * @return string
852 */
853 public static function get_form_style( $form ) {
854 $style = 1;
855 if ( empty( $form ) || 'default' == 'form' ) {
856 return $style;
857 } elseif ( is_object( $form ) && $form->parent_form_id ) {
858 // get the parent form if this is a child
859 $form = $form->parent_form_id;
860 } elseif ( is_array( $form ) && isset( $form['parent_form_id'] ) && $form['parent_form_id'] ) {
861 $form = $form['parent_form_id'];
862 } elseif ( is_array( $form ) && isset( $form['custom_style'] ) ) {
863 $style = $form['custom_style'];
864 }
865
866 if ( $form && is_string( $form ) ) {
867 $form = FrmForm::getOne( $form );
868 }
869
870 $style = ( $form && is_object( $form ) && isset( $form->options['custom_style'] ) ) ? $form->options['custom_style'] : $style;
871
872 return $style;
873 }
874
875 /**
876 * Display the validation error messages when an entry is submitted
877 *
878 * @param array $args - includes img, errors
879 *
880 * @since 2.0.6
881 */
882 public static function show_errors( $args ) {
883 $invalid_msg = self::get_invalid_error_message( $args );
884
885 if ( empty( $invalid_msg ) ) {
886 $show_img = false;
887 } else {
888 echo wp_kses_post( $invalid_msg );
889 $show_img = true;
890 }
891
892 self::show_error(
893 array(
894 'img' => $args['img'],
895 'errors' => $args['errors'],
896 'show_img' => $show_img,
897 )
898 );
899 }
900
901 /**
902 * Display the error message in the front-end along with the image if set
903 * The image was removed from the styling settings, but it may still be set with a hook
904 * If the message in the global settings is empty, show every validation message in the error box
905 *
906 * @param array $args - includes img, errors, and show_img
907 *
908 * @since 2.0.6
909 */
910 public static function show_error( $args ) {
911 // remove any blank messages
912 $args['errors'] = array_filter( (array) $args['errors'] );
913
914 $line_break_first = $args['show_img'];
915 foreach ( $args['errors'] as $error_key => $error ) {
916 if ( $line_break_first && ! is_numeric( $error_key ) && ( $error_key == 'cptch_number' || strpos( $error_key, 'field' ) === 0 ) ) {
917 continue;
918 }
919
920 $id = str_replace( 'field', 'field_', $error_key );
921 echo '<div id="' . esc_attr( $id ) . '_error">';
922
923 if ( $args['show_img'] && ! empty( $args['img'] ) ) {
924 echo '<img src="' . esc_attr( $args['img'] ) . '" alt="" />';
925 } else {
926 $args['show_img'] = true;
927 }
928
929 echo wp_kses_post( $error );
930
931 echo '</div>';
932 }
933 }
934
935 public static function maybe_get_scroll_js( $id ) {
936 $offset = apply_filters( 'frm_scroll_offset', 4, array( 'form_id' => $id ) );
937 if ( $offset != - 1 ) {
938 self::get_scroll_js( $id );
939 }
940 }
941
942 public static function get_scroll_js( $form_id ) {
943 echo '<script type="text/javascript">document.addEventListener(\'DOMContentLoaded\',function(){frmFrontForm.scrollMsg(' . (int) $form_id . ');})</script>';
944 }
945
946 /**
947 * @since 3.0
948 */
949 public static function actions_dropdown( $atts ) {
950 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
951 $status = $atts['status'];
952 $form_id = isset( $atts['id'] ) ? $atts['id'] : FrmAppHelper::get_param( 'id', 0, 'get', 'absint' );
953 $trash_link = self::delete_trash_info( $form_id, $status );
954 $links = self::get_action_links( $form_id, $status );
955 include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/actions-dropdown.php' );
956 }
957 }
958
959 /**
960 * @since 3.0
961 */
962 public static function get_action_links( $form_id, $form ) {
963 if ( ! is_object( $form ) ) {
964 $form = FrmForm::getOne( $form_id );
965 }
966
967 $actions = array();
968 $trash_links = self::delete_trash_links( $form_id );
969 if ( 'trash' == $form->status ) {
970 $actions['restore'] = $trash_links['restore'];
971
972 if ( current_user_can( 'frm_delete_forms' ) ) {
973 $actions['trash'] = $trash_links['delete'];
974 }
975 } elseif ( current_user_can( 'frm_edit_forms' ) ) {
976 $duplicate_link = '?page=formidable&frm_action=duplicate&id=' . $form_id;
977 if ( $form->is_template ) {
978 $actions['frm_duplicate'] = array(
979 'url' => wp_nonce_url( $duplicate_link ),
980 'label' => __( 'Create Form from Template', 'formidable' ),
981 'icon' => 'frm_icon_font frm_clone_icon',
982 );
983 } else {
984 $actions['duplicate'] = array(
985 'url' => wp_nonce_url( $duplicate_link ),
986 'label' => __( 'Duplicate Form', 'formidable' ),
987 'icon' => 'frm_icon_font frm_clone_icon',
988 );
989 }
990
991 $actions['trash'] = self::delete_trash_info( $form_id, $form->status );
992 }
993
994 return $actions;
995 }
996
997 public static function edit_form_link( $form_id ) {
998 if ( is_object( $form_id ) ) {
999 $form = $form_id;
1000 $name = $form->name;
1001 $form_id = $form->id;
1002 } else {
1003 $name = FrmForm::getName( $form_id );
1004 }
1005
1006 if ( $form_id ) {
1007 $val = '<a href="' . esc_url( FrmForm::get_edit_link( $form_id ) ) . '">' . ( '' == $name ? __( '(no title)', 'formidable' ) : FrmAppHelper::truncate( $name, 40 ) ) . '</a>';
1008 } else {
1009 $val = '';
1010 }
1011
1012 return $val;
1013 }
1014
1015 public static function delete_trash_link( $id, $status, $length = 'label' ) {
1016 $link_details = self::delete_trash_info( $id, $status );
1017
1018 return self::format_link_html( $link_details, $length );
1019 }
1020
1021 /**
1022 * @since 3.0
1023 */
1024 public static function format_link_html( $link_details, $length = 'label' ) {
1025 $link = '';
1026 if ( ! empty( $link_details ) ) {
1027 $link = '<a href="' . esc_url( $link_details['url'] ) . '" class="frm-trash-link"';
1028 if ( isset( $link_details['data'] ) ) {
1029 foreach ( $link_details['data'] as $data => $value ) {
1030 $link .= ' data-' . esc_attr( $data ) . '="' . esc_attr( $value ) . '"';
1031 }
1032 } elseif ( isset( $link_details['confirm'] ) ) {
1033 $link .= ' onclick="return confirm(\'' . esc_attr( $link_details['confirm'] ) . '\')"';
1034 }
1035
1036 $label = ( isset( $link_details[ $length ] ) ? $link_details[ $length ] : $link_details['label'] );
1037 if ( $length == 'icon' && isset( $link_details[ $length ] ) ) {
1038 $label = '<span class="' . $label . '" title="' . esc_attr( $link_details['label'] ) . '" aria-hidden="true"></span>';
1039 $link .= ' aria-label="' . esc_attr( $link_details['label'] ) . '"';
1040 }
1041
1042 $link .= '>' . $label . '</a>';
1043 }
1044
1045 return $link;
1046 }
1047
1048 /**
1049 * @since 3.0
1050 */
1051 public static function delete_trash_info( $id, $status ) {
1052 $labels = self::delete_trash_links( $id );
1053
1054 if ( 'trash' == $status ) {
1055 $info = $labels['restore'];
1056 } elseif ( current_user_can( 'frm_delete_forms' ) ) {
1057 if ( EMPTY_TRASH_DAYS ) {
1058 $info = $labels['trash'];
1059 } else {
1060 $info = $labels['delete'];
1061 }
1062 } else {
1063 $info = array();
1064 }
1065
1066 return $info;
1067 }
1068
1069 /**
1070 * @since 3.0
1071 */
1072 private static function delete_trash_links( $id ) {
1073 $current_page = FrmAppHelper::get_simple_request( array( 'param' => 'form_type' ) );
1074 $base_url = '?page=formidable&form_type=' . $current_page . '&id=' . $id;
1075
1076 return array(
1077 'restore' => array(
1078 'label' => __( 'Restore from Trash', 'formidable' ),
1079 'short' => __( 'Restore', 'formidable' ),
1080 'url' => wp_nonce_url( $base_url . '&frm_action=untrash', 'untrash_form_' . absint( $id ) ),
1081 ),
1082 'trash' => array(
1083 'label' => __( 'Move Form to Trash', 'formidable' ),
1084 'short' => __( 'Trash', 'formidable' ),
1085 'url' => wp_nonce_url( $base_url . '&frm_action=trash', 'trash_form_' . absint( $id ) ),
1086 'icon' => 'frm_icon_font frm_delete_icon',
1087 'data' => array( 'frmverify' => __( 'Do you want to move this form to the trash?', 'formidable' ) ),
1088 ),
1089 'delete' => array(
1090 'label' => __( 'Delete Permanently', 'formidable' ),
1091 'short' => __( 'Delete', 'formidable' ),
1092 'url' => wp_nonce_url( $base_url . '&frm_action=destroy', 'destroy_form_' . absint( $id ) ),
1093 'confirm' => __( 'Are you sure you want to delete this form and all its entries?', 'formidable' ),
1094 'icon' => 'frm_icon_font frm_delete_icon',
1095 'data' => array( 'frmverify' => __( 'This will permanently delete the form and all its entries. This is irreversible. Are you sure you want to continue?', 'formidable' ) ),
1096 ),
1097 );
1098 }
1099
1100 /**
1101 * @since 3.0
1102 */
1103 public static function css_classes() {
1104 $classes = array(
1105 'frm_total' => array(
1106 'label' => __( 'Total', 'formidable' ),
1107 'title' => __( 'Add this to a read-only field to display the text in bold without a border or background.', 'formidable' ),
1108 ),
1109 'frm_scroll_box' => array(
1110 'label' => __( 'Scroll Box', 'formidable' ),
1111 'title' => __( 'If you have many checkbox or radio button options, you may add this class to allow your user to easily scroll through the options. Or add a scrolling area around content in an HTML field.', 'formidable' ),
1112 ),
1113 'frm_first' => array(
1114 'label' => __( 'First', 'formidable' ),
1115 'title' => __( 'Add this to the first field in each row along with a width. ie frm_first frm4', 'formidable' ),
1116 ),
1117 'frm_alignright' => __( 'Right', 'formidable' ),
1118 'frm_grid_first' => __( 'First Grid Row', 'formidable' ),
1119 'frm_grid' => __( 'Even Grid Row', 'formidable' ),
1120 'frm_grid_odd' => __( 'Odd Grid Row', 'formidable' ),
1121 'frm_capitalize' => array(
1122 'label' => __( 'Capitalize', 'formidable' ),
1123 'title' => __( 'Automatically capitalize the first letter in each word.', 'formidable' ),
1124 ),
1125 );
1126
1127 return apply_filters( 'frm_layout_classes', $classes );
1128 }
1129
1130 public static function grid_classes() {
1131 $base = array(
1132 'frm_half' => '1/2',
1133
1134 'frm_third' => '1/3',
1135 'frm_two_thirds' => '2/3',
1136
1137 'frm_fourth' => '1/4',
1138 'frm_three_fourths' => '3/4',
1139 );
1140
1141 $frm_settings = FrmAppHelper::get_settings();
1142 if ( $frm_settings->old_css ) {
1143 $classes = array(
1144 'frm_sixth' => '1/6',
1145 'frm10' => '5/6',
1146
1147 'frm_full' => '100%',
1148 );
1149 } else {
1150 $classes = array(
1151 'frm_sixth' => '1/6',
1152 'frm10' => '5/6',
1153 'frm12' => '100%',
1154 );
1155 }
1156
1157 return array_merge( $base, $classes );
1158 }
1159
1160 /**
1161 * @since 3.0
1162 */
1163 public static function style_class_label( $style, $class ) {
1164 $label = '';
1165 if ( empty( $style ) ) {
1166 $label = $class;
1167 } elseif ( ! is_array( $style ) ) {
1168 $label = $style;
1169 } elseif ( isset( $style['label'] ) ) {
1170 $label = $style['label'];
1171 }
1172
1173 return $label;
1174 }
1175
1176 public static function status_nice_name( $status ) {
1177 $nice_names = array(
1178 'draft' => __( 'Draft', 'formidable' ),
1179 'trash' => __( 'Trash', 'formidable' ),
1180 'publish' => __( 'Published', 'formidable' ),
1181 );
1182
1183 if ( ! in_array( $status, array_keys( $nice_names ) ) ) {
1184 $status = 'publish';
1185 }
1186
1187 $name = $nice_names[ $status ];
1188
1189 return $name;
1190 }
1191
1192 /**
1193 * If a template or add-on cannot be installed, show a message
1194 * about which plan is required.
1195 *
1196 * @since 4.0
1197 */
1198 public static function show_plan_required( $requires, $link ) {
1199 if ( empty( $requires ) ) {
1200 return;
1201 }
1202
1203 ?>
1204 <p>
1205 <?php esc_html_e( 'License plan required:', 'formidable' ); ?>
1206 <a href="<?php echo esc_url( $link ); ?>" target="_blank" rel="noopener">
1207 <?php echo esc_html( $requires ); ?>
1208 </a>
1209 </p>
1210 <?php
1211 }
1212
1213 /**
1214 * @since 4.0
1215 */
1216 public static function get_plan_required( &$item ) {
1217 if ( ! isset( $item['categories'] ) || ( isset( $item['url'] ) && ! empty( $item['url'] ) ) ) {
1218 return false;
1219 }
1220
1221 $plans = array( 'free', 'Personal', 'Business', 'Elite' );
1222
1223 foreach ( $item['categories'] as $k => $category ) {
1224 if ( in_array( $category, $plans ) ) {
1225 unset( $item['categories'][ $k ] );
1226 return $category;
1227 }
1228 }
1229
1230 return false;
1231 }
1232 }
1233