Completed
Push — master ( abd49c...f34f00 )
by Stephanie
03:37
created

FrmFormActionsController   F

Complexity

Total Complexity 70

Size/Duplication

Total Lines 390
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 0
loc 390
rs 2.8
c 0
b 0
f 0
wmc 70
lcom 1
cbo 8

16 Methods

Rating   Name   Duplication   Size   Complexity  
A actions_init() 0 5 1
A register_post_types() 0 19 1
A register_actions() 0 21 2
B get_form_actions() 0 40 10
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 8 1
F trigger_actions() 0 83 27
A duplicate_form_actions() 0 13 4
A limit_by_type() 0 10 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
            //'aweber'    => 'FrmDefAweberAction',
46
            'mailchimp' => 'FrmDefMlcmpAction',
47
            'twilio'    => 'FrmDefTwilioAction',
48
            'payment'   => 'FrmDefHrsAction',
49
			'api'       => 'FrmDefApiAction',
50
        );
51
		$action_classes = apply_filters( 'frm_registered_form_actions', $action_classes );
52
53
		include_once( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/email_action.php' );
54
		include_once( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/default_actions.php' );
55
56
        foreach ( $action_classes as $action_class ) {
57
			self::$registered_actions->register( $action_class );
58
        }
59
    }
60
61
	public static function get_form_actions( $action = 'all' ) {
62
        $temp_actions = self::$registered_actions;
63
		if ( empty( $temp_actions ) ) {
64
            self::actions_init();
65
            $temp_actions = self::$registered_actions->actions;
66
        } else {
67
            $temp_actions = $temp_actions->actions;
68
        }
69
70
        $actions = array();
71
72
        foreach ( $temp_actions as $a ) {
73
            if ( 'all' != $action && $a->id_base == $action ) {
74
                return $a;
75
            }
76
77
			$actions[ $a->id_base ] = $a;
78
        }
79
        unset( $temp_actions, $a );
80
81
        $action_limit = 10;
82
        if ( count( $actions ) <= $action_limit ) {
83
            return $actions;
84
        }
85
86
        // remove the last few inactive icons if there are too many
87
        $temp_actions = $actions;
88
        arsort( $temp_actions );
89
        foreach ( $temp_actions as $type => $a ) {
90
            if ( ! isset( $a->action_options['active'] ) || empty( $a->action_options['active'] ) ) {
91
				unset( $actions[ $type ] );
92
                if ( count( $actions ) <= $action_limit ) {
93
                    break;
94
                }
95
            }
96
            unset( $type, $a );
97
        }
98
99
        return $actions;
100
    }
101
102
	/**
103
	 * @since 2.0
104
	 */
105
    public static function list_actions( $form, $values ) {
106
        if ( empty( $form ) ) {
107
            return;
108
        }
109
110
		/**
111
		 * Use this hook to migrate old settings into a new action
112
		 *
113
		 * @since 2.0
114
		 */
115
		do_action( 'frm_before_list_actions', $form );
116
117
		$filters = array(
118
			'post_status' => 'all',
119
		);
120
		$form_actions = FrmFormAction::get_action_for_form( $form->id, 'all', $filters );
121
122
        $action_controls = self::get_form_actions();
123
124
        $action_map = array();
125
126
		foreach ( $action_controls as $key => $control ) {
127
            $action_map[ $control->id_base ] = $key;
128
        }
129
130
    	foreach ( $form_actions as $action ) {
131
    	    if ( ! isset( $action_map[ $action->post_excerpt ] ) ) {
132
    	        // don't try and show settings if action no longer exists
133
    	        continue;
134
    	    }
135
136
    		self::action_control( $action, $form, $action->ID, $action_controls[ $action_map[ $action->post_excerpt ] ], $values );
137
    	}
138
    }
139
140
	public static function action_control( $form_action, $form, $action_key, $action_control, $values ) {
141
		$action_control->_set( $action_key );
142
143
		$use_logging = self::should_show_log_message( $form_action->post_excerpt );
144
145
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php' );
146
    }
147
148
    public static function add_form_action() {
149
		FrmAppHelper::permission_check( 'frm_edit_forms' );
150
        check_ajax_referer( 'frm_ajax', 'nonce' );
151
152
        global $frm_vars;
153
154
		$action_key = absint( $_POST['list_id'] );
155
        $action_type = sanitize_text_field( $_POST['type'] );
156
157
        $action_control = self::get_form_actions( $action_type );
158
		$action_control->_set( $action_key );
159
160
        $form_id = absint( $_POST['form_id'] );
161
162
		$form_action = $action_control->prepare_new( $form_id );
163
		$use_logging = self::should_show_log_message( $action_type );
164
165
        $values = array();
166
		$form = self::fields_to_values( $form_id, $values );
167
168
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php' );
169
        wp_die();
170
    }
171
172
    public static function fill_action() {
173
		FrmAppHelper::permission_check( 'frm_edit_forms' );
174
        check_ajax_referer( 'frm_ajax', 'nonce' );
175
176
        $action_key = absint( $_POST['action_id'] );
177
        $action_type = sanitize_text_field( $_POST['action_type'] );
178
179
        $action_control = self::get_form_actions( $action_type );
180
		if ( empty( $action_control ) ) {
181
            wp_die();
182
        }
183
184
        $form_action = $action_control->get_single_action( $action_key );
185
186
        $values = array();
187
		$form = self::fields_to_values( $form_action->menu_order, $values );
188
189
		$use_logging = self::should_show_log_message( $action_type );
190
191
		include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_inside.php' );
192
        wp_die();
193
    }
194
195
	/**
196
	 * @since 3.06.04
197
	 * @return bool
198
	 */
199
	private static function should_show_log_message( $action_type ) {
200
		$logging     = array( 'api', 'salesforce', 'constantcontact', 'activecampaign' );
201
		return in_array( $action_type, $logging ) && ! function_exists( 'frm_log_autoloader' );
202
	}
203
204
	private static function fields_to_values( $form_id, array &$values ) {
205
		$form = FrmForm::getOne( $form_id );
206
207
		$values = array(
208
			'fields' => array(),
209
			'id'     => $form->id,
210
		);
211
212
		$fields = FrmField::get_all_for_form( $form->id );
213
        foreach ( $fields as $k => $f ) {
214
            $f = (array) $f;
215
            $opts = (array) $f['field_options'];
216
			$f = array_merge( $opts, $f );
217
            if ( ! isset( $f['post_field'] ) ) {
218
                $f['post_field'] = '';
219
            }
220
            $values['fields'][] = $f;
221
			unset( $k, $f );
222
        }
223
224
        return $form;
225
    }
226
227
	public static function update_settings( $form_id ) {
228
		$process_form = FrmAppHelper::get_post_param( 'process_form', '', 'sanitize_text_field' );
229
		if ( ! wp_verify_nonce( $process_form, 'process_form_nonce' ) ) {
230
			wp_die( esc_html__( 'You do not have permission to do that', 'formidable' ) );
231
		}
232
233
        global $wpdb;
234
235
        $registered_actions = self::$registered_actions->actions;
236
237
		$old_actions = FrmDb::get_col(
238
			$wpdb->posts,
239
			array(
240
				'post_type'  => self::$action_post_type,
241
				'menu_order' => $form_id,
242
			),
243
			'ID'
244
		);
245
        $new_actions = array();
246
247
        foreach ( $registered_actions as $registered_action ) {
248
			$action_ids = $registered_action->update_callback( $form_id );
249
            if ( ! empty( $action_ids ) ) {
250
                $new_actions[] = $action_ids;
251
            }
252
        }
253
254
        //Only use array_merge if there are new actions
255
        if ( ! empty( $new_actions ) ) {
256
            $new_actions = call_user_func_array( 'array_merge', $new_actions );
257
        }
258
        $old_actions = array_diff( $old_actions, $new_actions );
259
260
		self::delete_missing_actions( $old_actions );
261
    }
262
263
	public static function delete_missing_actions( $old_actions ) {
264
		if ( ! empty( $old_actions ) ) {
265
			foreach ( $old_actions as $old_id ) {
266
				wp_delete_post( $old_id );
267
			}
268
			FrmDb::cache_delete_group( 'frm_actions' );
269
		}
270
	}
271
272
	public static function trigger_create_actions( $entry_id, $form_id, $args = array() ) {
273
		$filter_args = $args;
274
		$filter_args['entry_id'] = $entry_id;
275
		$filter_args['form_id']  = $form_id;
276
		$event = apply_filters( 'frm_trigger_create_action', 'create', $args );
277
278
		self::trigger_actions( $event, $form_id, $entry_id, 'all', $args );
279
	}
280
281
    /**
282
     * @param string $event
283
     */
284
	public static function trigger_actions( $event, $form, $entry, $type = 'all', $args = array() ) {
285
		$action_status = array(
286
			'post_status' => 'publish',
287
		);
288
		$form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
289
290
		if ( empty( $form_actions ) ) {
291
            return;
292
        }
293
294
		FrmForm::maybe_get_form( $form );
295
296
        $link_settings = self::get_form_actions( $type );
297
        if ( 'all' != $type ) {
298
            $link_settings = array( $type => $link_settings );
299
        }
300
301
		$stored_actions = array();
302
		$action_priority = array();
303
304
		if ( in_array( $event, array( 'create', 'update' ) ) && defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
305
			$this_event = 'import';
306
		} else {
307
			$this_event = $event;
308
		}
309
310
        foreach ( $form_actions as $action ) {
311
312
			$skip_this_action = ( ! in_array( $this_event, $action->post_content['event'] ) );
313
			$skip_this_action = apply_filters( 'frm_skip_form_action', $skip_this_action, compact( 'action', 'entry', 'form', 'event' ) );
314
			if ( $skip_this_action ) {
315
                continue;
316
            }
317
318
            if ( ! is_object( $entry ) ) {
319
                $entry = FrmEntry::getOne( $entry, true );
320
            }
321
322
			if ( empty( $entry ) || ( $entry->is_draft && $event != 'draft' ) ) {
323
				continue;
324
			}
325
326
			$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'] ) );
327
328
			if ( $child_entry ) {
329
				// maybe trigger actions for sub forms
330
				$trigger_children = apply_filters( 'frm_use_embedded_form_actions', false, compact( 'form', 'entry' ) );
331
				if ( ! $trigger_children ) {
332
					continue;
333
				}
334
            }
335
336
            // check conditional logic
337
			$stop = FrmFormAction::action_conditions_met( $action, $entry );
338
            if ( $stop ) {
339
                continue;
340
            }
341
342
            // store actions so they can be triggered with the correct priority
343
            $stored_actions[ $action->ID ] = $action;
344
            $action_priority[ $action->ID ] = $link_settings[ $action->post_excerpt ]->action_options['priority'];
345
346
			unset( $action );
347
        }
348
349
        if ( ! empty( $stored_actions ) ) {
350
			asort( $action_priority );
351
352
            // make sure hooks are loaded
353
            new FrmNotification();
354
355
            foreach ( $action_priority as $action_id => $priority ) {
356
                $action = $stored_actions[ $action_id ];
357
				do_action( 'frm_trigger_' . $action->post_excerpt . '_action', $action, $entry, $form, $event );
358
				do_action( 'frm_trigger_' . $action->post_excerpt . '_' . $event . '_action', $action, $entry, $form );
359
360
                // If post is created, get updated $entry object
361
                if ( $action->post_excerpt == 'wppost' && $event == 'create' ) {
362
					$entry = FrmEntry::getOne( $entry->id, true );
363
                }
364
            }
365
        }
366
    }
367
368
	public static function duplicate_form_actions( $form_id, $values, $args = array() ) {
369
		if ( ! isset( $args['old_id'] ) || empty( $args['old_id'] ) ) {
370
            // continue if we know which actions to copy
371
            return;
372
        }
373
374
		$action_controls = self::get_form_actions();
375
376
        foreach ( $action_controls as $action_control ) {
377
            $action_control->duplicate_form_actions( $form_id, $args['old_id'] );
378
            unset( $action_control );
379
        }
380
    }
381
382
    public static function limit_by_type( $where ) {
383
        global $frm_vars, $wpdb;
384
385
        if ( ! isset( $frm_vars['action_type'] ) ) {
386
            return $where;
387
        }
388
389
        $where .= $wpdb->prepare( ' AND post_excerpt = %s ', $frm_vars['action_type'] );
390
        return $where;
391
    }
392
}
393
394
395
class Frm_Form_Action_Factory {
396
	public $actions = array();
397
398
	public function __construct() {
399
		add_action( 'frm_form_actions_init', array( $this, '_register_actions' ), 100 );
400
	}
401
402
	public function register( $action_class ) {
403
		$this->actions[ $action_class ] = new $action_class();
404
	}
405
406
	public function unregister( $action_class ) {
407
		if ( isset( $this->actions[ $action_class ] ) ) {
408
			unset( $this->actions[ $action_class ] );
409
		}
410
	}
411
412
	public function _register_actions() {
413
		$keys = array_keys( $this->actions );
414
415
		foreach ( $keys as $key ) {
416
			// don't register new action if old action with the same id is already registered
417
			if ( ! isset( $this->actions[ $key ] ) ) {
418
			    $this->actions[ $key ]->_register();
419
			}
420
		}
421
	}
422
}
423