PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.12
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.12
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 / FrmEntriesHelper.php

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

866 lines 27.1 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 FrmEntriesHelper {
7
8 /**
9 * "Submitted" entry status.
10 *
11 * @since 6.4.2
12 * @var int
13 */
14 const SUBMITTED_ENTRY_STATUS = 0;
15
16 /**
17 * "Draft" entry status.
18 *
19 * @since 6.4.2
20 * @var int
21 */
22 const DRAFT_ENTRY_STATUS = 1;
23
24 public static function setup_new_vars( $fields, $form = '', $reset = false, $args = array() ) {
25 remove_action( 'media_buttons', 'FrmFormsController::insert_form_button' );
26
27 $values = array(
28 'name' => '',
29 'description' => '',
30 'item_key' => '',
31 );
32
33 $values['fields'] = array();
34 if ( empty( $fields ) ) {
35 return apply_filters( 'frm_setup_new_entry', $values );
36 }
37
38 foreach ( (array) $fields as $field ) {
39 $original_default = $field->default_value;
40 self::prepare_field_default_value( $field );
41 $new_value = self::get_field_value_for_new_entry( $field, $reset, $args );
42
43 $field_array = FrmAppHelper::start_field_array( $field );
44 $field_array['value'] = $new_value;
45 $field_array['type'] = apply_filters( 'frm_field_type', $field->type, $field, $new_value );
46 $field_array['parent_form_id'] = isset( $args['parent_form_id'] ) ? $args['parent_form_id'] : $field->form_id;
47 $field_array['reset_value'] = $reset;
48 $field_array['in_embed_form'] = isset( $args['in_embed_form'] ) ? $args['in_embed_form'] : '0';
49 $field_array['original_default'] = $original_default;
50
51 FrmFieldsHelper::prepare_new_front_field( $field_array, $field, $args );
52
53 if ( ! is_array( $field->field_options ) ) {
54 $field->field_options = array();
55 }
56
57 $field_array = array_merge( $field->field_options, $field_array );
58
59 $values['fields'][] = $field_array;
60
61 if ( ! $form || ! isset( $form->id ) ) {
62 $form = FrmForm::getOne( $field->form_id );
63 }
64 }//end foreach
65
66 FrmAppHelper::unserialize_or_decode( $form->options );
67 if ( is_array( $form->options ) ) {
68 $values = array_merge( $values, $form->options );
69 }
70
71 $form_defaults = FrmFormsHelper::get_default_opts();
72 $form_defaults['custom_style'] = FrmAppHelper::custom_style_value( array() );
73
74 $values = array_merge( $form_defaults, $values );
75
76 return apply_filters( 'frm_setup_new_entry', $values );
77 }
78
79 /**
80 * @since 2.05
81 *
82 * @param object $field
83 */
84 private static function prepare_field_default_value( &$field ) {
85 // If checkbox, multi-select dropdown, or checkbox data from entries field, the value should be an array.
86 $return_array = FrmField::is_field_with_multiple_values( $field );
87
88 /**
89 * Do any shortcodes in default value and allow customization of default value.
90 * Calls FrmProFieldsHelper::get_default_value
91 */
92 $field->default_value = apply_filters( 'frm_get_default_value', $field->default_value, $field, true, $return_array );
93
94 if ( isset( $field->field_options['placeholder'] ) ) {
95 $field->field_options['placeholder'] = apply_filters( 'frm_get_default_value', $field->field_options['placeholder'], $field, false, false );
96 }
97 }
98
99 /**
100 * Set the value for each field
101 * This function is used when the form is first loaded and on all page turns *for a new entry*
102 *
103 * @since 2.0.13
104 *
105 * @param object $field - this is passed by reference since it is an object.
106 * @param bool $reset
107 * @param array $args
108 *
109 * @return array|string $new_value
110 */
111 private static function get_field_value_for_new_entry( $field, $reset, $args ) {
112 $new_value = $field->default_value;
113
114 if ( ! $reset && self::value_is_posted( $field, $args ) ) {
115 self::get_posted_value( $field, $new_value, $args );
116 }
117
118 if ( ! is_array( $new_value ) ) {
119 $new_value = str_replace( '"', '&quot;', $new_value );
120 }
121
122 return $new_value;
123 }
124
125 /**
126 * Check if a field has a posted value
127 *
128 * @since 2.01.0
129 *
130 * @param object $field
131 * @param array $args
132 *
133 * @return bool $value_is_posted
134 */
135 public static function value_is_posted( $field, $args ) {
136 $value_is_posted = false;
137 if ( $_POST ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
138 $repeating = isset( $args['repeating'] ) && $args['repeating'];
139 if ( $repeating ) {
140 if ( isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
141 $value_is_posted = true;
142 }
143 } elseif ( isset( $_POST['item_meta'][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
144 $value_is_posted = true;
145 }
146 }
147
148 return $value_is_posted;
149 }
150
151 public static function setup_edit_vars( $values, $record ) {
152 remove_action( 'media_buttons', 'FrmFormsController::insert_form_button' );
153
154 $values['item_key'] = FrmAppHelper::get_post_param( 'item_key', $record->item_key, 'sanitize_title' );
155 $values['form_id'] = $record->form_id;
156 $values['is_draft'] = $record->is_draft;
157
158 return apply_filters( 'frm_setup_edit_entry_vars', $values, $record );
159 }
160
161 public static function replace_default_message( $message, $atts ) {
162 if ( strpos( $message, '[default-message' ) === false &&
163 strpos( $message, '[default_message' ) === false &&
164 ! empty( $message ) ) {
165 return $message;
166 }
167
168 if ( empty( $message ) ) {
169 $message = '[default-message]';
170 }
171
172 preg_match_all( "/\[(default-message|default_message)\b(.*?)(?:(\/))?\]/s", $message, $shortcodes, PREG_PATTERN_ORDER );
173
174 foreach ( $shortcodes[0] as $short_key => $tag ) {
175 $add_atts = FrmShortcodeHelper::get_shortcode_attribute_array( $shortcodes[2][ $short_key ] );
176 if ( ! empty( $add_atts ) ) {
177 $this_atts = array_merge( $atts, $add_atts );
178 } else {
179 $this_atts = $atts;
180 }
181
182 $default = FrmEntriesController::show_entry_shortcode( $this_atts );
183
184 // Add the default message.
185 $message = str_replace( $shortcodes[0][ $short_key ], $default, $message );
186 }
187
188 return $message;
189 }
190
191 /**
192 * @param stdClass $entry
193 * @param stdClass $field
194 * @param array $atts
195 * @return string
196 */
197 public static function prepare_display_value( $entry, $field, $atts ) {
198 $field_value = isset( $entry->metas[ $field->id ] ) ? $entry->metas[ $field->id ] : false;
199
200 if ( FrmAppHelper::pro_is_installed() ) {
201 $empty = empty( $field_value );
202 FrmProEntriesHelper::get_dynamic_list_values( $field, $entry, $field_value );
203 if ( $empty && ! empty( $field_value ) ) {
204 // We've got an entry id, so switch it to a value.
205 $atts['force_id'] = true;
206 }
207 }
208
209 if ( $field->form_id == $entry->form_id || empty( $atts['embedded_field_id'] ) ) {
210 return self::display_value( $field_value, $field, $atts );
211 }
212
213 if ( ! FrmAppHelper::pro_is_installed() ) {
214 return '';
215 }
216 if ( is_callable( 'FrmProEntriesHelper::prepare_child_display_value' ) ) {
217 return FrmProEntriesHelper::prepare_child_display_value( $entry, $field, $atts );
218 }
219
220 // This is an embedded form.
221 if ( strpos( $atts['embedded_field_id'], 'form' ) === 0 ) {
222 // This is a repeating section.
223 $child_entries = FrmEntry::getAll( array( 'it.parent_item_id' => $entry->id ), '', '', true );
224 } else {
225 // Get all values for this field.
226 $child_values = isset( $entry->metas[ $atts['embedded_field_id'] ] ) ? $entry->metas[ $atts['embedded_field_id'] ] : false;
227
228 if ( $child_values ) {
229 $child_entries = FrmEntry::getAll( array( 'it.id' => (array) $child_values ) );
230 }
231 }
232
233 $field_value = array();
234
235 if ( empty( $child_entries ) ) {
236 return '';
237 }
238
239 foreach ( $child_entries as $child_entry ) {
240 $atts['item_id'] = $child_entry->id;
241 $atts['post_id'] = $child_entry->post_id;
242
243 // Fet the value for this field -- check for post values as well.
244 $entry_val = FrmProEntryMetaHelper::get_post_or_meta_value( $child_entry, $field );
245
246 if ( $entry_val || '0' === $entry_val ) {
247 // foreach entry get display_value.
248 $field_value[] = self::display_value( $entry_val, $field, $atts );
249 }
250
251 unset( $child_entry );
252 }
253
254 $sep = ', ';
255 if ( strpos( implode( ' ', $field_value ), '<img' ) !== false ) {
256 $sep = '<br/>';
257 }
258 $val = implode( $sep, $field_value );
259
260 return FrmAppHelper::kses( $val, 'all' );
261 }
262
263 /**
264 * Prepare the saved value for display
265 *
266 * @param array|string $value
267 * @param object $field
268 * @param array $atts
269 *
270 * @return string
271 */
272 public static function display_value( $value, $field, $atts = array() ) {
273
274 $defaults = array(
275 'type' => '',
276 'html' => false,
277 'show_filename' => true,
278 'truncate' => false,
279 'sep' => ', ',
280 'post_id' => 0,
281 'form_id' => $field->form_id,
282 'field' => $field,
283 'keepjs' => 0,
284 'return_array' => false,
285 );
286
287 $atts = wp_parse_args( $atts, $defaults );
288
289 if ( FrmField::is_image( $field ) || $field->type === 'star' ) {
290 $atts['truncate'] = false;
291 $atts['html'] = true;
292 }
293
294 $atts = apply_filters( 'frm_display_value_atts', $atts, $field, $value );
295
296 if ( ! isset( $field->field_options['post_field'] ) ) {
297 $field->field_options['post_field'] = '';
298 }
299
300 if ( ! isset( $field->field_options['custom_field'] ) ) {
301 $field->field_options['custom_field'] = '';
302 }
303
304 if ( FrmAppHelper::pro_is_installed() && $atts['post_id'] && ( $field->field_options['post_field'] || $atts['type'] === 'tag' ) ) {
305 $atts['pre_truncate'] = $atts['truncate'];
306 $atts['truncate'] = true;
307 $atts['exclude_cat'] = isset( $field->field_options['exclude_cat'] ) ? $field->field_options['exclude_cat'] : 0;
308
309 $value = FrmProEntryMetaHelper::get_post_value( $atts['post_id'], $field->field_options['post_field'], $field->field_options['custom_field'], $atts );
310 $atts['truncate'] = $atts['pre_truncate'];
311 }
312
313 if ( $value == '' ) {
314 return $value;
315 }
316
317 $unfiltered_value = $value;
318 FrmFieldsHelper::prepare_field_value( $unfiltered_value, $field->type );
319
320 $value = apply_filters( 'frm_display_value_custom', $unfiltered_value, $field, $atts );
321 $value = apply_filters( 'frm_display_' . $field->type . '_value_custom', $value, compact( 'field', 'atts' ) );
322
323 if ( $value == $unfiltered_value ) {
324 $value = FrmFieldsHelper::get_unfiltered_display_value( compact( 'value', 'field', 'atts' ) );
325 }
326
327 if ( $atts['truncate'] && $atts['type'] !== 'url' ) {
328 $value = FrmAppHelper::truncate( $value, 50 );
329 }
330
331 if ( ! $atts['keepjs'] && ! is_array( $value ) ) {
332 $value = FrmAppHelper::kses( $value, 'all' );
333 }
334
335 return apply_filters( 'frm_display_value', $value, $field, $atts );
336 }
337
338 public static function set_posted_value( $field, $value, $args ) {
339 // If validating a field with "other" opt, set back to prev value now.
340 if ( ! empty( $args['other'] ) ) {
341 $value = $args['temp_value'];
342 }
343 if ( empty( $args['parent_field_id'] ) ) {
344 $_POST['item_meta'][ $field->id ] = $value;
345 } else {
346 self::set_parent_field_posted_value( $field, $value, $args );
347 }
348 }
349
350 /**
351 * Init arrays if necessary, else we get fatal error.
352 *
353 * @since 4.01
354 */
355 private static function set_parent_field_posted_value( $field, $value, $args ) {
356 if ( isset( $_POST['item_meta'][ $args['parent_field_id'] ] ) && is_array( $_POST['item_meta'][ $args['parent_field_id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
357 if ( ! isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] ) || ! is_array( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
358 $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] = array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
359 }
360 } else {
361 // All of the section was probably removed.
362 $_POST['item_meta'][ $args['parent_field_id'] ] = array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
363 $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ] = array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
364 }
365
366 $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field->id ] = $value; // phpcs:ignore WordPress.Security.NonceVerification.Missing
367 }
368
369 public static function get_posted_value( $field, &$value, $args ) {
370 if ( is_array( $field ) ) {
371 $field_id = $field['id'];
372 $field_obj = FrmFieldFactory::get_field_object( $field['id'] );
373 } elseif ( is_object( $field ) ) {
374 $field_id = $field->id;
375 $field_obj = FrmFieldFactory::get_field_object( $field );
376 } elseif ( is_numeric( $field ) ) {
377 $field_id = $field;
378 $field_obj = FrmFieldFactory::get_field_object( $field );
379 } else {
380 $value = self::get_posted_meta( $field, $args );
381 FrmAppHelper::sanitize_value( 'sanitize_text_field', $value );
382 return;
383 }
384
385 $value = self::get_posted_meta( $field_id, $args );
386
387 $field_obj->sanitize_value( $value );
388 }
389
390 /**
391 * @since 4.02.04
392 */
393 private static function get_posted_meta( $field_id, $args ) {
394 if ( empty( $args['parent_field_id'] ) ) {
395 // Sanitizing is done next.
396 $value = isset( $_POST['item_meta'][ $field_id ] ) ? wp_unslash( $_POST['item_meta'][ $field_id ] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
397 } else {
398 $value = isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field_id ] ) ? wp_unslash( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ][ $field_id ] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
399 }
400 return $value;
401 }
402
403 /**
404 * Check if field has an "Other" option and if any other values are posted
405 *
406 * @since 2.0
407 *
408 * @param object $field
409 * @param array|string $value
410 * @param array $args
411 */
412 public static function maybe_set_other_validation( $field, &$value, &$args ) {
413 $args['other'] = false;
414 if ( ! $value || ! FrmAppHelper::pro_is_installed() ) {
415 return;
416 }
417
418 // Trim excess values if selection limit is exceeded for checkbox. Necessary to do here
419 // as the value set here will be used later in this class's set_posted_value() method.
420 if ( FrmField::is_checkbox( $field ) ) {
421 $field_obj = FrmFieldFactory::get_field_object( $field );
422 $field_obj->maybe_trim_excess_values( $value );
423 }
424
425 // Get other value for fields in repeating section.
426 self::set_other_repeating_vals( $field, $value, $args );
427
428 // Check if there are any posted "Other" values.
429 if ( FrmField::is_option_true( $field, 'other' ) && isset( $_POST['item_meta']['other'][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
430
431 // Save original value.
432 $args['temp_value'] = $value;
433 $args['other'] = true;
434
435 // Sanitizing is done next.
436 $other_vals = wp_unslash( $_POST['item_meta']['other'][ $field->id ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
437 FrmAppHelper::sanitize_value( 'sanitize_text_field', $other_vals );
438
439 // Set the validation value now
440 self::set_other_validation_val( $value, $other_vals, $field, $args );
441 }
442 }
443
444 /**
445 * Sets radio or checkbox value equal to "other" value if it is set - FOR REPEATING SECTIONS
446 *
447 * @since 2.0
448 *
449 * @param object $field
450 * @param array|string $value
451 * @param array $args
452 */
453 public static function set_other_repeating_vals( $field, &$value, &$args ) {
454 if ( ! $args['parent_field_id'] ) {
455 return;
456 }
457
458 // Check if there are any other posted "other" values for this field.
459 if ( FrmField::is_option_true( $field, 'other' ) && isset( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ]['other'][ $field->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
460 // Save original value
461 $args['temp_value'] = $value;
462 $args['other'] = true;
463
464 $other_vals = wp_unslash( $_POST['item_meta'][ $args['parent_field_id'] ][ $args['key_pointer'] ]['other'][ $field->id ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
465 FrmAppHelper::sanitize_value( 'sanitize_text_field', $other_vals );
466
467 // Set the validation value now.
468 self::set_other_validation_val( $value, $other_vals, $field, $args );
469 }
470 }
471
472 /**
473 * Modify value used for validation
474 * This function essentially removes the "Other" radio or checkbox value from the $value being validated.
475 * It also adds any text from the free text fields to the value
476 *
477 * Needs to accommodate for times when other opt is selected, but no other free text is entered
478 *
479 * @since 2.0
480 *
481 * @param array|string $value
482 * @param array|string $other_vals (usually of posted values).
483 * @param object $field
484 * @param array $args
485 */
486 public static function set_other_validation_val( &$value, $other_vals, $field, &$args ) {
487 // Checkboxes and multi-select dropdowns.
488 if ( is_array( $value ) && $field->type === 'checkbox' ) {
489 // Combine "Other" values with checked values. "Other" values will override checked box values.
490 foreach ( $other_vals as $k => $v ) {
491 if ( isset( $value[ $k ] ) && trim( $v ) === '' ) {
492 // If the other box is checked, but doesn't have a value.
493 $value = '';
494 break;
495 }
496 }
497
498 if ( is_array( $value ) && ! empty( $value ) ) {
499 $value = array_merge( $value, $other_vals );
500 }
501 } else {
502 // Radio and dropdowns.
503 $other_key = array_filter( array_keys( $field->options ), 'is_string' );
504 $other_key = reset( $other_key );
505
506 // Multi-select dropdown.
507 if ( is_array( $value ) ) {
508 $o_key = array_search( $field->options[ $other_key ], $value );
509
510 if ( $o_key !== false ) {
511 // Modify the original value so other key will be preserved.
512 $value[ $other_key ] = $value[ $o_key ];
513
514 // By default, the array keys will be numeric for multi-select dropdowns.
515 // If going backwards and forwards between pages, the array key will match the other key.
516 if ( $o_key !== $other_key ) {
517 unset( $value[ $o_key ] );
518 }
519
520 $args['temp_value'] = $value;
521 $value[ $other_key ] = reset( $other_vals );
522 if ( FrmAppHelper::is_empty_value( $value[ $other_key ] ) ) {
523 unset( $value[ $other_key ] );
524 }
525 }
526 } elseif ( $field->options[ $other_key ] == $value ) {
527 $value = $other_vals;
528 }//end if
529 }//end if
530 }
531
532 /**
533 * Add submitted values to a string for spam checking.
534 *
535 * @param array $values
536 * @return string
537 */
538 public static function entry_array_to_string( $values ) {
539 $content = '';
540 foreach ( $values['item_meta'] as $val ) {
541 if ( $content != '' ) {
542 $content .= "\n\n";
543 }
544
545 if ( is_array( $val ) ) {
546 $val = FrmAppHelper::array_flatten( $val );
547 $val = implode( ', ', $val );
548 }
549
550 $content .= $val;
551 }
552
553 return $content;
554 }
555
556 /**
557 * Get the browser from the user agent
558 *
559 * @since 2.04
560 *
561 * @param string $u_agent
562 *
563 * @return string
564 */
565 public static function get_browser( $u_agent ) {
566 $bname = __( 'Unknown', 'formidable' );
567 $platform = $bname;
568 $ub = '';
569
570 // Get the operating system
571 if ( preg_match( '/windows|win32/i', $u_agent ) ) {
572 $platform = 'Windows';
573 } elseif ( preg_match( '/android/i', $u_agent ) ) {
574 $platform = 'Android';
575 } elseif ( preg_match( '/linux/i', $u_agent ) ) {
576 $platform = 'Linux';
577 } elseif ( preg_match( '/macintosh|mac os x/i', $u_agent ) ) {
578 $platform = 'OS X';
579 }
580
581 $agent_options = array(
582 'Chrome' => 'Google Chrome',
583 'Safari' => 'Apple Safari',
584 'Opera' => 'Opera',
585 'Netscape' => 'Netscape',
586 'Firefox' => 'Mozilla Firefox',
587 );
588
589 // Next get the name of the useragent yes separately and for good reason.
590 if ( strpos( $u_agent, 'MSIE' ) !== false && strpos( $u_agent, 'Opera' ) === false ) {
591 $bname = 'Internet Explorer';
592 $ub = 'MSIE';
593 } else {
594 foreach ( $agent_options as $agent_key => $agent_name ) {
595 if ( strpos( $u_agent, $agent_key ) !== false ) {
596 $bname = $agent_name;
597 $ub = $agent_key;
598 break;
599 }
600 }
601 }
602
603 // finally get the correct version number
604 $known = array( 'Version', $ub, 'other' );
605 $pattern = '#(?<browser>' . join( '|', $known ) . ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
606 // Get the matching numbers.
607 preg_match_all( $pattern, $u_agent, $matches );
608
609 // see how many we have
610 $i = count( $matches['browser'] );
611
612 if ( $i > 1 ) {
613 // We will have two since we are not using 'other' argument yet
614 // see if version is before or after the name.
615 if ( strripos( $u_agent, 'Version' ) < strripos( $u_agent, $ub ) ) {
616 $version = $matches['version'][0];
617 } else {
618 $version = $matches['version'][1];
619 }
620 } elseif ( $i === 1 ) {
621 $version = $matches['version'][0];
622 } else {
623 $version = '';
624 }
625
626 // check if we have a number
627 if ( $version == '' ) {
628 $version = '?';
629 }
630
631 return $bname . ' ' . $version . ' / ' . $platform;
632 }
633
634 /**
635 * @since 3.0
636 */
637 public static function actions_dropdown( $atts ) {
638 $id = isset( $atts['id'] ) ? $atts['id'] : FrmAppHelper::get_param( 'id', 0, 'get', 'absint' );
639 $links = self::get_action_links( $id, $atts['entry'] );
640
641 foreach ( $links as $link ) {
642 ?>
643 <div class="misc-pub-section">
644 <a href="<?php echo esc_url( $link['url'] ); ?>"
645 <?php
646 if ( isset( $link['data'] ) ) {
647 foreach ( $link['data'] as $data => $value ) {
648 echo 'data-' . esc_attr( $data ) . '="' . esc_attr( $value ) . '" ';
649 }
650 }
651 if ( isset( $link['class'] ) ) {
652 echo 'class="' . esc_attr( $link['class'] ) . '" ';
653 }
654 if ( isset( $link['id'] ) ) {
655 echo 'id="' . esc_attr( $link['id'] ) . '" ';
656 }
657 ?>
658 >
659 <?php FrmAppHelper::icon_by_class( $link['icon'], array( 'aria-hidden' => 'true' ) ); ?>
660 <span class="frm_link_label"><?php echo esc_html( $link['label'] ); ?></span>
661 </a>
662 </div>
663 <?php
664 }//end foreach
665 }
666
667 /**
668 * @since 3.0
669 */
670 private static function get_action_links( $id, $entry ) {
671 $page = FrmAppHelper::get_param( 'frm_action' );
672 $actions = array();
673
674 if ( $page !== 'show' ) {
675 $actions['frm_view'] = array(
676 'url' => admin_url( 'admin.php?page=formidable-entries&frm_action=show&id=' . $id . '&form=' . $entry->form_id ),
677 'label' => __( 'View Entry', 'formidable' ),
678 'icon' => 'frm_icon_font frm_save_icon',
679 );
680 }
681
682 if ( current_user_can( 'frm_delete_entries' ) ) {
683 $actions['frm_delete'] = array(
684 'url' => wp_nonce_url( admin_url( 'admin.php?page=formidable-entries&frm_action=destroy&id=' . $id . '&form=' . $entry->form_id ) ),
685 'label' => __( 'Delete Entry', 'formidable' ),
686 'icon' => 'frm_icon_font frm_delete_icon',
687 'data' => array(
688 'frmverify' => __( 'Delete this form entry?', 'formidable' ),
689 ),
690 );
691 }
692
693 if ( $page === 'show' ) {
694 $actions['frm_print'] = array(
695 'url' => '#',
696 'label' => __( 'Print Entry', 'formidable' ),
697 'data' => array(
698 'frmprint' => '1',
699 ),
700 'icon' => 'frm_icon_font frm_printer_icon',
701 );
702 }
703
704 $actions['frm_resend'] = array(
705 'url' => '#',
706 'label' => __( 'Resend Emails', 'formidable' ),
707 'class' => 'frm_noallow',
708 'data' => array(
709 'upgrade' => __( 'Resend Emails', 'formidable' ),
710 'medium' => 'resend-email',
711 'content' => 'entry',
712 ),
713 'icon' => 'frm_icon_font frm_email_icon',
714 );
715
716 if ( ! function_exists( 'frm_pdfs_autoloader' ) && FrmAppHelper::show_new_feature( 'pdfs' ) ) {
717 $actions['frm_download_pdf'] = array(
718 'url' => '#',
719 'label' => __( 'Download as PDF', 'formidable' ),
720 'class' => 'frm_noallow',
721 'data' => self::get_pdfs_upgrade_link_data( 'download-pdf-entry' ),
722 'icon' => 'frm_icon_font frm_download_icon',
723 );
724 }
725
726 $actions['frm_edit'] = array(
727 'url' => '#',
728 'label' => __( 'Edit Entry', 'formidable' ),
729 'class' => 'frm_noallow',
730 'data' => array(
731 'upgrade' => __( 'Entry edits', 'formidable' ),
732 'medium' => 'edit-entries',
733 'content' => 'entry',
734 ),
735 'icon' => 'frm_icon_font frm_pencil_icon',
736 );
737
738 return apply_filters( 'frm_entry_actions_dropdown', $actions, compact( 'id', 'entry' ) );
739 }
740
741 /**
742 * Gets data attributes for PDFs addon upgrade link.
743 *
744 * @param string $medium The source of the upgrade link used for analytics data.
745 * @return array
746 */
747 private static function get_pdfs_upgrade_link_data( $medium = 'pdfs' ) {
748 $data = array(
749 'oneclick' => '',
750 'requires' => '',
751 'upgrade' => __( 'Forms to PDF', 'formidable' ),
752 'medium' => $medium,
753 );
754
755 $upgrading = FrmAddonsController::install_link( 'pdfs' );
756 if ( isset( $upgrading['url'] ) ) {
757 $data['oneclick'] = json_encode( $upgrading );
758 } else {
759 $data['requires'] = FrmAddonsController::get_addon_required_plan( 28136428 );
760 }
761
762 return $data;
763 }
764
765 /**
766 * @since 5.0.15
767 *
768 * @param int|string $entry_id
769 * @return void
770 */
771 public static function maybe_render_captcha_score( $entry_id ) {
772 $query = array(
773 'item_id' => (int) $entry_id,
774 'field_id' => 0,
775 );
776 $metas_without_a_field = (array) FrmEntryMeta::getAll( $query, ' ORDER BY it.created_at DESC', '', true );
777 foreach ( $metas_without_a_field as $meta ) {
778 if ( ! empty( $meta->meta_value['captcha_score'] ) ) {
779 echo '<div class="misc-pub-section">';
780 FrmAppHelper::icon_by_class( 'frm_icon_font frm_shield_check_icon', array( 'aria-hidden' => 'true' ) );
781 echo ' ' . esc_html__( 'reCAPTCHA Score', 'formidable' ) . ': ';
782 echo '<b>' . esc_html( $meta->meta_value['captcha_score'] ) . '</b>';
783 echo '</div>';
784 return;
785 }
786 }
787 }
788
789 /**
790 * Return entry status based on is_draft column value.
791 *
792 * @since 6.5
793 *
794 * @param int $status is_draft column.
795 *
796 * @return int
797 */
798 public static function get_entry_status( $status ) {
799 $statuses = self::get_entry_statuses();
800
801 if ( array_key_exists( $status, $statuses ) ) {
802 return $status;
803 }
804
805 if ( empty( $status ) ) {
806 // If the status is empty, let's default to 0.
807 return self::SUBMITTED_ENTRY_STATUS;
808 }
809
810 // If it has a value that isn't in the array, let's default to 1. There may be old entries that don't have a value for is_draft.
811 return self::DRAFT_ENTRY_STATUS;
812 }
813
814 /**
815 * Return entry status label based on passed value.
816 *
817 * @since 6.5
818 *
819 * @param int $status is_draft column.
820 *
821 * @return string
822 */
823 public static function get_entry_status_label( $status ) {
824 $statuses = self::get_entry_statuses();
825
826 return $statuses[ self::get_entry_status( $status ) ];
827 }
828
829 /**
830 * Get all entry statuses.
831 *
832 * @since 6.5
833 * @since 6.6 function went from private to public.
834 *
835 * @return array<string>
836 */
837 public static function get_entry_statuses() {
838
839 $default_entry_statuses = array(
840 self::SUBMITTED_ENTRY_STATUS => __( 'Submitted', 'formidable' ),
841 self::DRAFT_ENTRY_STATUS => __( 'Draft', 'formidable' ),
842 );
843
844 /**
845 * Register entry status.
846 *
847 * "2" is used in abandonment-addon and reserved for "In progress".
848 * "3" is used in abandonment-addon and reserved for "Abandoned".
849 *
850 * @since 6.5
851 *
852 * @param array<string> $extended_entry_status Entry statuses.
853 */
854 $extended_entry_status = apply_filters( 'frm_entry_statuses', array() );
855
856 if ( ! is_array( $extended_entry_status ) ) {
857 _doing_it_wrong( __METHOD__, esc_html__( 'Entry status must be return in array format.', 'formidable' ), '6.5' );
858 $extended_entry_status = array();
859 }
860
861 $existing_entry_statuses = array_replace( $default_entry_statuses, $extended_entry_status );
862
863 return $existing_entry_statuses;
864 }
865 }
866