Completed
Push — staging ( 99a729...9693fc )
by
unknown
19:21
created

Yikes_Easy_MC_Checkbox_Integration_Class   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 270
Duplicated Lines 7.04 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 19
loc 270
rs 9.2
c 0
b 0
f 0
wmc 40
lcom 1
cbo 1

6 Methods

Rating   Name   Duplication   Size   Complexity  
A is_user_subscribed() 11 30 4
B is_user_already_subscribed() 0 34 10
B yikes_get_checkbox() 0 24 7
C subscribe_user_integration() 8 90 14
A user_merge_vars() 0 24 3
A was_checkbox_checked() 0 3 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Yikes_Easy_MC_Checkbox_Integration_Class 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 Yikes_Easy_MC_Checkbox_Integration_Class, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Takes care of all the integration checkboxes.
4
 */
5
6
// Prevent direct access to the file.
7
defined( 'ABSPATH' ) || die( esc_html_e( "Whoops, you shouldn't be accessing this file directly. Abort!", 'yikes-inc-easy-mailchimp-extender' ) );
8
9
/**
10
 * Main Checkbox Integration class.
11
 */
12
class Yikes_Easy_MC_Checkbox_Integration_Class {
13
14
	/**
15
	 * The integration type.
16
	 *
17
	 * @var string $type
18
	 */
19
	protected $type = '';
20
21
	/**
22
	 * Determine whether the current user is subscribed to all of the lists.
23
	 *
24
	 * @author Jeremy Pry
25
	 *
26
	 * @param string $type  The integration type to check.
27
	 * @param string $email The email address to check.
28
	 *
29
	 * @return bool Whether the current user is subscribed to a list.
30
	 */
31
	public function is_user_already_subscribed( $type, $email = '' ) {
32
		// Make sure we have an email address to use.
33
		if ( empty( $email ) ) {
34
			if ( ! is_user_logged_in() ) {
35
				return false;
36
			}
37
38
			$current_user = wp_get_current_user();
39
			$email        = $current_user->user_email;
40
		}
41
42
		// Ensure we have a valid email.
43
		if ( ! is_email( $email ) ) {
44
			return false;
45
		}
46
47
		// Convert the integration type to a list ID.
48
		$checkbox_options = get_option( 'optin-checkbox-init', '' );
49
		if ( empty( $checkbox_options ) || ! isset( $checkbox_options[ $type ] ) || ! isset( $checkbox_options[ $type ]['associated-list'] ) ) {
50
			return false;
51
		}
52
53
		$list_ids = $checkbox_options[ $type ]['associated-list'];
54
		$list_ids = is_array( $list_ids ) ? $list_ids : array( $list_ids );
55
56
		// Go through each list...
57
		foreach ( $list_ids as $list_id ) {
58
			if ( ! $this->is_user_subscribed( $email, $list_id, $type ) ) {
59
				return false;
60
			}
61
		}
62
63
		return true;
64
	}
65
66
	/**
67
	 * Determine whether a given email is subscribed to a given list.
68
	 *
69
	 * @author Jeremy Pry
70
	 *
71
	 * @param string $email   The email address to check.
72
	 * @param string $list_id The list ID to check.
73
	 * @param string $type    The integration type.
74
	 *
75
	 * @return bool Whether the email is subscribed to the list.
76
	 */
77
	public function is_user_subscribed( $email, $list_id, $type ) {
78
		$email      = sanitize_email( $email );
79
		$email_hash = md5( $email );
80
81
		// Check the API to see the status.
82
		$response = yikes_get_mc_api_manager()->get_list_handler()->get_member( $list_id, $email_hash, false );
83
		if ( is_wp_error( $response ) ) {
84
			$data = $response->get_error_data();
85
86
			// If the error response is a 404, they are not subscribed.
87
			if ( isset( $data['status'] ) && 404 === (int) $data['status'] ) {
88
				return false;
89 View Code Duplication
			} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
90
				$error_logging = new Yikes_Inc_Easy_Mailchimp_Error_Logging();
91
				$error_logging->maybe_write_to_log(
92
					$response->get_error_code(),
93
					__( 'Get Member Info', 'yikes-inc-easy-mailchimp-extender' ),
94
					'Checkbox Integrations Page'
95
				);
96
97
				// If there was some other error, let's just assume they're not subscribed.
98
				return false;
99
			}
100
		}
101
102
		// Look at the status from the API.
103
		$subscribed = 'subscribed' === $response['status'];
104
105
		return apply_filters( 'yikes-mailchimp-integration-is-user-subscribed', $subscribed, $type );
106
	}
