PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / trunk
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster vtrunk
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / block-editor / blocks / optin / crm / mailchimp.php

mailchimp.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster trunk, at includes/block-editor/blocks/optin/crm/mailchimp.php

318 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Sellkit\Blocks\Optin;
3
4 defined( 'ABSPATH' ) || die();
5
6 /**
7 * Mailchimp class.
8 *
9 * @since 2.3.0
10 */
11 class Mailchimp {
12 /**
13 * Object of helper class.
14 *
15 * @since 2.3.0
16 * @var object
17 */
18 private static $helper;
19
20 /**
21 * The Mailchimp API URL.
22 *
23 * @since 2.3.0
24 * @var string
25 */
26 private static $api_key = '';
27
28 /**
29 * The Mailchimp API server.
30 *
31 * @since 2.3.0
32 * @var string
33 */
34 private static $api_server = '';
35
36 /**
37 * Run the mailchimp process.
38 *
39 * @param object $helper The helper class instance.
40 */
41 public static function run( $helper ) {
42 self::$helper = $helper;
43
44 if ( empty( self::$helper ) ) {
45 return;
46 }
47
48 self::handle_mailchimp();
49 }
50
51 /**
52 * Handle Mailchimp.
53 *
54 * @since 2.3.0
55 */
56 private static function handle_mailchimp() {
57 if ( empty( self::$helper->attributes['mailChimp'] ) ) {
58 return self::$helper->add_response( 'admin_errors', esc_html__( 'Mailchimp error: Missing configuration.', 'sellkit' ) );
59 }
60
61 self::$helper->check_api_params( 'mailchimp', 'Mailchimp' );
62
63 $mapping_fields = self::$helper->attributes['mailChimp'];
64 self::$helper->check_required_fields( $mapping_fields, [ 'audience', 'email' ] );
65 self::get_api_params();
66
67 $fields = self::$helper->form_data['fields'];
68
69 $subscriber_data = self::map_fields_to_subscriber( $mapping_fields, $fields );
70
71 $response = self::send_subscriber_to_mailchimp( $subscriber_data, $mapping_fields['audience'] );
72
73 if ( is_wp_error( $response ) ) {
74 return self::$helper->add_response( 'admin_errors', $response->get_error_message() );
75 }
76
77 $code = $response['code'];
78
79 if ( $code < 200 || $code >= 300 ) {
80 return self::$helper->add_response(
81 'admin_errors',
82 sprintf(
83 /* Translators: 1: CRM name 2: Error code 3: Error message */
84 esc_html__( '%1$s: Request error-%2$s -- %3$s', 'sellkit' ),
85 'Mailchimp',
86 esc_html( $code ),
87 wp_remote_retrieve_response_message( $response )
88 ) . esc_html__( ' (issued by endpoint)', 'sellkit' )
89 );
90 }
91 }
92
93 /**
94 * Map fields to Mailchimp subscriber data.
95 *
96 * @param array $mapping_fields The mapping fields.
97 * @param array $fields The form data fields.
98 * @since 2.3.0
99 * @return array The subscriber data.
100 * @SuppressWarnings(PHPMD.NPathComplexity)
101 */
102 private static function map_fields_to_subscriber( $mapping_fields, $fields ) {
103 $subscriber_data = [
104 'email_address' => ! empty( $fields[ $mapping_fields['email'] ] ) ? $fields[ $mapping_fields['email'] ] : '',
105 'full_name' => ( isset( $mapping_fields['full_name'] ) && ! empty( $fields[ $mapping_fields['full_name'] ] ) ) ? $fields[ $mapping_fields['full_name'] ] : '',
106 'status' => 'subscribed',
107 'status_if_new' => 'subscribed',
108 'skip_merge_validation' => true,
109 'ip_opt' => self::$helper::get_client_ip(),
110 ];
111
112 foreach ( $mapping_fields as $index => $value ) {
113 if ( ! empty( $fields[ $value ] ) ) {
114 $fields[ $value ] = self::$helper->get_address_field( $fields[ $value ], 'hidden' );
115 }
116
117 if ( ! in_array( $index, [ 'audience', 'email', 'group', 'full_name', 'doubleOptIn' ], true ) && ! empty( $fields[ $value ] ) ) {
118 $subscriber_data['merge_fields'][ $index ] = $fields[ $value ];
119 }
120
121 if ( 'BIRTHDAY' === $index && ! empty( $fields[ $value ] ) ) {
122 $birthday_formatted = gmdate( 'Y/m/d', strtotime( $fields[ $value ] ) );
123
124 $subscriber_data['merge_fields'][ $index ] = $birthday_formatted;
125 }
126
127 if ( 'ADDRESS' === $index && ! empty( $fields[ $value ] ) ) {
128 $address_data = self::map_address_fields_to_mailchimp( $fields[ $value ] );
129
130 if ( ! empty( array_filter( $address_data ) ) ) {
131 $subscriber_data['merge_fields']['ADDRESS'] = $address_data;
132 }
133 }
134 }
135
136 $reactivate = isset( $mapping_fields['doubleOptIn'] ) ? $mapping_fields['doubleOptIn'] : '';
137
138 if ( empty( $reactivate ) ) {
139 $email_hash = md5( strtolower( $subscriber_data['email_address'] ) );
140 $list_id = $mapping_fields['audience'];
141
142 $subscriber_info = self::send_get( "lists/{$list_id}/members/{$email_hash}" );
143
144 if ( ! empty( $subscriber_info['body']['status'] ) && 'subscribed' !== $subscriber_info['body']['status'] ) {
145 $subscriber_data['status'] = 'pending';
146 }
147 }
148
149 if ( ! empty( $mapping_fields['tagsValue'] ) ) {
150 $subscriber_data['tags'] = [ $mapping_fields['tagsValue'] ];
151 }
152
153 if ( ! empty( $mapping_fields['group'] ) ) {
154 $subscriber_data['interests'] = array_fill_keys( [ $mapping_fields['group'] ], true );
155 }
156
157 return $subscriber_data;
158 }
159
160 /**
161 * Send subscriber data to Mailchimp API.
162 *
163 * @param array $subscriber_data The subscriber data.
164 * @param string $audience_id The Mailchimp audience ID.
165 * @return array|WP_Error The response or WP_Error on failure.
166 */
167 private static function send_subscriber_to_mailchimp( $subscriber_data, $audience_id ) {
168 $email_hash = md5( strtolower( $subscriber_data['email_address'] ) );
169
170 $endpoint = "lists/{$audience_id}/members/{$email_hash}";
171 $args = [
172 'method' => 'PUT',
173 'timeout' => 100,
174 'headers' => self::get_headers(),
175 'body' => wp_json_encode( $subscriber_data ),
176 ];
177
178 return self::send_post( $endpoint, $args );
179 }
180
181 /**
182 * Send a POST request to the specified endpoint.
183 *
184 * @param string $endpoint The API endpoint.
185 * @param array $args The request arguments.
186 * @return array|WP_Error The response or WP_Error on failure.
187 */
188 private static function send_post( $endpoint, $args ) {
189 $api_url = trailingslashit( 'https://' . self::$api_server . '.api.mailchimp.com/3.0/' ) . $endpoint;
190 $response = wp_remote_post( $api_url, $args );
191
192 if ( is_wp_error( $response ) ) {
193 return $response;
194 }
195
196 $code = (int) wp_remote_retrieve_response_code( $response );
197
198 if ( $code < 200 || $code >= 300 ) {
199 self::$helper->add_response(
200 'admin_errors',
201 /* translators: %s Error code */
202 sprintf( esc_html__( 'Mailchimp: Error in request, code: %s', 'sellkit' ), esc_html( $code ) )
203 );
204 }
205
206 return [
207 'code' => $code,
208 'body' => json_decode( wp_remote_retrieve_body( $response ), true ),
209 ];
210 }
211
212 /**
213 * Send a GET request to the specified endpoint.
214 *
215 * @param string $endpoint The API endpoint.
216 * @return array|WP_Error The response or WP_Error on failure.
217 */
218 private static function send_get( $endpoint ) {
219 $api_url = trailingslashit( 'https://' . self::$api_server . '.api.mailchimp.com/3.0/' ) . $endpoint;
220 $args = [
221 'method' => 'GET',
222 'timeout' => 100,
223 'sslverify' => false,
224 'headers' => self::get_headers(),
225 ];
226
227 $response = wp_remote_get( $api_url, $args );
228
229 if ( is_wp_error( $response ) ) {
230 return $response;
231 }
232
233 $code = (int) wp_remote_retrieve_response_code( $response );
234
235 return [
236 'code' => $code,
237 'body' => json_decode( wp_remote_retrieve_body( $response ), true ),
238 ];
239 }
240
241 /**
242 * Get headers for the API request.
243 *
244 * @return array The headers for the API request.
245 */
246 private static function get_headers() {
247 return [
248 'Content-Type' => 'application/json',
249 'Authorization' => 'Basic ' . base64_encode( 'user:' . self::$api_key ),
250 'User-Agent' => 'sellkit'
251 ];
252 }
253
254 /**
255 * Get Mailchimp API parameters.
256 *
257 * @since 2.3.0
258 * @return void
259 */
260 private static function get_api_params() {
261 $api_key = sellkit_get_option( 'mailchimp_api_key', '' );
262
263 $parts = explode( '-', $api_key );
264
265 if ( 2 === count( $parts ) ) {
266 self::$api_key = $parts[0];
267 self::$api_server = $parts[1];
268 }
269 }
270
271 /**
272 * Map address fields to Mailchimp format.
273 *
274 * @param string $address_fields The address fields.
275 * @since 2.3.0
276 * @return array The address data.
277 */
278 private static function map_address_fields_to_mailchimp( $address_fields ) {
279 if ( empty( $address_fields ) ) {
280 return [];
281 }
282
283 $cleaned_json = stripslashes( $address_fields );
284
285 $addresses = json_decode( $cleaned_json, true );
286
287 $mapping = [
288 'addr1' => [ 'street_number', 'route' ],
289 'city' => 'locality',
290 'state' => 'administrative_area_level_1',
291 'zip' => 'postal_code',
292 'country' => 'country'
293 ];
294
295 $address_data = [];
296
297 foreach ( $mapping as $mailchimp_key => $source_keys ) {
298 if ( is_array( $source_keys ) ) {
299 $value = '';
300
301 foreach ( $source_keys as $key ) {
302 if ( ! empty( $addresses[ $key ] ) ) {
303 $value .= $addresses[ $key ] . ' ';
304 }
305 }
306
307 $address_data[ $mailchimp_key ] = trim( $value );
308
309 continue;
310 }
311
312 $address_data[ $mailchimp_key ] = ! empty( $addresses[ $source_keys ] ) ? $addresses[ $source_keys ] : '';
313 }
314
315 return $address_data;
316 }
317 }
318