PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.4
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.4
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 / models / FrmForm.php

FrmForm.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 5.4, at classes/models/FrmForm.php

1,105 lines 31.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmForm {
7
8 /**
9 * @param array $values
10 * @return int|boolean id on success or false on failure
11 */
12 public static function create( $values ) {
13 global $wpdb;
14
15 $values = FrmAppHelper::maybe_filter_array( $values, array( 'name', 'description' ) );
16
17 $new_values = array(
18 'form_key' => FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key' ),
19 'name' => $values['name'],
20 'description' => $values['description'],
21 'status' => isset( $values['status'] ) ? $values['status'] : 'published',
22 'logged_in' => isset( $values['logged_in'] ) ? $values['logged_in'] : 0,
23 'is_template' => isset( $values['is_template'] ) ? (int) $values['is_template'] : 0,
24 'parent_form_id' => isset( $values['parent_form_id'] ) ? absint( $values['parent_form_id'] ) : 0,
25 'editable' => isset( $values['editable'] ) ? (int) $values['editable'] : 0,
26 'created_at' => isset( $values['created_at'] ) ? $values['created_at'] : current_time( 'mysql', 1 ),
27 );
28
29 $options = isset( $values['options'] ) ? (array) $values['options'] : array();
30 FrmFormsHelper::fill_form_options( $options, $values );
31
32 $options['before_html'] = isset( $values['options']['before_html'] ) ? $values['options']['before_html'] : FrmFormsHelper::get_default_html( 'before' );
33 $options['after_html'] = isset( $values['options']['after_html'] ) ? $values['options']['after_html'] : FrmFormsHelper::get_default_html( 'after' );
34 $options['submit_html'] = isset( $values['options']['submit_html'] ) ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html( 'submit' );
35
36 /**
37 * Allows modifying form options before updating or creating.
38 *
39 * @since 5.4 Add the third param.
40 *
41 * @param array $options Form options.
42 * @param array $values Form data.
43 * @param bool $update Is form updating or creating. It's `true` if is updating.
44 */
45 $options = apply_filters( 'frm_form_options_before_update', $options, $values, false );
46 $options = self::maybe_filter_form_options( $options );
47 $new_values['options'] = serialize( $options );
48
49 $wpdb->insert( $wpdb->prefix . 'frm_forms', $new_values );
50
51 $id = $wpdb->insert_id;
52
53 // Clear form caching
54 self::clear_form_cache();
55
56 return $id;
57 }
58
59 /**
60 * @since 5.0.08
61 *
62 * @param array $options
63 * @return array
64 */
65 private static function maybe_filter_form_options( $options ) {
66 if ( ! FrmAppHelper::allow_unfiltered_html() && ! empty( $options['submit_html'] ) ) {
67 $options['submit_html'] = FrmAppHelper::kses_submit_button( $options['submit_html'] );
68 }
69 return FrmAppHelper::maybe_filter_array( $options, array( 'submit_value', 'success_msg', 'before_html', 'after_html' ) );
70 }
71
72 /**
73 * @return int|boolean ID on success or false on failure
74 */
75 public static function duplicate( $id, $template = false, $copy_keys = false, $blog_id = false ) {
76 global $wpdb;
77
78 $values = self::getOne( $id, $blog_id );
79 if ( ! $values ) {
80 return false;
81 }
82
83 $new_key = $copy_keys ? $values->form_key : '';
84
85 $new_values = array(
86 'form_key' => FrmAppHelper::get_unique_key( $new_key, $wpdb->prefix . 'frm_forms', 'form_key' ),
87 'name' => $values->name,
88 'description' => $values->description,
89 'status' => $values->status ? $values->status : 'published',
90 'logged_in' => $values->logged_in ? $values->logged_in : 0,
91 'editable' => $values->editable ? $values->editable : 0,
92 'created_at' => current_time( 'mysql', 1 ),
93 'is_template' => $template ? 1 : 0,
94 );
95
96 if ( $blog_id ) {
97 $new_values['status'] = 'published';
98 $new_options = $values->options;
99 FrmAppHelper::unserialize_or_decode( $new_options );
100 $new_options['email_to'] = get_option( 'admin_email' );
101 $new_options['copy'] = false;
102 $new_values['options'] = $new_options;
103 } else {
104 $new_values['options'] = $values->options;
105 }
106
107 if ( is_array( $new_values['options'] ) ) {
108 $new_values['options'] = serialize( $new_values['options'] );
109 }
110
111 $query_results = $wpdb->insert( $wpdb->prefix . 'frm_forms', $new_values );
112
113 if ( $query_results ) {
114 // Clear form caching
115 self::clear_form_cache();
116
117 $form_id = $wpdb->insert_id;
118 FrmField::duplicate( $id, $form_id, $copy_keys, $blog_id );
119
120 // update form settings after fields are created
121 do_action( 'frm_after_duplicate_form', $form_id, $new_values, array( 'old_id' => $id ) );
122
123 return $form_id;
124 }
125
126 return false;
127 }
128
129 public static function after_duplicate( $form_id, $values ) {
130 $new_opts = $values['options'];
131 FrmAppHelper::unserialize_or_decode( $new_opts );
132 $values['options'] = $new_opts;
133
134 if ( isset( $new_opts['success_msg'] ) ) {
135 $new_opts['success_msg'] = FrmFieldsHelper::switch_field_ids( $new_opts['success_msg'] );
136 }
137
138 $new_opts = apply_filters( 'frm_after_duplicate_form_values', $new_opts, $form_id );
139
140 if ( $new_opts != $values['options'] ) {
141 global $wpdb;
142 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $new_opts ) ), array( 'id' => $form_id ) );
143 }
144
145 self::switch_field_ids_in_fields( $form_id );
146 }
147
148 /**
149 * Switches field ID in fields.
150 *
151 * @since 5.3
152 *
153 * @param int $form_id Form ID.
154 */
155 private static function switch_field_ids_in_fields( $form_id ) {
156 global $wpdb;
157
158 // Keys of fields that you want to check to replace field ID.
159 $keys = array( 'default_value', 'field_options' );
160 $sql_cols = 'fi.id';
161 foreach ( $keys as $key ) {
162 $sql_cols .= ( ',fi.' . $key );
163 }
164
165 $fields = FrmDb::get_results(
166 "{$wpdb->prefix}frm_fields AS fi LEFT OUTER JOIN {$wpdb->prefix}frm_forms AS fr ON fi.form_id = fr.id",
167 array(
168 'or' => 1,
169 'fi.form_id' => $form_id,
170 'fr.parent_form_id' => $form_id,
171 ),
172 $sql_cols
173 );
174
175 if ( ! $fields || ! is_array( $fields ) ) {
176 return;
177 }
178
179 foreach ( $fields as $field ) {
180 self::switch_field_ids_in_field( (array) $field );
181 }
182 }
183
184 /**
185 * Switches field ID in a field.
186 *
187 * @since 5.3
188 *
189 * @param array $field Field array.
190 */
191 private static function switch_field_ids_in_field( $field ) {
192 $new_values = array();
193 foreach ( $field as $key => $value ) {
194 if ( 'id' === $key || ! $value ) {
195 continue;
196 }
197
198 if ( ! is_string( $value ) && ! is_array( $value ) ) {
199 continue;
200 }
201
202 if ( 'field_options' === $key ) {
203 // Need to loop through field_options to prevent breaking serialized string when length changed.
204 FrmAppHelper::unserialize_or_decode( $value );
205 $new_val = FrmFieldsHelper::switch_field_ids( $value );
206 $new_val = serialize( $new_val );
207 } else {
208 $new_val = FrmFieldsHelper::switch_field_ids( $value );
209 }
210
211 if ( $new_val !== $value ) {
212 $new_values[ $key ] = $new_val;
213 }
214 }
215
216 if ( ! empty( $new_values ) ) {
217 FrmField::update( $field['id'], $new_values );
218 }
219 }
220
221 /**
222 * @return int|boolean
223 */
224 public static function update( $id, $values, $create_link = false ) {
225 global $wpdb;
226
227 $values = FrmAppHelper::maybe_filter_array( $values, array( 'name', 'description' ) );
228
229 if ( ! isset( $values['status'] ) && ( $create_link || isset( $values['options'] ) || isset( $values['item_meta'] ) || isset( $values['field_options'] ) ) ) {
230 $values['status'] = 'published';
231 }
232
233 if ( isset( $values['form_key'] ) ) {
234 $values['form_key'] = FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key', $id );
235 }
236
237 $form_fields = array( 'form_key', 'name', 'description', 'status', 'parent_form_id' );
238
239 $new_values = self::set_update_options( array(), $values, array( 'form_id' => $id ) );
240
241 foreach ( $values as $value_key => $value ) {
242 if ( $value_key && in_array( $value_key, $form_fields ) ) {
243 $new_values[ $value_key ] = $value;
244 }
245 }
246
247 if ( isset( $values['new_status'] ) && ! empty( $values['new_status'] ) ) {
248 $new_values['status'] = $values['new_status'];
249 }
250
251 if ( ! empty( $new_values ) ) {
252 $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', $new_values, array( 'id' => $id ) );
253 if ( $query_results ) {
254 self::clear_form_cache();
255 }
256 } else {
257 $query_results = true;
258 }
259 unset( $new_values );
260
261 $values = self::update_fields( $id, $values );
262
263 do_action( 'frm_update_form', $id, $values );
264 do_action( 'frm_update_form_' . $id, $values );
265
266 return $query_results;
267 }
268
269 /**
270 * @param array $new_values
271 * @param array $values
272 * @param array $args
273 * @return array
274 */
275 public static function set_update_options( $new_values, $values, $args = array() ) {
276 if ( ! isset( $values['options'] ) ) {
277 return $new_values;
278 }
279
280 $options = isset( $values['options'] ) ? (array) $values['options'] : array();
281 FrmFormsHelper::fill_form_options( $options, $values );
282
283 $options['custom_style'] = isset( $values['options']['custom_style'] ) ? $values['options']['custom_style'] : 0;
284 $options['before_html'] = isset( $values['options']['before_html'] ) ? $values['options']['before_html'] : FrmFormsHelper::get_default_html( 'before' );
285 $options['after_html'] = isset( $values['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' );
287
288 if ( ! empty( $options['success_url'] ) && ! empty( $args['form_id'] ) ) {
289 $options['success_url'] = FrmFormsHelper::maybe_add_sanitize_url_attr( $options['success_url'], (int) $args['form_id'] );
290 $values['options']['success_url'] = $options['success_url'];
291 }
292
293 /**
294 * Allows modifying form options before updating or creating.
295 *
296 * @since 5.4 Added the third param.
297 *
298 * @param array $options Form options.
299 * @param array $values Form data.
300 * @param bool $update Is form updating or creating. It's `true` if is updating.
301 */
302 $options = apply_filters( 'frm_form_options_before_update', $options, $values, true );
303 $options = self::maybe_filter_form_options( $options );
304 $new_values['options'] = serialize( $options );
305
306 return $new_values;
307 }
308
309 /**
310 * @return array
311 */
312 public static function update_fields( $id, $values ) {
313
314 if ( ! isset( $values['item_meta'] ) && ! isset( $values['field_options'] ) ) {
315 return $values;
316 }
317
318 $all_fields = FrmField::get_all_for_form( $id );
319 if ( empty( $all_fields ) ) {
320 return $values;
321 }
322
323 if ( ! isset( $values['item_meta'] ) ) {
324 $values['item_meta'] = array();
325 }
326
327 $field_array = array();
328 $existing_keys = array_keys( $values['item_meta'] );
329 foreach ( $all_fields as $fid ) {
330 if ( ! in_array( $fid->id, $existing_keys ) && ( isset( $values['frm_fields_submitted'] ) && in_array( $fid->id, $values['frm_fields_submitted'] ) ) || isset( $values['options'] ) ) {
331 $values['item_meta'][ $fid->id ] = '';
332 }
333 $field_array[ $fid->id ] = $fid;
334 }
335 unset( $all_fields );
336
337 foreach ( $values['item_meta'] as $field_id => $default_value ) {
338 if ( isset( $field_array[ $field_id ] ) ) {
339 $field = $field_array[ $field_id ];
340 } else {
341 $field = FrmField::getOne( $field_id );
342 }
343
344 if ( ! $field ) {
345 continue;
346 }
347
348 $is_settings_page = ( isset( $values['options'] ) || isset( $values['field_options'][ 'custom_html_' . $field_id ] ) );
349 if ( $is_settings_page ) {
350 self::get_settings_page_html( $values, $field );
351
352 if ( ! defined( 'WP_IMPORTING' ) ) {
353 continue;
354 }
355 }
356
357 //updating the form
358 $update_options = FrmFieldsHelper::get_default_field_options_from_field( $field );
359 unset( $update_options['custom_html'] ); // don't check for POST html
360 $update_options = apply_filters( 'frm_field_options_to_update', $update_options );
361
362 foreach ( $update_options as $opt => $default ) {
363 $field->field_options[ $opt ] = isset( $values['field_options'][ $opt . '_' . $field_id ] ) ? $values['field_options'][ $opt . '_' . $field_id ] : $default;
364 self::sanitize_field_opt( $opt, $field->field_options[ $opt ] );
365 }
366
367 $field->field_options = apply_filters( 'frm_update_field_options', $field->field_options, $field, $values );
368
369 $new_field = array(
370 'field_options' => $field->field_options,
371 'default_value' => isset( $values[ 'default_value_' . $field_id ] ) ? FrmAppHelper::maybe_json_encode( $values[ 'default_value_' . $field_id ] ) : '',
372 );
373
374 self::prepare_field_update_values( $field, $values, $new_field );
375
376 FrmField::update( $field_id, $new_field );
377
378 FrmField::delete_form_transient( $field->form_id );
379 }
380 self::clear_form_cache();
381
382 return $values;
383 }
384
385 private static function sanitize_field_opt( $opt, &$value ) {
386 if ( is_string( $value ) ) {
387 if ( $opt === 'calc' ) {
388 $value = self::sanitize_calc( $value );
389 } else {
390 $value = FrmAppHelper::kses( $value, 'all' );
391 }
392 $value = trim( $value );
393 }
394 }
395
396 /**
397 * @param string $value
398 * @return string
399 */
400 private static function sanitize_calc( $value ) {
401 if ( false !== strpos( $value, '<' ) ) {
402 $value = self::normalize_calc_spaces( $value );
403 }
404 $allow = array( '<= ', ' >=' ); // Allow <= and >=
405 $temp = array( '< = ', ' > =' );
406 $value = str_replace( $allow, $temp, $value );
407 $value = strip_tags( $value );
408 $value = str_replace( $temp, $allow, $value );
409 return $value;
410 }
411
412 /**
413 * Format a comparison like 5<10 to 5 < 10. Also works on 5< 10, 5 <10, 5<=10 variations.
414 * This is to avoid an issue with unspaced calculations being recognized as HTML that gets removed when strip_tags is called.
415 *
416 * @param string $calc
417 * @return string
418 */
419 private static function normalize_calc_spaces( $calc ) {
420 // Check for a pattern with 5 parts
421 // $1 \d the first comparison digit.
422 // $2 a space (optional).
423 // $3 an equals sign (optional) that follows the < operator for <= comparisons.
424 // $4 another space (optional).
425 // $5 \d the second comparison digit.
426 return preg_replace( '/(\d)( ){0,1}<(=){0,1}( ){0,1}(\d)/', '$1 <$3 $5', $calc );
427 }
428
429 /**
430 * Updating the settings page
431 */
432 private static function get_settings_page_html( $values, &$field ) {
433 if ( isset( $values['field_options'][ 'custom_html_' . $field->id ] ) ) {
434 $prev_opts = array();
435 $fallback_html = isset( $field->field_options['custom_html'] ) ? $field->field_options['custom_html'] : FrmFieldsHelper::get_default_html( $field->type );
436
437 $field->field_options['custom_html'] = isset( $values['field_options'][ 'custom_html_' . $field->id ] ) ? $values['field_options'][ 'custom_html_' . $field->id ] : $fallback_html;
438 } elseif ( $field->type == 'hidden' || $field->type == 'user_id' ) {
439 $prev_opts = $field->field_options;
440 }
441
442 if ( isset( $prev_opts ) ) {
443 $field->field_options = apply_filters( 'frm_update_form_field_options', $field->field_options, $field, $values );
444 if ( $prev_opts != $field->field_options ) {
445 FrmField::update( $field->id, array( 'field_options' => $field->field_options ) );
446 }
447 }
448 }
449
450 private static function prepare_field_update_values( $field, $values, &$new_field ) {
451 $field_cols = array(
452 'field_order' => 0,
453 'field_key' => '',
454 'required' => false,
455 'type' => '',
456 'description' => '',
457 'options' => '',
458 'name' => '',
459 );
460 foreach ( $field_cols as $col => $default ) {
461 $default = ( $default === '' ) ? $field->{$col} : $default;
462
463 $new_field[ $col ] = isset( $values['field_options'][ $col . '_' . $field->id ] ) ? $values['field_options'][ $col . '_' . $field->id ] : $default;
464 }
465
466 // Don't save the template option.
467 if ( is_array( $new_field['options'] ) && isset( $new_field['options']['000'] ) ) {
468 unset( $new_field['options']['000'] );
469 }
470 }
471
472 /**
473 * Get a list of all form settings that should be translated
474 * on a multilingual site.
475 *
476 * @since 3.06.01
477 * @param object $form - The form object
478 */
479 public static function translatable_strings( $form ) {
480 $strings = array(
481 'name',
482 'description',
483 'submit_value',
484 'submit_msg',
485 'success_msg',
486 );
487
488 return apply_filters( 'frm_form_strings', $strings, $form );
489 }
490
491 /**
492 * @param string $status
493 *
494 * @return int|boolean
495 */
496 public static function set_status( $id, $status ) {
497 if ( 'trash' == $status ) {
498 return self::trash( $id );
499 }
500
501 $statuses = array( 'published', 'draft', 'trash' );
502 if ( ! in_array( $status, $statuses ) ) {
503 return false;
504 }
505
506 global $wpdb;
507
508 if ( is_array( $id ) ) {
509 $where = array(
510 'id' => $id,
511 'parent_form_id' => $id,
512 'or' => 1,
513 );
514 FrmDb::get_where_clause_and_values( $where );
515 array_unshift( $where['values'], $status );
516
517 $query_results = $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->prefix . 'frm_forms SET status = %s ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
518 } else {
519 $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'id' => $id ) );
520 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'parent_form_id' => $id ) );
521 }
522
523 if ( $query_results ) {
524 self::clear_form_cache();
525 }
526
527 return $query_results;
528 }
529
530 /**
531 * @return int|boolean
532 */
533 public static function trash( $id ) {
534 if ( ! EMPTY_TRASH_DAYS ) {
535 return self::destroy( $id );
536 }
537
538 $form = self::getOne( $id );
539 if ( ! $form ) {
540 return false;
541 }
542
543 $options = $form->options;
544 $options['trash_time'] = time();
545
546 global $wpdb;
547 $query_results = $wpdb->update(
548 $wpdb->prefix . 'frm_forms',
549 array(
550 'status' => 'trash',
551 'options' => serialize( $options ),
552 ),
553 array(
554 'id' => $id,
555 )
556 );
557
558 $wpdb->update(
559 $wpdb->prefix . 'frm_forms',
560 array(
561 'status' => 'trash',
562 'options' => serialize( $options ),
563 ),
564 array(
565 'parent_form_id' => $id,
566 )
567 );
568
569 if ( $query_results ) {
570 self::clear_form_cache();
571 }
572
573 return $query_results;
574 }
575
576 /**
577 * @return int|boolean
578 */
579 public static function destroy( $id ) {
580 global $wpdb;
581
582 $form = self::getOne( $id );
583 if ( ! $form ) {
584 return false;
585 }
586 $id = $form->id;
587
588 // Disconnect the entries from this form
589 $entries = FrmDb::get_col( $wpdb->prefix . 'frm_items', array( 'form_id' => $id ) );
590 foreach ( $entries as $entry_id ) {
591 FrmEntry::destroy( $entry_id );
592 unset( $entry_id );
593 }
594
595 // Disconnect the fields from this form
596 $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 ) );
597
598 $query_results = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_forms WHERE id=%d OR parent_form_id=%d', $id, $id ) );
599 if ( $query_results ) {
600 // Delete all form actions linked to this form
601 $action_control = FrmFormActionsController::get_form_actions( 'email' );
602 $action_control->destroy( $id, 'all' );
603
604 // Clear form caching
605 self::clear_form_cache();
606
607 do_action( 'frm_destroy_form', $id );
608 do_action( 'frm_destroy_form_' . $id );
609 }
610
611 return $query_results;
612 }
613
614 /**
615 * Delete trashed forms based on how long they have been trashed
616 *
617 * @return int The number of forms deleted
618 */
619 public static function scheduled_delete( $delete_timestamp = '' ) {
620 global $wpdb;
621
622 $trash_forms = FrmDb::get_results( $wpdb->prefix . 'frm_forms', array( 'status' => 'trash' ), 'id, options' );
623
624 if ( ! $trash_forms ) {
625 return 0;
626 }
627
628 if ( empty( $delete_timestamp ) ) {
629 $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
630 }
631
632 $count = 0;
633 foreach ( $trash_forms as $form ) {
634 FrmAppHelper::unserialize_or_decode( $form->options );
635 if ( ! isset( $form->options['trash_time'] ) || $form->options['trash_time'] < $delete_timestamp ) {
636 self::destroy( $form->id );
637 $count ++;
638 }
639
640 unset( $form );
641 }
642
643 return $count;
644 }
645
646 /**
647 * @return string form name
648 */
649 public static function getName( $id ) {
650 $form = FrmDb::check_cache( $id, 'frm_form' );
651 if ( $form ) {
652 $r = stripslashes( $form->name );
653
654 return $r;
655 }
656
657 $query_key = is_numeric( $id ) ? 'id' : 'form_key';
658 $r = FrmDb::get_var( 'frm_forms', array( $query_key => $id ), 'name' );
659 $r = stripslashes( $r );
660
661 return $r;
662 }
663
664 /**
665 * @since 3.0
666 *
667 * @param string $key
668 *
669 * @return int form id
670 */
671 public static function get_id_by_key( $key ) {
672 return (int) FrmDb::get_var( 'frm_forms', array( 'form_key' => sanitize_title( $key ) ) );
673 }
674
675 /**
676 * @since 3.0
677 *
678 * @param int $id
679 *
680 * @return string form key
681 */
682 public static function get_key_by_id( $id ) {
683 $id = (int) $id;
684 $cache = FrmDb::check_cache( $id, 'frm_form' );
685 if ( $cache ) {
686 return $cache->form_key;
687 }
688
689 $key = FrmDb::get_var( 'frm_forms', array( 'id' => $id ), 'form_key' );
690
691 return $key;
692 }
693
694 /**
695 * If $form is numeric, get the form object
696 *
697 * @param object|int $form
698 *
699 * @since 2.0.9
700 */
701 public static function maybe_get_form( &$form ) {
702 if ( ! is_object( $form ) && ! is_array( $form ) && ! empty( $form ) ) {
703 $form = self::getOne( $form );
704 }
705 }
706
707 /**
708 * @return object form
709 */
710 public static function getOne( $id, $blog_id = false ) {
711 global $wpdb;
712
713 if ( $blog_id && is_multisite() ) {
714 global $wpmuBaseTablePrefix;
715 $prefix = $wpmuBaseTablePrefix ? $wpmuBaseTablePrefix . $blog_id . '_' : $wpdb->get_blog_prefix( $blog_id );
716
717 $table_name = $prefix . 'frm_forms';
718 } else {
719 $table_name = $wpdb->prefix . 'frm_forms';
720 $cache = wp_cache_get( $id, 'frm_form' );
721 if ( $cache ) {
722 if ( isset( $cache->options ) ) {
723 FrmAppHelper::unserialize_or_decode( $cache->options );
724 }
725
726 return wp_unslash( $cache );
727 }
728 }
729
730 if ( is_numeric( $id ) ) {
731 $where = array( 'id' => $id );
732 } else {
733 $where = array( 'form_key' => $id );
734 }
735
736 $results = FrmDb::get_row( $table_name, $where );
737
738 if ( isset( $results->options ) ) {
739 FrmDb::set_cache( $results->id, $results, 'frm_form' );
740 FrmAppHelper::unserialize_or_decode( $results->options );
741 }
742
743 return apply_filters( 'frm_form_object', wp_unslash( $results ) );
744 }
745
746 /**
747 * @return object|array of objects
748 */
749 public static function getAll( $where = array(), $order_by = '', $limit = '' ) {
750 if ( is_array( $where ) && ! empty( $where ) ) {
751 if ( isset( $where['is_template'] ) && $where['is_template'] && ! isset( $where['status'] ) && ! isset( $where['status !'] ) ) {
752 // don't get trashed templates
753 $where['status'] = array( null, '', 'published' );
754 }
755
756 $results = FrmDb::get_results( 'frm_forms', $where, '*', compact( 'order_by', 'limit' ) );
757 } else {
758 global $wpdb;
759
760 // the query has already been prepared if this is not an array
761 $query = 'SELECT * FROM ' . $wpdb->prefix . 'frm_forms' . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . FrmDb::esc_order( $order_by ) . FrmDb::esc_limit( $limit );
762 $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
763 }
764
765 if ( $results ) {
766 foreach ( $results as $result ) {
767 FrmDb::set_cache( $result->id, $result, 'frm_form' );
768 FrmAppHelper::unserialize_or_decode( $result->options );
769 }
770 }
771
772 if ( $limit == ' LIMIT 1' || $limit == 1 ) {
773 // return the first form object if we are only getting one form
774 $results = reset( $results );
775 }
776
777 return wp_unslash( $results );
778 }
779
780 /**
781 * Get all published forms
782 *
783 * @since 2.0
784 * @return array of forms
785 */
786 public static function get_published_forms( $query = array(), $limit = 999, $inc_children = 'exclude' ) {
787 $query['is_template'] = 0;
788 $query['status'] = array( null, '', 'published' );
789 if ( $inc_children == 'exclude' ) {
790 $query['parent_form_id'] = array( null, 0 );
791 }
792
793 $forms = self::getAll( $query, 'name', $limit );
794
795 return $forms;
796 }
797
798 /**
799 * @return object count of forms
800 */
801 public static function get_count() {
802 global $wpdb;
803
804 $cache_key = 'frm_form_counts';
805
806 $counts = wp_cache_get( $cache_key, 'frm_form' );
807 if ( false !== $counts ) {
808 return $counts;
809 }
810
811 $results = (array) FrmDb::get_results(
812 'frm_forms',
813 array(
814 'or' => 1,
815 'parent_form_id' => null,
816 'parent_form_id <' => 0,
817 ),
818 'status, is_template'
819 );
820
821 $statuses = array( 'published', 'draft', 'template', 'trash' );
822 $counts = array_fill_keys( $statuses, 0 );
823
824 foreach ( $results as $row ) {
825 if ( 'trash' != $row->status ) {
826 if ( $row->is_template ) {
827 $counts['template'] ++;
828 } else {
829 $counts['published'] ++;
830 }
831 } else {
832 $counts['trash'] ++;
833 }
834
835 if ( 'draft' == $row->status ) {
836 $counts['draft'] ++;
837 }
838
839 unset( $row );
840 }
841
842 $counts = (object) $counts;
843 FrmDb::set_cache( $cache_key, $counts, 'frm_form' );
844
845 return $counts;
846 }
847
848 /**
849 * Clear form caching
850 * Called when a form is created, updated, duplicated, or deleted
851 * or when the form status is changed
852 *
853 * @since 2.0.4
854 */
855 public static function clear_form_cache() {
856 FrmDb::cache_delete_group( 'frm_form' );
857 }
858
859 /**
860 * @return array of errors
861 */
862 public static function validate( $values ) {
863 $errors = array();
864
865 return apply_filters( 'frm_validate_form', $errors, $values );
866 }
867
868 public static function get_params( $form = null ) {
869 global $frm_vars;
870
871 if ( ! $form ) {
872 $form = self::getAll( array(), 'name', 1 );
873 } else {
874 self::maybe_get_form( $form );
875 }
876
877 if ( isset( $frm_vars['form_params'] ) && is_array( $frm_vars['form_params'] ) && isset( $frm_vars['form_params'][ $form->id ] ) ) {
878 return $frm_vars['form_params'][ $form->id ];
879 }
880
881 $action_var = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
882 $action = apply_filters( 'frm_show_new_entry_page', FrmAppHelper::get_param( $action_var, 'new', 'get', 'sanitize_title' ), $form );
883
884 $default_values = array(
885 'id' => '',
886 'form_name' => '',
887 'paged' => 1,
888 'form' => $form->id,
889 'form_id' => $form->id,
890 'field_id' => '',
891 'search' => '',
892 'sort' => '',
893 'sdir' => '',
894 'action' => $action,
895 );
896
897 $values = array();
898 $values['posted_form_id'] = FrmAppHelper::get_param( 'form_id', '', 'get', 'absint' );
899 if ( ! $values['posted_form_id'] ) {
900 $values['posted_form_id'] = FrmAppHelper::get_param( 'form', '', 'get', 'absint' );
901 }
902
903 if ( $form->id == $values['posted_form_id'] ) {
904 //if there are two forms on the same page, make sure not to submit both
905 foreach ( $default_values as $var => $default ) {
906 if ( $var == 'action' ) {
907 $values[ $var ] = FrmAppHelper::get_param( $action_var, $default, 'get', 'sanitize_title' );
908 } else {
909 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
910 }
911 unset( $var, $default );
912 }
913 } else {
914 foreach ( $default_values as $var => $default ) {
915 $values[ $var ] = $default;
916 unset( $var, $default );
917 }
918 }
919
920 if ( in_array( $values['action'], array( 'create', 'update' ) ) &&
921 ( ! $_POST || ( ! isset( $_POST['action'] ) && ! isset( $_POST['frm_action'] ) ) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing
922 ) {
923 $values['action'] = 'new';
924 }
925
926 return $values;
927 }
928
929 public static function list_page_params() {
930 $values = array();
931 $defaults = array(
932 'template' => 0,
933 'id' => '',
934 'paged' => 1,
935 'form' => '',
936 'search' => '',
937 'sort' => '',
938 'sdir' => '',
939 );
940 foreach ( $defaults as $var => $default ) {
941 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
942 }
943
944 return $values;
945 }
946
947 public static function get_admin_params( $form = null ) {
948 $form_id = $form;
949 if ( $form === null ) {
950 $form_id = self::get_current_form_id();
951 } elseif ( $form && is_object( $form ) ) {
952 $form_id = $form->id;
953 }
954
955 $values = array();
956 $defaults = array(
957 'id' => '',
958 'form_name' => '',
959 'paged' => 1,
960 'form' => $form_id,
961 'field_id' => '',
962 'search' => '',
963 'sort' => '',
964 'sdir' => '',
965 'fid' => '',
966 'keep_post' => '',
967 );
968 foreach ( $defaults as $var => $default ) {
969 $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
970 }
971
972 return $values;
973 }
974
975 public static function get_current_form_id( $default_form = 'none' ) {
976 if ( 'first' == $default_form ) {
977 $form = self::get_current_form();
978 } else {
979 $form = self::maybe_get_current_form();
980 }
981 $form_id = $form ? $form->id : 0;
982
983 return $form_id;
984 }
985
986 public static function maybe_get_current_form( $form_id = 0 ) {
987 global $frm_vars;
988
989 if ( isset( $frm_vars['current_form'] ) && $frm_vars['current_form'] && ( ! $form_id || $form_id == $frm_vars['current_form']->id ) ) {
990 return $frm_vars['current_form'];
991 }
992
993 $form_id = FrmAppHelper::get_param( 'form', $form_id, 'get', 'absint' );
994 if ( $form_id ) {
995 $form_id = self::set_current_form( $form_id );
996 }
997
998 return $form_id;
999 }
1000
1001 public static function get_current_form( $form_id = 0 ) {
1002 $form = self::maybe_get_current_form( $form_id );
1003 if ( is_numeric( $form ) ) {
1004 $form = self::set_current_form( $form );
1005 }
1006
1007 return $form;
1008 }
1009
1010 public static function set_current_form( $form_id ) {
1011 global $frm_vars;
1012
1013 $query = array();
1014 if ( $form_id ) {
1015 $query['id'] = $form_id;
1016 }
1017
1018 $frm_vars['current_form'] = self::get_published_forms( $query, 1 );
1019
1020 return $frm_vars['current_form'];
1021 }
1022
1023 public static function is_form_loaded( $form, $this_load, $global_load ) {
1024 global $frm_vars;
1025 $small_form = new stdClass();
1026 foreach ( array( 'id', 'form_key', 'name' ) as $var ) {
1027 $small_form->{$var} = $form->{$var};
1028 unset( $var );
1029 }
1030
1031 $frm_vars['forms_loaded'][] = $small_form;
1032
1033 if ( $this_load && empty( $global_load ) ) {
1034 $global_load = true;
1035 $frm_vars['load_css'] = true;
1036 }
1037
1038 return ( ( ! isset( $frm_vars['css_loaded'] ) || ! $frm_vars['css_loaded'] ) && $global_load );
1039 }
1040
1041 /**
1042 * @since 4.06.03
1043 *
1044 * @param object $form
1045 *
1046 * @return bool
1047 */
1048 public static function &is_visible_to_user( $form ) {
1049 if ( $form->logged_in && isset( $form->options['logged_in_role'] ) ) {
1050 $visible = FrmAppHelper::user_has_permission( $form->options['logged_in_role'] );
1051 } else {
1052 $visible = true;
1053 }
1054
1055 return $visible;
1056 }
1057
1058 public static function show_submit( $form ) {
1059 $show = ( ! $form->is_template && $form->status == 'published' && ! FrmAppHelper::is_admin() );
1060 $show = apply_filters( 'frm_show_submit_button', $show, $form );
1061
1062 return $show;
1063 }
1064
1065 /**
1066 * @since 2.3
1067 */
1068 public static function get_option( $atts ) {
1069 $form = $atts['form'];
1070 $default = isset( $atts['default'] ) ? $atts['default'] : '';
1071
1072 return isset( $form->options[ $atts['option'] ] ) ? $form->options[ $atts['option'] ] : $default;
1073 }
1074
1075 /**
1076 * Get the link to edit this form.
1077 *
1078 * @since 4.0
1079 * @param int $form_id The id of the form.
1080 */
1081 public static function get_edit_link( $form_id ) {
1082 return admin_url( 'admin.php?page=formidable&frm_action=edit&id=' . $form_id );
1083 }
1084
1085 /**
1086 * @deprecated 3.0
1087 * @codeCoverageIgnore
1088 *
1089 * @param string $key
1090 *
1091 * @return int form id
1092 */
1093 public static function getIdByKey( $key ) {
1094 return FrmFormDeprecated::getIdByKey( $key );
1095 }
1096
1097 /**
1098 * @deprecated 3.0
1099 * @codeCoverageIgnore
1100 */
1101 public static function getKeyById( $id ) {
1102 return FrmFormDeprecated::getKeyById( $id );
1103 }
1104 }
1105