Completed
Push — master ( 5a8d2f...002617 )
by Stephanie
02:57
created

FrmFormAction::prepare_action()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 8
nop 1
dl 0
loc 24
rs 8.4444
c 0
b 0
f 0
1
<?php
2
3
class FrmFormAction {
4
5
	public $id_base;         // Root id for all actions of this type.
6
	public $name;            // Name for this action type.
7
	public $option_name;
8
	public $action_options;  // Option array passed to wp_register_sidebar_widget()
9
	public $control_options; // Option array passed to wp_register_widget_control()
10
11
	public $form_id;         // The ID of the form to evaluate
12
	public $number = false;  // Unique ID number of the current instance.
13
	public $id = '';         // Unique ID string of the current instance (id_base-number)
14
	public $updated = false; // Set true when we update the data after a POST submit - makes sure we don't do it twice.
15
16
	// Member functions that you must over-ride.
17
18
	/**
19
	 * This function should check that $new_instance is set correctly.
20
	 * The newly calculated value of $instance should be returned.
21
	 * If "false" is returned, the instance won't be saved/updated.
22
	 *
23
	 * @param array $new_instance New settings for this instance as input by the user via form()
24
	 * @param array $old_instance Old settings for this instance
25
	 * @return array Settings to save or bool false to cancel saving
26
	 */
27
	public function update( $new_instance, $old_instance ) {
28
		return $new_instance;
29
	}
30
31
	/**
32
     * Echo the settings update form
33
	 *
34
	 * @param array $instance Current settings
35
	 */
36
	public function form( $instance, $args = array() ) {
37
		echo '<p class="no-options-widget">' . esc_html__( 'There are no options for this action.', 'formidable' ) . '</p>';
38
		return 'noform';
39
	}
40
41
	/**
42
	 * @return array of the default options
43
	 */
44
	public function get_defaults() {
45
	    return array();
46
	}
47
48
	public function get_switch_fields() {
49
	    return array();
50
	}
51
52
	public function migrate_values( $action, $form ) {
53
	    return $action;
54
	}
55
56
	// Functions you'll need to call.
57
58
	/**
59
	 * PHP5 constructor
60
	 *
61
	 * @param string $id_base Optional Base ID for the widget, lower case,
62
	 * if left empty a portion of the widget's class name will be used. Has to be unique.
63
	 * @param string $name Name for the widget displayed on the configuration page.
64
	 * @param array $action_options Optional Passed to wp_register_sidebar_widget()
65
	 *   - description: shown on the configuration page
66
	 *   - classname
67
	 * @param array $control_options Optional Passed to wp_register_widget_control()
68
	 *   - width: required if more than 250px
69
	 *   - height: currently not used but may be needed in the future
70
	 */
71
	public function __construct( $id_base, $name, $action_options = array(), $control_options = array() ) {
72
		if ( ! defined( 'ABSPATH' ) ) {
73
			die( 'You are not allowed to call this page directly.' );
74
		}
75
76
		$this->id_base = strtolower( $id_base );
77
		$this->name = $name;
78
		$this->option_name = 'frm_' . $this->id_base . '_action';
79
80
        $default_options = array(
81
            'classes'   => '',
82
            'active'    => true,
83
			'event'     => array( 'create' ),
84
            'limit'     => 1,
85
            'force_event' => false,
86
            'priority'  => 20,
87
            'ajax_load' => true,
88
            'tooltip'   => $name,
89
        );
90
91
		$action_options = apply_filters( 'frm_' . $id_base . '_action_options', $action_options );
92
		$this->action_options = wp_parse_args( $action_options, $default_options );
93
		$this->control_options = wp_parse_args( $control_options, array( 'id_base' => $this->id_base ) );
94
	}
95
96
	/**
97
	 * @param string $id_base
98
	 */
99
	public function FrmFormAction( $id_base, $name, $action_options = array(), $control_options = array() ) {
100
		FrmFormAction::__construct( $id_base, $name, $action_options, $control_options );
101
	}
102
103
	/**
104
	 * Constructs name attributes for use in form() fields
105
	 *
106
	 * This function should be used in form() methods to create name attributes for fields to be saved by update()
107
	 *
108
	 * @param string $field_name Field name
109
	 * @return string Name attribute for $field_name
110
	 */
111
	public function get_field_name( $field_name, $post_field = 'post_content' ) {
112
		$name = $this->option_name . '[' . $this->number . ']';
113
		$name .= ( empty( $post_field ) ? '' : '[' . $post_field . ']' );
114
		$name .= '[' . $field_name . ']';
115
		return $name;
116
	}
117
118
	/**
119
	 * Constructs id attributes for use in form() fields
120
	 *
121
	 * This function should be used in form() methods to create id attributes for fields to be saved by update()
122
	 *
123
	 * @param string $field_name Field name
124
	 * @return string ID attribute for $field_name
125
	 */
126
	public function get_field_id( $field_name ) {
127
		return $field_name . '_' . $this->number;
128
	}
129
130
	// Private Function. Don't worry about this.
131
132
	public function _set( $number ) {
133
		$this->number = $number;
134
		$this->id = $this->id_base . '-' . $number;
135
	}
136
137
	public function prepare_new( $form_id = false ) {
138
        if ( $form_id ) {
139
            $this->form_id = $form_id;
140
        }
141
142
        $post_content = array();
143
        $default_values = $this->get_global_defaults();
144
145
		// fill default values
146
		$post_content = wp_parse_args( $post_content, $default_values );
147
148
		if ( ! isset( $post_content['event'] ) && ! $this->action_options['force_event'] ) {
149
			$post_content['event'] = array( reset( $this->action_options['event'] ) );
150
		}
151
152
        $form_action = array(
153
            'post_title'    => $this->name,
154
            'post_content'  => $post_content,
155
            'post_excerpt'  => $this->id_base,
156
            'ID'            => '',
157
            'post_status'   => 'publish',
158
            'post_type'     => FrmFormActionsController::$action_post_type,
159
			'post_name'     => $this->form_id . '_' . $this->id_base . '_' . $this->number,
160
            'menu_order'    => $this->form_id,
161
        );
162
		unset( $post_content );
163
164
        return (object) $form_action;
165
    }
166
167
	public function create( $form_id ) {
168
        $this->form_id = $form_id;
169
170
        $action = $this->prepare_new();
171
172
		return $this->save_settings( $action );
173
    }
174
175
	public function duplicate_form_actions( $form_id, $old_id ) {
176
        if ( $form_id == $old_id ) {
177
            // don't duplicate the actions if this is a template getting updated
178
            return;
179
        }
180
181
        $this->form_id = $old_id;
182
        $actions = $this->get_all( $old_id );
183
184
        $this->form_id = $form_id;
185
        foreach ( $actions as $action ) {
186
			$this->duplicate_one( $action, $form_id );
187
			unset( $action );
188
        }
189
    }
190
191
    /* Check if imported action should be created or updated
192
    *
193
    * Since 2.0
194
    *
195
    * @param array $action
196
    * @return integer $post_id
197
    */
198
    public function maybe_create_action( $action, $forms ) {
199
		if ( isset( $action['ID'] ) && is_numeric( $action['ID'] ) && $forms[ $action['menu_order'] ] == 'updated' ) {
200
            // Update action only
201
            $action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
202
            $post_id = $this->save_settings( $action );
203
        } else {
204
			// Create action
205
			$action['post_content'] = FrmAppHelper::maybe_json_decode( $action['post_content'] );
206
			$post_id = $this->duplicate_one( (object) $action, $action['menu_order'] );
207
        }
208
        return $post_id;
209
    }
210
211
	public function duplicate_one( $action, $form_id ) {
212
        global $frm_duplicate_ids;
213
214
        $action->menu_order = $form_id;
215
        $switch = $this->get_global_switch_fields();
216
        foreach ( (array) $action->post_content as $key => $val ) {
217
			if ( is_numeric( $val ) && isset( $frm_duplicate_ids[ $val ] ) ) {
218
				$action->post_content[ $key ] = $frm_duplicate_ids[ $val ];
219
            } else if ( ! is_array( $val ) ) {
220
				$action->post_content[ $key ] = FrmFieldsHelper::switch_field_ids( $val );
221
			} else if ( isset( $switch[ $key ] ) && is_array( $switch[ $key ] ) ) {
222
                // loop through each value if empty
223
				if ( empty( $switch[ $key ] ) ) {
224
					$switch[ $key ] = array_keys( $val );
225
				}
226
227
				foreach ( $switch[ $key ] as $subkey ) {
228
					$action->post_content[ $key ] = $this->duplicate_array_walk( $action->post_content[ $key ], $subkey, $val );
229
                }
230
            }
231
232
			unset( $key, $val );
233
		}
234
		unset( $action->ID );
235
236
		return $this->save_settings( $action );
237
    }
238
239
	private function duplicate_array_walk( $action, $subkey, $val ) {
240
        global $frm_duplicate_ids;
241
242
		if ( is_array( $subkey ) ) {
243
            foreach ( $subkey as $subkey2 ) {
244
                foreach ( (array) $val as $ck => $cv ) {
245
					if ( is_array( $cv ) ) {
246
						$action[ $ck ] = $this->duplicate_array_walk( $action[ $ck ], $subkey2, $cv );
247
					} else if ( isset( $cv[ $subkey ] ) && is_numeric( $cv[ $subkey ] ) && isset( $frm_duplicate_ids[ $cv[ $subkey ] ] ) ) {
248
						$action[ $ck ][ $subkey ] = $frm_duplicate_ids[ $cv[ $subkey ] ];
249
                    }
250
                }
251
            }
252
        } else {
253
            foreach ( (array) $val as $ck => $cv ) {
254
				if ( is_array( $cv ) ) {
255
					$action[ $ck ] = $this->duplicate_array_walk( $action[ $ck ], $subkey, $cv );
256
				} else if ( $ck == $subkey && isset( $frm_duplicate_ids[ $cv ] ) ) {
257
					$action[ $ck ] = $frm_duplicate_ids[ $cv ];
258
                }
259
            }
260
        }
261
262
        return $action;
263
    }
264
265
	/**
266
	 * Deal with changed settings.
267
	 *
268
	 * Do NOT over-ride this function
269
	 *
270
	 */
271
 	public function update_callback( $form_id ) {
272
        $this->form_id = $form_id;
273
274
 		$all_instances = $this->get_settings();
275
276
 		// We need to update the data
277
 		if ( $this->updated ) {
278
 			return;
279
 		}
280
281
		if ( isset( $_POST[ $this->option_name ] ) && is_array( $_POST[ $this->option_name ] ) ) {
282
			$settings = $_POST[ $this->option_name ];
283
 		} else {
284
 			return;
285
 		}
286
287
        $action_ids = array();
288
289
 		foreach ( $settings as $number => $new_instance ) {
290
 			$this->_set( $number );
291
292
 			if ( ! isset( $new_instance['post_title'] ) ) {
293
 			    // settings were never opened, so don't update
294
 			    $action_ids[] = $new_instance['ID'];
295
         		$this->updated = true;
296
         		continue;
297
 			}
298
299
			$old_instance = isset( $all_instances[ $number ] ) ? $all_instances[ $number ] : array();
300
301
 			$new_instance['post_type']  = FrmFormActionsController::$action_post_type;
302
			$new_instance['post_name']  = $this->form_id . '_' . $this->id_base . '_' . $this->number;
303
            $new_instance['menu_order']   = $this->form_id;
304
            $new_instance['post_status']  = 'publish';
305
            $new_instance['post_date'] = isset( $old_instance->post_date ) ? $old_instance->post_date : '';
306
307
 			$instance = $this->update( $new_instance, $old_instance );
308
309
			/**
310
			 * Filter an action's settings before saving.
311
			 *
312
			 * Returning false will effectively short-circuit the widget's ability
313
			 * to update settings.
314
			 *
315
			 * @since 2.0
316
			 *
317
			 * @param array     $instance     The current widget instance's settings.
318
			 * @param array     $new_instance Array of new widget settings.
319
			 * @param array     $old_instance Array of old widget settings.
320
			 * @param WP_Widget $this         The current widget instance.
321
			 */
322
			$instance = apply_filters( 'frm_action_update_callback', $instance, $new_instance, $old_instance, $this );
323
324
			$instance['post_content'] = apply_filters( 'frm_before_save_action', $instance['post_content'], $instance, $new_instance, $old_instance, $this );
325
			$instance['post_content'] = apply_filters( 'frm_before_save_' . $this->id_base . '_action', $new_instance['post_content'], $instance, $new_instance, $old_instance, $this );
326
327
			if ( false !== $instance ) {
328
				$all_instances[ $number ] = $instance;
329
			}
330
331
			$action_ids[] = $this->save_settings( $instance );
332
333
     		$this->updated = true;
334
 		}
335
336
 		return $action_ids;
337
 	}
338
339
	public function save_settings( $settings ) {
340
		self::clear_cache();
341
		return FrmDb::save_settings( $settings, 'frm_actions' );
342
	}
343
344
	public function get_single_action( $id ) {
345
		$action = get_post( $id );
346
		if ( $action ) {
347
			$action = $this->prepare_action( $action );
348
			$this->_set( $id );
349
		}
350
	    return $action;
351
	}
352
353
	public function get_one( $form_id ) {
354
		return $this->get_all( $form_id, 1 );
355
	}
356
357
    public static function get_action_for_form( $form_id, $type = 'all', $limit = 99 ) {
358
        $action_controls = FrmFormActionsController::get_form_actions( $type );
359
		if ( empty( $action_controls ) ) {
360
            // don't continue if there are no available actions
361
            return array();
362
        }
363
364
		$limit = apply_filters( 'frm_form_action_limit', $limit, compact( 'type', 'form_id' ) );
365
366
        if ( 'all' != $type ) {
367
            return $action_controls->get_all( $form_id, $limit );
368
        }
369
370
		$args = self::action_args( $form_id, $limit );
371
		$actions = FrmDb::check_cache( serialize( $args ), 'frm_actions', $args, 'get_posts' );
372
373
        if ( ! $actions ) {
374
            return array();
375
        }
376
377
        $settings = array();
378
        foreach ( $actions as $action ) {
379
			// some plugins/themes are formatting the post_excerpt
380
			$action->post_excerpt = sanitize_title( $action->post_excerpt );
381
382
			if ( ! isset( $action_controls[ $action->post_excerpt ] ) ) {
383
                continue;
384
            }
385
386
            $action = $action_controls[ $action->post_excerpt ]->prepare_action( $action );
387
			$settings[ $action->ID ] = $action;
388
389
			if ( count( $settings ) >= $limit ) {
390
				break;
391
			}
392
        }
393
394
        if ( 1 === $limit ) {
395
			$settings = reset( $settings );
396
        }
397
398
        return $settings;
399
    }
400
401
	/**
402
	 * @param int $action_id
403
	 */
404
	public static function get_single_action_type( $action_id, $type ) {
405
		if ( ! $type ) {
406
			return false;
407
		}
408
		$action_control = FrmFormActionsController::get_form_actions( $type );
409
		return $action_control->get_single_action( $action_id );
410
	}
411
412
	/**
413
	 * @param int $form_id
414
	 * @return bool
415
	 */
416
	public static function form_has_action_type( $form_id, $type ) {
417
		$payment_actions = self::get_action_for_form( $form_id, $type );
418
		return ! empty( $payment_actions );
419
	}
420
421
	public function get_all( $form_id = false, $limit = 99 ) {
422
	    if ( $form_id ) {
423
	        $this->form_id = $form_id;
424
	    }
425
426
	    $type = $this->id_base;
427
428
	    global $frm_vars;
429
	    $frm_vars['action_type'] = $type;
430
431
		add_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
432
		$query = self::action_args( $form_id, $limit );
433
        $query['post_status']      = 'any';
434
        $query['suppress_filters'] = false;
435
436
		$actions = FrmDb::check_cache( serialize( $query ) . '_type_' . $type, 'frm_actions', $query, 'get_posts' );
437
		unset( $query );
438
439
		remove_filter( 'posts_where', 'FrmFormActionsController::limit_by_type' );
440
441
		if ( empty( $actions ) ) {
442
            return array();
443
        }
444
445
        $settings = array();
446
        foreach ( $actions as $action ) {
447
			if ( count( $settings ) >= $limit ) {
448
                continue;
449
            }
450
451
			$action = $this->prepare_action( $action );
452
453
			$settings[ $action->ID ] = $action;
454
        }
455
456
        if ( 1 === $limit ) {
457
			$settings = reset( $settings );
458
        }
459
460
        return $settings;
461
	}
462
463
	public static function action_args( $form_id = 0, $limit = 99 ) {
464
		$args = array(
465
			'post_type'   => FrmFormActionsController::$action_post_type,
466
			'post_status' => 'publish',
467
			'numberposts' => $limit,
468
			'orderby'     => 'title',
469
			'order'       => 'ASC',
470
		);
471
472
		if ( $form_id && $form_id != 'all' ) {
473
			$args['menu_order'] = $form_id;
474
		}
475
476
		return $args;
477
	}
478
479
	public function prepare_action( $action ) {
480
		$action->post_content = (array) FrmAppHelper::maybe_json_decode( $action->post_content );
481
		$action->post_excerpt = sanitize_title( $action->post_excerpt );
482
483
        $default_values = $this->get_global_defaults();
484
485
        // fill default values
486
        $action->post_content += $default_values;
487
488
        foreach ( $default_values as $k => $vals ) {
489
			if ( is_array( $vals ) && ! empty( $vals ) ) {
490
				if ( 'event' == $k && ! $this->action_options['force_event'] && ! empty( $action->post_content[ $k ] ) ) {
491
                    continue;
492
                }
493
				$action->post_content[ $k ] = wp_parse_args( $action->post_content[ $k ], $vals );
494
            }
495
        }
496
497
		if ( ! is_array( $action->post_content['event'] ) ) {
498
			$action->post_content['event'] = explode( ',', $action->post_content['event'] );
499
		}
500
501
        return $action;
502
	}
503
504
	public function destroy( $form_id = false, $type = 'default' ) {
505
	    global $wpdb;
506
507
	    $this->form_id = $form_id;
508
509
	    $query = array( 'post_type' => FrmFormActionsController::$action_post_type );
510
	    if ( $form_id ) {
511
	        $query['menu_order'] = $form_id;
512
	    }
513
	    if ( 'all' != $type ) {
514
	        $query['post_excerpt'] = $this->id_base;
515
	    }
516
517
        $post_ids = FrmDb::get_col( $wpdb->posts, $query, 'ID' );
518
519
        foreach ( $post_ids as $id ) {
520
			wp_delete_post( $id );
521
        }
522
		self::clear_cache();
523
	}
524
525
	/**
526
	 * Delete the action cache when a form action is created, deleted, or updated
527
	 *
528
	 * @since 2.0.5
529
	 */
530
	public static function clear_cache() {
531
		FrmDb::cache_delete_group( 'frm_actions' );
532
	}
533
534
	public function get_settings() {
535
		return self::get_action_for_form( $this->form_id, $this->id_base );
536
	}
537
538
	public function get_global_defaults() {
539
	    $defaults = $this->get_defaults();
540
541
		if ( ! isset( $defaults['event'] ) ) {
542
			$defaults['event'] = array( 'create' );
543
	    }
544
545
		if ( ! isset( $defaults['conditions'] ) ) {
546
	        $defaults['conditions'] = array(
547
                'send_stop' => '',
548
                'any_all'   => '',
549
            );
550
        }
551
552
        return $defaults;
553
	}
554
555
	public function get_global_switch_fields() {
556
	    $switch = $this->get_switch_fields();
557
		$switch['conditions'] = array( 'hide_field' );
558
	    return $switch;
559
	}
560
561
	/**
562
	 * Migrate settings from form->options into new action.
563
	 */
564
	public function migrate_to_2( $form, $update = 'update' ) {
565
		$action = $this->prepare_new( $form->id );
566
		$form->options = maybe_unserialize( $form->options );
567
568
        // fill with existing options
569
        foreach ( $action->post_content as $name => $val ) {
570
			if ( isset( $form->options[ $name ] ) ) {
571
				$action->post_content[ $name ] = $form->options[ $name ];
572
				unset( $form->options[ $name ] );
573
            }
574
        }
575
576
		$action = $this->migrate_values( $action, $form );
577
578
        // check if action already exists
579
		$post_id = get_posts(
580
			array(
581
				'name'          => $action->post_name,
582
				'post_type'     => FrmFormActionsController::$action_post_type,
583
				'post_status'   => $action->post_status,
584
				'numberposts'   => 1,
585
			)
586
		);
587
588
		if ( empty( $post_id ) ) {
589
			// create action now
590
			$post_id = $this->save_settings( $action );
591
		}
592
593
        if ( $post_id && 'update' == $update ) {
594
            global $wpdb;
595
			$form->options = maybe_serialize( $form->options );
596
597
            // update form options
598
			$wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => $form->options ), array( 'id' => $form->id ) );
599
	        FrmForm::clear_form_cache();
600
        }
