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

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