PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.28
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.28
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.28, at classes/models/FrmFormAction.php

1,030 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 if ( 'event' === $k && ! $this->action_options['force_event'] && ! empty( $action->post_content[ $k ] ) ) {
806 continue;
807 }
808 $action->post_content[ $k ] = wp_parse_args( $action->post_content[ $k ], $vals );
809 }
810 }
811
812 if ( ! is_array( $action->post_content['event'] ) ) {
813 $action->post_content['event'] = explode( ',', $action->post_content['event'] );
814 }
815
816 return $action;
817 }
818
819 /**
820 * @param false|int|string $form_id
821 * @param string $type
822 *
823 * @return void
824 */
825 public function destroy( $form_id = false, $type = 'default' ) {
826 global $wpdb;
827
828 $this->form_id = $form_id;
829
830 $query = array( 'post_type' => FrmFormActionsController::$action_post_type );
831
832 if ( $form_id ) {
833 $query['menu_order'] = $form_id;
834 }
835
836 if ( 'all' !== $type ) {
837 $query['post_excerpt'] = $this->id_base;
838 }
839
840 $post_ids = FrmDb::get_col( $wpdb->posts, $query, 'ID' );
841
842 foreach ( $post_ids as $id ) {
843 wp_delete_post( $id );
844 }
845 self::clear_cache();
846 }
847
848 /**
849 * Delete the action cache when a form action is created, deleted, or updated
850 *
851 * @since 2.0.5
852 *
853 * @return void
854 */
855 public static function clear_cache() {
856 FrmDb::cache_delete_group( 'frm_actions' );
857 }
858
859 /**
860 * @return array
861 */
862 public function get_settings() {
863 return self::get_action_for_form( $this->form_id, $this->id_base );
864 }
865
866 /**
867 * @return array
868 */
869 public function get_global_defaults() {
870 $defaults = $this->get_defaults();
871
872 if ( ! isset( $defaults['event'] ) ) {
873 $defaults['event'] = array( 'create' );
874 }
875
876 if ( ! isset( $defaults['conditions'] ) ) {
877 $defaults['conditions'] = array(
878 'send_stop' => '',
879 'any_all' => '',
880 );
881 }
882
883 return $defaults;
884 }
885
886 /**
887 * @return array
888 */
889 public function get_global_switch_fields() {
890 $switch = $this->get_switch_fields();
891 $switch['conditions'] = array( 'hide_field' );
892
893 return apply_filters( 'frm_global_switch_fields', $switch );
894 }
895
896 /**
897 * Migrate settings from form->options into new action.
898 *
899 * @param object $form
900 * @param string $update
901 *
902 * @return int|WP_Error
903 */
904 public function migrate_to_2( $form, $update = 'update' ) {
905 $action = $this->prepare_new( $form->id );
906 FrmAppHelper::unserialize_or_decode( $form->options );
907
908 // Fill with existing options
909 foreach ( $action->post_content as $name => $val ) {
910 if ( isset( $form->options[ $name ] ) ) {
911 $action->post_content[ $name ] = $form->options[ $name ];
912 unset( $form->options[ $name ] );
913 }
914 }
915
916 $action = $this->migrate_values( $action, $form );
917
918 // Check if action already exists
919 $post_id = get_posts(
920 array(
921 'name' => $action->post_name,
922 'post_type' => FrmFormActionsController::$action_post_type,
923 'post_status' => $action->post_status,
924 'numberposts' => 1,
925 )
926 );
927
928 if ( ! $post_id ) {
929 // Create action now
930 $post_id = $this->save_settings( $action );
931 }
932
933 if ( ! $post_id || 'update' !== $update ) {
934 return $post_id;
935 }
936
937 global $wpdb;
938 $form->options = maybe_serialize( $form->options );
939
940 // Update form options
941 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => $form->options ), array( 'id' => $form->id ) );
942 FrmForm::clear_form_cache();
943
944 return $post_id;
945 }
946
947 /**
948 * @param WP_Post $action
949 * @param stdClass $entry
950 *
951 * @return bool
952 */
953 public static function action_conditions_met( $action, $entry ) {
954 if ( is_callable( 'FrmProFormActionsController::action_conditions_met' ) ) {
955 return FrmProFormActionsController::action_conditions_met( $action, $entry );
956 }
957 return false;
958 }
959
960 /**
961 * @param string $class
962 *
963 * @return array
964 */
965 public static function default_action_opts( $class = '' ) {
966 return array(
967 'classes' => 'frmfont ' . $class,
968 'active' => false,
969 'limit' => 0,
970 );
971 }
972
973 /**
974 * @return array
975 */
976 public static function trigger_labels() {
977 $triggers = array(
978 'draft' => __( 'Draft is saved', 'formidable' ),
979 'create' => __( 'Entry is created', 'formidable' ),
980 'update' => __( 'Entry is updated', 'formidable' ),
981 'delete' => __( 'Entry is deleted', 'formidable' ),
982 'import' => __( 'Entry is imported', 'formidable' ),
983 );
984
985 return apply_filters( 'frm_action_triggers', $triggers );
986 }
987
988 /**
989 * @return void
990 */
991 public function render_conditional_logic_call_to_action() {
992 // phpcs:disable Generic.WhiteSpace.ScopeIndent
993 ?>
994 <h3>
995 <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 ?>
996 <?php esc_html_e( 'Use Conditional Logic', 'formidable' ); ?>
997 </a>
998 </h3>
999 <?php
1000 // phpcs:enable Generic.WhiteSpace.ScopeIndent
1001 }
1002
1003 /**
1004 * @return string
1005 */
1006 protected function get_upgrade_text() {
1007 return __( 'Conditional form actions', 'formidable' );
1008 }
1009
1010 /**
1011 * Gets form fields for form action settings.
1012 *
1013 * @since 6.10
1014 *
1015 * @param int $form_id Form ID.
1016 *
1017 * @return object[]
1018 */
1019 protected function get_form_fields( $form_id ) {
1020 // Get form fields, include embedded and repeater child fields.
1021 $form_fields = FrmField::get_all_for_form( $form_id, '', 'include' );
1022 return array_filter(
1023 $form_fields,
1024 function ( $form_field ) {
1025 return ! FrmField::is_no_save_field( $form_field->type );
1026 }
1027 );
1028 }
1029 }
1030