PluginProbe
WPBot – ChatBot Conversational Forms / 1.4.7
WPBot – ChatBot Conversational Forms v1.4.7
1.5.0 1.4.8 1.4.7 trunk 0.9.2 0.9.3 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.6 1.1.7 1.1.8 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 All 36 releases
conversational-forms / classes / forms.php

forms.php in WPBot – ChatBot Conversational Forms 1.4.7, at classes/forms.php

1,131 lines 27.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Gets form configs in and out of the database
4 *
5 * @package Caldera_Forms Modified by QuantumCloud
6 * @author Josh Pollock <Josh@CalderaWP.com>
7 * @license GPL-2.0+
8 * @link
9 * @copyright 2016 CalderaWP LLC
10 */
11
12 /**
13 * Class Qcformbuilder_Forms_Forms
14 *
15 * @since 1.3.4
16 */
17 class Qcformbuilder_Forms_Forms {
18
19 /**
20 * Holds registry of forms
21 *
22 * @since 1.3.4
23 *
24 * @var array
25 */
26 protected static $registry_cache;
27
28 /**
29 * Cache key for storing form registry in
30 *
31 * @since 1.3.4
32 *
33 * @var string
34 */
35 protected static $registry_cache_key = '_qcformbuilder_forms';
36
37 /**
38 * Holds simple index of form IDs
39 *
40 * @since 1.3.4
41 *
42 * @var array
43 */
44 protected static $index;
45
46 /**
47 * Holds stored forms
48 *
49 * @since 1.3.4
50 *
51 * @var array
52 */
53 protected static $stored_forms;
54
55 /**
56 * Option key for storing registry in
57 *
58 * @since 1.3.4
59 *
60 * @var string
61 */
62 protected static $registry_option_key = '_qcformbuilder_forms_forms';
63
64 /**
65 * Fields used when converting flat registry to detailed registry
66 *
67 * @since 1.3.4
68 *
69 * @var array
70 */
71 protected static $detail_fields = array(
72 'ID',
73 'name',
74 'description',
75 'success',
76 'form_ajax',
77 'hide_form',
78 'db_support',
79 'mailer',
80 'pinned',
81 'pin_roles',
82 'hidden',
83 'form_draft'
84 );
85
86 /**
87 * Load a form by ID or name
88 *
89 * @since 1.3.4
90 *
91 * @param string $id_name ID or name of form.
92 * @param string $type Optional. Default is "primary" the main form. Can also be "revision" for getting a revision.
93 *
94 * @return array|null Form config array if found. If not null.
95 */
96 public static function get_form( $id_name, $type = 'primary' ){
97 $id_name = sanitize_text_field( $id_name );
98
99 $forms = self::get_forms();
100 $form = null;
101
102 if ( self::is_internal_form( $id_name ) ) {
103 if ( isset( $forms[ $id_name ] ) ) {
104 $form = self::get_from_db( $id_name, $type );
105 if( empty( $form ) ){
106 $form = get_option( $forms[ $id_name ] );
107 if( ! empty( $form ) ){
108 $form = self::maybe_migrate( $form );
109 }
110
111 }
112
113 } else {
114 $forms = self::get_forms( true );
115 foreach ( $forms as $form_id => $form_maybe ) {
116 if ( trim( strtolower( $id_name ) ) == strtolower( $form_maybe[ 'name' ] ) && empty( $form_maybe[ '_external_form' ] ) ) {
117 $form = self::get_from_db( $form_maybe[ 'ID' ], $type );
118 if( empty( $form ) ){
119 $form = get_option( $forms[ $id_name ] );
120 if( ! empty( $form ) ){
121 $form = self::maybe_migrate( $form );
122 }
123 }
124 }
125 }
126 }
127 }
128
129 if( empty( $form ) ){
130 $external = true;
131 }else{
132 $form = self::db_to_return( $form );
133 }
134
135 $form = self::filter_form( $id_name, $form );
136
137 if( is_array( $form ) && empty( $form['ID'] ) ){
138 $form['ID'] = $id_name;
139 }
140
141 if( ! empty( $form ) && ! empty( $external ) ){
142 $form['_external_form'] = true;
143 }
144
145 // remove submit on editing
146 if( !empty( $_GET['modal'] ) && $_GET['modal'] == 'view_entry' && !empty( $_GET['group'] ) && $_GET['group'] == 'editentry' ){
147 if( !empty( $form['fields'] ) ){
148 foreach( $form['fields'] as $field_id=>$field ){
149 if( $field['type'] == 'button' && $field['config']['type'] == 'submit' ){
150 unset( $form['fields'][ $field_id ] );
151 }
152 }
153 }
154 }
155
156 return $form;
157 }
158
159 /**
160 * Get registry of forms
161 *
162 * @since 1.3.4
163 *
164 * @param bool|false $with_details Optional. If false, the default, just form IDs are returned. If true, basic details of each are returned.
165 * @param bool|false $internal_only Optional. If false, the default, all forms -- in DB and in files system -- are returned -- If true, only those in DB are returned.
166 *
167 * @return array
168 */
169 public static function get_forms( $with_details = false, $internal_only = false, $orderby = false ){
170 if( isset( $_GET[ 'wfb-cache-clear' ] ) ){
171 self::clear_cache();
172 }
173
174 if( empty( static::$index ) ){
175 static::$index = static::get_stored_forms();
176 }
177
178 if ( false === $internal_only ) {
179 /**
180 * Runs after getting internal forms, use to add forms defined in file system
181 *
182 * @since unknown
183 *
184 * @param array $base_forms Forms saved in DB
185 */
186 $forms = apply_filters('qcformbuilder_forms_get_forms', static::$index);
187 if (!empty($forms) && is_array($forms)) {
188 foreach ($forms as $form_id => $form) {
189 $forms[$form_id] = $form_id;
190 }
191 }
192 }
193
194
195 if( $with_details ){
196 $forms = self::add_details( static::$index );
197 }else{
198 $forms = static::$index;
199 }
200
201 if( $orderby && ! empty( $forms ) ){
202 $forms = self::order_forms( $forms, $orderby );
203 }
204
205 return is_array($forms) ? $forms : [];
206
207 }
208
209 /**
210 * Check if a form is a revision
211 *
212 * @since 1.5.4
213 *
214 * @param array $form Form config
215 *
216 * @return bool
217 */
218 public static function is_revision( array $form ){
219 return isset( $form[ 'type' ] ) && 'revision' === $form[ 'type' ];
220
221 }
222
223 /**
224 * Make a reivison the primary form
225 *
226 * @since 1.5.3
227 *
228 * @param int $revision_id Revision ID
229 *
230 * @return false|int
231 */
232 public static function restore_revision( $revision_id ){
233 return Qcformbuilder_Forms_DB_Form::get_instance( )->make_revision_primary( $revision_id );
234 }
235
236 /**
237 * Get forms stored in DB
238 *
239 * @since 1.3.4
240 *
241 * @return array
242 */
243 protected static function get_stored_forms() {
244
245 if ( empty( self::$stored_forms ) ) {
246 $forms = Qcformbuilder_Forms_DB_Form::get_instance()->get_all();
247 if( ! empty( $forms ) ){
248 foreach( $forms as $form ){
249 if ( ! empty( $form[ 'config' ] ) ) {
250 static::$stored_forms[$form['form_id']] = $form['form_id'];
251 }
252 }
253
254 }
255 }
256
257 return is_array(self::$stored_forms ) ? self::$stored_forms : [];
258 }
259
260 /**
261 * Import form
262 *
263 * @since 1.3.4
264 *
265 * @param array $data Form config
266 * @param bool $trusted Is import data trusted? Default is to trust.
267 *
268 * @return string Form ID
269 */
270 public static function import_form( $data, $trusted = true ){
271 $forms = self::get_forms();
272 if ( isset( $data[ 'ID' ] ) && array_key_exists( $data[ 'ID' ], $forms ) ) {
273 // generate a new ID
274 $data[ 'ID' ] = self::create_unique_form_id();
275 }
276
277 if( isset( $data[ 'ID' ] ) ){
278 $id = $data[ 'ID' ];
279 }else{
280 $id = $data[ 'ID' ] = self::create_unique_form_id();
281 }
282
283 $data[ 'ID' ] = trim( $id );
284 unset( $data[ 'db_id' ] );
285
286 $importer = new Qcformbuilder_Forms_Import_Form($data, $trusted );
287 $data = $importer->get_prepared_form();
288 $new_form = self::save_form( $data );
289 if( is_array( $new_form ) && isset( $new_form[ 'ID' ] ) ){
290 $new_form = $new_form[ 'ID' ];
291 }
292
293 return $new_form;
294
295 }
296
297 /**
298 * Apply qcformbuilder_forms_get_form filters
299 *
300 * @since 1.5.3
301 *
302 * @param string $id_name Form ID or name
303 * @param array $config Form config
304 * @param bool $is_revision Optional. Is this a revision of a form? Default is false
305 *
306 * @return mixed|void
307 */
308 protected static function filter_form( $id_name, $config, $is_revision = false ){
309
310 if( ! isset( $config[ 'type' ] ) ){
311 if( $is_revision ){
312 $config[ 'type' ] = 'revision';
313 }else{
314 $config[ 'type' ] = 'primary';
315 }
316
317 }
318
319 /**
320 * Filter settings of a form or all forms or use to define a form in file
321 *
322 * @since unknown
323 *
324 * @param array $config Form config
325 * @param string $id_name ID or name of form
326 * @param bool $is_revision Is this a revision of a form? @since 1.5.3
327 */
328 $config = apply_filters( 'qcformbuilder_forms_get_form', $config, $id_name, $is_revision );
329
330 /**
331 * Filter settings of a specific form or all forms or use to define a form in file
332 *
333 * @since unknown
334 *
335 * @param array $config Form config
336 * @param string $id_name ID or name of form
337 * @param bool $is_revision Is this a revision of a form? @since 1.5.3
338 */
339 $config = apply_filters( 'qcformbuilder_forms_get_form-' . $id_name, $config, $id_name, $is_revision );
340
341 return $config;
342
343 }
344
345 /**
346 * Convert array returned from database to form config array expected by admin and front-end and like everything
347 *
348 * @since 1.5.3
349 *
350 * @param $form
351 *
352 * @return mixed
353 */
354 protected static function db_to_return( $form ){
355 $_form = $form[ 'config' ];
356 $_form[ 'db_id' ] = $form[ 'id' ];
357 $_form[ 'type' ] = $form[ 'type' ];
358
359 return $_form;
360
361 }
362
363 /**
364 * Get the filter value for maximum revisions
365 *
366 * @since 1.5.3
367 *
368 * @param array $form Form config
369 *
370 * @return int
371 */
372 protected static function max_revisions( array $form ){
373 /**
374 * Change the number fo form revisions to store per form
375 *
376 * @since 1.5.3
377 *
378 * @param int|bool Number of revisions to save. Set to false or 0 to disable form revisions.
379 * @param array $form Form Config
380 */
381 $max_revisions = apply_filters( 'qcformbuilder_forms_max_form_revisions', 15, $form );
382
383 return (int) $max_revisions;
384 }
385
386 /**
387 * Use to switch form arrays to ID strings
388 *
389 * @since 1.3.4
390 *
391 * @param array|int $val Index to convert
392 *
393 * @return string
394 */
395 protected function force_string( $val ){
396 if( is_array( $val ) ){
397 $val = $val[ 'ID' ];
398 }
399
400 return $val;
401 }
402
403 /**
404 * Add details to form registry
405 *
406 * @since 1.3.4
407 *
408 * @param array $forms
409 *
410 * @return array
411 */
412 protected static function add_details( $forms ){
413 if( empty( $forms ) ){
414 return [];
415 }
416
417 if( ! empty( $valid_forms = get_transient( self::$registry_cache_key ) ) ) {
418 return $valid_forms;
419 }else{
420 $valid_forms = [];
421 }
422
423 foreach( $forms as $id => $form ){
424 $_form = self::get_form( $id );
425 if( empty( $_form ) ){
426 //if its empty, there is no form. we can't just make up stuff.
427 continue;
428 }
429
430 $valid_forms[ $id ] = array();
431 foreach( self::$detail_fields as $key ){
432 if ( isset( $_form[ $key ] ) ) {
433 $valid_forms[ $id ][ $key ] = $_form[ $key ];
434 } elseif ( 'name' == $key ) {
435 $valid_forms[ $id ][ $key ] = $id;
436 } elseif ( 'mailer' == $key ) {
437 $valid_forms[ $id ][ $key ] = array( 'on_insert' => 1 );
438 } elseif ( in_array( $key, array( 'form_ajax', 'check_honey', 'hide_form', 'db_support' ) ) ) {
439 $valid_forms[ $id ][ $key ] = 1;
440 } elseif( 'form_draft' == $key ) {
441 $valid_forms[ $id ][ $key ] = 0;
442 }else {
443 $valid_forms[ $id ][ $key ] = '';
444 }
445
446
447
448 }
449 }
450
451 $base_forms = self::get_stored_forms();
452
453 foreach ( $valid_forms as $form_id => $form ) {
454 if ( ! isset( $base_forms[ $form_id ] ) ) {
455 $valid_forms[ $form_id ][ '_external_form' ] = true;
456 if ( empty( $forms[ $form_id ][ 'ID' ] ) ) {
457 $valid_forms[ $form_id ][ 'ID' ] = $form_id;
458 }
459
460 }
461 }
462
463 if ( ! empty( $valid_forms ) ) {
464 set_transient( self::$registry_cache_key, $valid_forms, HOUR_IN_SECONDS );
465 }
466
467 self::$registry_cache = $valid_forms;
468 return self::$registry_cache;
469
470 }
471
472 /**
473 * Save a form
474 *
475 * @since 1.3.4
476 *
477 * @param array $data Form config
478 * @param string $type Optional. Default is "primary" the main form. Can also be "revision" for saving a revision. @since 1.5.3
479
480 *
481 * @return string|bool Form ID if updated, false if not
482 */
483 public static function save_form( $data, $type = 'primary' ){
484
485
486 if(!empty($data['fields'])){
487 foreach($data['fields'] as &$field){
488 // option value labels
489 if(!empty($field['config']['option']) && is_array($field['config']['option'])){
490 foreach($field['config']['option'] as &$option){
491 if(!isset($option['value'])){
492 $option['value'] = $option['label'];
493 }
494 }
495 // trim manual calculations
496 } else if(!empty($field["config"]["manual_formula"]) && is_string($field["config"]["manual_formula"])){
497 $field["config"]["manual_formula"] = Qcformbuilder_Forms_Sanitize::finish_trim( Qcformbuilder_Forms_Sanitize::sanitize_header( $field["config"]["manual_formula"] ) );
498 }
499 }
500 }
501
502 // combine structure pages
503 if ( isset( $data['layout_grid']['structure'] ) && is_array( $data['layout_grid']['structure'] ) ) {
504 $data[ 'layout_grid' ][ 'structure' ] = implode( '#', $data[ 'layout_grid' ][ 'structure' ] );
505 }
506 // remove fields from conditions
507 if( !empty( $data['conditional_groups']['fields'] ) ){
508 unset( $data['conditional_groups']['fields'] );
509 }
510 // remove magics ( yes, not used yet.)
511 if( !empty( $data['conditional_groups']['magic'] ) ){
512 unset( $data['conditional_groups']['magic'] );
513 }
514 // sanitize condition values
515 if( !empty( $data['conditional_groups']['conditions'] ) ){
516 foreach( $data['conditional_groups']['conditions'] as $condition_id => &$condition ){
517 if( !empty( $condition['group'] ) ){
518 $condition['name'] = htmlentities( $condition['name'] );
519 foreach ($condition['group'] as $group_id => &$group) {
520 foreach( $group as $case_id=>&$case ){
521 $case['value'] = htmlentities( $case['value'] );
522 }
523 }
524 }
525 }
526 }
527
528 $data[ '_last_updated' ] = date('r');
529 $data[ 'version' ] = WFBCORE_VER;
530
531 /**
532 * Filter form config directly before saving
533 *
534 * @since 1.4.0
535 *
536 * @param array $data Form config
537 */
538 $data = apply_filters( 'qcformbuilder_forms_presave_form', $data );
539
540 // add form to registry
541 self::update_registry( $data[ "ID" ] );
542
543
544 self::save_to_db( $data, $type );
545 self::clear_cache();
546 /**
547 * Fires after a form is saved
548 *
549 * @since unknown
550 *
551 * @param array $data The form data
552 * @param string $from_id The form ID
553 */
554 do_action('qcformbuilder_forms_save_form', $data, $data['ID']);
555
556
557 return $data[ 'ID' ];
558 }
559
560 /**
561 * Create a new form
562 *
563 * @since 1.3.4
564 *
565 * @param array $newform Data for new form
566 *
567 * @return array|mixed|void
568 */
569 public static function create_form( $newform ){
570 require_once( WFBCORE_PATH . 'classes/admin.php' );
571
572 // get form templates (PROBABLY NEED TO MOVE METHOD INTO THIS CLASS)
573 $form_templates = Qcformbuilder_Forms_Admin::internal_form_templates();
574
575 $original_function_args = $newform;
576 if(!empty($newform['clone'])){
577 $clone = $newform['clone'];
578 }
579
580 // load template if any
581 if( !empty( $newform['template'] ) ){
582 if( isset( $form_templates[ $newform['template'] ] ) && !empty( $form_templates[ $newform['template'] ]['template'] ) ){
583 $form_template = $form_templates[ $newform['template'] ]['template'];
584 }
585 }
586
587 $forms = self::get_forms();
588 if( ! isset( $newform[ 'ID' ] ) || ( ! isset( $newform[ 'ID' ] ) && array_key_exists( $newform[ 'ID' ], $forms ) ) ) {
589 $id = uniqid('CF');
590 }else{
591 $id = $newform[ 'ID' ];
592 }
593
594 $id = trim( $id );
595 $defaults = array(
596 "ID" => $id,
597 "name" => '',
598 "description" => '',
599 "success" => __( 'Form has been successfully submitted. Thank you.', 'qcformbuilder-forms' ),
600 "form_ajax" => 1,
601 "hide_form" => 1,
602 "check_honey" => 1,
603 "db_support" => 1,
604 'mailer' => array( 'on_insert' => 1 )
605 );
606
607 $newform = wp_parse_args( $newform, $defaults );
608
609 // is template?
610 if( !empty( $form_template ) && is_array( $form_template ) ){
611 $newform = array_merge( $form_template, $newform );
612 $newform[ 'ID' ] = $id;
613 }
614
615 /**
616 * Filter newly created form before saving
617 *
618 * @since unknown
619 *
620 * @param array $newform New form config
621 */
622 $newform = apply_filters( 'qcformbuilder_forms_create_form', $newform);
623
624 self::update_registry( $id );
625
626 if(!empty($clone)){
627 $clone_form = self::get_form( $clone );
628 if(!empty($clone_form['ID']) && $clone == $clone_form['ID']){
629 $newform = array_merge($clone_form, $original_function_args);
630 unset( $newform[ 'db_id' ] );
631 $newform[ 'ID' ] = $id;
632 }
633 }
634
635 // add form to db
636 $added = self::save_to_db( $newform, 'primary' );
637 if( ! $added ){
638 return false;
639
640 }
641
642 /**
643 * Runs after form is created
644 *
645 * @since unkown
646 *
647 * @param array $newform New form config
648 */
649 do_action('qcformbuilder_forms_create_form', $newform);
650 return $newform;
651 }
652
653 /**
654 * Delete a form
655 *
656 * Will delete all revisions
657 *
658 * @since 1.3.4
659 *
660 * @param string $id Form ID
661 *
662 * @return bool
663 */
664 public static function delete_form( $id ){
665 $forms = self::get_forms();
666 if( ! isset( $forms[ $id ] ) ){
667 return false;
668 }
669
670 unset( $forms[ $id ] );
671 $deleted = Qcformbuilder_Forms_DB_Form::get_instance()->delete_by_form_id( $id );
672 if ( $deleted ) {
673 self::update_registry( $forms );
674
675 return $deleted;
676 }
677
678 return false;
679 }
680
681 /**
682 * Update form registry
683 *
684 * @since 1.3.4
685 *
686 * @param string|array $new Depreacted argument
687 *
688 */
689 protected static function update_registry( $new ){
690
691 self::clear_cache();
692 $forms = self::get_forms(false,true);
693
694 /**
695 * Fires after form registry is updated by saving a from
696 *
697 * @since unknown
698 *
699 * @param array $deprecated
700 * @param array $forms Array of forms in registry
701 */
702 do_action('qcformbuilder_forms_save_form_register', array(), $forms );
703
704 }
705
706 /**
707 * Clear the caching performed by this class
708 *
709 * @since 1.3.4
710 */
711 protected static function clear_cache(){
712 self::$index = array();
713 self::$registry_cache = array();
714 self::$stored_forms = array();
715 wp_cache_delete( '_qcformbuilder_forms_forms', 'options' );
716 delete_transient( self::$registry_cache_key );
717 }
718
719 /**
720 * Check if a form is stored in DB by name oir ID
721 *
722 * @since 1.3.4
723 *
724 * @param string $id_name Form name or ID
725 *
726 * @return bool
727 */
728 public static function is_internal_form( $id_name ){
729 return ! empty(self::get_stored_forms() ) && in_array( $id_name, self::get_stored_forms() );
730 }
731
732 /**
733 * Change a form's state form enabled to disabled or vise vera
734 *
735 * @since 1.3.5
736 *
737 * @param array $form Form config.
738 * @param bool|true $enable Optional. If true, enable form, if false, disable form.
739 */
740 public static function form_state( $form, $enable = true ){
741 if( $enable ){
742 $form['form_draft'] = 0;
743
744 }else{
745 $form['form_draft'] = 1;
746
747 }
748
749 if( is_array( self::$registry_cache ) && isset( self::$registry_cache[ $form[ 'ID' ] ] ) ){
750 delete_transient( self::$registry_cache_key );
751 self::$registry_cache[ $form[ 'ID' ] ][ 'form_draft' ] = $form['form_draft'];
752 }
753
754 self::save_form( $form );
755
756 }
757
758 /**
759 * Get all fields of a form
760 *
761 * @since 1.4.4
762 *
763 * @param array $form The form config
764 * @param bool $in_order Optional. Return in layout order, the default, or in stored order (false).
765 *
766 * @return array|mixed
767 */
768 public static function get_fields( array $form, $in_order = true ){
769 if( empty( $form[ 'fields' ] ) ){
770 return array();
771 }
772
773 $fields = $form[ 'fields' ];
774
775 if ( $in_order ) {
776
777 if( isset( $form[ 'layout_grid' ][ 'fields' ] ) ){
778 $order = array_keys( $form[ 'layout_grid' ][ 'fields' ] );
779 }else{
780 $order = array_keys( $fields );
781 }
782
783 /**
784 * Change order of fields
785 *
786 * Very useful for reordering fields outputted with {summary} magic tag
787 *
788 * @since 1.4.5
789 *
790 * @param array $order Order -- array of field IDs
791 * @param array $form Form config
792 */
793 $order = apply_filters( 'qcformbuilder_forms_get_field_order', $order, $form );
794
795 $ordered = array();
796 foreach ( $order as $key ) {
797 if ( isset( $fields[ $key ] ) ) {
798 $ordered[ $key ] = $fields[ $key ];
799 }
800
801 }
802
803 return $ordered;
804
805 }else{
806 return $fields;
807 }
808
809
810 }
811
812 /**
813 * Get entry list fields of a form
814 *
815 * @since 1.5.0
816 *
817 * @param array $form Form config
818 * @param bool $configs Optional. If true, field config arrays are returned. If false, the default, field IDs are returned
819 *
820 * @return array
821 */
822 public static function entry_list_fields( array $form, $configs = false ){
823 $fields = self::get_fields( $form );
824 $entry_list_fields = array();
825 foreach ( $fields as $field_id => $field ){
826 if( ! empty( $field[ 'entry_list'])){
827 if ( $configs ) {
828 $entry_list_fields[ $field_id ] = $field;
829 }else{
830 $entry_list_fields[] = $field_id;
831 }
832 }
833 }
834
835 return $entry_list_fields;
836 }
837
838 /**
839 * Get all fields of a form that provide personally identifying information
840 *
841 * @since 1.6.1
842 *
843 * @param array $form Form config
844 * @param bool $ids_only Optional. If true, indexed array of field IDs is returned. If false, the default, array of field configs, keyed by field ID is returned.
845 * @return array
846 */
847 public static function personally_identifying_fields(array $form, $ids_only = false ){
848 $fields = self::get_fields( $form, false );
849 $personally_identifying_fields = array();
850 if( ! empty( $fields ) ){
851 foreach ( $fields as $field_id => $field ){
852 if( Qcformbuilder_Forms_Field_Util::is_personally_identifying( $field, $form ) ){
853 $personally_identifying_fields[ $field_id ] = $field;
854 }
855 }
856 }
857
858 if( $ids_only ){
859 return array_keys( $personally_identifying_fields );
860 }
861
862 return $personally_identifying_fields;
863 }
864
865 /**
866 * Get all fields of a form that represents the email of someone who's personal information is in the form submssion.
867 *
868 * @since 1.7.0
869 *
870 * @param array $form Form config
871 * @param bool $ids_only Optional. If true, indexed array of field IDs is returned. If false, the default, array of field configs, keyed by field ID is returned.
872 * @return array
873 */
874 public static function email_identifying_fields( array $form, $ids_only = false ){
875 $fields = self::get_fields( $form, false );
876 $matching_fields = array();
877 if( ! empty( $fields ) ){
878 foreach ( $fields as $field_id => $field ){
879 if( Qcformbuilder_Forms_Field_Util::is_email_identifying_field( $field, $form ) ){
880 $matching_fields[ $field_id ] = $field;
881 }
882 }
883 }
884
885 if( $ids_only ){
886 return array_keys( $matching_fields );
887 }
888
889 return $matching_fields;
890 }
891
892 /**
893 * Discover if a form has GDPR/privacy exporter enabled
894 *
895 * @since 1.7.0
896 *
897 * @param array $form Form config
898 * @return bool
899 */
900 public static function is_privacy_export_enabled(array $form )
901 {
902 return ! empty( $form[ 'privacy_exporter_enabled' ] );
903 }
904
905 /**
906 * Toggle enabling of GDPR/privacy exporter enabled
907 *
908 * Note, does not save. Use Qcformbuilder_Forms_Forms::save_form( Qcformbuilder_Forms_Forms::update_privacy_export_enabled( $form, true ) ) );
909 *
910 * @since 1.7.0
911 *
912 * @param array $form Form config
913 * @param bool $enabled Optional. To enable or not. Default is true
914 *
915 * @return array
916 */
917 public static function update_privacy_export_enabled(array $form, $enabled = true )
918 {
919 $form[ 'privacy_exporter_enabled' ] = (bool) $enabled;
920 return $form;
921
922 }
923
924 /**
925 * Get all revisions of a forms
926 *
927 * @since 1.5.3
928 *
929 * @param string $form_id Form ID
930 *
931 * @return array
932 */
933 public static function get_revisions( $form_id, $simple = false ){
934 $forms = Qcformbuilder_Forms_DB_Form::get_instance()->get_by_form_id( $form_id, false );
935 $revisions = array();
936 if( ! empty( $forms ) ){
937 foreach ( $forms as $i => $form ){
938 if( 'revision' === $form[ 'type' ] ){
939 if( empty( $form ) || ! isset( $form[ 'id' ] ) ){
940 continue;
941 }
942 if( $simple ){
943 $revisions[] = $form[ 'id' ];
944 }else{
945 $form = self::db_to_return( $form );
946 $revisions[] = self::filter_form( $form[ 'ID' ], $form, true );
947 }
948
949 }
950 }
951 }
952
953
954 return $revisions;
955 }
956
957 /**
958 * Get a revision of a form
959 *
960 * @since 1.5.3
961 *
962 * @param int $id Revision ID
963 *
964 * @return array
965 */
966 public static function get_revision( $id ){
967 $form = Qcformbuilder_Forms_DB_Form::get_instance()->get_record( $id );
968 $form = self::db_to_return( $form );
969 $form = self::filter_form( $form[ 'ID' ], $form, true );
970 return $form;
971 }
972
973 /**
974 * If necessary migrate to database table added in Qcformbuilder Forms 1.5.3
975 *
976 * @since 1.5.3
977 *
978 * @param array $form Form config
979 *
980 * @return array|bool
981 */
982 protected static function maybe_migrate( array $form ){
983 $in_db = Qcformbuilder_Forms_DB_Form::get_instance()->get_by_form_id( $form[ 'ID' ] );
984 if( empty( $in_db ) ){
985 self::save_to_db( $form, 'primary' );
986 }
987
988 return self::get_from_db( $form[ 'ID' ] );
989 }
990
991 /**
992 * Save form to database
993 *
994 * @param array $form Form config
995 * @param string $type Optional. What type of form state is "primary" or "revision". Default is primary.
996 *
997 * @return bool|false|int|null
998 */
999 protected static function save_to_db( array $form, $type = 'primary' ){
1000 if( 'primary' !== $type ){
1001 $max_revisions = self::max_revisions( $form );
1002 if( ! $max_revisions ){
1003 return false;
1004 }
1005 }
1006
1007 $data = array(
1008 'form_id' => $form[ 'ID' ],
1009 'config' => $form,
1010 'type' => $type
1011 );
1012
1013 if( isset( $form[ 'db_id' ] ) ){
1014 $data[ 'db_id' ] = $form[ 'db_id' ];
1015 $db_id = Qcformbuilder_Forms_DB_Form::get_instance()->update( $data );
1016 self::maybe_delete_old_revisions( $form );
1017 }else{
1018 $db_id = Qcformbuilder_Forms_DB_Form::get_instance()->create( $data );
1019
1020 }
1021
1022
1023 return $db_id;
1024 }
1025
1026 /**
1027 * Get a form or forms (IE revisions of form) from database
1028 *
1029 * @since 1.5.3
1030 *
1031 * @param string $form_id Form ID
1032 * @param bool $primary_only Optional. Default is true, to only return primary form. False to include all revisions.
1033 *
1034 * @return array|bool
1035 */
1036 protected static function get_from_db( $form_id, $primary_only = true ){
1037 return Qcformbuilder_Forms_DB_Form::get_instance()->get_by_form_id( $form_id, $primary_only );
1038
1039 }
1040
1041 /**
1042 * Delete form revisions if there are more than the max revisions
1043 *
1044 *
1045 * @since 1.5.3
1046 *
1047 * @param array $form Form config
1048 */
1049 protected static function maybe_delete_old_revisions( array $form ){
1050 $revisions = self::get_revisions( $form[ 'ID' ], true);
1051 if( ! empty( $revisions ) ) {
1052 $max_revisions = self::max_revisions( $form );
1053
1054 if( $max_revisions < count( $revisions ) ){
1055 sort( $revisions );
1056 $deletes = array();
1057 foreach ( $revisions as $key => $id ){
1058 if( $key + 1 < $max_revisions ){
1059 $deletes[] = $id;
1060 }
1061 }
1062 Qcformbuilder_Forms_DB_Form::get_instance()->delete( $deletes );
1063
1064 }
1065
1066 }
1067
1068 }
1069
1070 /**
1071 * Order forms by a value
1072 *
1073 * @since 1.5.6
1074 *
1075 * @param array $forms Forms to sort.
1076 * @param string $by Optional. Default is "name" as of 1.5.6, no other values are allowed.
1077 *
1078 * @return array|mixed|void
1079 */
1080 protected static function order_forms( array $forms, $by = 'name' ){
1081 if( ! in_array( $by, array(
1082 'name',
1083 ))){
1084 $by = 'name';
1085 }
1086
1087 if( ! empty( $forms ) ){
1088 $values = array_values($forms);
1089
1090 if( ! is_array( $values[0] ) ) {
1091 $forms = self::get_forms( true );
1092 }
1093 }
1094
1095 if( empty( $forms ) ){
1096 return $forms;
1097 }
1098
1099 switch( $by ) {
1100 case 'name' :
1101 default :
1102 $map = array_combine( wp_list_pluck( $forms, $by ), array_keys( $forms ) );
1103
1104 break;
1105 }
1106
1107 ksort( $map, SORT_ASC );
1108 $final = array();
1109 foreach( $map as $name => $id ){
1110 $final[ $id ] = $forms[ $id ];
1111 }
1112
1113 return $final;
1114
1115
1116 }
1117
1118 /**
1119 * Create a unique form ID
1120 *
1121 * @since 1.6.0
1122 *
1123 * @return string
1124 */
1125 public static function create_unique_form_id(){
1126 return uniqid( 'CF' );
1127 }
1128 }
1129
1130
1131