Completed
Push — master ( eb5e35...a86bd1 )
by Stephanie
24s queued 11s
created

FrmFormsHelper::reserved_words()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 46
rs 9.1781
c 0
b 0
f 0
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
		if ( count( $forms ) < 2 ) {
116
			?>
117
			<div id="frm_bs_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
				</h1>
123
			</div>
124
			<?php
125
			return;
126
		}
127
		?>
128
		<div id="frm_bs_dropdown" class="dropdown <?php echo esc_attr( is_rtl() ? 'pull-right' : 'pull-left' ); ?>">
129
			<a href="#" id="frm-navbarDrop" class="frm-dropdown-toggle" data-toggle="dropdown">
130
				<h1>
131
					<span class="frm_bstooltip" title="<?php echo esc_attr( $truncated_name === $name ? '' : $name ); ?>" data-placement="right">
132
						<?php echo esc_html( $name ); ?>
133
					</span>
134
					<?php FrmAppHelper::icon_by_class( 'frmfont frm_arrowdown4_icon', array( 'aria-hidden' => 'true' ) ); ?>
135
				</h1>
136
			</a>
137
			<ul class="frm-dropdown-menu frm-on-top frm-inline-modal frm_code_list frm-full-hover" role="menu" aria-labelledby="frm-navbarDrop">
138 View Code Duplication
				<?php if ( count( $forms ) > 8 ) { ?>
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
139
				<li class="frm-with-search">
140
					<?php
141
					FrmAppHelper::show_search_box(
142
						array(
143
							'input_id'    => 'dropform',
144
							'placeholder' => __( 'Search Forms', 'formidable' ),
145
							'tosearch'    => 'frm-dropdown-form',
146
						)
147
					);
148
					?>
149
				</li>
150
				<?php } ?>
151
				<?php
152
				foreach ( $forms as $form ) {
153
					if ( $form->id === $form_id ) {
154
						// Don't include the selected form in the switcher since it does nothing.
155
						continue;
156
					}
157
158
					if ( isset( $args['id'] ) ) {
159
						$args['id'] = $form->id;
160
					}
161
					if ( isset( $args['form'] ) ) {
162
						$args['form'] = $form->id;
163
					}
164
165
					$url       = isset( $base ) ? add_query_arg( $args, $base ) : add_query_arg( $args );
166
					$form_name = empty( $form->name ) ? __( '(no title)', 'formidable' ) : $form->name;
167
					?>
168
					<li class="frm-dropdown-form">
169
						<a href="<?php echo esc_url( $url ); ?>" tabindex="-1">
170
							<span class="frm-sub-label">
171
							<?php
172
							printf(
173
								/* translators: %d: Form ID */
174
								esc_html__( '(ID %d)', 'formidable' ),
175
								esc_attr( $form->id )
176
							);
177
							?>
178
							</span>
179
							<?php echo esc_html( $form_name ); ?>
180
							<span class="frm_hidden"><?php echo esc_html( $form->form_key ); ?></span>
181
						</a>
182
					</li>
183
					<?php
184
					unset( $form );
185
				}
186
				?>
187
			</ul>
188
		</div>
189
		<?php
190
	}
191
192
	/**
193
	 * @since 3.05
194
	 * @deprecated 4.0
195
	 *
196
	 * @param array $values - The form array
197
	 */
198
	public static function builder_submit_button( $values ) {
199
		FrmDeprecated::builder_submit_button( $values );
200
	}
201
202
	public static function get_sortable_classes( $col, $sort_col, $sort_dir ) {
203
		echo ( $sort_col == $col ) ? 'sorted' : 'sortable';
204
		echo ( $sort_col == $col && $sort_dir == 'desc' ) ? ' asc' : ' desc';
205
	}
206
207
	/**
208
	 * @since 3.0
209
	 */
210
	public static function get_field_link_name( $field_type ) {
211
		if ( is_array( $field_type ) ) {
212
			$field_label = $field_type['name'];
213
		} else {
214
			$field_label = $field_type;
215
		}
216
217
		return $field_label;
218
	}
219
220
	/**
221
	 * @since 3.0
222
	 */
223
	public static function get_field_link_icon( $field_type ) {
224
		if ( is_array( $field_type ) && isset( $field_type['icon'] ) ) {
225
			$icon = $field_type['icon'];
226
		} else {
227
			$icon = 'frm_icon_font frm_pencil_icon';
228
		}
229
230
		return $icon;
231
	}
232
233
	/**
234
	 * Get the invalid form error message
235
	 *
236
	 * @since 2.02.07
237
	 *
238
	 * @param array $args
239
	 *
240
	 * @return string
241
	 */
242
	public static function get_invalid_error_message( $args ) {
243
		$settings_args = $args;
244
		if ( isset( $args['form'] ) ) {
245
			$settings_args['current_form'] = $args['form']->id;
246
		}
247
248
		$frm_settings = FrmAppHelper::get_settings( $settings_args );
249
		$invalid_msg = do_shortcode( $frm_settings->invalid_msg );
250
		return apply_filters( 'frm_invalid_error_message', $invalid_msg, $args );
251
	}
252
253
	public static function get_success_message( $atts ) {
254
		$message = apply_filters( 'frm_content', $atts['message'], $atts['form'], $atts['entry_id'] );
255
		$message = FrmAppHelper::use_wpautop( do_shortcode( $message ) );
256
		$message = '<div class="' . esc_attr( $atts['class'] ) . '">' . $message . '</div>';
257
258
		return $message;
259
	}
260
261
	/**
262
	 * Used when a form is created
263
	 */
