PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.29
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.29
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 / FrmFormAction.php

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

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