PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.7.9
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.7.9
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 / elementor / modules / optin / actions / mailchimp.php

mailchimp.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 1.7.9, at includes/elementor/modules/optin/actions/mailchimp.php

327 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 defined( 'ABSPATH' ) || die();
4
5 use Sellkit_Elementor_Optin_Ajaxhandler as AjaxHandler;
6
7 /**
8 * Initializing the MailChimp action by extending Action base and using CRM trait.
9 *
10 * @since 1.5.0
11 */
12 class Sellkit_Elementor_Optin_Action_Mailchimp extends Sellkit_Elementor_Optin_Action_Base {
13 use Sellkit_Elementor_Optin_CRM;
14
15 private $api_key;
16
17 private $api_server;
18
19 public static $instance;
20
21 public static function get_instance() {
22 if ( empty( static::$instance ) ) {
23 static::$instance = new static();
24 }
25
26 return static::$instance;
27 }
28
29 public function get_name() {
30 return 'mailchimp';
31 }
32
33 public function get_title() {
34 return esc_html__( 'MailChimp', 'sellkit' );
35 }
36
37 protected function get_base_url() {
38 return 'https://' . $this->api_server . '.api.mailchimp.com/3.0/';
39 }
40
41 protected function get_headers() {
42 return [
43 'Authorization' => 'Basic ' . base64_encode( 'user:' . $this->api_key ),
44 'Content-Type' => 'application/json',
45 'User-Agent' => $this->user_agent,
46 ];
47 }
48
49 protected function get_get_request_args() {
50 return [
51 'timeout' => 100,
52 'sslverify' => false,
53 'headers' => $this->get_headers(),
54 ];
55 }
56
57 /**
58 * An override of the same named function in CRM trait.\
59 * Because MailChimp's api key is like XXXX-us1 and we must extract its parts.
60 */
61 private function get_api_params( $settings ) {
62 $name = $this->get_name();
63 $api_key_source = $settings[ "{$name}_api_key_source" ];
64 $api_key = '';
65
66 if ( 'custom' === $api_key_source ) {
67 $api_key = $settings[ "{$name}_custom_api_key" ];
68 } else {
69 $options = get_option( 'sellkit' );
70
71 if ( ! empty( $options[ "{$name}_api_key" ] ) ) {
72 $api_key = $options[ "{$name}_api_key" ];
73 }
74 }
75
76 $result = [
77 'token' => '',
78 'server' => '',
79 ];
80
81 $parts = explode( '-', $api_key );
82 if ( 2 === count( $parts ) ) {
83 $result['token'] = $parts[0];
84 $result['server'] = $parts[1];
85 }
86
87 return $result;
88 }
89
90 public function add_controls( $widget ) {
91 $action = $this->get_name();
92
93 $this->add_api_controls( $widget, esc_html__( 'Audience', 'sellkit' ) );
94 $this->add_field_mapping_controls( $widget );
95
96 $widget->add_control( "{$action}_groups",
97 [
98 'label' => esc_html__( 'Groups', 'sellkit' ),
99 'type' => 'select2',
100 'multiple' => 'true',
101 'label_block' => true,
102 'conditions' => [
103 'terms' => [
104 [
105 'name' => "{$action}_list",
106 'operator' => '!in',
107 'value' => [ 'none', 'fetching', 'noList' ],
108 ],
109 ],
110 ],
111 ]
112 );
113
114 $this->add_tag_control( $widget );
115
116 $widget->add_control( "{$action}_resubscribe",
117 [
118 'label' => esc_html__( 'Double Opt-In', 'sellkit' ),
119 'type' => 'switcher',
120 'description' => esc_html__( 'Activates the existing user, if unsubscribed.', 'sellkit' ),
121 'conditions' => [
122 'terms' => [
123 [
124 'name' => "{$action}_list",
125 'operator' => '!in',
126 'value' => [ 'none', 'fetching', 'noList' ],
127 ],
128 ],
129 ],
130 ]
131 );
132 }
133
134 public function run( AjaxHandler $ajax_handler ) {
135 $form_settings = $ajax_handler->form['settings'];
136
137 // Retrieve and check List.
138 $list_id = $form_settings[ $this->get_name() . '_list' ];
139 if ( empty( $list_id ) || in_array( $list_id, [ 'default', 'fetching', 'noList' ], true ) ) {
140 return $ajax_handler->add_response( 'admin_errors', $this->get_invalid_list_message( 'audience' ) );
141 }
142
143 // Retireve and check API credentials.
144 $api_data = $this->get_api_params( $form_settings );
145 $this->api_key = $api_data['token'];
146 $this->api_server = $api_data['server'];
147 if ( empty( $this->api_key ) || empty( $this->api_server ) ) {
148 return $ajax_handler->add_response( 'admin_errors', "{$this->get_title()}: " . esc_html__( 'Missing API credentials.', 'sellkit' ) );
149 }
150
151 // Try subscription.
152 $this->ajax_handler = $ajax_handler;
153 $subscriber = $this->create_subscriber_object();
154 $this->subscribe( $subscriber, $list_id );
155 }
156
157 public function get_list( AjaxHandler $ajax_handler, $params ) {
158 $api_data = $this->get_api_params( $params );
159 $this->api_key = $api_data['token'];
160 $this->api_server = $api_data['server'];
161 $results = $this->send_get( 'lists?count=999' );
162 $lists = [];
163
164 if ( ! empty( $results['body']['lists'] ) ) {
165 foreach ( $results['body']['lists'] as $list ) {
166 $lists[ $list['id'] ] = $list['name'];
167 }
168 }
169
170 $list = [ 'lists' => $lists ];
171
172 return $ajax_handler->add_response( 'success', $list );
173 }
174
175 public function get_additional_data( AjaxHandler $ajax_handler, $params ) {
176 $api_data = $this->get_api_params( $params );
177 $this->api_key = $api_data['token'];
178 $this->api_server = $api_data['server'];
179
180 $data = [
181 'custom_fields' => $this->get_remote_custom_fields( $params['list_id'] ),
182 'groups' => $this->get_remote_groups( $params['list_id'] ),
183 'tags' => $this->get_remote_tags( $params['list_id'] ),
184 ];
185
186 return $ajax_handler->add_response( 'success', $data );
187 }
188
189 private function get_remote_custom_fields( $list_id ) {
190 $results = $this->send_get( "lists/{$list_id}/merge-fields?count=999" );
191
192 $default_fields = $this->get_default_remote_fields()['optional'];
193 $custom_fields = [];
194
195 if ( empty( $results['body']['merge_fields'] ) ) {
196 return $custom_fields;
197 }
198
199 foreach ( $results['body']['merge_fields'] as $field ) {
200 if ( ! array_key_exists( $field['tag'], $default_fields ) ) {
201 $custom_fields[ $field['tag'] ] = $field['name'];
202 }
203 }
204
205 return $custom_fields;
206 }
207
208 private function get_remote_tags( $list_id ) {
209 $results = $this->send_get( "lists/{$list_id}/tag-search" );
210 $tags = [];
211
212 if ( empty( $results['body']['tags'] ) ) {
213 return $tags;
214 }
215
216 foreach ( $results['body']['tags'] as $tag ) {
217 $tags[ $tag['name'] ] = $tag['name'];
218 }
219
220 return $tags;
221 }
222
223 private function get_remote_groups( $list_id ) {
224 $results = $this->send_get( "lists/{$list_id}/interest-categories?count=999" );
225 $groups = [];
226
227 if ( ! empty( $results['body']['categories'] ) ) {
228 foreach ( $results['body']['categories'] as $category ) {
229 $_results = $this->send_get( "lists/{$list_id}/interest-categories/{$category['id']}/interests?count=999" );
230
231 if ( ! empty( $_results['body']['interests'] ) ) {
232 foreach ( $_results['body']['interests'] as $interests ) {
233 $groups[ $interests['id'] ] = "{$category['title']}: {$interests['name']}";
234 }
235 }
236 }
237 }
238
239 return $groups;
240 }
241
242 protected function get_default_remote_fields() {
243 return [
244 'required' => [
245 'email_address' => esc_html__( 'Email', 'sellkit' ),
246 ],
247 'optional' => [
248 'full_name' => esc_html__( 'Full Name', 'sellkit' ),
249 ],
250 ];
251 }
252
253 protected function create_subscriber_object() {
254 $mapped_fields = $this->get_field_mappings();
255 $subscriber = [
256 'ip_opt' => static::get_client_ip(),
257 'status' => 'subscribed',
258 'status_if_new' => 'subscribed',
259 'skip_merge_validation' => true,
260 ];
261 $default_fields = $this->get_default_remote_fields();
262
263 foreach ( $mapped_fields as $key => $value ) {
264 $is_custom =
265 ! array_key_exists( $key, $default_fields['required'] ) &&
266 ! array_key_exists( $key, $default_fields['optional'] );
267
268 if ( $is_custom ) {
269 $subscriber['merge_fields'][ $key ] = $value;
270 continue;
271 }
272
273 $subscriber[ $key ] = $value;
274 }
275
276 if ( empty( $subscriber['email_address'] ) ) {
277 return [];
278 }
279
280 $settings = $this->ajax_handler->form['settings'];
281
282 // Reactivation status.
283 $reactivate = $settings['mailchimp_resubscribe'];
284 if ( 'yes' !== $reactivate ) {
285 $email_hash = md5( strtolower( $subscriber['email_address'] ) );
286 $list_id = $settings['mailchimp_list'];
287
288 $subscriber_info = $this->send_get( "lists/{$list_id}/members/{$email_hash}" );
289
290 if ( ! empty( $subscriber_info['body']['status'] ) && 'subscribed' !== $subscriber_info['body']['status'] ) {
291 $subscriber['status'] = 'pending';
292 }
293 }
294
295 // Add additional data.
296 $subscriber['tags'] = $settings['mailchimp_tags'];
297
298 $groups = $settings['mailchimp_groups'];
299
300 if ( ! empty( $groups ) ) {
301 $groups = is_array( $groups ) ? $groups : [ $groups ];
302 $subscriber['interests'] = array_fill_keys( $groups, true );
303 }
304
305 return $subscriber;
306 }
307
308 protected function subscribe( $subscriber_data, $list_id ) {
309 if ( empty( $subscriber_data['email_address'] ) ) {
310 return;
311 }
312
313 $email_hash = md5( strtolower( $subscriber_data['email_address'] ) );
314
315 $endpoint = "lists/{$list_id}/members/{$email_hash}";
316
317 $args = [
318 'method' => 'PUT',
319 'timeout' => 100,
320 'headers' => $this->get_headers(),
321 'body' => wp_json_encode( $subscriber_data ),
322 ];
323
324 return $this->send_post( $endpoint, $args );
325 }
326 }
327