264
	public static function setup_new_vars( $values = array() ) {
265
		global $wpdb;
266
267
		if ( ! empty( $values ) ) {
268
			$post_values = $values;
269
		} else {
270
			$values      = array();
271
			$post_values = isset( $_POST ) ? $_POST : array();
272
		}
273
274
		$defaults = array(
275
			'name'        => '',
276
			'description' => '',
277
		);
278 View Code Duplication
		foreach ( $defaults as $var => $default ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
			if ( ! isset( $values[ $var ] ) ) {
280
				$values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
281
			}
282
		}
283
284
		$values['description'] = FrmAppHelper::use_wpautop( $values['description'] );
285
286
		$defaults = array(
287
			'form_id'        => '',
288
			'logged_in'      => '',
289
			'editable'       => '',
290
			'is_template'    => 0,
291
			'status'         => 'published',
292
			'parent_form_id' => 0,
293
		);
294 View Code Duplication
		foreach ( $defaults as $var => $default ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
			if ( ! isset( $values[ $var ] ) ) {
296
				$values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
297
			}
298
		}
299
		unset( $defaults );
300
301
		if ( ! isset( $values['form_key'] ) ) {
302
			$values['form_key'] = ( $post_values && isset( $post_values['form_key'] ) ) ? $post_values['form_key'] : FrmAppHelper::get_unique_key( '', $wpdb->prefix . 'frm_forms', 'form_key' );
303
		}
304
305
		$values                 = self::fill_default_opts( $values, false, $post_values );
306
		$values['custom_style'] = FrmAppHelper::custom_style_value( $post_values );
307
308
		return apply_filters( 'frm_setup_new_form_vars', $values );
309
	}
310
311
	/**
312
	 * Used when editing a form
313
	 */
314
	public static function setup_edit_vars( $values, $record, $post_values = array() ) {
315
		if ( empty( $post_values ) ) {
316
			$post_values = wp_unslash( $_POST );
317
		}
318
319
		$values['form_key']    = isset( $post_values['form_key'] ) ? $post_values['form_key'] : $record->form_key;
320
		$values['is_template'] = isset( $post_values['is_template'] ) ? $post_values['is_template'] : $record->is_template;
321
		$values['status']      = $record->status;
322
323
		$values = self::fill_default_opts( $values, $record, $post_values );
324
325
		return apply_filters( 'frm_setup_edit_form_vars', $values );
326
	}
327
328
	public static function fill_default_opts( $values, $record, $post_values ) {
329
330
		$defaults = self::get_default_opts();
331
		foreach ( $defaults as $var => $default ) {
332
			if ( is_array( $default ) ) {
333
				if ( ! isset( $values[ $var ] ) ) {
334
					$values[ $var ] = ( $record && isset( $record->options[ $var ] ) ) ? $record->options[ $var ] : array();
335
				}
336
337
				foreach ( $default as $k => $v ) {
338
					$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 );
339
340
					if ( is_array( $v ) ) {
341
						foreach ( $v as $k1 => $v1 ) {
342
							$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 );
343
							unset( $k1, $v1 );
344
						}
345
					}
346
347
					unset( $k, $v );
348
				}
349
			} else {
350
				$values[ $var ] = ( $post_values && isset( $post_values['options'][ $var ] ) ) ? $post_values['options'][ $var ] : ( ( $record && isset( $record->options[ $var ] ) ) ? $record->options[ $var ] : $default );
351
			}
352
353
			unset( $var, $default );
354
		}
355
356
		return $values;
357
	}
358
359
	public static function get_default_opts() {
360
		$frm_settings = FrmAppHelper::get_settings();
361
362
		return array(
363
			'submit_value'   => $frm_settings->submit_value,
364
			'success_action' => 'message',
365
			'success_msg'    => $frm_settings->success_msg,
366
			'show_form'      => 0,
367
			'akismet'        => '',
368
			'no_save'        => 0,
369
			'ajax_load'      => 0,
370
			'js_validate'    => 0,
371
			'form_class'     => '',
372
			'custom_style'   => 1,
373
			'before_html'    => self::get_default_html( 'before' ),
374
			'after_html'     => '',
375
			'submit_html'    => self::get_default_html( 'submit' ),
376
		);
377
	}
378
379
	/**
380
	 * @param array $options
381
	 * @param array $values
382
	 *
383
	 * @since 2.0.6
384
	 */
385
	public static function fill_form_options( &$options, $values ) {
386
		$defaults = self::get_default_opts();
387
		foreach ( $defaults as $var => $default ) {
388
			$options[ $var ] = isset( $values['options'][ $var ] ) ? $values['options'][ $var ] : $default;
389
			unset( $var, $default );
390
		}
391
	}
392
393
	/**
394
	 * @param string $loc
395
	 */
396
	public static function get_default_html( $loc ) {
397
		if ( $loc == 'submit' ) {
398
			$draft_link   = self::get_draft_link();
399
			$default_html = <<<SUBMIT_HTML
400
<div class="frm_submit">
401
[if back_button]<button type="submit" name="frm_prev_page" formnovalidate="formnovalidate" class="frm_prev_page" [back_hook]>[back_label]</button>[/if back_button]
402
<button class="frm_button_submit" type="submit"  [button_action]>[button_label]</button>
403
$draft_link
404
</div>
405
SUBMIT_HTML;
406
		} elseif ( $loc == 'before' ) {
407
			$default_html = <<<BEFORE_HTML
408
<legend class="frm_screen_reader">[form_name]</legend>
409
[if form_name]<h3 class="frm_form_title">[form_name]</h3>[/if form_name]
410
[if form_description]<div class="frm_description">[form_description]</div>[/if form_description]
411
BEFORE_HTML;
412
		} else {
413
			$default_html = '';
414
		}
415
416
		return $default_html;
417
	}
418
419
	public static function get_draft_link() {
420
		$link = '[if save_draft]<a href="#" tabindex="0" class="frm_save_draft" [draft_hook]>[draft_label]</a>[/if save_draft]';
421
422
		return $link;
423
	}
424
425
	public static function get_custom_submit( $html, $form, $submit, $form_action, $values ) {
426
		$button = self::replace_shortcodes( $html, $form, $submit, $form_action, $values );
427
		if ( ! strpos( $button, '[button_action]' ) ) {
428
			echo $button; // WPCS: XSS ok.
429
430
			return;
431
		}
432
433
		$button_parts = explode( '[button_action]', $button );
434
435
		$classes = apply_filters( 'frm_submit_button_class', array(), $form );
436
		if ( ! empty( $classes ) ) {
437
			$classes      = implode( ' ', $classes );
438
			$button_class = ' class="frm_button_submit';
439
			if ( strpos( $button_parts[0], $button_class ) !== false ) {
440
				$button_parts[0] = str_replace( $button_class, $button_class . ' ' . esc_attr( $classes ), $button_parts[0] );
441
			} else {
442
				$button_parts[0] .= ' class="' . esc_attr( $classes ) . '"';
443
			}
444
		}
445
446
		echo $button_parts[0]; // WPCS: XSS ok.
447
		do_action( 'frm_submit_button_action', $form, $form_action );
448
		echo $button_parts[1]; // WPCS: XSS ok.
449
	}
