PluginProbe
weForms – Easy Drag & Drop Contact Form Builder For WordPress / 1.6.27
weForms – Easy Drag & Drop Contact Form Builder For WordPress v1.6.27
1.6.7 1.6.8 1.6.9 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.18 1.6.19 1.6.2 1.6.20 1.6.21 1.6.22 1.6.23 1.6.24 1.6.25 1.6.26 1.6.27 1.6.28 1.6.3 1.6.4 1.6.5 1.6.6 All 74 releases
weforms / includes / class-form.php

class-form.php in weForms – Easy Drag & Drop Contact Form Builder For WordPress 1.6.27, at includes/class-form.php

666 lines 21.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The Form Class
5 *
6 * @since 1.1.0
7 */
8 class WeForms_Form {
9
10 /**
11 * The form id
12 *
13 * @var int
14 */
15 public $id = 0;
16
17 /**
18 * The form title
19 *
20 * @var string
21 */
22 public $name = '';
23
24 /**
25 * Holds the post data object
26 *
27 * @var WP_post|null
28 */
29 public $data = null;
30
31 /**
32 * Derived/formatted stats & metadata used by admin/AJAX/API responses.
33 * Declared explicitly to avoid PHP 8.2 "dynamic property" deprecations.
34 *
35 * @var int
36 */
37 public $entries = 0;
38
39 /**
40 * @var array
41 */
42 public $settings = [];
43
44 /**
45 * @var int
46 */
47 public $views = 0;
48
49 /**
50 * @var int
51 */
52 public $payments = 0;
53
54 /**
55 * @var array
56 */
57 public $author = [];
58
59 /**
60 * Form fields
61 *
62 * @var array
63 */
64 public $form_fields = [];
65
66 /**
67 * The Constructor
68 *
69 * @param int|WP_Post $form
70 */
71 public function __construct( $form = null ) {
72 if ( is_numeric( $form ) ) {
73 $the_post = get_post( $form );
74
75 if ( $the_post ) {
76 $this->id = $the_post->ID;
77 $this->name = $the_post->post_title;
78 $this->data = $the_post;
79 }
80 } elseif ( is_a( $form, 'WP_Post' ) ) {
81 $this->id = $form->ID;
82 $this->name = $form->post_title;
83 $this->data = $form;
84 }
85 }
86
87 /**
88 * Get the form ID
89 *
90 * @return int
91 */
92 public function get_id() {
93 return $this->id;
94 }
95
96 /**
97 * Get the form name
98 *
99 * @return string
100 */
101 public function get_name() {
102 return $this->name;
103 }
104
105 /**
106 * Get all form fields of this form
107 *
108 * @return array
109 */
110 public function get_fields() {
111
112 // return if already fetched
113 if ( $this->form_fields ) {
114 return $this->form_fields;
115 }
116
117 $fields = get_children( [
118 'post_parent' => $this->id,
119 'post_status' => 'publish',
120 'post_type' => 'wpuf_input',
121 'numberposts' => '-1',
122 'orderby' => 'menu_order',
123 'order' => 'ASC',
124 ] );
125
126 $form_fields = [];
127
128 foreach ( $fields as $key => $content ) {
129 // Security fix: Prevent PHP Object Injection by restricting allowed classes
130 $field = is_serialized( $content->post_content )
131 ? @unserialize( $content->post_content, [ 'allowed_classes' => false ] )
132 : $content->post_content;
133
134 if ( empty( $field['template'] ) ) {
135 continue;
136 }
137
138 $field['id'] = $content->ID;
139
140 // Add inline property for radio and checkbox fields
141 $inline_supported_fields = apply_filters( 'inline_supported_fields_list', [ 'radio_field', 'checkbox_field' ] );
142
143 if ( in_array( $field['template'], $inline_supported_fields ) ) {
144 if ( !isset( $field['inline'] ) ) {
145 $field['inline'] = 'no';
146 }
147 }
148
149 // Add 'selected' property
150 $option_based_fields = apply_filters( 'option_based_fields_list', [ 'dropdown_field', 'multiple_select', 'radio_field', 'checkbox_field' ] );
151
152 if ( in_array( $field['template'], $option_based_fields ) ) {
153 if ( !isset( $field['selected'] ) ) {
154 if ( 'dropdown_field' === $field['template'] || 'radio_field' === $field['template'] ) {
155 $field['selected'] = '';
156 } else {
157 $field['selected'] = [];
158 }
159 }
160 }
161
162 // Add 'multiple' key for template:repeat
163 if ( 'repeat_field' === $field['template'] && !isset( $field['multiple'] ) ) {
164 $field['multiple'] = '';
165 }
166
167 if ( 'recaptcha' === $field['template'] ) {
168 $field['name'] = 'recaptcha';
169 $field['enable_no_captcha'] = isset( $field['enable_no_captcha'] ) ? $field['enable_no_captcha'] : '';
170 $field['recaptcha_theme'] = isset( $field['recaptcha_theme'] ) ? $field['recaptcha_theme'] : 'light';
171 }
172
173 // Check if meta_key has changed when saving form compared current entries
174 if ( isset( $field['name'] ) ) {
175 $field['original_name'] = $field['name'];
176 }
177 $form_fields[] = apply_filters( 'weforms-get-form-field', $field, $this->id );
178 }
179
180 $this->form_fields = apply_filters( 'weforms-get-form-fields', $form_fields, $this->id );
181
182 return $this->form_fields;
183 }
184
185 /**
186 * Check if any perticular field template is used in a form
187 *
188 * @return array
189 */
190 public function has_field( $field_template ) {
191 foreach ( $this->get_fields() as $key => $field ) {
192 if ( isset( $field['template'] ) && $field['template'] == $field_template ) {
193 return true;
194 }
195 }
196 }
197
198 /**
199 * Get all fields by a template
200 *
201 * @return array
202 */
203 public function search_fields( $field_template ) {
204 $fields = [];
205
206 foreach ( $this->get_fields() as $key => $field ) {
207 if ( isset( $field['template'] ) && $field['template'] == $field_template ) {
208 $fields[] = $field;
209 }
210 }
211
212 return $fields;
213 }
214
215 /**
216 * Search fileds and get the first one
217 *
218 * @return array
219 */
220 public function search_field( $field_template ) {
221 $fields = $this->search_fields( $field_template );
222
223 return isset( $fields[0] ) ? $fields[0] : [];
224 }
225
226 /**
227 * Get formatted field name/values
228 *
229 * @return array
230 */
231 public function get_field_values() {
232 $values = [];
233 $fields = $this->get_fields();
234
235 if ( !$fields ) {
236 return $values;
237 }
238
239 $ignore_fields = apply_filters( 'ignore_fields_list', [ 'recaptcha', 'section_break' ] );
240 $options_fields = apply_filters( 'option_fields_list', [ 'dropdown_field', 'radio_field', 'multiple_select', 'checkbox_field' ] );
241
242 foreach ( $fields as $field ) {
243 if ( in_array( $field['template'], $ignore_fields ) ) {
244 continue;
245 }
246
247 // Prepare column field data
248 if ( $field['template'] == 'column_field' ) {
249 $inner_columns = $field['inner_fields'];
250
251 if ( !empty( $inner_columns ) ) {
252 foreach ( $inner_columns as $column => $column_fields ) {
253 if ( !empty( $column_fields ) ) {
254 foreach ( $column_fields as $field_obj ) {
255 if ( in_array( $field_obj['template'], $ignore_fields ) ) {
256 continue;
257 }
258
259 if ( !isset( $field_obj['name'] ) ) {
260 continue;
261 }
262
263 $field_value = [
264 'label' => isset( $field_obj['label'] ) ? $field_obj['label'] : '',
265 'type' => $field_obj['template'],
266 ];
267
268 // put options if this is an option field
269 if ( in_array( $field_obj['template'], $options_fields ) ) {
270 $field_value['options'] = $field_obj['options'];
271 }
272
273 $values[ $field_obj['name'] ] = array_merge( $field_obj, $field_value );
274 }
275 }
276 }
277 }
278 }
279
280 if ( !isset( $field['name'] ) ) {
281 continue;
282 }
283
284 $value = [
285 'label' => isset( $field['label'] ) ? $field['label'] : '',
286 'type' => $field['template'],
287 ];
288
289 // put options if this is an option field
290 if ( in_array( $field['template'], $options_fields ) ) {
291 $value['options'] = $field['options'];
292 }
293
294 $values[ $field['name'] ] = array_merge( $field, $value );
295 }
296
297 return apply_filters( 'weforms_get_field_values', $values );
298 }
299
300 /**
301 * Get form settings
302 *
303 * @return array
304 */
305 public function get_settings() {
306 $settings = get_post_meta( $this->id, 'wpuf_form_settings', true );
307 $default = weforms_get_default_form_settings();
308
309 return apply_filters( 'weforms-get-form-settings', array_merge( $default, $settings ), $this->id );
310 }
311
312 /**
313 * Check if the form submission is open
314 *
315 * @return bool|WP_Error
316 */
317 public function is_submission_open() {
318 $settings = $this->get_settings();
319
320 $needs_login = ( isset( $settings['require_login'] ) && $settings['require_login'] == 'true' ) ? true : false;
321 $has_limit = ( isset( $settings['limit_entries'] ) && $settings['limit_entries'] == 'true' ) ? true : false;
322 $is_scheduled = ( isset( $settings['schedule_form'] ) && $settings['schedule_form'] == 'true' ) ? true : false;
323
324 if ( $this->data->post_status != 'publish' ) {
325 return new WP_Error( 'needs-publish', __( 'The form is not published yet.', 'weforms' ) );
326 }
327
328 if ( $needs_login && !is_user_logged_in() ) {
329 return new WP_Error( 'needs-login', $settings['req_login_message'] );
330 }
331
332 if ( $has_limit ) {
333 $limit = (int) $settings['limit_number'];
334 $form_entries = $this->num_form_entries();
335
336 if ( $limit <= $form_entries ) {
337 return new WP_Error( 'entry-limit', $settings['limit_message'] );
338 }
339 }
340
341 if ( $is_scheduled ) {
342 $start_time = strtotime( $settings['schedule_start'] );
343 $end_time = strtotime( $settings['schedule_end'] );
344 $current_time = current_time( 'timestamp' );
345
346 // too early?
347 if ( $current_time < $start_time ) {
348 return new WP_Error( 'form-pending', $settings['sc_pending_message'] );
349 } elseif ( $current_time > $end_time ) {
350 return new WP_Error( 'form-expired', $settings['sc_expired_message'] );
351 }
352 }
353
354 return apply_filters( 'weforms_is_submission_open', true, $settings, $this );
355 }
356
357 /**
358 * Get form notifications
359 *
360 * @return array
361 */
362 public function get_notifications() {
363 $notifications = get_post_meta( $this->id, 'notifications', true );
364 $defualt = weforms_get_default_form_notification();
365
366 if ( !$notifications ) {
367 $notifications = [];
368 }
369
370 $notifications = array_map( function ( $notification ) use ( $defualt ) {
371 if ( empty( $notification ) ) {
372 $notification = [];
373 }
374
375 return array_merge( $defualt, $notification );
376 }, $notifications );
377
378 return $notifications;
379 }
380
381 /**
382 * Get all the integrations
383 *
384 * @return array
385 */
386 public function get_integrations() {
387 $integrations = get_post_meta( $this->id, 'integrations', true );
388
389 if ( !$integrations ) {
390 return [];
391 }
392
393 return $integrations;
394 }
395
396 /**
397 * Get entries of this form
398 *
399 * @return \WeForms_Form_Entry_Manager
400 */
401 public function entries() {
402 return new WeForms_Form_Entry_Manager( $this->id, $this );
403 }
404
405 /**
406 * When a user is editing their form they may change a fields name.
407 * This method will loop through existing entries to match the new field names.
408 *
409 * @since 1.6.9
410 *
411 * @param int $form_id
412 * @param array $form_fields
413 */
414 public function maybe_update_entries( $form_fields ) {
415 $changed_fields = $this->get_changed_fields( $form_fields );
416 // Loop through changed fields and update entries
417 foreach ( $changed_fields as $old => $new) {
418 $updated_fields = $this->rename_field( $old, $new );
419 }
420 }
421
422 /**
423 * When a user is editing their form they may change a fields name.
424 * This method will loop through all fields that have changed.
425 *
426 * @since 1.6.9
427 *
428 * @param int $form_id
429 * @param array $form_fields
430 *
431 * @return array
432 */
433 public function get_changed_fields( $form_fields ) {
434 $changed_fields = array();
435 foreach ( $form_fields as $field ) {
436 $org_field = $field['original_name'];
437 // All form fields should have an original name.
438 if ( empty( $field['original_name'] ) ) {
439 continue;
440 }
441 if ( $field['name'] !== $field['original_name'] ) {
442 $changed_fields[$field['original_name']] = $field['name'];
443 } else {
444 continue;
445 }
446 }
447 return $changed_fields;
448
449 }
450
451 /**
452 * When a user changes the field names of a form, the existing entries will need updated.
453 * This method will loop through the existing entries and update them will the new names.
454 *
455 * @since 1.6.9
456 *
457 * @param int $form_id
458 * @param array $form_fields
459 *
460 * @return array
461 */
462 public function rename_field ( $old, $new ) {
463 global $wpdb;
464
465 $entries = weforms_get_form_entries( $this->id );
466
467 foreach ( $entries as $entry ) {
468 $entry_id = $entry->id;
469 $values = weforms_get_entry_meta( $entry_id );
470 $update_keys = $wpdb->update( $wpdb->weforms_entrymeta, array( 'meta_key' => $new ), array( 'meta_key' => $old, 'weforms_entry_id' => $entry_id ) );
471 }
472 }
473
474 /**
475 * Get number of form entries
476 *
477 * @return int
478 */
479 public function num_form_entries() {
480 return weforms_count_form_entries( $this->id );
481 }
482
483 /**
484 * Get number of form payments
485 *
486 * @return int
487 */
488 public function num_form_payments() {
489 return weforms_count_form_payments( $this->id );
490 }
491
492 /**
493 * Get form author details
494 *
495 * @return array
496 */
497 public function get_form_author_details() {
498 return weforms_get_form_author_details( $this->id );
499 }
500
501 /**
502 * Get the number of form views
503 *
504 * @return int
505 */
506 public function num_form_views() {
507 return weforms_get_form_views( $this->id );
508 }
509
510 /**
511 * prepare_entries
512 *
513 * @return array
514 */
515 public function prepare_entries( $args = [] ) {
516 $fields = weforms()->fields->get_fields();
517 $form_fields = $this->get_fields();
518
519 $entry_fields = [];
520
521 $ignore_list = apply_filters( 'wefroms_entry_ignore_list', [
522 'recaptcha', 'section_break', 'step_start',
523 ] );
524
525 foreach ( $form_fields as $field ) {
526 if ( in_array( $field['template'], $ignore_list ) ) {
527 continue;
528 }
529
530 if ( !array_key_exists( $field['template'], $fields ) ) {
531 continue;
532 }
533
534 // Prepare column field data
535 if ( $field['template'] == 'column_field' ) {
536 $inner_columns = $field['inner_fields'];
537
538 if ( !empty( $inner_columns ) ) {
539 foreach ( $inner_columns as $column => $column_fields ) {
540 if ( !empty( $column_fields ) ) {
541 foreach ( $column_fields as $field_obj ) {
542 if ( in_array( $field_obj['template'], $ignore_list ) ) {
543 continue;
544 }
545
546 $fieldClass = $fields[ $field_obj['template'] ];
547 $entry_fields[ $field_obj['name'] ] = $fieldClass->prepare_entry( $field_obj );
548 }
549 }
550 }
551 }
552 }
553
554 $field_class = $fields[ $field['template'] ];
555
556 $entry_fields[ $field['name'] ] = $field_class->prepare_entry( $field, $args );
557 }
558
559 return apply_filters( 'weforms_prepare_entries', $entry_fields );
560 }
561
562 /**
563 * Check if the form submission is open On API
564 *
565 * @return bool|WP_Error
566 */
567 public function is_api_form_submission_open() {
568 $response = [];
569 $settings = $this->get_settings();
570 $form_entries = $this->num_form_entries();
571 $needs_login = isset( $settings['require_login'] ) ? $settings['require_login'] : 'false';
572 $limit_entries = isset( $settings['limit_entries'] ) ? $settings['limit_entries'] : 'false';
573 $schedule_form = isset( $settings['schedule_form'] ) ? $settings['schedule_form'] : 'false';
574 $limit_number = isset( $settings['limit_number'] ) ? $settings['limit_number'] : '';
575 $schedule_start = isset( $settings['schedule_start'] ) ? $settings['schedule_start'] : '';
576 $schedule_end = isset( $settings['schedule_end'] ) ? $settings['schedule_end'] : '';
577 $schedule_start_date = date_i18n( 'M d, Y', strtotime( $schedule_start ) );
578 $schedule_end_date = date_i18n( 'M d, Y', strtotime( $schedule_end ) );
579
580 if ( $this->data->post_status != 'publish' ) {
581 $response['type'] = __( 'Closed', 'weforms' );
582 }
583
584 if ( $this->isFormStatusClosed( $settings, $form_entries ) ) {
585 $response['type'] = __( 'Closed', 'weforms' );
586 } else {
587 $response['type'] = __( 'Open', 'weforms' );
588 }
589
590 if ( $limit_entries === 'true' ) {
591 if ( $schedule_form === 'true' && $this->isExpiredForm( $schedule_end ) ) {
592 $response['message'] = __( "Expired at {$schedule_end_date}", 'weforms' );
593 } elseif ( $schedule_form === 'true' && $this->isPendingForm( $schedule_start ) ) {
594 $response['message'] = __( "Starts at {$schedule_start_date}", 'weforms' );
595 } elseif ( $form_entries >= $limit_number ) {
596 $response['message'] = __( 'Reached maximum entry limit', 'weforms' );
597 } else {
598 $remaining_entries = $limit_number - $form_entries;
599 $response['message'] = __( "{$remaining_entries} entries remaining ", 'weforms' );
600 }
601 } elseif ( $schedule_form === 'true' ) {
602 if ( $this->isPendingForm( $schedule_start ) ) {
603 $response['message'] = __( "Starts at {$schedule_start_date}", 'weforms' );
604 } elseif ( $this->isExpiredForm( $schedule_end ) ) {
605 $response['message'] = __( "Expired at {$schedule_end_date}", 'weforms' );
606 } elseif ( $this->isOpenForm( $schedule_start, $schedule_end ) ) {
607 $response['message'] = __( "Expires at {$schedule_end_date}", 'weforms' );
608 }
609 } elseif ( $needs_login === 'true' ) {
610 $response['message'] =__( 'Requires login', 'weforms' );
611 }
612
613 return apply_filters( 'weforms_is_submission_open', $response, $settings, $this );
614 }
615
616 public function isPendingForm( $scheduleStart ) {
617 $currentTime = current_time( 'timestamp' );
618 $startTime = strtotime( $scheduleStart );
619
620 if ( $currentTime < $startTime ) {
621 return true;
622 }
623
624 return false;
625 }
626
627 public function isExpiredForm( $scheduleEnd ) {
628 $currentTime = current_time( 'timestamp' );
629 $endTime = strtotime( $scheduleEnd );
630
631 if ( $currentTime > $endTime ) {
632 return true;
633 }
634
635 return false;
636 }
637
638 public function isOpenForm( $scheduleStart, $scheduleEnd ) {
639 $currentTime = current_time( 'timestamp' );
640 $startTime = strtotime( $scheduleStart );
641 $endTime = strtotime( $scheduleEnd );
642
643 if ( $currentTime > $startTime && $currentTime < $endTime ) {
644 return true;
645 }
646
647 return false;
648 }
649
650 public function isFormStatusClosed( $formSettings, $entries ) {
651 if ( $formSettings['schedule_form'] === 'true' && $this->isPendingForm( $formSettings['schedule_start'] ) ) {
652 return true;
653 }
654
655 if ( $formSettings['schedule_form'] === 'true' && $this->isExpiredForm( $formSettings['schedule_end'] ) ) {
656 return true;
657 }
658
659 if ( $formSettings['limit_entries'] === 'true' && $entries >= $formSettings['limit_number'] ) {
660 return true;
661 }
662
663 return false;
664 }
665 }
666