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