107
108
	/**
109
	 * Render the checkbox.
110
	 *
111
	 * @return string The HTML for the checkbox.
112
	 */
113
	public function yikes_get_checkbox() {
114
115
		// Get our options.
116
		$checkbox_options = get_option( 'optin-checkbox-init', array() );
117
		$has_list_ids     = isset( $checkbox_options[ $this->type ]['associated-list'] ) && '-' !== $checkbox_options[ $this->type ]['associated-list'];
118
		$has_list_ids     = $has_list_ids && ! in_array( '-', $checkbox_options[ $this->type ]['associated-list'], true );
119
120
		if ( $has_list_ids ) {
121
			$label    = isset( $checkbox_options[ $this->type ]['label'] ) && ! empty( $checkbox_options[ $this->type ]['label'] ) ? trim( $checkbox_options[ $this->type ]['label'] ) : __( 'Sign me up for your mailing list.', 'yikes-inc-easy-mailchimp-extender' );
122
			$checked  = 'true' === $checkbox_options[ $this->type ]['precheck'] ? 'checked="checked"' : '';
123
			$before   = apply_filters( 'yikes-mailchimp-before-checkbox-html', '' );
124
			$content  = '<p id="yikes-easy-mailchimp-' . esc_attr( $this->type ) . '-checkbox" class="yikes-easy-mailchimp-' . esc_attr( $this->type ) . '-checkbox">';
125
			$content .= '<label>';
126
			$content .= '<input type="checkbox" name="yikes_mailchimp_checkbox_' . esc_attr( $this->type ) . '" value="1" ' . $checked . '/>';
127
			$content .= apply_filters( 'yikes_mailchimp_checkbox_integration_checkbox_label', $label, $this->type, $checkbox_options );
128
			$content .= '</label>';
129
			$content .= '</p>';
130
			$content  = apply_filters( 'yikes_mailchimp_checkbox_integration_checkbox_html', $content, $this->type, $checkbox_options );
131
			$after    = apply_filters( 'yikes-mailchimp-after-checkbox-html', '' );
132
			$after   .= '<!-- Easy Forms for Mailchimp -->';
133
			$checkbox = $before . $content . $after;
134
			return apply_filters( 'yikes_mailchimp_checkbox_integration_html', $checkbox, $this->type, $checkbox_options );
135
		}
136
	}
137
138
	/**
139
	 * Hook to submit the data to Mailchimp when a new integration type is submitted.
140
	 *
141
	 * @since 6.0.0
142
	 *
143
	 * @param string $email            The email address.
144
	 * @param string $type             The integration type.
145
	 * @param array  $merge_vars       The array of form data to send.
146
	 * @param array  $integration_vars An array of additional information that can be used to filter the subscribe request.
147
	 */
