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

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