601
602
        return $post_id;
603
    }
604
605
	public static function action_conditions_met( $action, $entry ) {
606
		$notification = $action->post_content;
607
		$stop = false;
608
		$met = array();
609
610
		if ( ! isset( $notification['conditions'] ) || empty( $notification['conditions'] ) ) {
611
			return $stop;
612
		}
613
614
		foreach ( $notification['conditions'] as $k => $condition ) {
615
			if ( ! is_numeric( $k ) ) {
616
				continue;
617
			}
618
619
			if ( $stop && 'any' == $notification['conditions']['any_all'] && 'stop' == $notification['conditions']['send_stop'] ) {
620
				continue;
621
			}
622
623
			self::prepare_logic_value( $condition['hide_opt'] );
624
625
			$observed_value = self::get_value_from_entry( $entry, $condition['hide_field'] );
626
627
			$stop = FrmFieldsHelper::value_meets_condition( $observed_value, $condition['hide_field_cond'], $condition['hide_opt'] );
628
629
			if ( $notification['conditions']['send_stop'] == 'send' ) {
630
				$stop = $stop ? false : true;
631
			}
632
633
			$met[ $stop ] = $stop;
634
		}
635
636
		if ( $notification['conditions']['any_all'] == 'all' && ! empty( $met ) && isset( $met[0] ) && isset( $met[1] ) ) {
637
			$stop = ( $notification['conditions']['send_stop'] == 'send' );
638
		} elseif ( $notification['conditions']['any_all'] == 'any' && $notification['conditions']['send_stop'] == 'send' && isset( $met[0] ) ) {
639
			$stop = false;
640
		}
641
642
		return $stop;
643
	}