450
451
	/**
452
	 * @since 4.0
453
	 */
454
	public static function html_shortcodes() {
455
		$codes = array(
456
			'id'             => array(
457
				'label' => __( 'Field ID', 'formidable' ),
458
				'class' => 'show_field_custom_html',
459
			),
460
			'key'            => array(
461
				'label' => __( 'Field Key', 'formidable' ),
462
				'class' => 'show_field_custom_html',
463
			),
464
			'field_name'     => array(
465
				'label' => __( 'Field Name', 'formidable' ),
466
				'class' => 'show_field_custom_html',
467
			),
468
			'description'    => array(
469
				'label' => __( 'Field Description', 'formidable' ),
470
				'class' => 'show_field_custom_html',
471
			),
472
			'label_position' => array(
473
				'label' => __( 'Label Position', 'formidable' ),
474
				'class' => 'show_field_custom_html',
475
			),
476
			'required_label' => array(
477
				'label' => __( 'Required Label', 'formidable' ),
478
				'class' => 'show_field_custom_html',
479
			),
480
			'input'          => array(
481
				'label' => __( 'Input Field', 'formidable' ),
482
				'class' => 'show_field_custom_html',
483
			),
484
			'input opt=1'    => array(
485
				'label' => __( 'Single Option', 'formidable' ),
486
				'title' => __( 'Show a single radio or checkbox option by replacing 1 with the order of the option', 'formidable' ),
487
				'class' => 'show_field_custom_html',
488
			),
489
			'input label=0'  => array(
490
				'label' => __( 'Hide Option Label', 'formidable' ),
491
				'class' => 'show_field_custom_html',
492
			),
493
			'required_class' => array(
494
				'label' => __( 'Required Class', 'formidable' ),
495
				'title' => __( 'Add class name if field is required', 'formidable' ),
496
				'class' => 'show_field_custom_html',
497
			),
498
			'error_class'    => array(
499
				'label' => __( 'Error Class', 'formidable' ),
500
				'title' => __( 'Add class name if field has an error on form submit', 'formidable' ),
501
				'class' => 'show_field_custom_html',
502
			),
503
504
			'form_name'        => array(
505
				'label' => __( 'Form Name', 'formidable' ),
506
				'class' => 'show_before_html show_after_html',
507
			),
508
			'form_description' => array(
509
				'label' => __( 'Form Description', 'formidable' ),
510
				'class' => 'show_before_html show_after_html',
511
			),
512
			'form_key'         => array(
513
				'label' => __( 'Form Key', 'formidable' ),
514
				'class' => 'show_before_html show_after_html',
515
			),
516
			'deletelink'       => array(
517
				'label' => __( 'Delete Entry Link', 'formidable' ),
518
				'class' => 'show_before_html show_after_html',
519
			),
520
521
			'button_label' => array(
522
				'label' => __( 'Button Label', 'formidable' ),
523
				'class' => 'show_submit_html',
524
			),
525
			'button_action' => array(
526
				'label' => __( 'Button Hook', 'formidable' ),
527
				'class' => 'show_submit_html',
528
			),
529
		);
530
531
		/**
532
		 * @since 4.0
533
		 */
534
		return apply_filters( 'frm_html_codes', $codes );
535
	}
536
537
	/**
538
	 * @since 4.0
539
	 * @param array $args
540
	 */
541
	public static function insert_opt_html( $args ) {
542
		$class  = isset( $args['class'] ) ? $args['class'] : '';
543
		$fields = FrmField::all_field_selection();
544
		$field  = isset( $fields[ $args['type'] ] ) ? $fields[ $args['type'] ] : array();
545
546
		self::prepare_field_type( $field );
547
548
		if ( ! isset( $field['icon'] ) ) {
549
			$field['icon'] = 'frmfont frm_pencil_icon';
550
		}
551
552
		$possible_email_field = FrmFieldFactory::field_has_property( $args['type'], 'holds_email_values' );
553
		if ( $possible_email_field ) {
554
			$class .= ' show_frm_not_email_to';
555
		}
556
		?>
557
		<li class="<?php echo esc_attr( $class ); ?>">
558
			<a href="javascript:void(0)" class="frmids frm_insert_code"
559
				data-code="<?php echo esc_attr( $args['id'] ); ?>">
560
				<span>[<?php echo esc_attr( isset( $args['id_label'] ) ? $args['id_label'] : $args['id'] ); ?>]</span>
561
				<?php FrmAppHelper::icon_by_class( $field['icon'], array( 'aria-hidden' => 'true' ) ); ?>
562
				<?php echo esc_attr( FrmAppHelper::truncate( $args['name'], 60 ) ); ?>
563
			</a>
564
			<a href="javascript:void(0)" class="frmkeys frm_insert_code frm_hidden"
565
				data-code="<?php echo esc_attr( $args['key'] ); ?>">
566
				<span>[<?php echo esc_attr( FrmAppHelper::truncate( isset( $args['key_label'] ) ? $args['key_label'] : $args['key'], 7 ) ); ?>]</span>
567
				<?php if ( isset( $field['icon'] ) ) { ?>
568
					<?php FrmAppHelper::icon_by_class( $field['icon'], array( 'aria-hidden' => 'true' ) ); ?>
569
				<?php } ?>
570
				<?php echo esc_attr( FrmAppHelper::truncate( $args['name'], 60 ) ); ?>
571
			</a>
572
		</li>
573
		<?php
574
	}
575
576
	/**
577
	 * @since 4.0
578
	 * @param array $args
579
	 */
