PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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
← All changes | classes/models/FrmFormAction.php +118 -125 6.26 → trunk View file →
@@ -93,9 +93,8 @@
93 93 * @return string
94 94 */
95 95 public function form( $instance, $args = array() ) {
96 96 echo '<p class="no-options-widget">' . esc_html__( 'There are no options for this action.', 'formidable' ) . '</p>';
97 -
98 97 return 'noform';
99 98 }
100 99
101 100 /**
@@ -141,9 +140,17 @@
141 140 if ( ! defined( 'ABSPATH' ) ) {
142 141 die( 'You are not allowed to call this page directly.' );
143 142 }
144 143
145 - $this->id_base = strtolower( $id_base );
144 + $this->id_base = strtolower( $id_base );
145 +
146 + /**
147 + * @since 6.31
148 + *
149 + * @param string $name
150 + */
151 + $name = apply_filters( 'frm_' . $id_base . '_action_name', $name );
152 +
146 153 $this->name = $name;
147 154 $this->option_name = 'frm_' . $this->id_base . '_action';
148 155
149 156 $default_options = array(
@@ -158,8 +165,11 @@
158 165 'tooltip' => $name,
159 166 'group' => $id_base,
160 167 'color' => '',
161 168 'keywords' => '',
169 + 'description' => '',
170 + 'is_new' => false,
171 + 'is_beta' => false,
162 172 );
163 173
164 174 $action_options = apply_filters( 'frm_' . $id_base . '_action_options', $action_options );
165 175 $group = $this->get_group( $action_options );
@@ -165,17 +175,18 @@
165 175 $group = $this->get_group( $action_options );
166 176 $action_options['group'] = $group['id'];
167 177
168 178 if ( ! isset( $action_options['color'] ) ) {
169 - $colors = array( 'green', 'orange', 'purple' );
170 - shuffle( $colors );
171 - $action_options['color'] = 'var(--' . reset( $colors ) . ')';
179 + // Deterministic fallback so all instances of the same action type render with the same color across requests.
180 + $colors = array( 'green', 'orange', 'purple' );
181 + $index = abs( crc32( $id_base ) ) % count( $colors );
182 + $action_options['color'] = 'var(--' . $colors[ $index ] . ')';
172 183 }
173 184
174 185 $upgrade_class = isset( $action_options['classes'] ) && $action_options['classes'] === 'frm_show_upgrade';
175 186
176 187 if ( $action_options['group'] === $id_base ) {
177 - $upgrade_class = strpos( $action_options['classes'], 'frm_show_upgrade' ) !== false;
188 + $upgrade_class = str_contains( $action_options['classes'], 'frm_show_upgrade' );
178 189 $action_options['classes'] = $group['icon'];
179 190 } elseif ( empty( $action_options['classes'] ) || $upgrade_class ) {
180 191 $action_options['classes'] = $group['icon'];
181 192 }
@@ -210,10 +221,11 @@
210 221 public function maybe_switch_field_ids( $action ) {
211 222 $updated_action = apply_filters( 'frm_maybe_switch_field_ids', $action );
212 223
213 224 if ( $updated_action === $action ) {
214 - $updated_action = FrmFieldsHelper::switch_field_ids( $action );
225 + return FrmFieldsHelper::switch_field_ids( $action );
215 226 }
227 +
216 228 return $updated_action;
217 229 }
218 230
219 231 /**
@@ -232,9 +244,9 @@
232 244 } elseif ( isset( $groups[ $this->id_base ] ) ) {
233 245 $group = $this->id_base;
234 246 } else {
235 247 foreach ( $groups as $name => $check_group ) {
236 - if ( isset( $check_group['actions'] ) && in_array( $this->id_base, $check_group['actions'] ) ) {
248 + if ( isset( $check_group['actions'] ) && in_array( $this->id_base, $check_group['actions'], true ) ) {
237 249 $group = $name;
238 250 break;
239 251 }
240 252 }
@@ -255,12 +267,11 @@
255 267 * @return string Name attribute for $field_name
256 268 */
257 269 public function get_field_name( $field_name, $post_field = 'post_content' ) {
258 270 $name = $this->option_name . '[' . $this->number . ']';
259 - $name .= ( empty( $post_field ) ? '' : '[' . $post_field . ']' );
260 - $name .= '[' . $field_name . ']';
271 + $name .= $post_field ? '[' . $post_field . ']' : '';
261 272
262 - return $name;
273 + return $name . ( '[' . $field_name . ']' );
263 274 }
264 275
265 276 /**
266 277 * Constructs id attributes for use in form() fields
@@ -297,9 +308,9 @@
297 308
298 309 $post_content = array();
299 310 $default_values = $this->get_global_defaults();
300 311
301 - // fill default values
312 + // Fill default values
302 313 $post_content = wp_parse_args( $post_content, $default_values );
303 314
304 315 if ( ! isset( $post_content['event'] ) && ! $this->action_options['force_event'] ) {
305 316 $post_content['event'] = array( reset( $this->action_options['event'] ) );
@@ -314,9 +325,8 @@
314 325 'post_type' => FrmFormActionsController::$action_post_type,
315 326 'post_name' => $this->form_id . '_' . $this->id_base . '_' . $this->number,
316 327 'menu_order' => $this->form_id,
317 328 );
318 - unset( $post_content );
319 329
320 330 return (object) $form_action;
321 331 }
322 332
@@ -339,10 +349,11 @@
339 349 *
340 350 * @return void
341 351 */
342 352 public function duplicate_form_actions( $form_id, $old_id ) {
353 + // phpcs:ignore Universal.Operators.StrictComparisons
343 354 if ( $form_id == $old_id ) {
344 - // don't duplicate the actions if this is a template getting updated
355 + // Don't duplicate the actions if this is a template getting updated
345 356 return;
346 357 }
347 358
348 359 $this->form_id = $old_id;
@@ -363,22 +374,19 @@
363 374 *
364 375 * @param array $action
365 376 * @param array $forms
366 377 *
367 - * @return int $post_id
378 + * @return int Post ID.
368 379 */
369 380 public function maybe_create_action( $action, $forms ) {
370 381 if ( isset( $action['ID'] ) && is_numeric( $action['ID'] ) && isset( $forms[ $action['menu_order'] ] ) && $forms[ $action['menu_order'] ] === 'updated' ) {
371 382 // Update action only
372 383 $action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
373 - $post_id = $this->save_settings( $action );
374 - } else {
375 - // Create action
376 - $action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
377 - $post_id = $this->duplicate_one( (object) $action, $action['menu_order'] );
384 + return $this->save_settings( $action );
378 385 }
379 -
380 - return $post_id;
386 + // Create action
387 + $action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
388 + return $this->duplicate_one( (object) $action, $action['menu_order'] );
381 389 }
382 390
383 391 /**
384 392 * @param object $action
@@ -397,9 +405,9 @@
397 405 $action->post_content[ $key ] = $frm_duplicate_ids[ $val ];
398 406 } elseif ( ! is_array( $val ) ) {
399 407 $action->post_content[ $key ] = FrmFieldsHelper::switch_field_ids( $val );
400 408 } elseif ( isset( $switch[ $key ] ) && is_array( $switch[ $key ] ) ) {
401 - // loop through each value if empty
409 + // Loop through each value if empty
402 410 if ( empty( $switch[ $key ] ) ) {
403 411 $switch[ $key ] = array_keys( $val );
404 412 }
405 413
@@ -438,11 +446,11 @@
438 446 } else {
439 447 foreach ( (array) $val as $ck => $cv ) {
440 448 if ( is_array( $cv ) ) {
441 449 $action[ $ck ] = $this->duplicate_array_walk( $action[ $ck ], $subkey, $cv );
442 - } elseif ( $ck == $subkey && isset( $frm_duplicate_ids[ $cv ] ) ) {
450 + } elseif ( $ck == $subkey && isset( $frm_duplicate_ids[ $cv ] ) ) { // phpcs:ignore Universal.Operators.StrictComparisons
443 451 $action[ $ck ] = $frm_duplicate_ids[ $cv ];
444 - } elseif ( $ck == $subkey ) {
452 + } elseif ( $ck == $subkey ) { // phpcs:ignore Universal.Operators.StrictComparisons
445 453 $action[ $ck ] = $this->maybe_switch_field_ids( $action[ $ck ] );
446 454 }
447 455 }
448 456 }//end if
@@ -465,20 +473,20 @@
465 473 $all_instances = $this->get_settings();
466 474
467 475 // We need to update the data
468 476 if ( $this->updated ) {
469 - return;
477 + return null;
470 478 }
471 479
472 480 // phpcs:ignore WordPress.Security.NonceVerification.Missing
473 - if ( isset( $_POST[ $this->option_name ] ) && is_array( $_POST[ $this->option_name ] ) ) {
474 - // Sanitizing removes scripts and <email> type of values.
475 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
476 - $settings = wp_unslash( $_POST[ $this->option_name ] );
477 - } else {
478 - return;
481 + if ( ! isset( $_POST[ $this->option_name ] ) || ! is_array( $_POST[ $this->option_name ] ) ) {
482 + return null;
479 483 }
480 484
485 + // Sanitizing removes scripts and <email> type of values.
486 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
487 + $settings = wp_unslash( $_POST[ $this->option_name ] );
488 +
481 489 $action_ids = array();
482 490
483 491 foreach ( $settings as $number => $new_instance ) {
484 492 $this->_set( $number );
@@ -488,9 +496,9 @@
488 496 if ( ! isset( $new_instance['post_status'] ) ) {
489 497 $new_instance['post_status'] = 'draft';
490 498 }
491 499
492 - // settings were never opened, so don't update
500 + // Settings were never opened, so don't update
493 501 if ( ! isset( $new_instance['post_title'] ) ) {
494 502 $this->maybe_update_status( $new_instance, $old_instance );
495 503 $action_ids[] = $new_instance['ID'];
496 504 $this->updated = true;
@@ -563,9 +571,8 @@
563 571 * @return int|WP_Error
564 572 */
565 573 public function save_settings( $settings ) {
566 574 self::clear_cache();
567 -
568 575 return FrmDb::save_settings( $settings, 'frm_actions' );
569 576 }
570 577
571 578 /**
@@ -602,10 +609,10 @@
602 609 */
603 610 public static function get_action_for_form( $form_id, $type = 'all', $atts = array() ) {
604 611 $action_controls = FrmFormActionsController::get_form_actions( $type );
605 612
606 - if ( empty( $action_controls ) ) {
607 - // don't continue if there are no available actions
613 + if ( ! $action_controls ) {
614 + // Don't continue if there are no available actions
608 615 return array();
609 616 }
610 617
611 618 if ( 'all' !== $type ) {
@@ -611,15 +618,15 @@
611 618 if ( 'all' !== $type ) {
612 619 if ( is_array( $action_controls ) ) {
613 620 return array();
614 621 }
622 +
615 623 return $action_controls->get_all( $form_id, $atts );
616 624 }
617 625
618 626 self::prepare_get_action( $atts );
619 627
620 - $limit = self::get_action_limit( $form_id, $atts['limit'] );
621 -
628 + $limit = self::get_action_limit( $form_id, $atts['limit'] );
622 629 $args = self::action_args( $form_id, $limit );
623 630 $args['post_status'] = $atts['post_status'];
624 631 $actions = FrmDb::check_cache( json_encode( $args ), 'frm_actions', $args, 'get_posts' );
625 632
@@ -629,9 +636,9 @@
629 636
630 637 $settings = array();
631 638
632 639 foreach ( $actions as $action ) {
633 - // some plugins/themes are formatting the post_excerpt
640 + // Some plugins/themes are formatting the post_excerpt
634 641 $action->post_excerpt = sanitize_title( $action->post_excerpt );
635 642
636 643 if ( ! isset( $action_controls[ $action->post_excerpt ] ) ) {
637 644 continue;
@@ -644,13 +651,9 @@
644 651 break;
645 652 }
646 653 }
647 654
648 - if ( 1 === $limit ) {
649 - $settings = reset( $settings );
650 - }
651 -
652 - return $settings;
655 + return 1 === $limit ? reset( $settings ) : $settings;
653 656 }
654 657
655 658 /**
656 659 * Get the limit for the number of actions for a single form. By default, this is 99, but
@@ -663,9 +666,9 @@
663 666 *
664 667 * @return int The filtered limit value.
665 668 */
666 669 public static function get_action_limit( $form_id, $limit = 99 ) {
667 - $type = 'all';
670 + $type = 'all';
668 671 return (int) apply_filters( 'frm_form_action_limit', (int) $limit, compact( 'type', 'form_id' ) );
669 672 }
670 673
671 674 /**
@@ -670,16 +673,16 @@
670 673
671 674 /**
672 675 * @since 3.04
673 676 *
674 - * @param array $args
675 - * @param string $default_status
677 + * @param array|string $args
678 + * @param string $default_status
676 679 *
677 680 * @return void
678 681 */
679 682 protected static function prepare_get_action( &$args, $default_status = 'publish' ) {
680 683 if ( is_numeric( $args ) ) {
681 - // for reverse compatibility. $limit was changed to $args
684 + // For reverse compatibility. $limit was changed to $args
682 685 $args = array(
683 686 'limit' => $args,
684 687 );
685 688 }
@@ -754,9 +757,9 @@
754 757 unset( $query );
755 758
756 759 remove_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
757 760
758 - if ( empty( $actions ) ) {
761 + if ( ! $actions ) {
759 762 return array();
760 763 }
761 764
762 765 $settings = array();
@@ -765,23 +768,18 @@
765 768 if ( count( $settings ) >= $limit ) {
766 769 continue;
767 770 }
768 771
769 - $action = $this->prepare_action( $action );
770 -
772 + $action = $this->prepare_action( $action );
771 773 $settings[ $action->ID ] = $action;
772 774 }
773 775
774 - if ( 1 === $limit ) {
775 - $settings = reset( $settings );
776 - }
777 -
778 - return $settings;
776 + return 1 === $limit ? reset( $settings ) : $settings;
779 777 }
780 778
781 779 /**
782 - * @param int $form_id
783 - * @param int $limit
780 + * @param int|string $form_id
781 + * @param int $limit
784 782 *
785 783 * @return array
786 784 */
787 785 public static function action_args( $form_id = 0, $limit = 99 ) {
@@ -792,9 +790,9 @@
792 790 'orderby' => 'title',
793 791 'order' => 'ASC',
794 792 );
795 793
796 - if ( $form_id && $form_id != 'all' ) {
794 + if ( $form_id && $form_id !== 'all' ) {
797 795 $args['menu_order'] = $form_id;
798 796 }
799 797
800 798 return $args;
@@ -810,18 +808,20 @@
810 808 $action->post_excerpt = sanitize_title( $action->post_excerpt );
811 809
812 810 $default_values = $this->get_global_defaults();
813 811
814 - // fill default values
812 + // Fill default values
815 813 $action->post_content += $default_values;
816 814
817 815 foreach ( $default_values as $k => $vals ) {
818 - if ( is_array( $vals ) && ! empty( $vals ) ) {
819 - if ( 'event' === $k && ! $this->action_options['force_event'] && ! empty( $action->post_content[ $k ] ) ) {
820 - continue;
821 - }
822 - $action->post_content[ $k ] = wp_parse_args( $action->post_content[ $k ], $vals );
816 + if ( ! is_array( $vals ) || ! $vals ) {
817 + continue;
823 818 }
819 +
820 + if ( 'event' === $k && ! $this->action_options['force_event'] && ! empty( $action->post_content[ $k ] ) ) {
821 + continue;
822 + }
823 + $action->post_content[ $k ] = wp_parse_args( $action->post_content[ $k ], $vals );
824 824 }
825 825
826 826 if ( ! is_array( $action->post_content['event'] ) ) {
827 827 $action->post_content['event'] = explode( ',', $action->post_content['event'] );
@@ -846,9 +846,9 @@
846 846 if ( $form_id ) {
847 847 $query['menu_order'] = $form_id;
848 848 }
849 849
850 - if ( 'all' != $type ) {
850 + if ( 'all' !== $type ) {
851 851 $query['post_excerpt'] = $this->id_base;
852 852 }
853 853
854 854 $post_ids = FrmDb::get_col( $wpdb->posts, $query, 'ID' );
@@ -903,11 +903,9 @@
903 903 public function get_global_switch_fields() {
904 904 $switch = $this->get_switch_fields();
905 905 $switch['conditions'] = array( 'hide_field' );
906 906
907 - $switch = apply_filters( 'frm_global_switch_fields', $switch );
908 -
909 - return $switch;
907 + return apply_filters( 'frm_global_switch_fields', $switch );
910 908 }
911 909
912 910 /**
913 911 * Migrate settings from form->options into new action.
@@ -920,19 +918,21 @@
920 918 public function migrate_to_2( $form, $update = 'update' ) {
921 919 $action = $this->prepare_new( $form->id );
922 920 FrmAppHelper::unserialize_or_decode( $form->options );
923 921
924 - // fill with existing options
922 + // Fill with existing options
925 923 foreach ( $action->post_content as $name => $val ) {
926 - if ( isset( $form->options[ $name ] ) ) {
927 - $action->post_content[ $name ] = $form->options[ $name ];
928 - unset( $form->options[ $name ] );
924 + if ( ! isset( $form->options[ $name ] ) ) {
925 + continue;
929 926 }
927 +
928 + $action->post_content[ $name ] = $form->options[ $name ];
929 + unset( $form->options[ $name ] );
930 930 }
931 931
932 932 $action = $this->migrate_values( $action, $form );
933 933
934 - // check if action already exists
934 + // Check if action already exists
935 935 $post_id = get_posts(
936 936 array(
937 937 'name' => $action->post_name,
938 938 'post_type' => FrmFormActionsController::$action_post_type,
@@ -940,22 +940,24 @@
940 940 'numberposts' => 1,
941 941 )
942 942 );
943 943
944 - if ( empty( $post_id ) ) {
945 - // create action now
944 + if ( ! $post_id ) {
945 + // Create action now
946 946 $post_id = $this->save_settings( $action );
947 947 }
948 948
949 - if ( $post_id && 'update' == $update ) {
950 - global $wpdb;
951 - $form->options = maybe_serialize( $form->options );
949 + if ( ! $post_id || 'update' !== $update ) {
950 + return $post_id;
951 + }
952 952
953 - // update form options
954 - $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => $form->options ), array( 'id' => $form->id ) );
955 - FrmForm::clear_form_cache();
956 - }
953 + global $wpdb;
954 + $form->options = maybe_serialize( $form->options );
957 955
956 + // Update form options
957 + $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => $form->options ), array( 'id' => $form->id ) );
958 + FrmForm::clear_form_cache();
959 +
958 960 return $post_id;
959 961 }
960 962
961 963 /**
@@ -967,44 +969,12 @@
967 969 public static function action_conditions_met( $action, $entry ) {
968 970 if ( is_callable( 'FrmProFormActionsController::action_conditions_met' ) ) {
969 971 return FrmProFormActionsController::action_conditions_met( $action, $entry );
970 972 }
971 -
972 - $stop = false;
973 - return $stop;
973 + return false;
974 974 }
975 975
976 976 /**
977 - * Get the value from a specific field and entry
978 - *
979 - * @since 2.01.02
980 - *
981 - * @param object $entry
982 - * @param int $field_id
983 - *
984 - * @return array|bool|mixed|string
985 - */
986 - private static function get_value_from_entry( $entry, $field_id ) {
987 - $observed_value = '';
988 -
989 - if ( isset( $entry->metas[ $field_id ] ) ) {
990 - $observed_value = $entry->metas[ $field_id ];
991 - } elseif ( $entry->post_id && FrmAppHelper::pro_is_installed() ) {
992 - $field = FrmField::getOne( $field_id );
993 - $observed_value = FrmProEntryMetaHelper::get_post_or_meta_value(
994 - $entry,
995 - $field,
996 - array(
997 - 'links' => false,
998 - 'truncate' => false,
999 - )
1000 - );
1001 - }
1002 -
1003 - return $observed_value;
1004 - }
1005 -
1006 - /**
1007 977 * @param string $class
1008 978 *
1009 979 * @return array
1010 980 */
@@ -1009,11 +979,12 @@
1009 979 * @return array
1010 980 */
1011 981 public static function default_action_opts( $class = '' ) {
1012 982 return array(
1013 - 'classes' => 'frm_icon_font ' . $class,
1014 - 'active' => false,
1015 - 'limit' => 0,
983 + 'classes' => 'frmfont ' . $class,
984 + 'active' => false,
985 + 'limit' => 0,
986 + 'description' => '',
1016 987 );
1017 988 }
1018 989
1019 990 /**
@@ -1031,18 +1002,40 @@
1031 1002 return apply_filters( 'frm_action_triggers', $triggers );
1032 1003 }
1033 1004
1034 1005 /**
1006 + * @param string $action_key The unique key for this action instance.
1007 + *
1035 1008 * @return void
1036 1009 */
1037 - public function render_conditional_logic_call_to_action() {
1010 + public function render_conditional_logic_call_to_action( $action_key = '' ) {
1011 + $params = array(
1012 + 'class' => 'frm-h-stack-xs frm-bt-200 frm-py-md frm_show_upgrade',
1013 + 'data-upgrade' => $this->get_upgrade_text(),
1014 + 'data-medium' => 'conditional-' . $this->id_base,
1015 + 'data-content' => 'conditional-logic',
1016 + );
1017 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
1038 1018 ?>
1039 - <h3>
1040 - <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 ); ?>">
1041 - <?php esc_html_e( 'Use Conditional Logic', 'formidable' ); ?>
1042 - </a>
1043 - </h3>
1019 + <div <?php FrmAppHelper::array_to_html_params( $params, true ); ?>>
1020 + <?php
1021 + FrmHtmlHelper::toggle(
1022 + 'frm_logic_cta_' . $action_key,
1023 + 'frm_logic_cta_' . $action_key,
1024 + array(
1025 + 'div_class' => 'with_frm_style frm_toggle',
1026 + 'checked' => false,
1027 + 'echo' => true,
1028 + 'disabled' => true,
1029 + )
1030 + );
1031 + ?>
1032 + <label for="frm_logic_cta_<?php echo esc_attr( $action_key ); ?>" class="frm_noallow">
1033 + <?php esc_html_e( 'Use Conditional Logic', 'formidable' ); ?>
1034 + </label>
1035 + </div>
1044 1036 <?php
1037 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
1045 1038 }
1046 1039
1047 1040 /**
1048 1041 * @return string