PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.34
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.34
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 6.5.4 All 140 releases
formidable / classes / models / FrmFormAction.php

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

1,066 lines 27.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 FrmFormAction {
7
8 /**
9 * Root id for all actions of this type.
10 *
11 * @var string
12 */
13 public $id_base;
14
15 /**
16 * Name for this action type.
17 *
18 * @var string
19 */
20 public $name;
21
22 /**
23 * Name of the option used to store the settings for this action type.
24 *
25 * @var string
26 */
27 public $option_name;
28
29 /**
30 * Option array passed to wp_register_sidebar_widget().
31 *
32 * @var array
33 */
34 public $action_options;
35
36 /**
37 * Option array passed to wp_register_widget_control().
38 *
39 * @var array
40 */
41 public $control_options;
42
43 /**
44 * The ID of the form to evaluate.
45 *
46 * @var int
47 */
48 public $form_id;
49
50 /**
51 * Unique ID number of the current instance.
52 *
53 * @var int
54 */
55 public $number = false;
56
57 /**
58 * Unique ID string of the current instance (id_base-number).
59 *
60 * @var string
61 */
62 public $id = '';
63
64 /**
65 * Set true when we update the data after a POST submit - makes sure we don't do it twice.
66 *
67 * @var bool
68 */
69 public $updated = false;
70
71 // Member functions that you must over-ride.
72
73 /**
74 * This function should check that $new_instance is set correctly.
75 * The newly calculated value of $instance should be returned.
76 * If "false" is returned, the instance won't be saved/updated.
77 *
78 * @param array $new_instance New settings for this instance as input by the user via form().
79 * @param array $old_instance Old settings for this instance.
80 *
81 * @return array Settings to save or bool false to cancel saving
82 */
83 public function update( $new_instance, $old_instance ) {
84 return $new_instance;
85 }
86
87 /**
88 * Echo the settings update form
89 *
90 * @param WP_Post $instance Current settings.
91 * @param array $args
92 *
93 * @return string
94 */
95 public function form( $instance, $args = array() ) {
96 echo '<p class="no-options-widget">' . esc_html__( 'There are no options for this action.', 'formidable' ) . '</p>';
97 return 'noform';
98 }
99
100 /**
101 * @return array of the default options
102 */
103 public function get_defaults() {
104 return array();
105 }
106
107 /**
108 * @return array
109 */
110 public function get_switch_fields() {
111 return array();
112 }
113
114 /**
115 * @param object $action
116 * @param object $form
117 *
118 * @return object
119 */
120 public function migrate_values( $action, $form ) {
121 return $action;
122 }
123
124 // Functions you'll need to call.
125
126 /**
127 * PHP5 constructor
128 *
129 * @param string $id_base Optional Base ID for the widget, lower case,
130 * if left empty a portion of the widget's class name will be used. Has to be unique.
131 * @param string $name Name for the widget displayed on the configuration page.
132 * @param array $action_options Optional Passed to wp_register_sidebar_widget().
133 * - description: shown on the configuration page.
134 * - classname.
135 * @param array $control_options Optional Passed to wp_register_widget_control().
136 * - width: required if more than 250px.
137 * - height: currently not used but may be needed in the future.
138 */
139 public function __construct( $id_base, $name, $action_options = array(), $control_options = array() ) {
140 if ( ! defined( 'ABSPATH' ) ) {
141 die( 'You are not allowed to call this page directly.' );
142 }
143
144 $this->id_base = strtolower( $id_base );
145
146 /**
147 * @since 6.31
148 *
149 * @param string $name
150 */
151 $name = apply_filters( 'frm_' . $id_base . '_action_name', $name );
152
153 $this->name = $name;
154 $this->option_name = 'frm_' . $this->id_base . '_action';
155
156 $default_options = array(
157 'classes' => '',
158 'active' => true,
159 'event' => array( 'create' ),
160 'limit' => 1,
161 'force_event' => false,
162 'priority' => 20,
163 'ajax_load' => true,
164 'plugin' => $this->id_base,
165 'tooltip' => $name,
166 'group' => $id_base,
167 'color' => '',
168 'keywords' => '',
169 'description' => '',
170 'is_new' => false,
171 'is_beta' => false,
172 );
173
174 $action_options = apply_filters( 'frm_' . $id_base . '_action_options', $action_options );
175 $group = $this->get_group( $action_options );
176 $action_options['group'] = $group['id'];
177
178 if ( ! isset( $action_options['color'] ) ) {
179 // Deterministic fallback so all instances of the same action type render with the same color across requests.
180 $colors = array( 'green', 'orange', 'purple' );
181 $index = abs( crc32( $id_base ) ) % count( $colors );
182 $action_options['color'] = 'var(--' . $colors[ $index ] . ')';
183 }
184
185 $upgrade_class = isset( $action_options['classes'] ) && $action_options['classes'] === 'frm_show_upgrade';
186
187 if ( $action_options['group'] === $id_base ) {
188 $upgrade_class = str_contains( $action_options['classes'], 'frm_show_upgrade' );
189 $action_options['classes'] = $group['icon'];
190 } elseif ( empty( $action_options['classes'] ) || $upgrade_class ) {
191 $action_options['classes'] = $group['icon'];
192 }
193
194 if ( $upgrade_class ) {
195 $action_options['classes'] .= ' frm_show_upgrade';
196 }
197
198 $this->action_options = wp_parse_args( $action_options, $default_options );
199 $this->control_options = wp_parse_args( $control_options, array( 'id_base' => $this->id_base ) );
200 }
201
202 /**
203 * @param string $id_base
204 * @param string $name
205 * @param array $action_options
206 * @param array $control_options
207 *
208 * @return void
209 */
210 public function FrmFormAction( $id_base, $name, $action_options = array(), $control_options = array() ) {
211 self::__construct( $id_base, $name, $action_options, $control_options );
212 }
213
214 /**
215 * Help to switch old field id by new field id for duplicate form
216 *
217 * @param string $action id of the field that needs to be switched.
218 *
219 * @return string
220 */
221 public function maybe_switch_field_ids( $action ) {
222 $updated_action = apply_filters( 'frm_maybe_switch_field_ids', $action );
223
224 if ( $updated_action === $action ) {
225 return FrmFieldsHelper::switch_field_ids( $action );
226 }
227
228 return $updated_action;
229 }
230
231 /**
232 * @since 4.0
233 *
234 * @param array $action_options
235 *
236 * @return array
237 */
238 protected function get_group( $action_options ) {
239 $groups = FrmFormActionsController::form_action_groups();
240 $group = 'misc';
241
242 if ( isset( $action_options['group'] ) && isset( $groups[ $action_options['group'] ] ) ) {
243 $group = $action_options['group'];
244 } elseif ( isset( $groups[ $this->id_base ] ) ) {
245 $group = $this->id_base;
246 } else {
247 foreach ( $groups as $name => $check_group ) {
248 if ( isset( $check_group['actions'] ) && in_array( $this->id_base, $check_group['actions'], true ) ) {
249 $group = $name;
250 break;
251 }
252 }
253 }
254
255 $groups[ $group ]['id'] = $group;
256 return $groups[ $group ];
257 }
258
259 /**
260 * Constructs name attributes for use in form() fields
261 *
262 * This function should be used in form() methods to create name attributes for fields to be saved by update()
263 *
264 * @param string $field_name Field name.
265 * @param string $post_field
266 *
267 * @return string Name attribute for $field_name
268 */
269 public function get_field_name( $field_name, $post_field = 'post_content' ) {
270 $name = $this->option_name . '[' . $this->number . ']';
271 $name .= $post_field ? '[' . $post_field . ']' : '';
272
273 return $name . ( '[' . $field_name . ']' );
274 }
275
276 /**
277 * Constructs id attributes for use in form() fields
278 *
279 * This function should be used in form() methods to create id attributes for fields to be saved by update()
280 *
281 * @param string $field_name Field name.
282 *
283 * @return string ID attribute for $field_name
284 */
285 public function get_field_id( $field_name ) {
286 return $field_name . '_' . $this->number;
287 }
288
289 /**
290 * @param int|string $number
291 *
292 * @return void
293 */
294 public function _set( $number ) {
295 $this->number = $number;
296 $this->id = $this->id_base . '-' . $number;
297 }
298
299 /**
300 * @param false|int|string $form_id
301 *
302 * @return object
303 */
304 public function prepare_new( $form_id = false ) {
305 if ( $form_id ) {
306 $this->form_id = $form_id;
307 }
308
309 $post_content = array();
310 $default_values = $this->get_global_defaults();
311
312 // Fill default values
313 $post_content = wp_parse_args( $post_content, $default_values );
314
315 if ( ! isset( $post_content['event'] ) && ! $this->action_options['force_event'] ) {
316 $post_content['event'] = array( reset( $this->action_options['event'] ) );
317 }
318
319 $form_action = array(
320 'post_title' => $this->name,
321 'post_content' => $post_content,
322 'post_excerpt' => $this->id_base,
323 'ID' => '',
324 'post_status' => 'publish',
325 'post_type' => FrmFormActionsController::$action_post_type,
326 'post_name' => $this->form_id . '_' . $this->id_base . '_' . $this->number,
327 'menu_order' => $this->form_id,
328 );
329
330 return (object) $form_action;
331 }
332
333 /**
334 * @param int|string $form_id
335 *
336 * @return int|WP_Error
337 */
338 public function create( $form_id ) {
339 $this->form_id = $form_id;
340
341 $action = $this->prepare_new();
342
343 return $this->save_settings( $action );
344 }
345
346 /**
347 * @param int|string $form_id
348 * @param int|string $old_id
349 *
350 * @return void
351 */
352 public function duplicate_form_actions( $form_id, $old_id ) {
353 // phpcs:ignore Universal.Operators.StrictComparisons
354 if ( $form_id == $old_id ) {
355 // Don't duplicate the actions if this is a template getting updated
356 return;
357 }
358
359 $this->form_id = $old_id;
360 $actions = $this->get_all( $old_id );
361
362 $this->form_id = $form_id;
363
364 foreach ( $actions as $action ) {
365 $this->duplicate_one( $action, $form_id );
366 unset( $action );
367 }
368 }
369
370 /**
371 * Check if imported action should be created or updated.
372 *
373 * @since 2.0
374 *
375 * @param array $action
376 * @param array $forms
377 *
378 * @return int Post ID.
379 */
380 public function maybe_create_action( $action, $forms ) {
381 if ( isset( $action['ID'] ) && is_numeric( $action['ID'] ) && isset( $forms[ $action['menu_order'] ] ) && $forms[ $action['menu_order'] ] === 'updated' ) {
382 // Update action only
383 $action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
384 return $this->save_settings( $action );
385 }
386 // Create action
387 $action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
388 return $this->duplicate_one( (object) $action, $action['menu_order'] );
389 }
390
391 /**
392 * @param object $action
393 * @param int|string $form_id
394 *
395 * @return int|WP_Error
396 */
397 public function duplicate_one( $action, $form_id ) {
398 global $frm_duplicate_ids;
399
400 $action->menu_order = $form_id;
401 $switch = $this->get_global_switch_fields();
402
403 foreach ( (array) $action->post_content as $key => $val ) {
404 if ( is_numeric( $val ) && isset( $frm_duplicate_ids[ $val ] ) ) {
405 $action->post_content[ $key ] = $frm_duplicate_ids[ $val ];
406 } elseif ( ! is_array( $val ) ) {
407 $action->post_content[ $key ] = FrmFieldsHelper::switch_field_ids( $val );
408 } elseif ( isset( $switch[ $key ] ) && is_array( $switch[ $key ] ) ) {
409 // Loop through each value if empty
410 if ( empty( $switch[ $key ] ) ) {
411 $switch[ $key ] = array_keys( $val );
412 }
413
414 foreach ( $switch[ $key ] as $subkey ) {
415 $action->post_content[ $key ] = $this->duplicate_array_walk( $action->post_content[ $key ], $subkey, $val );
416 }
417 }
418
419 unset( $key, $val );
420 }
421 unset( $action->ID );
422
423 return $this->save_settings( $action );
424 }
425
426 /**
427 * @param array $action
428 * @param array|string $subkey
429 * @param mixed $val
430 *
431 * @return array
432 */
433 private function duplicate_array_walk( $action, $subkey, $val ) {
434 global $frm_duplicate_ids;
435
436 if ( is_array( $subkey ) ) {
437 foreach ( $subkey as $subkey2 ) {
438 foreach ( (array) $val as $ck => $cv ) {
439 if ( is_array( $cv ) ) {
440 $action[ $ck ] = $this->duplicate_array_walk( $action[ $ck ], $subkey2, $cv );
441 } elseif ( isset( $cv[ $subkey ] ) && is_numeric( $cv[ $subkey ] ) && isset( $frm_duplicate_ids[ $cv[ $subkey ] ] ) ) {
442 $action[ $ck ][ $subkey ] = $frm_duplicate_ids[ $cv[ $subkey ] ];
443 }
444 }
445 }
446 } else {
447 foreach ( (array) $val as $ck => $cv ) {
448 if ( is_array( $cv ) ) {
449 $action[ $ck ] = $this->duplicate_array_walk( $action[ $ck ], $subkey, $cv );
450 } elseif ( $ck == $subkey && isset( $frm_duplicate_ids[ $cv ] ) ) { // phpcs:ignore Universal.Operators.StrictComparisons
451 $action[ $ck ] = $frm_duplicate_ids[ $cv ];
452 } elseif ( $ck == $subkey ) { // phpcs:ignore Universal.Operators.StrictComparisons
453 $action[ $ck ] = $this->maybe_switch_field_ids( $action[ $ck ] );
454 }
455 }
456 }//end if
457
458 return $action;
459 }
460
461 /**
462 * Deal with changed settings.
463 *
464 * Do NOT over-ride this function
465 *
466 * @param int|string $form_id
467 *
468 * @return array|null
469 */
470 public function update_callback( $form_id ) {
471 $this->form_id = $form_id;
472
473 $all_instances = $this->get_settings();
474
475 // We need to update the data
476 if ( $this->updated ) {
477 return null;
478 }
479
480 // phpcs:ignore WordPress.Security.NonceVerification.Missing
481 if ( ! isset( $_POST[ $this->option_name ] ) || ! is_array( $_POST[ $this->option_name ] ) ) {
482 return null;
483 }
484
485 // Sanitizing removes scripts and <email> type of values.
486 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
487 $settings = wp_unslash( $_POST[ $this->option_name ] );
488
489 $action_ids = array();
490
491 foreach ( $settings as $number => $new_instance ) {
492 $this->_set( $number );
493
494 $old_instance = $all_instances[ $number ] ?? array();
495
496 if ( ! isset( $new_instance['post_status'] ) ) {
497 $new_instance['post_status'] = 'draft';
498 }
499
500 // Settings were never opened, so don't update
501 if ( ! isset( $new_instance['post_title'] ) ) {
502 $this->maybe_update_status( $new_instance, $old_instance );
503 $action_ids[] = $new_instance['ID'];
504 $this->updated = true;
505 continue;
506 }
507
508 $new_instance['post_type'] = FrmFormActionsController::$action_post_type;
509 $new_instance['post_name'] = $this->form_id . '_' . $this->id_base . '_' . $this->number;
510 $new_instance['menu_order'] = $this->form_id;
511 $new_instance['post_date'] = $old_instance->post_date ?? '';
512 $instance = $this->update( $new_instance, $old_instance );
513
514 /**
515 * Filter an action's settings before saving.
516 *
517 * Returning false will effectively short-circuit the widget's ability
518 * to update settings.
519 *
520 * @since 2.0
521 *
522 * @param array $instance The current widget instance's settings.
523 * @param array $new_instance Array of new widget settings.
524 * @param array $old_instance Array of old widget settings.
525 * @param FrmFormAction $form_action FrmFormAction instance.
526 */
527 $instance = apply_filters( 'frm_action_update_callback', $instance, $new_instance, $old_instance, $this );
528
529 $instance['post_content'] = apply_filters( 'frm_before_save_action', $instance['post_content'], $instance, $new_instance, $old_instance, $this );
530 $instance['post_content'] = apply_filters( 'frm_before_save_' . $this->id_base . '_action', $instance['post_content'], $instance, $new_instance, $old_instance, $this );
531
532 if ( false !== $instance ) {
533 $all_instances[ $number ] = $instance;
534 }
535
536 $action_ids[] = $this->save_settings( $instance );
537
538 $this->updated = true;
539 }//end foreach
540
541 return $action_ids;
542 }
543
544 /**
545 * If the status of the action has changed, update it
546 *
547 * @since 3.04
548 *
549 * @param array $new_instance
550 * @param array|stdClass $old_instance
551 *
552 * @return void
553 */
554 protected function maybe_update_status( $new_instance, $old_instance ) {
555 if ( ! is_object( $old_instance ) || $new_instance['post_status'] === $old_instance->post_status ) {
556 return;
557 }
558
559 self::clear_cache();
560 wp_update_post(
561 array(
562 'ID' => $new_instance['ID'],
563 'post_status' => $new_instance['post_status'],
564 )
565 );
566 }
567
568 /**
569 * @param array $settings
570 *
571 * @return int|WP_Error
572 */
573 public function save_settings( $settings ) {
574 self::clear_cache();
575 return FrmDb::save_settings( $settings, 'frm_actions' );
576 }
577
578 /**
579 * @param int $id
580 *
581 * @return object|null
582 */
583 public function get_single_action( $id ) {
584 $action = get_post( $id );
585
586 if ( $action ) {
587 $action = $this->prepare_action( $action );
588 $this->_set( $id );
589 }
590
591 return $action;
592 }
593
594 /**
595 * @param int|string $form_id
596 *
597 * @return array
598 */
599 public function get_one( $form_id ) {
600 return $this->get_all( $form_id, 1 );
601 }
602
603 /**
604 * @param int|string $form_id
605 * @param string $type
606 * @param array $atts
607 *
608 * @return array
609 */
610 public static function get_action_for_form( $form_id, $type = 'all', $atts = array() ) {
611 $action_controls = FrmFormActionsController::get_form_actions( $type );
612
613 if ( ! $action_controls ) {
614 // Don't continue if there are no available actions
615 return array();
616 }
617
618 if ( 'all' !== $type ) {
619 if ( is_array( $action_controls ) ) {
620 return array();
621 }
622
623 return $action_controls->get_all( $form_id, $atts );
624 }
625
626 self::prepare_get_action( $atts );
627
628 $limit = self::get_action_limit( $form_id, $atts['limit'] );
629 $args = self::action_args( $form_id, $limit );
630 $args['post_status'] = $atts['post_status'];
631 $actions = FrmDb::check_cache( json_encode( $args ), 'frm_actions', $args, 'get_posts' );
632
633 if ( ! $actions ) {
634 return array();
635 }
636
637 $settings = array();
638
639 foreach ( $actions as $action ) {
640 // Some plugins/themes are formatting the post_excerpt
641 $action->post_excerpt = sanitize_title( $action->post_excerpt );
642
643 if ( ! isset( $action_controls[ $action->post_excerpt ] ) ) {
644 continue;
645 }
646
647 $action = $action_controls[ $action->post_excerpt ]->prepare_action( $action );
648 $settings[ $action->ID ] = $action;
649
650 if ( count( $settings ) >= $limit ) {
651 break;
652 }
653 }
654
655 return 1 === $limit ? reset( $settings ) : $settings;
656 }
657
658 /**
659 * Get the limit for the number of actions for a single form. By default, this is 99, but
660 * it can be modified with a code snippet.
661 *
662 * @since 6.17 This logic from moved from FrmFormAction::get_action_for_form.
663 *
664 * @param int|string $form_id
665 * @param int|string $limit The unfiltered limit value.
666 *
667 * @return int The filtered limit value.
668 */
669 public static function get_action_limit( $form_id, $limit = 99 ) {
670 $type = 'all';
671 return (int) apply_filters( 'frm_form_action_limit', (int) $limit, compact( 'type', 'form_id' ) );
672 }
673
674 /**
675 * @since 3.04
676 *
677 * @param array|string $args
678 * @param string $default_status
679 *
680 * @return void
681 */
682 protected static function prepare_get_action( &$args, $default_status = 'publish' ) {
683 if ( is_numeric( $args ) ) {
684 // For reverse compatibility. $limit was changed to $args
685 $args = array(
686 'limit' => $args,
687 );
688 }
689
690 $defaults = array(
691 'limit' => 99,
692 'post_status' => $default_status,
693 );
694 $args = wp_parse_args( $args, $defaults );
695 }
696
697 /**
698 * @param int $action_id
699 * @param string $type
700 *
701 * @return bool|object
702 */
703 public static function get_single_action_type( $action_id, $type ) {
704 if ( ! $type ) {
705 return false;
706 }
707
708 /**
709 * @var FrmFormAction
710 */
711 $action_control = FrmFormActionsController::get_form_actions( $type );
712
713 return $action_control->get_single_action( $action_id );
714 }
715
716 /**
717 * @param int $form_id
718 * @param string $type
719 *
720 * @return bool
721 */
722 public static function form_has_action_type( $form_id, $type ) {
723 $actions = self::get_action_for_form( $form_id, $type );
724 return ! empty( $actions );
725 }
726
727 /**
728 * @param false|int|string $form_id
729 * @param array $atts
730 *
731 * @return array
732 */
733 public function get_all( $form_id = false, $atts = array() ) {
734 if ( is_array( $atts ) && ! isset( $atts['limit'] ) && $this->action_options['limit'] > 99 ) {
735 $atts['limit'] = $this->action_options['limit'];
736 }
737
738 self::prepare_get_action( $atts, 'any' );
739
740 $limit = $atts['limit'];
741
742 if ( $form_id ) {
743 $this->form_id = $form_id;
744 }
745
746 $type = $this->id_base;
747
748 global $frm_vars;
749 $frm_vars['action_type'] = $type;
750
751 add_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
752 $query = self::action_args( $form_id, $limit );
753 $query['post_status'] = $atts['post_status'];
754 $query['suppress_filters'] = false;
755
756 $actions = FrmDb::check_cache( json_encode( $query ) . '_type_' . $type, 'frm_actions', $query, 'get_posts' );
757 unset( $query );
758
759 remove_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
760
761 if ( ! $actions ) {
762 return array();
763 }
764
765 $settings = array();
766
767 foreach ( $actions as $action ) {
768 if ( count( $settings ) >= $limit ) {
769 continue;
770 }
771
772 $action = $this->prepare_action( $action );
773 $settings[ $action->ID ] = $action;
774 }
775
776 return 1 === $limit ? reset( $settings ) : $settings;
777 }
778
779 /**
780 * @param int|string $form_id
781 * @param int $limit
782 *
783 * @return array
784 */
785 public static function action_args( $form_id = 0, $limit = 99 ) {
786 $args = array(
787 'post_type' => FrmFormActionsController::$action_post_type,
788 'post_status' => 'publish',
789 'numberposts' => $limit,
790 'orderby' => 'title',
791 'order' => 'ASC',
792 );
793
794 if ( $form_id && $form_id !== 'all' ) {
795 $args['menu_order'] = $form_id;
796 }
797
798 return $args;
799 }
800
801 /**
802 * @param WP_Post $action
803 *
804 * @return WP_Post
805 */
806 public function prepare_action( $action ) {
807 $action->post_content = (array) FrmAppHelper::maybe_json_decode( $action->post_content );
808 $action->post_excerpt = sanitize_title( $action->post_excerpt );
809
810 $default_values = $this->get_global_defaults();
811
812 // Fill default values
813 $action->post_content += $default_values;
814
815 foreach ( $default_values as $k => $vals ) {
816 if ( ! is_array( $vals ) || ! $vals ) {
817 continue;
818 }
819
820 if ( 'event' === $k && ! $this->action_options['force_event'] && ! empty( $action->post_content[ $k ] ) ) {
821 continue;
822 }
823 $action->post_content[ $k ] = wp_parse_args( $action->post_content[ $k ], $vals );
824 }
825
826 if ( ! is_array( $action->post_content['event'] ) ) {
827 $action->post_content['event'] = explode( ',', $action->post_content['event'] );
828 }
829
830 return $action;
831 }
832
833 /**
834 * @param false|int|string $form_id
835 * @param string $type
836 *
837 * @return void
838 */
839 public function destroy( $form_id = false, $type = 'default' ) {
840 global $wpdb;
841
842 $this->form_id = $form_id;
843
844 $query = array( 'post_type' => FrmFormActionsController::$action_post_type );
845
846 if ( $form_id ) {
847 $query['menu_order'] = $form_id;
848 }
849
850 if ( 'all' !== $type ) {
851 $query['post_excerpt'] = $this->id_base;
852 }
853
854 $post_ids = FrmDb::get_col( $wpdb->posts, $query, 'ID' );
855
856 foreach ( $post_ids as $id ) {
857 wp_delete_post( $id );
858 }
859 self::clear_cache();
860 }
861
862 /**
863 * Delete the action cache when a form action is created, deleted, or updated
864 *
865 * @since 2.0.5
866 *
867 * @return void
868 */
869 public static function clear_cache() {
870 FrmDb::cache_delete_group( 'frm_actions' );
871 }
872
873 /**
874 * @return array
875 */
876 public function get_settings() {
877 return self::get_action_for_form( $this->form_id, $this->id_base );
878 }
879
880 /**
881 * @return array
882 */
883 public function get_global_defaults() {
884 $defaults = $this->get_defaults();
885
886 if ( ! isset( $defaults['event'] ) ) {
887 $defaults['event'] = array( 'create' );
888 }
889
890 if ( ! isset( $defaults['conditions'] ) ) {
891 $defaults['conditions'] = array(
892 'send_stop' => '',
893 'any_all' => '',
894 );
895 }
896
897 return $defaults;
898 }
899
900 /**
901 * @return array
902 */
903 public function get_global_switch_fields() {
904 $switch = $this->get_switch_fields();
905 $switch['conditions'] = array( 'hide_field' );
906
907 return apply_filters( 'frm_global_switch_fields', $switch );
908 }
909
910 /**
911 * Migrate settings from form->options into new action.
912 *
913 * @param object $form
914 * @param string $update
915 *
916 * @return int|WP_Error
917 */
918 public function migrate_to_2( $form, $update = 'update' ) {
919 $action = $this->prepare_new( $form->id );
920 FrmAppHelper::unserialize_or_decode( $form->options );
921
922 // Fill with existing options
923 foreach ( $action->post_content as $name => $val ) {
924 if ( ! isset( $form->options[ $name ] ) ) {
925 continue;
926 }
927
928 $action->post_content[ $name ] = $form->options[ $name ];
929 unset( $form->options[ $name ] );
930 }
931
932 $action = $this->migrate_values( $action, $form );
933
934 // Check if action already exists
935 $post_id = get_posts(
936 array(
937 'name' => $action->post_name,
938 'post_type' => FrmFormActionsController::$action_post_type,
939 'post_status' => $action->post_status,
940 'numberposts' => 1,
941 )
942 );
943
944 if ( ! $post_id ) {
945 // Create action now
946 $post_id = $this->save_settings( $action );
947 }
948
949 if ( ! $post_id || 'update' !== $update ) {
950 return $post_id;
951 }
952
953 global $wpdb;
954 $form->options = maybe_serialize( $form->options );
955
956 // Update form options
957 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => $form->options ), array( 'id' => $form->id ) );
958 FrmForm::clear_form_cache();
959
960 return $post_id;
961 }
962
963 /**
964 * @param WP_Post $action
965 * @param stdClass $entry
966 *
967 * @return bool
968 */
969 public static function action_conditions_met( $action, $entry ) {
970 if ( is_callable( 'FrmProFormActionsController::action_conditions_met' ) ) {
971 return FrmProFormActionsController::action_conditions_met( $action, $entry );
972 }
973 return false;
974 }
975
976 /**
977 * @param string $class
978 *
979 * @return array
980 */
981 public static function default_action_opts( $class = '' ) {
982 return array(
983 'classes' => 'frmfont ' . $class,
984 'active' => false,
985 'limit' => 0,
986 'description' => '',
987 );
988 }
989
990 /**
991 * @return array
992 */
993 public static function trigger_labels() {
994 $triggers = array(
995 'draft' => __( 'Draft is saved', 'formidable' ),
996 'create' => __( 'Entry is created', 'formidable' ),
997 'update' => __( 'Entry is updated', 'formidable' ),
998 'delete' => __( 'Entry is deleted', 'formidable' ),
999 'import' => __( 'Entry is imported', 'formidable' ),
1000 );
1001
1002 return apply_filters( 'frm_action_triggers', $triggers );
1003 }
1004
1005 /**
1006 * @param string $action_key The unique key for this action instance.
1007 *
1008 * @return void
1009 */
1010 public function render_conditional_logic_call_to_action( $action_key = '' ) {
1011 $params = array(
1012 'class' => 'frm-h-stack-xs frm-bt-200 frm-py-md frm_show_upgrade',
1013 'data-upgrade' => $this->get_upgrade_text(),
1014 'data-medium' => 'conditional-' . $this->id_base,
1015 );
1016 // phpcs:disable Generic.WhiteSpace.ScopeIndent
1017 ?>
1018 <div <?php FrmAppHelper::array_to_html_params( $params, true ); ?>>
1019 <?php
1020 FrmHtmlHelper::toggle(
1021 'frm_logic_cta_' . $action_key,
1022 'frm_logic_cta_' . $action_key,
1023 array(
1024 'div_class' => 'with_frm_style frm_toggle',
1025 'checked' => false,
1026 'echo' => true,
1027 'disabled' => true,
1028 )
1029 );
1030 ?>
1031 <label for="frm_logic_cta_<?php echo esc_attr( $action_key ); ?>" class="frm_noallow">
1032 <?php esc_html_e( 'Use Conditional Logic', 'formidable' ); ?>
1033 </label>
1034 </div>
1035 <?php
1036 // phpcs:enable Generic.WhiteSpace.ScopeIndent
1037 }
1038
1039 /**
1040 * @return string
1041 */
1042 protected function get_upgrade_text() {
1043 return __( 'Conditional form actions', 'formidable' );
1044 }
1045
1046 /**
1047 * Gets form fields for form action settings.
1048 *
1049 * @since 6.10
1050 *
1051 * @param int $form_id Form ID.
1052 *
1053 * @return object[]
1054 */
1055 protected function get_form_fields( $form_id ) {
1056 // Get form fields, include embedded and repeater child fields.
1057 $form_fields = FrmField::get_all_for_form( $form_id, '', 'include' );
1058 return array_filter(
1059 $form_fields,
1060 function ( $form_field ) {
1061 return ! FrmField::is_no_save_field( $form_field->type );
1062 }
1063 );
1064 }
1065 }
1066