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