Completed
Push — master ( feb49b...2e7061 )
by Stephanie
06:17 queued 03:03
created

FrmFormActionsController   F

Complexity

Total Complexity 86

Size/Duplication

Total Lines 548
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
dl 0
loc 548
rs 2
c 0
b 0
f 0
wmc 86
lcom 1
cbo 9

21 Methods

Rating   Name   Duplication   Size   Complexity  
A actions_init() 0 5 1
A register_post_types() 0 19 1
A register_actions() 0 30 2
A email_settings() 0 11 1
B maybe_add_action_to_group() 0 26 8
A form_action_groups() 0 45 1
A active_actions() 0 9 4
B show_action_icon_link() 0 41 7
A get_form_actions() 0 21 5
A list_actions() 0 34 5
A action_control() 0 7 1
A add_form_action() 0 23 1
A fill_action() 0 22 2
A should_show_log_message() 0 4 2
A fields_to_values() 0 22 3
A update_settings() 0 35 5
A delete_missing_actions() 0 8 3
A trigger_create_actions() 0 9 1
F trigger_actions() 0 83 27
A duplicate_form_actions() 0 13 4
A limit_by_type() 0 11 2

How to fix   Complexity   

Complex Class

Complex classes like FrmFormActionsController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FrmFormActionsController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
class FrmFormActionsController {
4
	public static $action_post_type = 'frm_form_actions';
5
	public static $registered_actions;
6
7
	/**
8
	 * Variables saved in the post:
9
	 * post_content: json settings
10
	 * menu_order: form id
11
	 * post_excerpt: action type
12
	 */
13
	public static function register_post_types() {
14
		register_post_type(
15
			self::$action_post_type,
16
			array(
17
				'label'               => __( 'Form Actions', 'formidable' ),
18
				'description'         => '',
19
				'public'              => false,
20
				'show_ui'             => false,
21
				'exclude_from_search' => true,
22
				'show_in_nav_menus'   => false,
23
				'show_in_menu'        => true,
24
				'capability_type'     => 'page',
25
				'supports'            => array( 'title', 'editor', 'excerpt', 'custom-fields', 'page-attributes' ),
26
				'has_archive'         => false,
27
			)
28
		);
29
30
		self::actions_init();
31
	}
32
33
	public static function actions_init() {
34
		self::$registered_actions = new Frm_Form_Action_Factory();
35
		self::register_actions();
36
		do_action( 'frm_form_actions_init' );
37
	}
38
39
	public static function register_actions() {
40
		$action_classes = array(
41
			'email'     => 'FrmEmailAction',
42
			'wppost'    => 'FrmDefPostAction',
43
			'register'  => 'FrmDefRegAction',
44
			'paypal'    => 'FrmDefPayPalAction',
45
			'payment'   => 'FrmDefHrsAction',
46
			'mailchimp' => 'FrmDefMlcmpAction',
47
			'api'       => 'FrmDefApiAction',
48
49
			'salesforce'      => 'FrmDefSalesforceAction',
50
			'activecampaign'  => 'FrmDefActiveCampaignAction',
51
			'constantcontact' => 'FrmDefConstContactAction',
52
			'getresponse'     => 'FrmDefGetResponseAction',
53
			'hubspot'         => 'FrmDefHubspotAction',
54
			'twilio'          => 'FrmDefTwilioAction',
55
			'highrise'        => 'FrmDefHighriseAction',
56
			'mailpoet'        => 'FrmDefMailpoetAction',
57
			'aweber'          => 'FrmDefAweberAction',
58
		);
59
60
		$action_classes = apply_filters( 'frm_registered_form_actions', $action_classes );
61
62
		include_once( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/email_action.php' );
63
		include_once( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/default_actions.php' );
64
65
		foreach ( $action_classes as $action_class ) {
66
			self::$registered_actions->register( $action_class );
67
		}
68
	}
69
70
	/**
71
	 * @since 4.0
72
	 *
73
	 * @param array $values
74
	 */
75
	public static function email_settings( $values ) {
76
		$form   = FrmForm::getOne( $values['id'] );
77
		$groups = self::form_action_groups();
78
79
		$action_controls = self::get_form_actions();
80
		self::maybe_add_action_to_group( $action_controls, $groups );
81
82
		$allowed = self::active_actions( $action_controls );
83
84
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/settings.php' );
85
	}
86
87
	/**
88
	 * Add unknown actions to a group.
89
	 *
90
	 * @since 4.0
91
	 */
92
	private static function maybe_add_action_to_group( $action_controls, &$groups ) {
93
		$grouped = array();
94
		foreach ( $groups as $group ) {
95
			if ( isset( $group['actions'] ) ) {
96
				$grouped = array_merge( $grouped, $group['actions'] );
97
			}
98
		}
99
100
		foreach ( $action_controls as $action ) {
101
			if ( isset( $groups[ $action->id_base ] ) || in_array( $action->id_base, $grouped ) ) {
102
				continue;
103
			}
104
105
			$this_group = $action->action_options['group'];
106
			if ( ! isset( $groups[ $this_group ] ) ) {
107
				$this_group = 'misc';
108
			}
109
110
			if ( ! isset( $groups[ $this_group ]['actions'] ) ) {
111
				$groups[ $this_group ]['actions'] = array();
112
			}
113
			$groups[ $this_group ]['actions'][] = $action->id_base;
114
115
			unset( $action );
116
		}
117
	}
118
119
	/**
120
	 * @since 4.0
121
	 *
122
	 * @return array
123
	 */
124
	public static function form_action_groups() {
125
		$groups = array(
126
			'misc'        => array(
127
				'name'    => '',
128
				'icon'    => 'frm_icon_font frm_shuffle_icon',
129
				'actions' => array(
130
					'email',
131
					'wppost',
132
					'register',
133
					'twilio',
134
				),
135
			),
136
			'payment'   => array(
137
				'name'    => __( 'eCommerce', 'formidable' ),
138
				'icon'    => 'frm_icon_font frm_credit_card_alt_icon',
139
				'actions' => array(
140
					'paypal',
141
					'payment',
142
				),
143
			),
144
			'marketing' => array(
145
				'name'    => __( 'Email Marketing', 'formidable' ),
146
				'icon'    => 'frm_icon_font frm_mail_bulk_icon',
147
				'actions' => array(
148
					'mailchimp',
149
					'activecampaign',
150
					'constantcontact',
151
					'getresponse',
152
					'aweber',
153
					'mailpoet',
154
				),
155
			),
156
			'crm'       => array(
157
				'name'    => __( 'CRM', 'formidable' ),
158
				'icon'    => 'frm_icon_font frm_address_card_icon',
159
				'actions' => array(
160
					'salesforce',
161
					'hubspot',
162
					'highrise',
163
				),
164
			),
165
		);
166
167
		return apply_filters( 'frm_action_groups', $groups );
168
	}
169
170
	/**
171
	 * Get the number of currently active form actions.
172
	 *
173
	 * @since 4.0
174
	 *
175
	 * @return array
176
	 */
177
	private static function active_actions( $action_controls ) {
178
		$allowed = array();
179
		foreach ( $action_controls as $action_control ) {
180
			if ( isset( $action_control->action_options['active'] ) && $action_control->action_options['active'] ) {
181
				$allowed[] = $action_control->id_base;
182
			}
183
		}
184
		return $allowed;
185
	}
186
187
	/**
188
	 * For each add-on, add an li, class, and javascript function. If active, add an additional class.
189
	 *
190
	 * @since 4.0
191
	 * @param object $action_control
192
	 * @param array  $allowed
193
	 */
194
	public static function show_action_icon_link( $action_control, $allowed ) {
195
		$data    = array();
196
		$classes = ' frm_' . $action_control->id_base . '_action frm_single_action';
197
198
		$group_class = ' frm-group-' . $action_control->action_options['group'];
199
200
		/* translators: %s: Name of form action */
201
		$upgrade_label = sprintf( esc_html__( '%s form actions', 'formidable' ), $action_control->action_options['tooltip'] );
202
203
		$default_shown    = array( 'wppost', 'register', 'paypal', 'payment', 'mailchimp' );
204
		$default_shown    = array_values( array_diff( $default_shown, $allowed ) );
205
		$default_position = array_search( $action_control->id_base, $default_shown );
206
		$allowed_count    = count( $allowed );
207
208
		if ( isset( $action_control->action_options['active'] ) && $action_control->action_options['active'] ) {
209
			$classes .= ' frm_active_action';
210
		} else {
211
			$classes .= ' frm_inactive_action';
212
			if ( $default_position !== false && ( $allowed_count + $default_position ) < 6 ) {
213
				$group_class .= ' frm-default-show';
214
			}
215
216
			$data['data-upgrade'] = $upgrade_label;
217
			$data['data-medium']  = 'settings-' . $action_control->id_base;
218
219
			$upgrading = FrmAddonsController::install_link( $action_control->action_options['plugin'] );
220
			if ( isset( $upgrading['url'] ) ) {
221
				$data['data-oneclick'] = json_encode( $upgrading );
222
			}
223
		}
224
225
		// HTML to include on the icon.
226
		$icon_atts = array();
227
		if ( $action_control->action_options['color'] !== 'var(--primary-hover)' ) {
228
			$icon_atts = array(
229
				'style' => '--primary-hover:' . $action_control->action_options['color'],
230
			);
231
		}
232
233
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_icon.php' );
234
	}
235
236
	public static function get_form_actions( $action = 'all' ) {
237
		$temp_actions = self::$registered_actions;
238
		if ( empty( $temp_actions ) ) {
239
			self::actions_init();
240
			$temp_actions = self::$registered_actions->actions;
241
		} else {
242
			$temp_actions = $temp_actions->actions;
243
		}
244
245
		$actions = array();
246
247
		foreach ( $temp_actions as $a ) {
248
			if ( 'all' != $action && $a->id_base == $action ) {
249
				return $a;
250
			}
251
252
			$actions[ $a->id_base ] = $a;
253
		}
254
255
		return $actions;
256
	}
257
258
	/**
259
	 * @since 2.0
260
	 */
261
	public static function list_actions( $form, $values ) {
262
		if ( empty( $form ) ) {
263
			return;
264
		}
265
266
		/**
267
		 * Use this hook to migrate old settings into a new action
268
		 *
269
		 * @since 2.0
270
		 */
271
		do_action( 'frm_before_list_actions', $form );
272
273
		$filters      = array(
274
			'post_status' => 'all',
275
		);
276
		$form_actions = FrmFormAction::get_action_for_form( $form->id, 'all', $filters );
277
278
		$action_controls = self::get_form_actions();
279
280
		$action_map = array();
281
282
		foreach ( $action_controls as $key => $control ) {
283
			$action_map[ $control->id_base ] = $key;
284
		}
285
286
		foreach ( $form_actions as $action ) {
287
			if ( ! isset( $action_map[ $action->post_excerpt ] ) ) {
288
				// don't try and show settings if action no longer exists
289
				continue;
290
			}
291
292
			self::action_control( $action, $form, $action->ID, $action_controls[ $action_map[ $action->post_excerpt ] ], $values );
293
		}
294
	}
295
296
	public static function action_control( $form_action, $form, $action_key, $action_control, $values ) {
297
		$action_control->_set( $action_key );
298
299
		$use_logging = self::should_show_log_message( $form_action->post_excerpt );
300
301
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php' );
302
	}
303
304
	public static function add_form_action() {
305
		FrmAppHelper::permission_check( 'frm_edit_forms' );
306
		check_ajax_referer( 'frm_ajax', 'nonce' );
307
308
		global $frm_vars;
309
310
		$action_key  = FrmAppHelper::get_param( 'list_id', '', 'post', 'absint' );
311
		$action_type = FrmAppHelper::get_param( 'type', '', 'post', 'sanitize_text_field' );
312
313
		$action_control = self::get_form_actions( $action_type );
314
		$action_control->_set( $action_key );
315
316
		$form_id = FrmAppHelper::get_param( 'form_id', '', 'post', 'absint' );
317
318
		$form_action = $action_control->prepare_new( $form_id );
319
		$use_logging = self::should_show_log_message( $action_type );
320
321
		$values = array();
322
		$form   = self::fields_to_values( $form_id, $values );
323
324
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php' );
325
		wp_die();
326
	}
327
328
	public static function fill_action() {
329
		FrmAppHelper::permission_check( 'frm_edit_forms' );
330
		check_ajax_referer( 'frm_ajax', 'nonce' );
331
332
		$action_key  = FrmAppHelper::get_param( 'action_id', '', 'post', 'absint' );
333
		$action_type = FrmAppHelper::get_param( 'action_type', '', 'post', 'sanitize_text_field' );
334
335
		$action_control = self::get_form_actions( $action_type );
336
		if ( empty( $action_control ) ) {
337
			wp_die();
338
		}
339
340
		$form_action = $action_control->get_single_action( $action_key );
341
342
		$values = array();
343
		$form   = self::fields_to_values( $form_action->menu_order, $values );
344
345
		$use_logging = self::should_show_log_message( $action_type );
346
347
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_inside.php' );
348
		wp_die();
349
	}
350
351
	/**
352
	 * @since 3.06.04
353
	 * @return bool
354
	 */
355
	private static function should_show_log_message( $action_type ) {
356
		$logging = array( 'api', 'salesforce', 'constantcontact', 'activecampaign' );
357
		return in_array( $action_type, $logging ) && ! function_exists( 'frm_log_autoloader' );
358
	}
359
360
	private static function fields_to_values( $form_id, array &$values ) {
361
		$form = FrmForm::getOne( $form_id );
362
363
		$values = array(
364
			'fields' => array(),
365
			'id'     => $form->id,
366
		);
367
368
		$fields = FrmField::get_all_for_form( $form->id );
369
		foreach ( $fields as $k => $f ) {
370
			$f    = (array) $f;
371
			$opts = (array) $f['field_options'];
372
			$f    = array_merge( $opts, $f );
373
			if ( ! isset( $f['post_field'] ) ) {
374
				$f['post_field'] = '';
375
			}
376
			$values['fields'][] = $f;
377
			unset( $k, $f );
378
		}
379
380
		return $form;
381
	}
382
383
	public static function update_settings( $form_id ) {
384
		$process_form = FrmAppHelper::get_post_param( 'process_form', '', 'sanitize_text_field' );
385
		if ( ! wp_verify_nonce( $process_form, 'process_form_nonce' ) ) {
386
			wp_die( esc_html__( 'You do not have permission to do that', 'formidable' ) );
387
		}
388
389
		global $wpdb;
390
391
		$registered_actions = self::$registered_actions->actions;
392
393
		$old_actions = FrmDb::get_col(
394
			$wpdb->posts,
395
			array(
396
				'post_type'  => self::$action_post_type,
397
				'menu_order' => $form_id,
398
			),
399
			'ID'
400
		);
401
		$new_actions = array();
402
403
		foreach ( $registered_actions as $registered_action ) {
404
			$action_ids = $registered_action->update_callback( $form_id );
405
			if ( ! empty( $action_ids ) ) {
406
				$new_actions[] = $action_ids;
407
			}
408
		}
409
410
		// Only use array_merge if there are new actions.
411
		if ( ! empty( $new_actions ) ) {
412
			$new_actions = call_user_func_array( 'array_merge', $new_actions );
413
		}
414
		$old_actions = array_diff( $old_actions, $new_actions );
415
416
		self::delete_missing_actions( $old_actions );
417
	}
418
419
	public static function delete_missing_actions( $old_actions ) {
420
		if ( ! empty( $old_actions ) ) {
421
			foreach ( $old_actions as $old_id ) {
422
				wp_delete_post( $old_id );
423
			}
424
			FrmDb::cache_delete_group( 'frm_actions' );
425
		}
426
	}
427
428
	public static function trigger_create_actions( $entry_id, $form_id, $args = array() ) {
429
		$filter_args             = $args;
430
		$filter_args['entry_id'] = $entry_id;
431
		$filter_args['form_id']  = $form_id;
432
433
		$event = apply_filters( 'frm_trigger_create_action', 'create', $args );
434
435
		self::trigger_actions( $event, $form_id, $entry_id, 'all', $args );
436
	}
437
438
	/**
439
	 * @param string $event
440
	 */
441
	public static function trigger_actions( $event, $form, $entry, $type = 'all', $args = array() ) {
442
		$action_status = array(
443
			'post_status' => 'publish',
444
		);
445
		$form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
446
447
		if ( empty( $form_actions ) ) {
448
			return;
449
		}
450
451
		FrmForm::maybe_get_form( $form );
452
453
		$link_settings = self::get_form_actions( $type );
454
		if ( 'all' != $type ) {
455
			$link_settings = array( $type => $link_settings );
456
		}
457
458
		$stored_actions  = array();
459
		$action_priority = array();
460
461
		if ( in_array( $event, array( 'create', 'update' ) ) && defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
462
			$this_event = 'import';
463
		} else {
464
			$this_event = $event;
465
		}
466
467
		foreach ( $form_actions as $action ) {
468
469
			$skip_this_action = ( ! in_array( $this_event, $action->post_content['event'] ) );
470
			$skip_this_action = apply_filters( 'frm_skip_form_action', $skip_this_action, compact( 'action', 'entry', 'form', 'event' ) );
471
			if ( $skip_this_action ) {
472
				continue;
473
			}
474
475
			if ( ! is_object( $entry ) ) {
476
				$entry = FrmEntry::getOne( $entry, true );
477
			}
478
479
			if ( empty( $entry ) || ( $entry->is_draft && $event != 'draft' ) ) {
480
				continue;
481
			}
482
483
			$child_entry = ( ( is_object( $form ) && is_numeric( $form->parent_form_id ) && $form->parent_form_id ) || ( $entry && ( $entry->form_id != $form->id || $entry->parent_item_id ) ) || ( isset( $args['is_child'] ) && $args['is_child'] ) );
484
485
			if ( $child_entry ) {
486
				// maybe trigger actions for sub forms
487
				$trigger_children = apply_filters( 'frm_use_embedded_form_actions', false, compact( 'form', 'entry' ) );
488
				if ( ! $trigger_children ) {
489
					continue;
490
				}
491
			}
492
493
			// Check conditional logic.
494
			$stop = FrmFormAction::action_conditions_met( $action, $entry );
495
			if ( $stop ) {
496
				continue;
497
			}
498
499
			// Store actions so they can be triggered with the correct priority.
500
			$stored_actions[ $action->ID ]  = $action;
501
			$action_priority[ $action->ID ] = $link_settings[ $action->post_excerpt ]->action_options['priority'];
502
503
			unset( $action );
504
		}
505
506
		if ( ! empty( $stored_actions ) ) {
507
			asort( $action_priority );
508
509
			// Make sure hooks are loaded.
510
			new FrmNotification();
511
512
			foreach ( $action_priority as $action_id => $priority ) {
513
				$action = $stored_actions[ $action_id ];
514
				do_action( 'frm_trigger_' . $action->post_excerpt . '_action', $action, $entry, $form, $event );
515
				do_action( 'frm_trigger_' . $action->post_excerpt . '_' . $event . '_action', $action, $entry, $form );
516
517
				// If post is created, get updated $entry object.
518
				if ( $action->post_excerpt == 'wppost' && $event == 'create' ) {
519
					$entry = FrmEntry::getOne( $entry->id, true );
520
				}
521
			}
522
		}
523
	}
524
525
	public static function duplicate_form_actions( $form_id, $values, $args = array() ) {
526
		if ( ! isset( $args['old_id'] ) || empty( $args['old_id'] ) ) {
527
			// Continue if we know which actions to copy.
528
			return;
529
		}
530
531
		$action_controls = self::get_form_actions();
532
533
		foreach ( $action_controls as $action_control ) {
534
			$action_control->duplicate_form_actions( $form_id, $args['old_id'] );
535
			unset( $action_control );
536
		}
537
	}
538
539
	public static function limit_by_type( $where ) {
540
		global $frm_vars, $wpdb;
541
542
		if ( ! isset( $frm_vars['action_type'] ) ) {
543
			return $where;
544
		}
545
546
		$where .= $wpdb->prepare( ' AND post_excerpt = %s ', $frm_vars['action_type'] );
547
548
		return $where;
549
	}
550
}
551
552
class Frm_Form_Action_Factory {
553
	public $actions = array();
554
555
	public function __construct() {
556
		add_action( 'frm_form_actions_init', array( $this, '_register_actions' ), 100 );
557
	}
558
559
	public function register( $action_class ) {
560
		$this->actions[ $action_class ] = new $action_class();
561
	}
562
563
	public function unregister( $action_class ) {
564
		if ( isset( $this->actions[ $action_class ] ) ) {
565
			unset( $this->actions[ $action_class ] );
566
		}
567
	}
568
569
	public function _register_actions() {
570
		$keys = array_keys( $this->actions );
571
572
		foreach ( $keys as $key ) {
573
			// don't register new action if old action with the same id is already registered
574
			if ( ! isset( $this->actions[ $key ] ) ) {
575
				$this->actions[ $key ]->_register();
576
			}
577
		}
578
	}
579
}
580