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

1,005 lines 26.5 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 = apply_filters( 'frm_form_action_limit', $atts['limit'], compact( 'type', 'form_id' ) );
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 * @since 3.04
584 *
585 * @param array $args
586 * @param string $default_status
587 *
588 * @return void
589 */
590 protected static function prepare_get_action( &$args, $default_status = 'publish' ) {
591 if ( is_numeric( $args ) ) {
592 // for reverse compatibility. $limit was changed to $args
593 $args = array(
594 'limit' => $args,
595 );
596 }
597 $defaults = array(
598 'limit' => 99,
599 'post_status' => $default_status,
600 );
601 $args = wp_parse_args( $args, $defaults );
602 }
603
604 /**
605 * @param int $action_id
606 */
607 public static function get_single_action_type( $action_id, $type ) {
608 if ( ! $type ) {
609 return false;
610 }
611
612 /**
613 * @var FrmFormAction
614 */
615 $action_control = FrmFormActionsController::get_form_actions( $type );
616
617 return $action_control->get_single_action( $action_id );
618 }
619
620 /**
621 * @param int $form_id
622 *
623 * @return bool
624 */
625 public static function form_has_action_type( $form_id, $type ) {
626 $payment_actions = self::get_action_for_form( $form_id, $type );
627
628 return ! empty( $payment_actions );
629 }
630
631 public function get_all( $form_id = false, $atts = array() ) {
632 if ( is_array( $atts ) && ! isset( $atts['limit'] ) && $this->action_options['limit'] > 99 ) {
633 $atts['limit'] = $this->action_options['limit'];
634 }
635
636 self::prepare_get_action( $atts, 'any' );
637
638 $limit = $atts['limit'];
639
640 if ( $form_id ) {
641 $this->form_id = $form_id;
642 }
643
644 $type = $this->id_base;
645
646 global $frm_vars;
647 $frm_vars['action_type'] = $type;
648
649 add_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
650 $query = self::action_args( $form_id, $limit );
651 $query['post_status'] = $atts['post_status'];
652 $query['suppress_filters'] = false;
653
654 $actions = FrmDb::check_cache( json_encode( $query ) . '_type_' . $type, 'frm_actions', $query, 'get_posts' );
655 unset( $query );
656
657 remove_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
658
659 if ( empty( $actions ) ) {
660 return array();
661 }
662
663 $settings = array();
664 foreach ( $actions as $action ) {
665 if ( count( $settings ) >= $limit ) {
666 continue;
667 }
668
669 $action = $this->prepare_action( $action );
670
671 $settings[ $action->ID ] = $action;
672 }
673
674 if ( 1 === $limit ) {
675 $settings = reset( $settings );
676 }
677
678 return $settings;
679 }
680
681 /**
682 * @return array
683 */
684 public static function action_args( $form_id = 0, $limit = 99 ) {
685 $args = array(
686 'post_type' => FrmFormActionsController::$action_post_type,
687 'post_status' => 'publish',
688 'numberposts' => $limit,
689 'orderby' => 'title',
690 'order' => 'ASC',
691 );
692
693 if ( $form_id && $form_id != 'all' ) {
694 $args['menu_order'] = $form_id;
695 }
696
697 return $args;
698 }
699
700 /**
701 * @param array|WP_Post $action
702 */
703 public function prepare_action( $action ) {
704 $action->post_content = (array) FrmAppHelper::maybe_json_decode( $action->post_content );
705 $action->post_excerpt = sanitize_title( $action->post_excerpt );
706
707 $default_values = $this->get_global_defaults();
708
709 // fill default values
710 $action->post_content += $default_values;
711
712 foreach ( $default_values as $k => $vals ) {
713 if ( is_array( $vals ) && ! empty( $vals ) ) {
714 if ( 'event' === $k && ! $this->action_options['force_event'] && ! empty( $action->post_content[ $k ] ) ) {
715 continue;
716 }
717 $action->post_content[ $k ] = wp_parse_args( $action->post_content[ $k ], $vals );
718 }
719 }
720
721 if ( ! is_array( $action->post_content['event'] ) ) {
722 $action->post_content['event'] = explode( ',', $action->post_content['event'] );
723 }
724
725 return $action;
726 }
727
728 /**
729 * @return void
730 */
731 public function destroy( $form_id = false, $type = 'default' ) {
732 global $wpdb;
733
734 $this->form_id = $form_id;
735
736 $query = array( 'post_type' => FrmFormActionsController::$action_post_type );
737 if ( $form_id ) {
738 $query['menu_order'] = $form_id;
739 }
740 if ( 'all' != $type ) {
741 $query['post_excerpt'] = $this->id_base;
742 }
743
744 $post_ids = FrmDb::get_col( $wpdb->posts, $query, 'ID' );
745
746 foreach ( $post_ids as $id ) {
747 wp_delete_post( $id );
748 }
749 self::clear_cache();
750 }
751
752 /**
753 * Delete the action cache when a form action is created, deleted, or updated
754 *
755 * @since 2.0.5
756 *
757 * @return void
758 */
759 public static function clear_cache() {
760 FrmDb::cache_delete_group( 'frm_actions' );
761 }
762
763 public function get_settings() {
764 return self::get_action_for_form( $this->form_id, $this->id_base );
765 }
766
767 /**
768 * @return array
769 */
770 public function get_global_defaults() {
771 $defaults = $this->get_defaults();
772
773 if ( ! isset( $defaults['event'] ) ) {
774 $defaults['event'] = array( 'create' );
775 }
776
777 if ( ! isset( $defaults['conditions'] ) ) {
778 $defaults['conditions'] = array(
779 'send_stop' => '',
780 'any_all' => '',
781 );
782 }
783
784 return $defaults;
785 }
786
787 public function get_global_switch_fields() {
788 $switch = $this->get_switch_fields();
789 $switch['conditions'] = array( 'hide_field' );
790
791 $switch = apply_filters( 'frm_global_switch_fields', $switch );
792
793 return $switch;
794 }
795
796 /**
797 * Migrate settings from form->options into new action.
798 */
799 public function migrate_to_2( $form, $update = 'update' ) {
800 $action = $this->prepare_new( $form->id );
801 FrmAppHelper::unserialize_or_decode( $form->options );
802
803 // fill with existing options
804 foreach ( $action->post_content as $name => $val ) {
805 if ( isset( $form->options[ $name ] ) ) {
806 $action->post_content[ $name ] = $form->options[ $name ];
807 unset( $form->options[ $name ] );
808 }
809 }
810
811 $action = $this->migrate_values( $action, $form );
812
813 // check if action already exists
814 $post_id = get_posts(
815 array(
816 'name' => $action->post_name,
817 'post_type' => FrmFormActionsController::$action_post_type,
818 'post_status' => $action->post_status,
819 'numberposts' => 1,
820 )
821 );
822
823 if ( empty( $post_id ) ) {
824 // create action now
825 $post_id = $this->save_settings( $action );
826 }
827
828 if ( $post_id && 'update' == $update ) {
829 global $wpdb;
830 $form->options = maybe_serialize( $form->options );
831
832 // update form options
833 $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => $form->options ), array( 'id' => $form->id ) );
834 FrmForm::clear_form_cache();
835 }
836
837 return $post_id;
838 }
839
840 public static function action_conditions_met( $action, $entry ) {
841 if ( is_callable( 'FrmProFormActionsController::action_conditions_met' ) ) {
842 return FrmProFormActionsController::action_conditions_met( $action, $entry );
843 }
844
845 // This is here for reverse compatibility.
846 $notification = $action->post_content;
847 $stop = false;
848 $met = array();
849
850 if ( empty( $notification['conditions'] ) ) {
851 return $stop;
852 }
853
854 foreach ( $notification['conditions'] as $k => $condition ) {
855 if ( ! is_numeric( $k ) ) {
856 continue;
857 }
858
859 if ( $stop && 'any' == $notification['conditions']['any_all'] && 'stop' == $notification['conditions']['send_stop'] ) {
860 continue;
861 }
862
863 self::prepare_logic_value( $condition['hide_opt'], $action, $entry );
864
865 $observed_value = self::get_value_from_entry( $entry, $condition['hide_field'] );
866
867 $stop = FrmFieldsHelper::value_meets_condition( $observed_value, $condition['hide_field_cond'], $condition['hide_opt'] );
868
869 if ( $notification['conditions']['send_stop'] === 'send' ) {
870 $stop = $stop ? false : true;
871 }
872
873 $met[ $stop ] = $stop;
874 }//end foreach
875
876 if ( $notification['conditions']['any_all'] === 'all' && ! empty( $met ) && isset( $met[0] ) && isset( $met[1] ) ) {
877 $stop = ( $notification['conditions']['send_stop'] === 'send' );
878 } elseif ( $notification['conditions']['any_all'] === 'any' && $notification['conditions']['send_stop'] === 'send' && isset( $met[0] ) ) {
879 $stop = false;
880 }
881
882 return $stop;
883 }
884
885 /**
886 * Prepare the logic value for comparison against the entered value
887 *
888 * @since 2.01.02
889 *
890 * @param array|string $logic_value
891 *
892 * @return void
893 */
894 private static function prepare_logic_value( &$logic_value, $action, $entry ) {
895 if ( is_array( $logic_value ) ) {
896 $logic_value = reset( $logic_value );
897 }
898
899 if ( $logic_value === 'current_user' ) {
900 $logic_value = get_current_user_id();
901 }
902
903 $logic_value = apply_filters( 'frm_content', $logic_value, $action->menu_order, $entry );
904
905 /**
906 * @since 4.04.05
907 */
908 $logic_value = apply_filters( 'frm_action_logic_value', $logic_value );
909 }
910
911 /**
912 * Get the value from a specific field and entry
913 *
914 * @since 2.01.02
915 *
916 * @param object $entry
917 * @param int $field_id
918 *
919 * @return array|bool|mixed|string
920 */
921 private static function get_value_from_entry( $entry, $field_id ) {
922 $observed_value = '';
923
924 if ( isset( $entry->metas[ $field_id ] ) ) {
925 $observed_value = $entry->metas[ $field_id ];
926 } elseif ( $entry->post_id && FrmAppHelper::pro_is_installed() ) {
927 $field = FrmField::getOne( $field_id );
928 $observed_value = FrmProEntryMetaHelper::get_post_or_meta_value(
929 $entry,
930 $field,
931 array(
932 'links' => false,
933 'truncate' => false,
934 )
935 );
936 }
937
938 return $observed_value;
939 }
940
941 /**
942 * @param string $class
943 *
944 * @return array
945 */
946 public static function default_action_opts( $class = '' ) {
947 return array(
948 'classes' => 'frm_icon_font ' . $class,
949 'active' => false,
950 'limit' => 0,
951 );
952 }
953
954 public static function trigger_labels() {
955 $triggers = array(
956 'draft' => __( 'Draft is saved', 'formidable' ),
957 'create' => __( 'Entry is created', 'formidable' ),
958 'update' => __( 'Entry is updated', 'formidable' ),
959 'delete' => __( 'Entry is deleted', 'formidable' ),
960 'import' => __( 'Entry is imported', 'formidable' ),
961 );
962
963 return apply_filters( 'frm_action_triggers', $triggers );
964 }
965
966 /**
967 * @return void
968 */
969 public function render_conditional_logic_call_to_action() {
970 ?>
971 <h3>
972 <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 ); ?>">
973 <?php esc_html_e( 'Use Conditional Logic', 'formidable' ); ?>
974 </a>
975 </h3>
976 <?php
977 }
978
979 /**
980 * @return string
981 */
982 protected function get_upgrade_text() {
983 return __( 'Conditional form actions', 'formidable' );
984 }
985
986 /**
987 * Gets form fields for form action settings.
988 *
989 * @since 6.10
990 *
991 * @param int $form_id Form ID.
992 * @return object[]
993 */
994 protected function get_form_fields( $form_id ) {
995 // Get form fields, include embedded and repeater child fields.
996 $form_fields = FrmField::get_all_for_form( $form_id, '', 'include' );
997 return array_filter(
998 $form_fields,
999 function ( $form_field ) {
1000 return ! FrmField::is_no_save_field( $form_field->type );
1001 }
1002 );
1003 }
1004 }
1005