580
	public static function insert_code_html( $args ) {
581
		$defaults = array(
582
			'class' => '',
583
			'code'  => '',
584
			'label' => '',
585
			'title' => '',
586
		);
587
588
		$args        = array_merge( $defaults, $args );
589
		$has_tooltip = ! empty( $args['title'] );
590
591
		?>
592
		<li class="<?php echo esc_attr( $args['class'] ); ?>">
593
			<a href="javascript:void(0)" class="frm_insert_code <?php echo $has_tooltip ? 'frm_help' : ''; ?>"
594
				<?php echo $has_tooltip ? 'title="' . esc_attr( $args['title'] ) . '"' : ''; ?>
595
				data-code="<?php echo esc_attr( $args['code'] ); ?>">
596
				<span>
597
					[<?php echo esc_attr( FrmAppHelper::truncate( $args['code'], 10 ) ); ?>]
598
				</span>
599
				<?php echo esc_attr( FrmAppHelper::truncate( $args['label'], 60 ) ); ?>
600
			</a>
601
		</li>
602
		<?php
603
	}
604
605
	/**
606
	 * Some field types in add-ons may have been added with only
607
	 * a field type and name.
608
	 *
609
	 * @since 4.0
610
	 */
611
	public static function prepare_field_type( &$field ) {
612
		if ( ! is_array( $field ) ) {
613
			$field = array(
614
				'name' => $field,
615
				'icon' => 'frm_icon_font frm_pencil_icon',
616
			);
617
		}
618
	}
619
620
	/**
621
	 * Automatically add end section fields if they don't exist (2.0 migration)
622
	 *
623
	 * @since 2.0
624
	 *
625
	 * @param boolean $reset_fields
626
	 */
627
	public static function auto_add_end_section_fields( $form, $fields, &$reset_fields ) {
628
		if ( empty( $fields ) ) {
629
			return;
630
		}
631
632
		$end_section_values = apply_filters( 'frm_before_field_created', FrmFieldsHelper::setup_new_vars( 'end_divider', $form->id ) );
633
		$open               = false;
634
		$prev_order         = false;
635
		$add_order          = 0;
636
		$last_field         = false;
637
		foreach ( $fields as $field ) {
638
			if ( $prev_order === $field->field_order ) {
639
				$add_order ++;
640
			}
641
642
			if ( $add_order ) {
643
				$reset_fields       = true;
644
				$field->field_order = $field->field_order + $add_order;
645
				FrmField::update( $field->id, array( 'field_order' => $field->field_order ) );
646
			}
647
648
			switch ( $field->type ) {
649
				case 'divider':
650
					// Create an end section if open.
651
					self::maybe_create_end_section( $open, $reset_fields, $add_order, $end_section_values, $field, 'move' );
652
653
					// Mark it open for the next end section.
654
					$open = true;
655
					break;
656
				case 'break':
657
					self::maybe_create_end_section( $open, $reset_fields, $add_order, $end_section_values, $field, 'move' );
658
					break;
659
				case 'end_divider':
660
					if ( ! $open ) {
661
						// The section isn't open, so this is an extra field that needs to be removed.
662
						FrmField::destroy( $field->id );
663
						$reset_fields = true;
664
					}
665
666
					// There is already an end section here, so there is no need to create one.
667
					$open = false;
668
			}
669
			$prev_order = $field->field_order;
670
671
			$last_field = $field;
672
			unset( $field );
673
		}
674
675
		self::maybe_create_end_section( $open, $reset_fields, $add_order, $end_section_values, $last_field );
676
	}
677
678
	/**
679
	 * Create end section field if it doesn't exist. This is for migration from < 2.0
680
	 * Fix any ordering that may be messed up
681
	 */
682
	public static function maybe_create_end_section( &$open, &$reset_fields, &$add_order, $end_section_values, $field, $move = 'no' ) {
683
		if ( ! $open ) {
684
			return;
685
		}
686
687
		$end_section_values['field_order'] = $field->field_order + 1;
688
689
		FrmField::create( $end_section_values );
690
691
		if ( $move == 'move' ) {
692
			// bump the order of current field unless we're at the end of the form
693
			FrmField::update( $field->id, array( 'field_order' => $field->field_order + 2 ) );
694
		}
695
696
		$add_order    += 2;
697
		$open         = false;
698
		$reset_fields = true;
699
	}
700
701
	public static function replace_shortcodes( $html, $form, $title = false, $description = false, $values = array() ) {
702
		$codes = array(
703
			'form_name'        => $title,
704
			'form_description' => $description,
705
			'entry_key'        => true,
706
		);
707
		foreach ( $codes as $code => $show ) {
708
			if ( $code == 'form_name' ) {
709
				$replace_with = $form->name;
710
			} elseif ( $code == 'form_description' ) {
711
				$replace_with = FrmAppHelper::use_wpautop( $form->description );
712
			} elseif ( $code == 'entry_key' && isset( $_GET ) && isset( $_GET['entry'] ) ) {
713
				$replace_with = FrmAppHelper::simple_get( 'entry' );
714
			} else {
715
				$replace_with = '';
716
			}
717
718
			FrmShortcodeHelper::remove_inline_conditions( ( FrmAppHelper::is_true( $show ) && $replace_with != '' ), $code, $replace_with, $html );
719
		}
720
721
		//replace [form_key]
722
		$html = str_replace( '[form_key]', $form->form_key, $html );
723
724
		//replace [frmurl]
725
		$html = str_replace( '[frmurl]', FrmFieldsHelper::dynamic_default_values( 'frmurl' ), $html );
726
727
		if ( strpos( $html, '[button_label]' ) ) {
728
			add_filter( 'frm_submit_button', 'FrmFormsHelper::submit_button_label', 1 );
729
			$submit_label = apply_filters( 'frm_submit_button', $title, $form );
730
			$submit_label = esc_attr( do_shortcode( $submit_label ) );
731
			$html         = str_replace( '[button_label]', $submit_label, $html );
732
		}
733
734
		$html = apply_filters( 'frm_form_replace_shortcodes', $html, $form, $values );
735
736
		if ( strpos( $html, '[if back_button]' ) ) {
737
			$html = preg_replace( '/(\[if\s+back_button\])(.*?)(\[\/if\s+back_button\])/mis', '', $html );
738
		}
739
740
		if ( strpos( $html, '[if save_draft]' ) ) {
741
			$html = preg_replace( '/(\[if\s+save_draft\])(.*?)(\[\/if\s+save_draft\])/mis', '', $html );
742
		}
743
744
		if ( apply_filters( 'frm_do_html_shortcodes', true ) ) {
745
			$html = do_shortcode( $html );
746
		}
747
748
		return $html;
749
	}