644
645
	/**
646
	 * Prepare the logic value for comparison against the entered value
647
	 *
648
	 * @since 2.01.02
649
	 * @param array|string $logic_value
650
	 */
651
	private static function prepare_logic_value( &$logic_value ) {
652
		if ( is_array( $logic_value ) ) {
653
			$logic_value = reset( $logic_value );
654
		}
655
656
		if ( $logic_value == 'current_user' ) {
657
			$logic_value = get_current_user_id();
658
		}
659
	}
660
661
662
	/**
663
	 * Get the value from a specific field and entry
664
	 *
665
	 * @since 2.01.02
666
	 * @param object $entry
667
	 * @param int $field_id
668
	 * @return array|bool|mixed|string
669
	 */
670
	private static function get_value_from_entry( $entry, $field_id ) {
671
		$observed_value = '';
672
673
		if ( isset( $entry->metas[ $field_id ] ) ) {
674
			$observed_value = $entry->metas[ $field_id ];
675
		} else if ( $entry->post_id && FrmAppHelper::pro_is_installed() ) {
676
			$field = FrmField::getOne( $field_id );
677
			$observed_value = FrmProEntryMetaHelper::get_post_or_meta_value(
678
				$entry,
679
				$field,
680
				array(
681
					'links'    => false,
682
					'truncate' => false,
683
				)
684
			);
685
		}
686
687
		return $observed_value;
688
	}
689
690
	public static function default_action_opts( $class = '' ) {
691
		return array(
692
			'classes'   => 'frm_icon_font ' . $class,
693
			'active'    => false,
694
			'limit'     => 0,
695
		);
696
	}
697
698
	public static function trigger_labels() {
699
		$triggers = array(
700
			'draft'  => __( 'Save Draft', 'formidable' ),
701
			'create' => __( 'Create', 'formidable' ),
702
			'update' => __( 'Update', 'formidable' ),
703
			'delete' => __( 'Delete', 'formidable' ),
704
			'import' => __( 'Import', 'formidable' ),
705
		) );
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ')'
Loading history...
706
		return apply_filters( 'frm_action_triggers', $triggers );
707
	}
708
}
709