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/models/FrmForm.php +271 -152 6.25 → trunk View file →
@@ -6,8 +6,9 @@
6 6 class FrmForm {
7 7
8 8 /**
9 9 * @param array $values
10 + *
10 11 * @return bool|int id on success or false on failure.
11 12 */
12 13 public static function create( $values ) {
13 14 global $wpdb;
@@ -15,9 +16,9 @@
15 16 $values = FrmAppHelper::maybe_filter_array( $values, array( 'name', 'description' ) );
16 17
17 18 $new_values = array(
18 19 'form_key' => FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key' ),
19 - 'name' => $values['name'],
20 + 'name' => FrmAppHelper::truncate( $values['name'], 255, 1, '', true ),
20 21 'description' => $values['description'],
21 22 'status' => $values['status'] ?? 'published',
22 23 'logged_in' => $values['logged_in'] ?? 0,
23 24 'is_template' => isset( $values['is_template'] ) ? (int) $values['is_template'] : 0,
@@ -59,8 +60,9 @@
59 60 /**
60 61 * @since 5.0.08
61 62 *
62 63 * @param array $options
64 + *
63 65 * @return array
64 66 */
65 67 private static function maybe_filter_form_options( $options ) {
66 68 if ( ! FrmAppHelper::allow_unfiltered_html() && ! empty( $options['submit_html'] ) ) {
@@ -69,8 +71,15 @@
69 71 return FrmAppHelper::maybe_filter_array( $options, array( 'submit_value', 'success_msg', 'before_html', 'after_html' ) );
70 72 }
71 73
72 74 /**
75 + * Duplicate a form.
76 + *
77 + * @param int $id Form ID to duplicate.
78 + * @param bool $template Whether the duplicated form is a template.
79 + * @param bool $copy_keys Whether to copy the original form key.
80 + * @param false|int $blog_id Blog ID when duplicating across sites, or false for current site.
81 + *
73 82 * @return bool|int ID on success or false on failure
74 83 */
75 84 public static function duplicate( $id, $template = false, $copy_keys = false, $blog_id = false ) {
76 85 global $wpdb;
@@ -75,8 +84,9 @@
75 84 public static function duplicate( $id, $template = false, $copy_keys = false, $blog_id = false ) {
76 85 global $wpdb;
77 86
78 87 $values = self::getOne( $id, $blog_id );
88 +
79 89 if ( ! $values ) {
80 90 return false;
81 91 }
82 92
@@ -116,9 +126,9 @@
116 126
117 127 $form_id = $wpdb->insert_id;
118 128 FrmField::duplicate( $id, $form_id, $copy_keys, $blog_id );
119 129
120 - // update form settings after fields are created
130 + // Update form settings after fields are created
121 131 do_action( 'frm_after_duplicate_form', $form_id, $new_values, array( 'old_id' => $id ) );
122 132
123 133 return $form_id;
124 134 }
@@ -125,8 +135,14 @@
125 135
126 136 return false;
127 137 }
128 138
139 + /**
140 + * @param int $form_id
141 + * @param array $values
142 + *
143 + * @return void
144 + */
129 145 public static function after_duplicate( $form_id, $values ) {
130 146 $new_opts = $values['options'];
131 147 FrmAppHelper::unserialize_or_decode( $new_opts );
132 148 $values['options'] = $new_opts;
@@ -136,8 +152,9 @@
136 152 }
137 153
138 154 $new_opts = apply_filters( 'frm_after_duplicate_form_values', $new_opts, $form_id );
139 155
156 + // phpcs:ignore Universal.Operators.StrictComparisons
140 157 if ( $new_opts != $values['options'] ) {
141 158 global $wpdb;
142 159 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $new_opts ) ), array( 'id' => $form_id ) );
143 160 }
@@ -148,17 +165,22 @@
148 165 /**
149 166 * Switches field ID in fields.
150 167 *
151 168 * @since 5.3
169 + * @since 6.35 The description column is checked too, so a field id in a description survives a
170 + * duplicate or import when the field it points at is created afterwards.
152 171 *
153 172 * @param int $form_id Form ID.
173 + *
174 + * @return void
154 175 */
155 176 private static function switch_field_ids_in_fields( $form_id ) {
156 177 global $wpdb;
157 178
158 179 // Keys of fields that you want to check to replace field ID.
159 - $keys = array( 'default_value', 'field_options' );
180 + $keys = array( 'default_value', 'description', 'field_options' );
160 181 $sql_cols = 'fi.id';
182 +
161 183 foreach ( $keys as $key ) {
162 184 $sql_cols .= ',fi.' . $key;
163 185 }
164 186
@@ -186,11 +208,14 @@
186 208 *
187 209 * @since 5.3
188 210 *
189 211 * @param array $field Field array.
212 + *
213 + * @return void
190 214 */
191 215 private static function switch_field_ids_in_field( $field ) {
192 216 $new_values = array();
217 +
193 218 foreach ( $field as $key => $value ) {
194 219 if ( 'id' === $key || ! $value ) {
195 220 continue;
196 221 }
@@ -212,14 +237,20 @@
212 237 $new_values[ $key ] = $new_val;
213 238 }
214 239 }//end foreach
215 240
216 - if ( ! empty( $new_values ) ) {
241 + if ( $new_values ) {
217 242 FrmField::update( $field['id'], $new_values );
218 243 }
219 244 }
220 245
221 246 /**
247 + * Update a form.
248 + *
249 + * @param int $id Form ID.
250 + * @param array $values Form values to update.
251 + * @param bool $create_link Whether this is being called from link creation.
252 + *
222 253 * @return bool|int
223 254 */
224 255 public static function update( $id, $values, $create_link = false ) {
225 256 global $wpdb;
@@ -234,14 +265,13 @@
234 265 $values['form_key'] = FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key', $id );
235 266 }
236 267
237 268 $form_fields = array( 'form_key', 'name', 'description', 'status', 'parent_form_id' );
269 + $new_values = self::set_update_options( array(), $values, array( 'form_id' => $id ) );
238 270
239 - $new_values = self::set_update_options( array(), $values, array( 'form_id' => $id ) );
240 -
241 271 foreach ( $values as $value_key => $value ) {
242 - if ( $value_key && in_array( $value_key, $form_fields ) ) {
243 - $new_values[ $value_key ] = $value;
272 + if ( $value_key && in_array( $value_key, $form_fields, true ) ) {
273 + $new_values[ $value_key ] = 'name' === $value_key ? FrmAppHelper::truncate( $value, 255, 1, '', true ) : $value;
244 274 }
245 275 }
246 276
247 277 if ( ! empty( $values['new_status'] ) ) {
@@ -247,10 +277,11 @@
247 277 if ( ! empty( $values['new_status'] ) ) {
248 278 $new_values['status'] = $values['new_status'];
249 279 }
250 280
251 - if ( ! empty( $new_values ) ) {
281 + if ( $new_values ) {
252 282 $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', $new_values, array( 'id' => $id ) );
283 +
253 284 if ( $query_results ) {
254 285 self::clear_form_cache();
255 286 }
256 287 } else {
@@ -269,8 +300,9 @@
269 300 /**
270 301 * @param array $new_values
271 302 * @param array $values
272 303 * @param array $args
304 + *
273 305 * @return array
274 306 */
275 307 public static function set_update_options( $new_values, $values, $args = array() ) {
276 308 if ( ! isset( $values['options'] ) ) {
@@ -282,9 +314,9 @@
282 314
283 315 $options['custom_style'] = $values['options']['custom_style'] ?? 0;
284 316 $options['before_html'] = $values['options']['before_html'] ?? FrmFormsHelper::get_default_html( 'before' );
285 317 $options['after_html'] = $values['options']['after_html'] ?? FrmFormsHelper::get_default_html( 'after' );
286 - $options['submit_html'] = isset( $values['options']['submit_html'] ) && '' !== $values['options']['submit_html'] ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html( 'submit' );
318 + $options['submit_html'] = isset( $values['options']['submit_html'] ) && '' !== $values['options']['submit_html'] ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html( 'submit' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
287 319
288 320 /**
289 321 * Allows modifying form options before updating or creating.
290 322 *
@@ -301,11 +333,14 @@
301 333 return $new_values;
302 334 }
303 335
304 336 /**
337 + * @param int $id Form ID.
338 + * @param array $values Form values array.
339 + *
305 340 * @return array
306 341 */
307 - public static function update_fields( $id, $values ) {
342 + public static function update_fields( $id, $values ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
308 343
309 344 if ( ! isset( $values['item_meta'] ) && ! isset( $values['field_options'] ) ) {
310 345 return $values;
311 346 }
@@ -310,9 +345,10 @@
310 345 return $values;
311 346 }
312 347
313 348 $all_fields = FrmField::get_all_for_form( $id );
314 - if ( empty( $all_fields ) ) {
349 +
350 + if ( ! $all_fields ) {
315 351 return $values;
316 352 }
317 353
318 354 if ( ! isset( $values['item_meta'] ) ) {
@@ -320,28 +356,28 @@
320 356 }
321 357
322 358 $field_array = array();
323 359 $existing_keys = array_keys( $values['item_meta'] );
360 +
324 361 foreach ( $all_fields as $fid ) {
362 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict, SlevomatCodingStandard.Files.LineLength.LineTooLong
325 363 if ( ! in_array( $fid->id, $existing_keys ) && ( isset( $values['frm_fields_submitted'] ) && in_array( $fid->id, $values['frm_fields_submitted'] ) ) || isset( $values['options'] ) ) {
326 364 $values['item_meta'][ $fid->id ] = '';
327 365 }
366 +
328 367 $field_array[ $fid->id ] = $fid;
329 368 }
330 369 unset( $all_fields );
331 370
332 371 foreach ( $values['item_meta'] as $field_id => $default_value ) {
333 - if ( isset( $field_array[ $field_id ] ) ) {
334 - $field = $field_array[ $field_id ];
335 - } else {
336 - $field = FrmField::getOne( $field_id );
337 - }
372 + $field = $field_array[ $field_id ] ?? FrmField::getOne( $field_id );
338 373
339 374 if ( ! $field ) {
340 375 continue;
341 376 }
342 377
343 - $is_settings_page = ( isset( $values['options'] ) || isset( $values['field_options'][ 'custom_html_' . $field_id ] ) );
378 + $is_settings_page = isset( $values['options'] ) || isset( $values['field_options'][ 'custom_html_' . $field_id ] );
379 +
344 380 if ( $is_settings_page ) {
345 381 self::get_settings_page_html( $values, $field );
346 382
347 383 if ( ! defined( 'WP_IMPORTING' ) ) {
@@ -370,15 +406,17 @@
370 406 'field_options' => $field->field_options,
371 407 'default_value' => isset( $values[ 'default_value_' . $field_id ] ) ? FrmAppHelper::maybe_json_encode( $values[ 'default_value_' . $field_id ] ) : '',
372 408 );
373 409
374 - if ( ! FrmAppHelper::allow_unfiltered_html() && isset( $values['field_options'][ 'options_' . $field_id ] ) && is_array( $values['field_options'][ 'options_' . $field_id ] ) ) {
410 + if ( ! FrmAppHelper::allow_unfiltered_html() && isset( $values['field_options'][ 'options_' . $field_id ] ) && is_array( $values['field_options'][ 'options_' . $field_id ] ) ) { // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
375 411 foreach ( $values['field_options'][ 'options_' . $field_id ] as $option_key => $option ) {
376 - if ( is_array( $option ) ) {
377 - foreach ( $option as $key => $item ) {
378 - $values['field_options'][ 'options_' . $field_id ][ $option_key ][ $key ] = FrmAppHelper::kses( $item, 'all' );
379 - }
412 + if ( ! is_array( $option ) ) {
413 + continue;
380 414 }
415 +
416 + foreach ( $option as $key => $item ) {
417 + $values['field_options'][ 'options_' . $field_id ][ $option_key ][ $key ] = FrmAppHelper::kses( $item, 'all' );
418 + }
381 419 }
382 420 }
383 421
384 422 self::prepare_field_update_values( $field, $values, $new_field );
@@ -397,31 +435,34 @@
397 435 * Resets the 'max' option of a field when changing paragraph field type to other field types like text, email etc.
398 436 *
399 437 * @since 6.7
400 438 *
401 - * @param array $field
402 - * @param array $values
403 - * @param array $new_field
439 + * @param object $field
440 + * @param array $values
441 + * @param array $new_field
442 + *
404 443 * @return void
405 444 */
406 445 private static function maybe_update_max_option( $field, $values, &$new_field ) {
407 - if ( $field->type === 'textarea' &&
408 - ! empty( $values['field_options'][ 'type_' . $field->id ] ) &&
409 - in_array( $values['field_options'][ 'type_' . $field->id ], array( 'text', 'email', 'url', 'password', 'phone' ), true ) ) {
446 + if ( $field->type !== 'textarea' ||
447 + empty( $values['field_options'][ 'type_' . $field->id ] ) ||
448 + ! in_array( $values['field_options'][ 'type_' . $field->id ], array( 'text', 'email', 'url', 'password', 'phone' ), true ) ) {
449 + return;
450 + }
410 451
411 - $new_field['field_options']['max'] = '';
452 + $new_field['field_options']['max'] = '';
412 453
413 - /**
414 - * Update posted field setting so that new 'max' option is displayed after form is saved and page reloads.
415 - * FrmFieldsHelper::fill_default_field_opts populates field options by calling self::get_posted_field_setting.
416 - */
417 - $_POST['field_options'][ 'max_' . $field->id ] = '';
418 - }
454 + /**
455 + * Update posted field setting so that new 'max' option is displayed after form is saved and page reloads.
456 + * FrmFieldsHelper::fill_default_field_opts populates field options by calling self::get_posted_field_setting.
457 + */
458 + $_POST['field_options'][ 'max_' . $field->id ] = '';
419 459 }
420 460
421 461 /**
422 462 * @param string $opt
423 463 * @param mixed $value
464 + *
424 465 * @return void
425 466 */
426 467 private static function sanitize_field_opt( $opt, &$value ) {
427 468 if ( ! is_string( $value ) ) {
@@ -442,23 +483,19 @@
442 483 if ( ! $should_sanitize ) {
443 484 return;
444 485 }
445 486
446 - if ( $opt === 'calc' ) {
447 - $value = self::sanitize_calc( $value );
448 - } else {
449 - $value = FrmAppHelper::kses( $value, 'all' );
450 - }
451 -
487 + $value = $opt === 'calc' ? self::sanitize_calc( $value ) : FrmAppHelper::kses( $value, 'all' );
452 488 $value = trim( $value );
453 489 }
454 490
455 491 /**
456 492 * @param string $value
493 + *
457 494 * @return string
458 495 */
459 496 private static function sanitize_calc( $value ) {
460 - if ( false !== strpos( $value, '<' ) ) {
497 + if ( str_contains( $value, '<' ) ) {
461 498 $value = self::normalize_calc_spaces( $value );
462 499 }
463 500 // Allow <= and >=.
464 501 $allow = array( '<= ', ' >=' );
@@ -464,10 +501,9 @@
464 501 $allow = array( '<= ', ' >=' );
465 502 $temp = array( '< = ', ' > =' );
466 503 $value = str_replace( $allow, $temp, $value );
467 504 $value = strip_tags( $value );
468 - $value = str_replace( $temp, $allow, $value );
469 - return $value;
505 + return str_replace( $temp, $allow, $value );
470 506 }
471 507
472 508 /**
473 509 * Format a comparison like 5<10 to 5 < 10. Also works on 5< 10, 5 <10, 5<=10 variations.
@@ -473,8 +509,9 @@
473 509 * Format a comparison like 5<10 to 5 < 10. Also works on 5< 10, 5 <10, 5<=10 variations.
474 510 * This is to avoid an issue with unspaced calculations being recognized as HTML that gets removed when strip_tags is called.
475 511 *
476 512 * @param string $calc
513 + *
477 514 * @return string
478 515 */
479 516 private static function normalize_calc_spaces( $calc ) {
480 517 // Check for a pattern with 5 parts
@@ -482,15 +519,18 @@
482 519 // $2 a space (optional).
483 520 // $3 an equals sign (optional) that follows the < operator for <= comparisons.
484 521 // $4 another space (optional).
485 522 // $5 \d|\[ the second comparison digit or the start of a comparison shortcode.
486 - $calc = preg_replace( '/(\d|\])( ){0,1}<(=){0,1}( ){0,1}(\d|\[)/', '$1 <$3 $5', $calc );
487 -
488 - return $calc;
523 + return preg_replace( '/(\d|\])( ){0,1}<(=){0,1}( ){0,1}(\d|\[)/', '$1 <$3 $5', $calc );
489 524 }
490 525
491 526 /**
492 527 * Updating the settings page
528 + *
529 + * @param array $values Form values array.
530 + * @param object $field Field object, passed by reference.
531 + *
532 + * @return void
493 533 */
494 534 private static function get_settings_page_html( $values, &$field ) {
495 535 if ( isset( $values['field_options'][ 'custom_html_' . $field->id ] ) ) {
496 536 $prev_opts = array();
@@ -500,16 +540,27 @@
500 540 } elseif ( $field->type === 'hidden' || $field->type === 'user_id' ) {
501 541 $prev_opts = $field->field_options;
502 542 }
503 543
504 - if ( isset( $prev_opts ) ) {
505 - $field->field_options = apply_filters( 'frm_update_form_field_options', $field->field_options, $field, $values );
506 - if ( $prev_opts != $field->field_options ) {
507 - FrmField::update( $field->id, array( 'field_options' => $field->field_options ) );
508 - }
544 + if ( ! isset( $prev_opts ) ) {
545 + return;
509 546 }
547 +
548 + $field->field_options = apply_filters( 'frm_update_form_field_options', $field->field_options, $field, $values );
549 +
550 + // phpcs:ignore Universal.Operators.StrictComparisons
551 + if ( $prev_opts != $field->field_options ) {
552 + FrmField::update( $field->id, array( 'field_options' => $field->field_options ) );
553 + }
510 554 }
511 555
556 + /**
557 + * @param object $field
558 + * @param array $values
559 + * @param array $new_field
560 + *
561 + * @return void
562 + */
512 563 private static function prepare_field_update_values( $field, $values, &$new_field ) {
513 564 $field_cols = array(
514 565 'field_order' => 0,
515 566 'field_key' => '',
@@ -518,8 +569,9 @@
518 569 'description' => '',
519 570 'options' => '',
520 571 'name' => '',
521 572 );
573 +
522 574 foreach ( $field_cols as $col => $default ) {
523 575 $default = $default === '' ? $field->{$col} : $default;
524 576 $new_field[ $col ] = $values['field_options'][ $col . '_' . $field->id ] ?? $default;
525 577 }
@@ -538,9 +590,12 @@
538 590 * Get a list of all form settings that should be translated
539 591 * on a multilingual site.
540 592 *
541 593 * @since 3.06.01
594 + *
542 595 * @param object $form The form object.
596 + *
597 + * @return array
543 598 */
544 599 public static function translatable_strings( $form ) {
545 600 $strings = array(
546 601 'name',
@@ -557,19 +612,20 @@
557 612 return apply_filters( 'frm_form_strings', $strings, $form );
558 613 }
559 614
560 615 /**
561 - * @param int $id
562 - * @param string $status
616 + * @param array|int $id
617 + * @param string $status
563 618 *
564 619 * @return bool|int
565 620 */
566 621 public static function set_status( $id, $status ) {
567 - if ( 'trash' == $status ) {
622 + if ( 'trash' === $status ) {
568 623 return self::trash( $id );
569 624 }
570 625
571 626 $statuses = array( 'published', 'draft', 'trash' );
627 +
572 628 if ( ! in_array( $status, $statuses, true ) ) {
573 629 return false;
574 630 }
575 631
@@ -583,9 +639,9 @@
583 639 );
584 640 FrmDb::get_where_clause_and_values( $where );
585 641 array_unshift( $where['values'], $status );
586 642
587 - $query_results = $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->prefix . 'frm_forms SET status = %s ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
643 + $query_results = $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->prefix . 'frm_forms SET status = %s ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, SlevomatCodingStandard.Files.LineLength.LineTooLong
588 644 } else {
589 645 $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'id' => $id ) );
590 646 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'parent_form_id' => $id ) );
591 647 }
@@ -597,8 +653,10 @@
597 653 return $query_results;
598 654 }
599 655
600 656 /**
657 + * @param int|string $id Form ID.
658 + *
601 659 * @return bool|int
602 660 */
603 661 public static function trash( $id ) {
604 662 if ( ! EMPTY_TRASH_DAYS ) {
@@ -605,8 +663,9 @@
605 663 return self::destroy( $id );
606 664 }
607 665
608 666 $form = self::getOne( $id );
667 +
609 668 if ( ! $form ) {
610 669 return false;
611 670 }
612 671
@@ -647,8 +706,10 @@
647 706 return $query_results;
648 707 }
649 708
650 709 /**
710 + * @param int|string $id Form ID.
711 + *
651 712 * @return bool|int
652 713 */
653 714 public static function destroy( $id ) {
654 715 global $wpdb;
@@ -653,15 +714,18 @@
653 714 public static function destroy( $id ) {
654 715 global $wpdb;
655 716
656 717 $form = self::getOne( $id );
718 +
657 719 if ( ! $form ) {
658 720 return false;
659 721 }
722 +
660 723 $id = $form->id;
661 724
662 725 // Disconnect the entries from this form
663 - $entries = FrmDb::get_col( $wpdb->prefix . 'frm_items', array( 'form_id' => $id ) );
726 + $entries = FrmDb::get_col( 'frm_items', array( 'form_id' => $id ) );
727 +
664 728 foreach ( $entries as $entry_id ) {
665 729 FrmEntry::destroy( $entry_id );
666 730 unset( $entry_id );
667 731 }
@@ -666,26 +730,29 @@
666 730 unset( $entry_id );
667 731 }
668 732
669 733 // Disconnect the fields from this form
670 - $wpdb->query( $wpdb->prepare( 'DELETE fi FROM ' . $wpdb->prefix . 'frm_fields AS fi LEFT JOIN ' . $wpdb->prefix . 'frm_forms fr ON (fi.form_id = fr.id) WHERE fi.form_id=%d OR parent_form_id=%d', $id, $id ) );
734 + $wpdb->query( $wpdb->prepare( 'DELETE fi FROM ' . $wpdb->prefix . 'frm_fields AS fi LEFT JOIN ' . $wpdb->prefix . 'frm_forms fr ON (fi.form_id = fr.id) WHERE fi.form_id=%d OR parent_form_id=%d', $id, $id ) ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
671 735
672 736 $query_results = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_forms WHERE id=%d OR parent_form_id=%d', $id, $id ) );
673 - if ( $query_results ) {
674 - // Delete all form actions linked to this form
675 - /**
676 - * @var FrmFormAction
677 - */
678 - $action_control = FrmFormActionsController::get_form_actions( 'email' );
679 - $action_control->destroy( $id, 'all' );
680 737
681 - // Clear form caching
682 - self::clear_form_cache();
738 + if ( ! $query_results ) {
739 + return $query_results;
740 + }
683 741
684 - do_action( 'frm_destroy_form', $id );
685 - do_action( 'frm_destroy_form_' . $id );
686 - }
742 + // Delete all form actions linked to this form
743 + /**
744 + * @var FrmFormAction
745 + */
746 + $action_control = FrmFormActionsController::get_form_actions( 'email' );
747 + $action_control->destroy( $id, 'all' );
687 748
749 + // Clear form caching
750 + self::clear_form_cache();
751 +
752 + do_action( 'frm_destroy_form', $id );
753 + do_action( 'frm_destroy_form_' . $id );
754 +
688 755 return $query_results;
689 756 }
690 757
691 758 /**
@@ -690,28 +757,31 @@
690 757
691 758 /**
692 759 * Delete trashed forms based on how long they have been trashed
693 760 *
761 + * @param int|string $delete_timestamp Timestamp cutoff for deletion.
762 + *
694 763 * @return int The number of forms deleted
695 764 */
696 765 public static function scheduled_delete( $delete_timestamp = '' ) {
697 - global $wpdb;
766 + $trash_forms = FrmDb::get_results( 'frm_forms', array( 'status' => 'trash' ), 'id, parent_form_id, options' );
698 767
699 - $trash_forms = FrmDb::get_results( $wpdb->prefix . 'frm_forms', array( 'status' => 'trash' ), 'id, parent_form_id, options' );
700 -
701 768 if ( ! $trash_forms ) {
702 769 return 0;
703 770 }
704 771
705 - if ( empty( $delete_timestamp ) ) {
772 + if ( ! $delete_timestamp ) {
706 773 $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
707 774 }
708 775
709 776 $count = 0;
777 +
710 778 foreach ( $trash_forms as $form ) {
711 779 FrmAppHelper::unserialize_or_decode( $form->options );
780 +
712 781 if ( ! isset( $form->options['trash_time'] ) || $form->options['trash_time'] < $delete_timestamp ) {
713 782 self::destroy( $form->id );
783 +
714 784 if ( empty( $form->parent_form_id ) ) {
715 785 ++$count;
716 786 }
717 787 }
@@ -722,16 +792,17 @@
722 792 return $count;
723 793 }
724 794
725 795 /**
796 + * @param int|string $id Form ID or key.
797 + *
726 798 * @return string form name
727 799 */
728 800 public static function getName( $id ) {
729 801 $form = FrmDb::check_cache( $id, 'frm_form' );
802 +
730 803 if ( $form ) {
731 - $r = stripslashes( $form->name );
732 -
733 - return $r;
804 + return stripslashes( $form->name );
734 805 }
735 806
736 807 $query_key = is_numeric( $id ) ? 'id' : 'form_key';
737 808 $r = FrmDb::get_var( 'frm_forms', array( $query_key => $id ), 'name' );
@@ -736,11 +807,9 @@
736 807 $query_key = is_numeric( $id ) ? 'id' : 'form_key';
737 808 $r = FrmDb::get_var( 'frm_forms', array( $query_key => $id ), 'name' );
738 809
739 810 // An empty form name can result in a null value.
740 - $r = is_null( $r ) ? '' : stripslashes( $r );
741 -
742 - return $r;
811 + return is_null( $r ) ? '' : stripslashes( $r );
743 812 }
744 813
745 814 /**
746 815 * @since 3.0
@@ -755,9 +824,9 @@
755 824
756 825 /**
757 826 * @since 3.0
758 827 *
759 - * @param int $id
828 + * @param int|string $id
760 829 *
761 830 * @return string form key
762 831 */
763 832 public static function get_key_by_id( $id ) {
@@ -762,15 +831,14 @@
762 831 */
763 832 public static function get_key_by_id( $id ) {
764 833 $id = (int) $id;
765 834 $cache = FrmDb::check_cache( $id, 'frm_form' );
835 +
766 836 if ( $cache ) {
767 837 return $cache->form_key;
768 838 }
769 839
770 - $key = FrmDb::get_var( 'frm_forms', array( 'id' => $id ), 'form_key' );
771 -
772 - return $key;
840 + return FrmDb::get_var( 'frm_forms', array( 'id' => $id ), 'form_key' );
773 841 }
774 842
775 843 /**
776 844 * If $form is numeric, get the form object
@@ -775,12 +843,15 @@
775 843 /**
776 844 * If $form is numeric, get the form object
777 845 *
778 846 * @since 2.0.9
779 - * @param int|object $form
847 + *
848 + * @param array|int|object $form
849 + *
850 + * @return void
780 851 */
781 852 public static function maybe_get_form( &$form ) {
782 - if ( ! is_object( $form ) && ! is_array( $form ) && ! empty( $form ) ) {
853 + if ( ! is_object( $form ) && ! is_array( $form ) && $form ) {
783 854 $form = self::getOne( $form );
784 855 }
785 856 }
786 857
@@ -786,8 +857,9 @@
786 857
787 858 /**
788 859 * @param int|string $id
789 860 * @param false|int $blog_id
861 + *
790 862 * @return stdClass|null
791 863 */
792 864 public static function getOne( $id, $blog_id = false ) {
793 865 global $wpdb;
@@ -792,29 +864,24 @@
792 864 public static function getOne( $id, $blog_id = false ) {
793 865 global $wpdb;
794 866
795 867 if ( $blog_id && is_multisite() ) {
796 - global $wpmuBaseTablePrefix;
797 - $prefix = $wpmuBaseTablePrefix ? $wpmuBaseTablePrefix . $blog_id . '_' : $wpdb->get_blog_prefix( $blog_id );
798 -
868 + $prefix = $wpdb->get_blog_prefix( $blog_id );
799 869 $table_name = $prefix . 'frm_forms';
800 870 } else {
801 871 $table_name = $wpdb->prefix . 'frm_forms';
802 872 $cache = wp_cache_get( $id, 'frm_form' );
873 +
803 874 if ( $cache ) {
804 875 if ( isset( $cache->options ) ) {
805 876 FrmAppHelper::unserialize_or_decode( $cache->options );
806 877 }
878 +
807 879 return self::prepare_form_row_data( $cache );
808 880 }
809 881 }
810 882
811 - if ( is_numeric( $id ) ) {
812 - $where = array( 'id' => $id );
813 - } else {
814 - $where = array( 'form_key' => $id );
815 - }
816 -
883 + $where = is_numeric( $id ) ? array( 'id' => $id ) : array( 'form_key' => $id );
817 884 $results = FrmDb::get_row( $table_name, $where );
818 885
819 886 if ( isset( $results->options ) ) {
820 887 FrmDb::set_cache( $results->id, $results, 'frm_form' );
@@ -829,12 +896,14 @@
829 896 *
830 897 * @since 6.8.3
831 898 *
832 899 * @param stdClass|null $row The database row for a target form.
900 + *
833 901 * @return stdClass|null
834 902 */
835 903 private static function prepare_form_row_data( $row ) {
836 904 $row = wp_unslash( $row );
905 +
837 906 if ( ! is_object( $row ) ) {
838 907 return $row;
839 908 }
840 909
@@ -850,14 +919,18 @@
850 919 return apply_filters( 'frm_form_object', $row );
851 920 }
852 921
853 922 /**
854 - * @return array|object of objects
923 + * @param array|string $where Where conditions array or raw WHERE string.
924 + * @param string $order_by Order by clause.
925 + * @param int|string $limit Limit clause or number.
926 + *
927 + * @return array|object Array of objects. If $limit is 1, a single object is returned.
855 928 */
856 929 public static function getAll( $where = array(), $order_by = '', $limit = '' ) {
857 - if ( is_array( $where ) && ! empty( $where ) ) {
930 + if ( is_array( $where ) && $where ) {
858 931 if ( ! empty( $where['is_template'] ) && ! isset( $where['status'] ) && ! isset( $where['status !'] ) ) {
859 - // don't get trashed templates
932 + // Don't get trashed templates
860 933 $where['status'] = array( null, '', 'published' );
861 934 }
862 935
863 936 $results = FrmDb::get_results( 'frm_forms', $where, '*', compact( 'order_by', 'limit' ) );
@@ -864,9 +937,9 @@
864 937 } else {
865 938 global $wpdb;
866 939
867 940 // The query has already been prepared if this is not an array.
868 - $query = 'SELECT * FROM ' . $wpdb->prefix . 'frm_forms' . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . FrmDb::esc_order( $order_by ) . FrmDb::esc_limit( $limit );
941 + $query = 'SELECT * FROM ' . $wpdb->prefix . 'frm_forms' . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . FrmDb::esc_order( $order_by ) . FrmDb::esc_limit( $limit ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
869 942 $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
870 943 }
871 944
872 945 if ( $results ) {
@@ -875,10 +948,10 @@
875 948 FrmAppHelper::unserialize_or_decode( $result->options );
876 949 }
877 950 }
878 951
879 - if ( $limit === ' LIMIT 1' || $limit == 1 ) {
880 - // return the first form object if we are only getting one form
952 + if ( $limit === ' LIMIT 1' || (int) $limit === 1 ) {
953 + // Return the first form object if we are only getting one form
881 954 $results = reset( $results );
882 955 }
883 956
884 957 return wp_unslash( $results );
@@ -891,20 +964,20 @@
891 964 *
892 965 * @param array $query
893 966 * @param int $limit
894 967 * @param string $inc_children
895 - * @return array|object of forms A single form object would be passed if $limit was set to 1.
968 + *
969 + * @return array|object Array of forms. A single form object is returned if $limit is set to 1.
896 970 */
897 971 public static function get_published_forms( $query = array(), $limit = 999, $inc_children = 'exclude' ) {
898 972 $query['is_template'] = 0;
899 973 $query['status'] = array( null, '', 'published' );
974 +
900 975 if ( $inc_children === 'exclude' ) {
901 976 $query['parent_form_id'] = array( null, 0 );
902 977 }
903 978
904 - $forms = self::getAll( $query, 'name', $limit );
905 -
906 - return $forms;
979 + return self::getAll( $query, 'name', $limit );
907 980 }
908 981
909 982 /**
910 983 * @return object count of forms
@@ -909,18 +982,16 @@
909 982 /**
910 983 * @return object count of forms
911 984 */
912 985 public static function get_count() {
913 - global $wpdb;
914 -
915 986 $cache_key = 'frm_form_counts';
987 + $counts = wp_cache_get( $cache_key, 'frm_form' );
916 988
917 - $counts = wp_cache_get( $cache_key, 'frm_form' );
918 989 if ( false !== $counts ) {
919 990 return $counts;
920 991 }
921 992
922 - $results = (array) FrmDb::get_results(
993 + $results = FrmDb::get_results(
923 994 'frm_forms',
924 995 array(
925 996 'or' => 1,
926 997 'parent_form_id' => null,
@@ -932,19 +1003,17 @@
932 1003 $statuses = array( 'published', 'draft', 'template', 'trash' );
933 1004 $counts = array_fill_keys( $statuses, 0 );
934 1005
935 1006 foreach ( $results as $row ) {
936 - if ( 'trash' != $row->status ) {
937 - if ( $row->is_template ) {
938 - ++$counts['template'];
939 - } else {
940 - ++$counts['published'];
941 - }
1007 + if ( 'trash' === $row->status ) {
1008 + ++$counts['trash'];
1009 + } elseif ( $row->is_template ) {
1010 + ++$counts['template'];
942 1011 } else {
943 - ++$counts['trash'];
1012 + ++$counts['published'];
944 1013 }
945 1014
946 - if ( 'draft' == $row->status ) {
1015 + if ( 'draft' === $row->status ) {
947 1016 ++$counts['draft'];
948 1017 }
949 1018
950 1019 unset( $row );
@@ -961,8 +1030,10 @@
961 1030 * Called when a form is created, updated, duplicated, or deleted
962 1031 * or when the form status is changed
963 1032 *
964 1033 * @since 2.0.4
1034 + *
1035 + * @return void
965 1036 */
966 1037 public static function clear_form_cache() {
967 1038 FrmDb::cache_delete_group( 'frm_form' );
968 1039 }
@@ -967,23 +1038,29 @@
967 1038 FrmDb::cache_delete_group( 'frm_form' );
968 1039 }
969 1040
970 1041 /**
1042 + * @param array $values Form values to validate.
1043 + *
971 1044 * @return array of errors
972 1045 */
973 1046 public static function validate( $values ) {
974 1047 $errors = array();
975 -
976 1048 return apply_filters( 'frm_validate_form', $errors, $values );
977 1049 }
978 1050
1051 + /**
1052 + * @param object|null $form
1053 + *
1054 + * @return array
1055 + */
979 1056 public static function get_params( $form = null ) {
980 1057 global $frm_vars;
981 1058
982 - if ( ! $form ) {
1059 + if ( $form ) {
1060 + self::maybe_get_form( $form );
1061 + } else {
983 1062 $form = self::getAll( array(), 'name', 1 );
984 - } else {
985 - self::maybe_get_form( $form );
986 1063 }
987 1064
988 1065 if ( isset( $frm_vars['form_params'] ) && is_array( $frm_vars['form_params'] ) && isset( $frm_vars['form_params'][ $form->id ] ) ) {
989 1066 return $frm_vars['form_params'][ $form->id ];
@@ -1006,12 +1083,14 @@
1006 1083 );
1007 1084
1008 1085 $values = array();
1009 1086 $values['posted_form_id'] = FrmAppHelper::get_param( 'form_id', '', 'get', 'absint' );
1087 +
1010 1088 if ( ! $values['posted_form_id'] ) {
1011 1089 $values['posted_form_id'] = FrmAppHelper::get_param( 'form', '', 'get', 'absint' );
1012 1090 }
1013 1091
1092 + // phpcs:ignore Universal.Operators.StrictComparisons
1014 1093 if ( $form->id == $values['posted_form_id'] ) {
1015 1094 // If there are two forms on the same page, make sure not to submit both.
1016 1095 foreach ( $default_values as $var => $default ) {
1017 1096 if ( $var === 'action' ) {
@@ -1027,9 +1106,9 @@
1027 1106 unset( $var, $default );
1028 1107 }
1029 1108 }
1030 1109
1031 - if ( in_array( $values['action'], array( 'create', 'update' ) ) &&
1110 + if ( in_array( $values['action'], array( 'create', 'update' ), true ) &&
1032 1111 ( ! $_POST || ( ! isset( $_POST['action'] ) && ! isset( $_POST['frm_action'] ) ) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing
1033 1112 ) {
1034 1113 $values['action'] = 'new';
1035 1114 }
@@ -1036,8 +1115,11 @@
1036 1115
1037 1116 return $values;
1038 1117 }
1039 1118
1119 + /**
1120 + * @return array
1121 + */
1040 1122 public static function list_page_params() {
1041 1123 $values = array();
1042 1124 $defaults = array(
1043 1125 'template' => 0,
@@ -1047,8 +1129,9 @@
1047 1129 'search' => '',
1048 1130 'sort' => '',
1049 1131 'sdir' => '',
1050 1132 );
1133 +
1051 1134 foreach ( $defaults as $var => $default ) {
1052 1135 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
1053 1136 }
1054 1137
@@ -1054,10 +1137,16 @@
1054 1137
1055 1138 return $values;
1056 1139 }
1057 1140
1141 + /**
1142 + * @param int|object|string|null $form
1143 + *
1144 + * @return array
1145 + */
1058 1146 public static function get_admin_params( $form = null ) {
1059 1147 $form_id = $form;
1148 +
1060 1149 if ( $form === null ) {
1061 1150 $form_id = self::get_current_form_id();
1062 1151 } elseif ( $form && is_object( $form ) ) {
1063 1152 $form_id = $form->id;
@@ -1075,8 +1164,9 @@
1075 1164 'sdir' => '',
1076 1165 'fid' => '',
1077 1166 'keep_post' => '',
1078 1167 );
1168 +
1079 1169 foreach ( $defaults as $var => $default ) {
1080 1170 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
1081 1171 }
1082 1172
@@ -1082,47 +1172,55 @@
1082 1172
1083 1173 return $values;
1084 1174 }
1085 1175
1176 + /**
1177 + * @param string $default_form
1178 + *
1179 + * @return int|string
1180 + */
1086 1181 public static function get_current_form_id( $default_form = 'none' ) {
1087 - if ( 'first' === $default_form ) {
1088 - $form = self::get_current_form();
1089 - } else {
1090 - $form = self::maybe_get_current_form();
1091 - }
1092 - $form_id = $form ? $form->id : 0;
1093 -
1094 - return $form_id;
1182 + $form = 'first' === $default_form ? self::get_current_form() : self::maybe_get_current_form();
1183 + return $form ? $form->id : 0;
1095 1184 }
1096 1185
1186 + /**
1187 + * @param int|string $form_id
1188 + *
1189 + * @return false|int|object|string
1190 + */
1097 1191 public static function maybe_get_current_form( $form_id = 0 ) {
1098 1192 global $frm_vars;
1099 1193
1100 - if ( ! empty( $frm_vars['current_form'] ) && ( ! $form_id || $form_id == $frm_vars['current_form']->id ) ) {
1194 + if ( ! empty( $frm_vars['current_form'] ) && ( ! $form_id || (int) $form_id === (int) $frm_vars['current_form']->id ) ) {
1101 1195 return $frm_vars['current_form'];
1102 1196 }
1103 1197
1104 1198 $form_id = FrmAppHelper::get_param( 'form', $form_id, 'get', 'absint' );
1105 - if ( $form_id ) {
1106 - $form_id = self::set_current_form( $form_id );
1107 - }
1108 1199
1109 - return $form_id;
1200 + return $form_id ? self::set_current_form( $form_id ) : $form_id;
1110 1201 }
1111 1202
1203 + /**
1204 + * @param int $form_id
1205 + *
1206 + * @return false|object
1207 + */
1112 1208 public static function get_current_form( $form_id = 0 ) {
1113 1209 $form = self::maybe_get_current_form( $form_id );
1114 - if ( is_numeric( $form ) ) {
1115 - $form = self::set_current_form( $form );
1116 - }
1117 -
1118 - return $form;
1210 + return is_numeric( $form ) ? self::set_current_form( $form ) : $form;
1119 1211 }
1120 1212
1213 + /**
1214 + * @param int $form_id
1215 + *
1216 + * @return false|object
1217 + */
1121 1218 public static function set_current_form( $form_id ) {
1122 1219 global $frm_vars;
1123 1220
1124 1221 $query = array();
1222 +
1125 1223 if ( $form_id ) {
1126 1224 $query['id'] = $form_id;
1127 1225 }
1128 1226
@@ -1130,11 +1228,19 @@
1130 1228
1131 1229 return $frm_vars['current_form'];
1132 1230 }
1133 1231
1232 + /**
1233 + * @param object $form
1234 + * @param int|string $this_load
1235 + * @param bool $global_load
1236 + *
1237 + * @return bool
1238 + */
1134 1239 public static function is_form_loaded( $form, $this_load, $global_load ) {
1135 1240 global $frm_vars;
1136 1241 $small_form = new stdClass();
1242 +
1137 1243 foreach ( array( 'id', 'form_key', 'name' ) as $var ) {
1138 1244 $small_form->{$var} = $form->{$var};
1139 1245 unset( $var );
1140 1246 }
@@ -1140,9 +1246,9 @@
1140 1246 }
1141 1247
1142 1248 $frm_vars['forms_loaded'][] = $small_form;
1143 1249
1144 - if ( $this_load && empty( $global_load ) ) {
1250 + if ( $this_load && ! $global_load ) {
1145 1251 $global_load = true;
1146 1252 $frm_vars['load_css'] = true;
1147 1253 }
1148 1254
@@ -1155,9 +1261,9 @@
1155 1261 * @param object $form
1156 1262 *
1157 1263 * @return bool
1158 1264 */
1159 - public static function &is_visible_to_user( $form ) {
1265 + public static function is_visible_to_user( $form ) {
1160 1266 if ( $form->logged_in && isset( $form->options['logged_in_role'] ) ) {
1161 1267 $visible = FrmAppHelper::user_has_permission( $form->options['logged_in_role'] );
1162 1268 } else {
1163 1269 $visible = true;
@@ -1168,22 +1274,27 @@
1168 1274 *
1169 1275 * @param bool $visible
1170 1276 * @param object $form
1171 1277 */
1172 - $visible = (bool) apply_filters( 'frm_form_is_visible', $visible, $form );
1173 -
1174 - return $visible;
1278 + return (bool) apply_filters( 'frm_form_is_visible', $visible, $form );
1175 1279 }
1176 1280
1281 + /**
1282 + * @param object $form
1283 + *
1284 + * @return bool
1285 + */
1177 1286 public static function show_submit( $form ) {
1178 - $show = ( ! $form->is_template && $form->status === 'published' && ! FrmAppHelper::is_admin() );
1179 - $show = apply_filters( 'frm_show_submit_button', $show, $form );
1180 -
1181 - return $show;
1287 + $show = ! $form->is_template && $form->status === 'published' && ! FrmAppHelper::is_admin();
1288 + return apply_filters( 'frm_show_submit_button', $show, $form );
1182 1289 }
1183 1290
1184 1291 /**
1185 1292 * @since 2.3
1293 + *
1294 + * @param array $atts Attributes including form, option, and default.
1295 + *
1296 + * @return mixed
1186 1297 */
1187 1298 public static function get_option( $atts ) {
1188 1299 $form = $atts['form'];
1189 1300 $default = $atts['default'] ?? '';
@@ -1194,9 +1305,12 @@
1194 1305 /**
1195 1306 * Get the link to edit this form.
1196 1307 *
1197 1308 * @since 4.0
1309 + *
1198 1310 * @param int $form_id The id of the form.
1311 + *
1312 + * @return string
1199 1313 */
1200 1314 public static function get_edit_link( $form_id ) {
1201 1315 return admin_url( 'admin.php?page=formidable&frm_action=edit&id=' . $form_id );
1202 1316 }
@@ -1206,8 +1320,9 @@
1206 1320 *
1207 1321 * @since 6.2
1208 1322 *
1209 1323 * @param stdClass $form
1324 + *
1210 1325 * @return bool
1211 1326 */
1212 1327 public static function is_ajax_on( $form ) {
1213 1328 return ! empty( $form->options['ajax_submit'] );
@@ -1216,12 +1331,12 @@
1216 1331 /**
1217 1332 * Get the latest form available.
1218 1333 *
1219 1334 * @since 6.8
1335 + *
1220 1336 * @return object
1221 1337 */
1222 1338 public static function get_latest_form() {
1223 -
1224 1339 $args = array(
1225 1340 array(
1226 1341 'or' => 1,
1227 1342 'parent_form_id' => null,
@@ -1237,12 +1352,12 @@
1237 1352 /**
1238 1353 * Count and return total forms.
1239 1354 *
1240 1355 * @since 6.8
1356 + *
1241 1357 * @return int
1242 1358 */
1243 1359 public static function get_forms_count() {
1244 -
1245 1360 $args = array(
1246 1361 array(
1247 1362 'or' => 1,
1248 1363 'parent_form_id' => null,
@@ -1256,11 +1371,13 @@
1256 1371 }
1257 1372
1258 1373 /**
1259 1374 * @deprecated 2.03.05 This is still referenced in a few add ons (API, locations).
1375 + *
1260 1376 * @codeCoverageIgnore
1261 1377 *
1262 1378 * @param string $key
1379 + *
1263 1380 * @return int form id
1264 1381 */
1265 1382 public static function getIdByKey( $key ) {
1266 1383 _deprecated_function( __FUNCTION__, '2.03.05', 'FrmForm::get_id_by_key' );
@@ -1268,11 +1385,13 @@
1268 1385 }
1269 1386
1270 1387 /**
1271 1388 * @deprecated 2.03.05 This is still referenced in the API add on as of v1.13.
1389 + *
1272 1390 * @codeCoverageIgnore
1273 1391 *
1274 1392 * @param int|string $id
1393 + *
1275 1394 * @return string
1276 1395 */
1277 1396 public static function getKeyById( $id ) {
1278 1397 _deprecated_function( __FUNCTION__, '2.03.05', 'FrmForm::get_key_by_id' );