750
751
	public static function submit_button_label( $submit ) {
752
		if ( ! $submit || empty( $submit ) ) {
753
			$frm_settings = FrmAppHelper::get_settings();
754
			$submit       = $frm_settings->submit_value;
755
		}
756
757
		return $submit;
758
	}
759
760
	/**
761
	 * If the Formidable styling isn't being loaded,
762
	 * use inline styling to hide the element
763
	 *
764
	 * @since 2.03.05
765
	 */
766
	public static function maybe_hide_inline() {
767
		$frm_settings = FrmAppHelper::get_settings();
768
		if ( $frm_settings->load_style == 'none' ) {
769
			echo ' style="display:none;"';
770
		} elseif ( $frm_settings->load_style == 'dynamic' ) {
771
			FrmStylesController::enqueue_style();
772
		}
773
	}
774
775
	public static function get_form_style_class( $form = false ) {
776
		$style = self::get_form_style( $form );
777
		$class = ' with_frm_style';
778
779
		if ( empty( $style ) ) {
780
			if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) ) {
781
				return $class;
782
			} else {
783
				return;
784
			}
785
		}
786
787
		// If submit button needs to be inline or centered.
788
		if ( is_object( $form ) ) {
789
			$form = $form->options;
790
		}
791
792
		$submit_align = isset( $form['submit_align'] ) ? $form['submit_align'] : '';
793
794
		if ( 'inline' === $submit_align ) {
795
			$class .= ' frm_inline_form';
796
			$class .= self::maybe_align_fields_top( $form );
797
		} elseif ( 'center' === $submit_align ) {
798
			$class .= ' frm_center_submit';
799
		}
800
801
		$class = apply_filters( 'frm_add_form_style_class', $class, $style );
802
803
		return $class;
804
	}
805
806
	/**
807
	 * Returns appropriate class if form has top labels
808
	 *
809
	 * @param $form
810
	 *
811
	 * @return string
812
	 */
813
	private static function maybe_align_fields_top( $form ) {
814
		return self::form_has_top_labels( $form ) ? ' frm_inline_top' : '';
815
	}
816
817
	/**
818
	 * Determine if a form has fields with top labels so submit button can be aligned properly
819
	 *
820
	 * @param $form
821
	 *
822
	 * @return bool
823
	 */
824
	private static function form_has_top_labels( $form ) {
825
		if ( ! isset( $form['fields'] ) ) {
826
			return false;
827
		}
828
829
		$fields = $form['fields'];
830
		if ( count( $fields ) <= 0 ) {
831
			return false;
832
		}
833
834
		$fields = array_reverse( $fields ); // start from the fields closest to the submit button
835
		foreach ( $fields as $field ) {
836
			$type      = isset( $field['original_type'] ) ? $field['original_type'] : $field['type'];
837
			$has_input = FrmFieldFactory::field_has_property( $type, 'has_input' );
838
			if ( $has_input ) {
839
				return self::field_has_top_label( $field, $form );
840
			}
841
		}
842
843
		return false;
844
	}
845
846
	/**
847
	 * Check if a field's label position is set to "top"
848
	 *
849
	 * @param $field
850
	 * @param $form
851
	 *
852
	 * @return bool
853
	 */
854
	private static function field_has_top_label( $field, $form ) {
855
		$label_position = FrmFieldsHelper::label_position( $field['label'], $field, $form );
856
857
		return in_array( $label_position, array( 'top', 'inside', 'hidden' ) );
858
	}
859
860
	/**
861
	 * @param object|string|boolean $form
862
	 *
863
	 * @return string
864
	 */
865
	public static function get_form_style( $form ) {
866
		$style = 1;
867
		if ( empty( $form ) || 'default' == 'form' ) {
868
			return $style;
869
		} elseif ( is_object( $form ) && $form->parent_form_id ) {
870
			// get the parent form if this is a child
871
			$form = $form->parent_form_id;
872
		} elseif ( is_array( $form ) && isset( $form['parent_form_id'] ) && $form['parent_form_id'] ) {
873
			$form = $form['parent_form_id'];
874
		} elseif ( is_array( $form ) && isset( $form['custom_style'] ) ) {
875
			$style = $form['custom_style'];
876
		}
877
878
		if ( $form && is_string( $form ) ) {
879
			$form = FrmForm::getOne( $form );
880
		}
881
882
		$style = ( $form && is_object( $form ) && isset( $form->options['custom_style'] ) ) ? $form->options['custom_style'] : $style;
883
884
		return $style;
885
	}
886
887
	/**
888
	 * Display the validation error messages when an entry is submitted
889
	 *
890
	 * @param array $args - includes img, errors
891
	 *
892
	 * @since 2.0.6
893
	 */
894
	public static function show_errors( $args ) {
895
		$invalid_msg = self::get_invalid_error_message( $args );
896
897
		if ( empty( $invalid_msg ) ) {
898
			$show_img = false;
899
		} else {
900
			echo wp_kses_post( $invalid_msg );
901
			$show_img = true;
902
		}
903
904
		self::show_error(
905
			array(
906
				'img'      => $args['img'],
907
				'errors'   => $args['errors'],
908
				'show_img' => $show_img,
909
			)
910
		);
911
	}
912
913
	/**
914
	 * Display the error message in the front-end along with the image if set
915
	 * The image was removed from the styling settings, but it may still be set with a hook
916
	 * If the message in the global settings is empty, show every validation message in the error box
917
	 *
918
	 * @param array $args - includes img, errors, and show_img
919
	 *
920
	 * @since 2.0.6
921
	 */
922
	public static function show_error( $args ) {
923
		// remove any blank messages
924
		$args['errors'] = array_filter( (array) $args['errors'] );
925
926
		$line_break_first = $args['show_img'];
927
		foreach ( $args['errors'] as $error_key => $error ) {
0 ignored issues
show
Bug introduced by
The expression $args['errors'] of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
928
			if ( $line_break_first && ! is_numeric( $error_key ) && ( $error_key == 'cptch_number' || strpos( $error_key, 'field' ) === 0 ) ) {
929
				continue;
930
			}
931
932
			$id = str_replace( 'field', 'field_', $error_key );
933
			echo '<div id="' . esc_attr( $id ) . '_error">';
934
935
			if ( $args['show_img'] && ! empty( $args['img'] ) ) {
936
				echo '<img src="' . esc_attr( $args['img'] ) . '" alt="" />';
937
			} else {
938
				$args['show_img'] = true;
939
			}
940
941
			echo wp_kses_post( $error );
942
943
			echo '</div>';
944
		}
945
	}