148
	public function subscribe_user_integration( $email, $type, $merge_vars, $integration_vars = array() ) {
149
		$options = get_option( 'optin-checkbox-init', '' );
150
151
		// Make sure we have a list ID.
152
		if ( ! isset( $options[ $type ] ) || ! isset( $options[ $type ]['associated-list'] ) ) {
153
			// @todo: Throw some kind of error?
154
			return;
155
		}
156
157
		$email = sanitize_email( $email );
158
159
		// Check for an IP address.
160
		$user_ip = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
161
		if ( isset( $merge_vars['OPTIN_IP'] ) ) {
162
			$user_ip = sanitize_text_field( $merge_vars['OPTIN_IP'] );
163
		}
164
165
		// Build our request data.
166
		$list_ids = $options[ $type ]['associated-list'];
0 ignored issues
show
Unused Code introduced by
$list_ids is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
167
		$list_ids = is_array( $options[ $type ]['associated-list'] ) ? $options[ $type ]['associated-list'] : array( $options[ $type ]['associated-list'] );
168
		$id       = md5( $email );
169
		$data     = array(
170
			'email_address' => $email,
171
			'merge_fields'  => apply_filters( 'yikes-mailchimp-checkbox-integration-merge-variables', $merge_vars, $type, $integration_vars ),
172
			'status_if_new' => 'pending',
173
			'status'        => 'pending',
174
			'ip_signup'     => $user_ip,
175
		);
176
177
		foreach ( $list_ids as $list_id ) {
178
179
			$interests = isset( $options[ $type ]['interest-groups'] ) ? $options[ $type ]['interest-groups'] : array();
180
			$interests = isset( $interests[ $list_id ] ) ? $interests[ $list_id ] : $interests;
181
182
			// Only re-format and add interest groups if not empty.
183
			if ( ! empty( $interests ) ) {
184
				$groups = array();
185
186
				// Need to reformat interest groups array as $interest_group_ID => true.
187
				foreach ( $interests as $interest ) {
188
					if ( is_array( $interest ) ) {
189
						foreach ( $interest as $group_id ) {
190
							$groups[ $group_id ] = true;
191
						}
192
					}
193
				}
194
195
				$data['interests'] = $groups;
196
			}
197
198
			/**
199
			 * 'yikes-mailchimp-checkbox-integration-body'
200
			 *
201
			 * Filter the request body for a Mailchimp subscription via the checkbox integrations
202
			 *
203
			 * @param array  | $data    | The request body
204
			 * @param string | $type    | The integration type, e.g. 'contact_form_7'
205
			 * @param string | $list_id | The list ID
206
			 */
207
			$data = apply_filters( 'yikes-mailchimp-checkbox-integration-body', $data, $type, $list_id, $integration_vars );
208
209
			/**
210
			 * 'yikes-mailchimp-checkbox-integration-list-id'
211
			 *
212
			 * Filter the list ID for a Mailchimp subscription via the checkbox integrations
213
			 *
214
			 * @param string $list_id The list ID
215
			 * @param array  $data    The request body
216
			 * @param string $type    The integration type, e.g. 'contact_form_7'
217
			 */
218
			$list_id = apply_filters( 'yikes-mailchimp-checkbox-integration-list-id', $list_id, $data, $type, $integration_vars );
219
220
			// Don't send an empty merge fields array.
221
			if ( empty( $data['merge_fields'] ) ) {
222
				unset( $data['merge_fields'] );
223
			}
224
225
			// Subscribe the user to the list via the API.
226
			$response = yikes_get_mc_api_manager()->get_list_handler()->member_subscribe( $list_id, $id, $data );
227
228 View Code Duplication
			if ( is_wp_error( $response ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
				$error_logging = new Yikes_Inc_Easy_Mailchimp_Error_Logging();
230
				$error_logging->maybe_write_to_log(
231
					$response->get_error_code(),
232
					__( 'Checkbox Integration Subscribe User', 'yikes-inc-easy-mailchimp-extender' ),
233
					'Checkbox Integrations'
234
				);
235
			}
236
		}
237
	}
238
239
	/**
240
	 * Build merge varaibles array
241
	 *
242
	 * This is currently used in both the BuddyPress and WP Registration integrations.
243
	 *
244
	 * @param WP_User $user A WP User.
245
	 */
246
	public function user_merge_vars( WP_User $user ) {
247
248
		// Setup our array.
249
		$merge_vars = array();
250
251
		if ( ! empty( $user->first_name ) ) {
252
			$merge_vars['FNAME'] = $user->first_name;
253
		}
254
		if ( ! empty( $user->last_name ) ) {
255
			$merge_vars['LNAME'] = $user->last_name;
256
		}
257
258
		/**
259
		 * Filter the user variables passed to Mailchimp.
260
		 *
261
		 * @param array   $merge_vars Merge variables to pass to Mailchimp.
262
		 * @param WP_User $user       The WordPress user.
263
		 *
264
		 * @return array $merge_vars Merge variables to pass to Mailchimp.
265
		 */
266
		$merge_vars = apply_filters( 'yikes-mailchimp-user-merge-vars', $merge_vars, $user );
267
268
		return $merge_vars;
269
	}
270
271
	/**
272
	 * Confirm the checkbox was checked.
273
	 *
274
	 * @param string $type The integration type.
275
	 *
276
	 * @return bool True if the checkbox was checked.
277
	 */
278
	public function was_checkbox_checked( $type ) {
279
		return isset( $_POST[ 'yikes_mailchimp_checkbox_' . $type ] ) && '1' === filter_var( $_POST[ 'yikes_mailchimp_checkbox_' . $type ], FILTER_SANITIZE_STRING );
280
	}
281
}
282