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

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