946
947
	public static function maybe_get_scroll_js( $id ) {
948
		$offset = apply_filters( 'frm_scroll_offset', 4, array( 'form_id' => $id ) );
949
		if ( $offset != - 1 ) {
950
			self::get_scroll_js( $id );
951
		}
952
	}
953
954
	public static function get_scroll_js( $form_id ) {
955
		echo '<script type="text/javascript">document.addEventListener(\'DOMContentLoaded\',function(){frmFrontForm.scrollMsg(' . (int) $form_id . ');})</script>';
956
	}
957
958
	/**
959
	 * @since 3.0
960
	 */
961
	public static function actions_dropdown( $atts ) {
962
		if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
963
			$status     = $atts['status'];
964
			$form_id    = isset( $atts['id'] ) ? $atts['id'] : FrmAppHelper::get_param( 'id', 0, 'get', 'absint' );
965
			$trash_link = self::delete_trash_info( $form_id, $status );
966
			$links      = self::get_action_links( $form_id, $status );
967
			include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/actions-dropdown.php' );
968
		}
969
	}
970
971
	/**
972
	 * @since 3.0
973
	 */
974
	public static function get_action_links( $form_id, $form ) {
975
		if ( ! is_object( $form ) ) {
976
			$form = FrmForm::getOne( $form_id );
977
		}
978
979
		$actions     = array();
980
		$trash_links = self::delete_trash_links( $form_id );
981
		if ( 'trash' == $form->status ) {
982
			$actions['restore'] = $trash_links['restore'];
983
984
			if ( current_user_can( 'frm_delete_forms' ) ) {
985
				$actions['trash'] = $trash_links['delete'];
986
			}
987
		} elseif ( current_user_can( 'frm_edit_forms' ) ) {
988
			$duplicate_link = '?page=formidable&frm_action=duplicate&id=' . $form_id;
989
			if ( $form->is_template ) {
990
				$actions['frm_duplicate'] = array(
991
					'url'   => wp_nonce_url( $duplicate_link ),
992
					'label' => __( 'Create Form from Template', 'formidable' ),
993
					'icon'  => 'frm_icon_font frm_clone_icon',
994
				);
995
			} else {
996
				$actions['duplicate'] = array(
997
					'url'   => wp_nonce_url( $duplicate_link ),
998
					'label' => __( 'Duplicate Form', 'formidable' ),
999
					'icon'  => 'frm_icon_font frm_clone_icon',
1000
				);
1001
			}
1002
1003
			$actions['trash'] = self::delete_trash_info( $form_id, $form->status );
1004
		}
1005
1006
		return $actions;
1007
	}
1008
1009
	public static function edit_form_link( $form_id ) {
1010
		if ( is_object( $form_id ) ) {
1011
			$form    = $form_id;
1012
			$name    = $form->name;
1013
			$form_id = $form->id;
1014
		} else {
1015
			$name = FrmForm::getName( $form_id );
1016
		}
1017
1018
		if ( $form_id ) {
1019
			$val = '<a href="' . esc_url( FrmForm::get_edit_link( $form_id ) ) . '">' . ( '' == $name ? __( '(no title)', 'formidable' ) : FrmAppHelper::truncate( $name, 40 ) ) . '</a>';
1020
		} else {
1021
			$val = '';
1022
		}
1023
1024
		return $val;
1025
	}
1026
1027
	public static function delete_trash_link( $id, $status, $length = 'label' ) {
1028
		$link_details = self::delete_trash_info( $id, $status );
1029
1030
		return self::format_link_html( $link_details, $length );
1031
	}
1032
1033
	/**
1034
	 * @since 3.0
1035
	 */
1036
	public static function format_link_html( $link_details, $length = 'label' ) {
1037
		$link = '';
1038
		if ( ! empty( $link_details ) ) {
1039
			$link = '<a href="' . esc_url( $link_details['url'] ) . '" class="frm-trash-link"';
1040
			if ( isset( $link_details['data'] ) ) {
1041
				foreach ( $link_details['data'] as $data => $value ) {
1042
					$link .= ' data-' . esc_attr( $data ) . '="' . esc_attr( $value ) . '"';
1043
				}
1044
			} elseif ( isset( $link_details['confirm'] ) ) {
1045
				$link .= ' onclick="return confirm(\'' . esc_attr( $link_details['confirm'] ) . '\')"';
1046
			}
1047
1048
			$label = ( isset( $link_details[ $length ] ) ? $link_details[ $length ] : $link_details['label'] );
1049
			if ( $length == 'icon' && isset( $link_details[ $length ] ) ) {
1050
				$label = '<span class="' . $label . '" title="' . esc_attr( $link_details['label'] ) . '" aria-hidden="true"></span>';
1051
				$link  .= ' aria-label="' . esc_attr( $link_details['label'] ) . '"';
1052
			}
1053
1054
			$link .= '>' . $label . '</a>';
1055
		}
1056
1057
		return $link;
1058
	}
1059
1060
	/**
1061
	 * @since 3.0
1062
	 */
1063
	public static function delete_trash_info( $id, $status ) {
1064
		$labels = self::delete_trash_links( $id );
1065
1066
		if ( 'trash' == $status ) {
1067
			$info = $labels['restore'];
1068
		} elseif ( current_user_can( 'frm_delete_forms' ) ) {
1069
			if ( EMPTY_TRASH_DAYS ) {
1070
				$info = $labels['trash'];
1071
			} else {
1072
				$info = $labels['delete'];
1073
			}
1074
		} else {
1075
			$info = array();
1076
		}
1077
1078
		return $info;
1079
	}
1080
1081
	/**
1082
	 * @since 3.0
1083
	 */
1084
	private static function delete_trash_links( $id ) {
1085
		$current_page = FrmAppHelper::get_simple_request( array( 'param' => 'form_type' ) );
1086
		$base_url     = '?page=formidable&form_type=' . $current_page . '&id=' . $id;
1087
1088
		return array(
1089
			'restore' => array(
1090
				'label' => __( 'Restore from Trash', 'formidable' ),
1091
				'short' => __( 'Restore', 'formidable' ),
1092
				'url'   => wp_nonce_url( $base_url . '&frm_action=untrash', 'untrash_form_' . absint( $id ) ),
1093
			),
1094
			'trash'   => array(
1095
				'label' => __( 'Move Form to Trash', 'formidable' ),
1096
				'short' => __( 'Trash', 'formidable' ),
1097
				'url'   => wp_nonce_url( $base_url . '&frm_action=trash', 'trash_form_' . absint( $id ) ),
1098
				'icon'  => 'frm_icon_font frm_delete_icon',
1099
				'data'  => array( 'frmverify' => __( 'Do you want to move this form to the trash?', 'formidable' ) ),
1100
			),
1101
			'delete'  => array(
1102
				'label'   => __( 'Delete Permanently', 'formidable' ),
1103
				'short'   => __( 'Delete', 'formidable' ),
1104
				'url'     => wp_nonce_url( $base_url . '&frm_action=destroy', 'destroy_form_' . absint( $id ) ),
1105
				'confirm' => __( 'Are you sure you want to delete this form and all its entries?', 'formidable' ),
1106
				'icon'    => 'frm_icon_font frm_delete_icon',
1107
				'data'    => array( 'frmverify' => __( 'This will permanently delete the form and all its entries. This is irreversible. Are you sure you want to continue?', 'formidable' ) ),
1108
			),
1109
		);
1110
	}
1111
1112
	/**
1113
	 * @since 3.0
1114
	 */
1115
	public static function css_classes() {
1116
		$classes = array(
1117
			'frm_total'      => array(
1118
				'label' => __( 'Total', 'formidable' ),
1119
				'title' => __( 'Add this to a read-only field to display the text in bold without a border or background.', 'formidable' ),
1120
			),
1121
			'frm_scroll_box' => array(
1122
				'label' => __( 'Scroll Box', 'formidable' ),
1123
				'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' ),
1124
			),
1125
			'frm_first'      => array(
1126
				'label' => __( 'First', 'formidable' ),
1127
				'title' => __( 'Add this to the first field in each row along with a width. ie frm_first frm4', 'formidable' ),
1128
			),
1129
			'frm_alignright' => __( 'Right', 'formidable' ),
1130
			'frm_grid_first' => __( 'First Grid Row', 'formidable' ),
1131
			'frm_grid'       => __( 'Even Grid Row', 'formidable' ),
1132
			'frm_grid_odd'   => __( 'Odd Grid Row', 'formidable' ),
1133
			'frm_capitalize' => array(
1134
				'label' => __( 'Capitalize', 'formidable' ),
1135
				'title' => __( 'Automatically capitalize the first letter in each word.', 'formidable' ),
1136
			),
1137
		);
1138
1139
		return apply_filters( 'frm_layout_classes', $classes );
1140
	}
1141
1142
	public static function grid_classes() {
1143
		$base = array(
1144
			'frm_half' => '1/2',
1145
1146
			'frm_third'      => '1/3',
1147
			'frm_two_thirds' => '2/3',
1148
1149
			'frm_fourth'        => '1/4',
1150
			'frm_three_fourths' => '3/4',
1151
		);
1152
1153
		$frm_settings = FrmAppHelper::get_settings();
1154
		if ( $frm_settings->old_css ) {
1155
			$classes = array(
1156
				'frm_sixth' => '1/6',
1157
				'frm10'     => '5/6',
1158
1159
				'frm_full' => '100%',
1160
			);
1161
		} else {
1162
			$classes = array(
1163
				'frm_sixth' => '1/6',
1164
				'frm10'     => '5/6',
1165
				'frm12' => '100%',
1166
			);
1167
		}
1168
1169
		return array_merge( $base, $classes );
1170
	}
1171
1172
	/**
1173
	 * @since 3.0
1174
	 */
1175
	public static function style_class_label( $style, $class ) {
1176
		$label = '';
1177
		if ( empty( $style ) ) {
1178
			$label = $class;
1179
		} elseif ( ! is_array( $style ) ) {
1180
			$label = $style;
1181
		} elseif ( isset( $style['label'] ) ) {
1182
			$label = $style['label'];
1183
		}
1184
1185
		return $label;
1186
	}
1187
1188
	public static function status_nice_name( $status ) {
1189
		$nice_names = array(
1190
			'draft'   => __( 'Draft', 'formidable' ),
1191
			'trash'   => __( 'Trash', 'formidable' ),
1192
			'publish' => __( 'Published', 'formidable' ),
1193
		);
1194
1195
		if ( ! in_array( $status, array_keys( $nice_names ) ) ) {
1196
			$status = 'publish';
1197
		}
1198
1199
		$name = $nice_names[ $status ];
1200
1201
		return $name;
1202
	}
1203
1204
	public static function template_icon( $categories ) {
1205
		$ignore     = self::ignore_template_categories();
1206
		$categories = array_diff( $categories, $ignore );
1207
1208
		$icons = array(
1209
			'WooCommerce'       => array( 'woocommerce', 'var(--purple)' ),
1210
			'Post'              => array( 'wordpress', 'rgb(0,160,210)' ),
1211
			'User Registration' => array( 'register', 'var(--pink)' ),
1212
			'PayPal'            => array( 'paypal' ),
1213
			'Stripe'            => array( 'credit_card', 'var(--green)' ),
1214
			'Twilio'            => array( 'sms', 'rgb(0,160,210)' ),
1215
			'Calculator'        => array( 'calculator', 'var(--orange)' ),
1216
			'Contact Form'      => array( 'address_card' ),
1217
			'Survey'            => array( 'align_right', 'var(--pink)' ),
1218
			'Application Form'  => array( 'align_right', 'rgb(0,160,210)' ),
1219
			''                  => array( 'align_right' ),
1220
		);
1221
1222
		$icon = $icons[''];
1223
1224
		if ( count( $categories ) === 1 ) {
1225
			$category = reset( $categories );
1226
			$icon     = isset( $icons[ $category ] ) ? $icons[ $category ] : $icon;
1227
		} elseif ( ! empty( $categories ) ) {
1228
			foreach ( $icons as $cat => $icon ) {
1229
				if ( ! in_array( $cat, $categories ) ) {
1230
					unset( $icons[ $cat ] );
1231
				}
1232
			}
1233
			$icon = reset( $icons );
1234
		}
1235
1236
		echo '<span class="frm-inner-circle" ' . ( isset( $icon[1] ) ? 'style="background-color:' . esc_attr( $icon[1] ) : '' ) . '">';
1237
		FrmAppHelper::icon_by_class( 'frmfont frm_' . $icon[0] . '_icon' );
1238
		echo '<span class="frm_hidden">';
1239
		FrmAppHelper::icon_by_class( 'frmfont frm_lock_icon' );
1240
		echo '</span>';
1241
		echo '</span>';
1242
	}
1243
1244
	/**
1245
	 * @since 4.03.01
1246
	 */
1247
	public static function ignore_template_categories() {
1248
		return array( 'Business', 'Elite', 'Personal', 'Creator', 'Basic', 'free' );
1249
	}
1250
1251
	/**
1252
	 * @since 4.02
1253
	 */
1254
	public static function get_template_install_link( $template, $args ) {
1255
		$defaults = array(
1256
			'class' => 'install-now',
1257
			'href'  => 'href',
1258
			'atts'  => true,
1259
		);
1260
1261
		if ( isset( $template['url'] ) && ! empty( $template['url'] ) ) {
1262
			$link = array(
1263
				'url'   => $template['url'],
1264
				'label' => __( 'Create Form', 'formidable' ),
1265
				'class' => 'frm-install-template',
1266
				'href'  => 'rel',
1267
				'atts'  => '',
1268
			);
1269
		} elseif ( self::plan_is_allowed( $args ) ) {
1270
			$link = array(
1271
				'url'   => FrmAppHelper::admin_upgrade_link( 'addons', 'account/downloads/' ) . '&utm_content=' . $template['slug'],
1272
				'label' => __( 'Renew', 'formidable' ),
1273
			);
1274
		} else {
1275
			$link = array(
1276
				'url'   => $args['pricing'],
1277
				'label' => __( 'Upgrade', 'formidable' ),
1278
			);
1279
		}
1280
1281
		return array_merge( $defaults, $link );
1282
	}
1283
1284
	/**
1285
	 * Is the template included with the license type?
1286
	 *
1287
	 * @since 4.02.02
1288
	 *
1289
	 * @param array $args
1290
	 *
1291
	 * @return bool
1292
	 */
1293
	private static function plan_is_allowed( $args ) {
1294
		if ( empty( $args['license_type'] ) ) {
1295
			return false;
1296
		}
1297
1298
		$included = $args['license_type'] === strtolower( $args['plan_required'] );
1299
1300
		$plans = array( 'free', 'personal', 'business', 'elite' );
1301
		if ( $included || ! in_array( strtolower( $args['plan_required'] ), $plans ) ) {
1302
			return $included;
1303
		}
1304
1305
		foreach ( $plans as $plan ) {
1306
			if ( $included || $plan === $args['license_type'] ) {
1307
				break;
1308
			}
1309
			$included = $plan === strtolower( $args['plan_required'] );
1310
		}
1311
1312
		return $included;
1313
	}
1314
1315
	/**
1316
	 * @since 4.02
1317
	 */
1318
	public static function template_install_html( $link, $class = '' ) {
1319
		$link['class'] .= ' ' . $class;
1320
		echo '<a ' . esc_attr( $link['href'] ) . '="' . esc_url( $link['url'] ) . '" class="' . esc_attr( $link['class'] ) . ' " aria-label="' . esc_attr( $link['label'] ) . '"' . ( $link['atts'] ? ' target="_blank" rel="noopener"' : '' ) . '>';
1321
	}
1322
1323
	/**
1324
	 * If a template or add-on cannot be installed, show a message
1325
	 * about which plan is required.
1326
	 *
1327
	 * @since 4.0
1328
	 */
1329
	public static function show_plan_required( $requires, $link ) {
1330
		if ( empty( $requires ) ) {
1331
			return;
1332
		}
1333
1334
		?>
1335
		<p class="frm_plan_required">
1336
			<?php esc_html_e( 'License plan required:', 'formidable' ); ?>
1337
			<a href="<?php echo esc_url( $link ); ?>" target="_blank" rel="noopener">
1338
				<?php echo esc_html( $requires ); ?>
1339
			</a>
1340
		</p>
1341
		<?php
1342
	}
1343
1344
	/**
1345
	 * @since 4.0
1346
	 */
1347
	public static function get_plan_required( &$item ) {
1348
		if ( ! isset( $item['categories'] ) || ( isset( $item['url'] ) && ! empty( $item['url'] ) ) ) {
1349
			return false;
1350
		}
1351
1352
		$plans = array( 'free', 'Personal', 'Business', 'Elite' );
1353
1354
		foreach ( $item['categories'] as $k => $category ) {
1355
			if ( in_array( $category, $plans ) ) {
1356
				unset( $item['categories'][ $k ] );
1357
				return $category;
1358
			}
1359
		}
1360
1361
		return false;
1362
	}
1363
1364
	/**
1365
	 * Returns an array of common reserved words in WordPress.
1366
	 *
1367
	 * An edited list of reserved terms from the Codex.
1368
	 * https://codex.wordpress.org/Reserved_Terms
1369
	 *
1370
	 * @return array Array of WordPress reserved words.
1371
	 */
1372
	public static function reserved_words() {
1373
		return array(
1374
			'id',
1375
			'attachment',
1376
			'author',
1377
			'author_name',
1378
			'calendar',
1379
			'cat',
1380
			'category',
1381
			'category_name',
1382
			'cpage',
1383
			'custom',
1384
			'day',
1385
			'date',
1386
			'error',
1387
			'feed',
1388
			'hour',
1389
			'm',
1390
			'minute',
1391
			'more',
1392
			'name',
1393
			'order',
1394
			'p',
1395
			'page',
1396
			'page_id',
1397
			'paged',
1398
			'pb',
1399
			'post',
1400
			'posts',
1401
			'preview',
1402
			's',
1403
			'search',
1404
			'second',
1405
			'sentence',
1406
			'tag',
1407
			'taxonomy',
1408
			'tb',
1409
			'term',
1410
			'terms',
1411
			'theme',
1412
			'title',
1413
			'type',
1414
			'w',
1415
			'year',
1416
		);
1417
	}
1418
}
1419