PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.13
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.13
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Services / Integrations / MailChimp / MailChimpIntegration.php

MailChimpIntegration.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.13, at app/Services/Integrations/MailChimp/MailChimpIntegration.php

512 lines 21.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Services\Integrations\MailChimp;
4
5 defined('ABSPATH') or die;
6
7 use FluentForm\App\Http\Controllers\IntegrationManagerController;
8 use FluentForm\App\Modules\Acl\Acl;
9 use FluentForm\App\Services\Integrations\MailChimp\MailChimpSubscriber as Subscriber;
10 use FluentForm\Framework\Foundation\Application;
11 use FluentForm\Framework\Helpers\ArrayHelper;
12
13 class MailChimpIntegration extends IntegrationManagerController
14 {
15 /**
16 * MailChimp Subscriber that handles & process all the subscribing logics.
17 */
18 use Subscriber;
19
20 public function __construct(Application $application)
21 {
22 parent::__construct(
23 $application,
24 'Mailchimp',
25 'mailchimp',
26 '_fluentform_mailchimp_details',
27 'mailchimp_feeds',
28 12
29 );
30
31 $this->description = __('Fluent Forms Mailchimp module allows you to create Mailchimp newsletter signup forms in WordPress', 'fluentform');
32
33 $this->logo = fluentFormMix('img/integrations/mailchimp.png');
34 $this->registerAdminHooks();
35
36 add_action('wp_ajax_fluentform_mailchimp_interest_groups', [$this, 'fetchInterestGroups']);
37
38 add_filter('fluentform/save_integration_value_mailchimp', [$this, 'sanitizeSettings'], 10, 3);
39
40 // add_filter('fluentform/notifying_async_mailchimp', '__return_false');
41 }
42
43 public function getGlobalFields($fields)
44 {
45 return [
46 'logo' => $this->logo,
47 'menu_title' => __('Mailchimp Settings', 'fluentform'),
48 'menu_description' => __('Mailchimp is a marketing platform for small businesses. Send beautiful emails, connect your e-commerce store, advertise, and build your brand. Use Fluent Forms to collect customer information and automatically add it to your Mailchimp campaign list. If you don\'t have a Mailchimp account, you can <a href="https://mailchimp.com/" target="_blank">sign up for one here.</a>', 'fluentform'),
49 'valid_message' => __('Your Mailchimp API Key is valid', 'fluentform'),
50 'invalid_message' => __('Your Mailchimp API Key is not valid', 'fluentform'),
51 'save_button_text' => __('Save Settings', 'fluentform'),
52 'fields' => [
53 'apiKey' => [
54 'type' => 'text',
55 'label_tips' => __('Enter your Mailchimp API Key, if you do not have <br>Please login to your Mailchimp account and go to<br>Profile -> Extras -> Api Keys', 'fluentform'),
56 'label' => __('Mailchimp API Key', 'fluentform'),
57 ],
58 ],
59 'hide_on_valid' => true,
60 'discard_settings' => [
61 'section_description' => __('Your Mailchimp API integration is up and running', 'fluentform'),
62 'button_text' => __('Disconnect Mailchimp', 'fluentform'),
63 'data' => [
64 'apiKey' => '',
65 ],
66 'show_verify' => true,
67 ],
68 ];
69 }
70
71 public function getGlobalSettings($settings)
72 {
73 $globalSettings = get_option($this->optionKey);
74 if (! $globalSettings) {
75 $globalSettings = [];
76 }
77 $defaults = [
78 'apiKey' => '',
79 'status' => '',
80 ];
81
82 return wp_parse_args($globalSettings, $defaults);
83 }
84
85 public function saveGlobalSettings($mailChimp)
86 {
87 if (! $mailChimp['apiKey']) {
88 $mailChimpSettings = [
89 'apiKey' => '',
90 'status' => false,
91 ];
92 // Update the reCaptcha details with siteKey & secretKey.
93 update_option($this->optionKey, $mailChimpSettings, 'no');
94 wp_send_json_success([
95 'message' => __('Your settings has been updated and disconnected', 'fluentform'),
96 'status' => false,
97 ], 200);
98 }
99
100 // Verify API key now
101 try {
102 $MailChimp = new MailChimp($mailChimp['apiKey']);
103 $result = $MailChimp->get('lists');
104 if (! $MailChimp->success()) {
105 throw new \Exception($MailChimp->getLastError());
106 }
107 } catch (\Exception $exception) {
108 wp_send_json_error([
109 'message' => $exception->getMessage(),
110 ], 400);
111 }
112
113 // Mailchimp key is verified now, Proceed now
114
115 $mailChimpSettings = [
116 'apiKey' => sanitize_text_field($mailChimp['apiKey']),
117 'status' => true,
118 ];
119
120 // Update the reCaptcha details with siteKey & secretKey.
121 update_option($this->optionKey, $mailChimpSettings, 'no`');
122
123 wp_send_json_success([
124 'message' => __('Your mailchimp api key has been verified and successfully set', 'fluentform'),
125 'status' => true,
126 ], 200);
127 }
128
129 public function pushIntegration($integrations, $formId)
130 {
131 $integrations['mailchimp'] = [
132 'title' => __('Mailchimp Feed', 'fluentform'),
133 'logo' => $this->logo,
134 'is_active' => $this->isConfigured(),
135 'configure_title' => __('Configuration required!', 'fluentform'),
136 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-mailchimp-settings'),
137 'configure_message' => __('Mailchimp is not configured yet! Please configure your mailchimp api first', 'fluentform'),
138 'configure_button_text' => __('Set Mailchimp API', 'fluentform'),
139 ];
140
141 return $integrations;
142 }
143
144 public function getIntegrationDefaults($settings, $formId)
145 {
146 $settings = [
147 'conditionals' => [
148 'conditions' => [],
149 'status' => false,
150 'type' => 'all',
151 ],
152 'enabled' => true,
153 'list_id' => '',
154 'list_name' => '',
155 'name' => '',
156 'merge_fields' => (object) [],
157 'tags' => '',
158 'tag_routers' => [],
159 'tag_ids_selection_type' => 'simple',
160 'markAsVIP' => false,
161 'fieldEmailAddress' => '',
162 'doubleOptIn' => false,
163 'resubscribe' => false,
164 'note' => '',
165 ];
166
167 return $settings;
168 }
169
170 public function getSettingsFields($settings, $formId)
171 {
172 return [
173 'fields' => [
174 [
175 'key' => 'name',
176 'label' => __('Name', 'fluentform'),
177 'required' => true,
178 'placeholder' => __('Your Feed Name', 'fluentform'),
179 'component' => 'text',
180 ],
181 [
182 'key' => 'list_id',
183 'label' => __('Mailchimp List', 'fluentform'),
184 'placeholder' => __('Select Mailchimp List', 'fluentform'),
185 'tips' => __('Select the Mailchimp list you would like to add your contacts to.', 'fluentform'),
186 'component' => 'list_ajax_options',
187 'options' => $this->getLists(),
188 ],
189 [
190 'key' => 'merge_fields',
191 'require_list' => true,
192 'label' => __('Map Fields', 'fluentform'),
193 'tips' => __('Associate your Mailchimp merge tags to the appropriate Fluent Forms fields by selecting the appropriate form field from the list. Also, Mailchimp Date fields supports only MM/DD/YYYY and DD/MM/YYYY format.', 'fluentform'),
194 'component' => 'map_fields',
195 'field_label_remote' => __('Mailchimp Field', 'fluentform'),
196 'field_label_local' => __('Form Field', 'fluentform'),
197 'primary_fileds' => [
198 [
199 'key' => 'fieldEmailAddress',
200 'label' => __('Email Address', 'fluentform'),
201 'required' => true,
202 'input_options' => 'emails',
203 ],
204 ],
205 ],
206 [
207 'key' => 'interest_group',
208 'require_list' => true,
209 'label' => __('Interest Group', 'fluentform'),
210 'tips' => __('You can map your mailchimp interest group for this contact', 'fluentform'),
211 'component' => 'chained_fields',
212 'sub_type' => 'radio',
213 'category_label' => __('Select Interest Category', 'fluentform'),
214 'subcategory_label' => __('Select Interest', 'fluentform'),
215 'remote_url' => add_query_arg([
216 'action' => 'fluentform_mailchimp_interest_groups',
217 'form_id' => (int) $formId,
218 ], admin_url('admin-ajax.php')),
219 'inline_tip' => __('Select the mailchimp interest category and interest', 'fluentform'),
220 ],
221 [
222 'key' => 'tags',
223 'require_list' => true,
224 'label' => __('Tags', 'fluentform'),
225 'tips' => __('Associate tags to your Mailchimp contacts with a comma separated list (e.g. new lead, FluentForms, web source). Commas within a merge tag value will be created as a single tag.', 'fluentform'),
226 'component' => 'selection_routing',
227 'simple_component' => 'value_text',
228 'routing_input_type' => 'text',
229 'routing_key' => 'tag_ids_selection_type',
230 'settings_key' => 'tag_routers',
231 'labels' => [
232 'choice_label' => __('Enable Dynamic Tag Input', 'fluentform'),
233 'input_label' => '',
234 'input_placeholder' => __('Tag', 'fluentform'),
235 ],
236 'inline_tip' => __('Please provide each tag by comma separated value, You can use dynamic smart codes', 'fluentform'),
237 ],
238 [
239 'key' => 'note',
240 'require_list' => true,
241 'label' => __('Note', 'fluentform'),
242 'tips' => __('You can write a note for this contact', 'fluentform'),
243 'component' => 'value_textarea',
244 ],
245 [
246 'key' => 'doubleOptIn',
247 'require_list' => true,
248 'label' => __('Double Opt-in', 'fluentform'),
249 'tips' => __('When the double opt-in option is enabled, Mailchimp will send a confirmation email to the user and will only add them to your <br /Mailchimp list upon confirmation.', 'fluentform'),
250 'component' => 'checkbox-single',
251 'checkbox_label' => __('Enable Double Opt-in', 'fluentform'),
252 ],
253 [
254 'key' => 'resubscribe',
255 'require_list' => true,
256 'label' => __('ReSubscribe', 'fluentform'),
257 'tips' => __('When this option is enabled, if the subscriber is in an inactive state or has previously been unsubscribed, they will be re-added to the active list. Therefore, this option should be used with caution and only when appropriate.', 'fluentform'),
258 'component' => 'checkbox-single',
259 'checkbox_label' => __('Enable ReSubscription', 'fluentform'),
260 ],
261 [
262 'key' => 'markAsVIP',
263 'require_list' => true,
264 'label' => __('VIP', 'fluentform'),
265 'tips' => __('When enabled, This contact will be marked as VIP.', 'fluentform'),
266 'component' => 'checkbox-single',
267 'checkbox_label' => __('Mark as VIP Contact', 'fluentform'),
268 ],
269 [
270 'require_list' => true,
271 'key' => 'conditionals',
272 'label' => __('Conditional Logics', 'fluentform'),
273 'tips' => __('Allow mailchimp integration conditionally based on your submission values', 'fluentform'),
274 'component' => 'conditional_block',
275 ],
276 [
277 'require_list' => true,
278 'key' => 'enabled',
279 'label' => __('Status', 'fluentform'),
280 'component' => 'checkbox-single',
281 'checkbox_label' => __('Enable This feed', 'fluentform'),
282 ],
283 ],
284 'button_require_list' => true,
285 'integration_title' => __('Mailchimp', 'fluentform'),
286 ];
287 }
288
289 public function prepareIntegrationFeed($setting, $feed, $formId)
290 {
291 $defaults = $this->getIntegrationDefaults([], $formId);
292
293 foreach ($setting as $settingKey => $settingValue) {
294 if ('true' == $settingValue) {
295 $setting[$settingKey] = true;
296 } elseif ('false' == $settingValue) {
297 $setting[$settingKey] = false;
298 } elseif ('conditionals' == $settingKey) {
299 if ('true' == $settingValue['status']) {
300 $settingValue['status'] = true;
301 } elseif ('false' == $settingValue['status']) {
302 $settingValue['status'] = false;
303 }
304 $setting['conditionals'] = $settingValue;
305 }
306 }
307
308 if (! empty($setting['list_id'])) {
309 $setting['list_id'] = (string) $setting['list_id'];
310 }
311
312 $settings['markAsVIP'] = ArrayHelper::isTrue($setting, 'markAsVIP');
313 $settings['doubleOptIn'] = ArrayHelper::isTrue($setting, 'doubleOptIn');
314
315 return wp_parse_args($setting, $defaults);
316 }
317
318 private function getLists()
319 {
320 $settings = get_option('_fluentform_mailchimp_details');
321 try {
322 $MailChimp = new MailChimp($settings['apiKey']);
323 $lists = $MailChimp->get('lists', ['count' => 9999]);
324 if (! $MailChimp->success()) {
325 return [];
326 }
327 } catch (\Exception $exception) {
328 return [];
329 }
330
331 $formattedLists = [];
332 if (is_array($lists) && isset($lists['lists'])) {
333 foreach ($lists['lists'] as $list) {
334 $formattedLists[$list['id']] = $list['name'];
335 }
336 }
337
338 return $formattedLists;
339 }
340
341 public function getMergeFields($list, $listId, $formId)
342 {
343 if (! $this->isConfigured()) {
344 return false;
345 }
346
347 $mergedFields = $this->findMergeFields($listId);
348
349 $fields = [];
350
351 foreach ($mergedFields as $merged_field) {
352 $fields[$merged_field['tag']] = $merged_field['name'];
353 }
354
355 return $fields;
356 }
357
358 public function findMergeFields($listId)
359 {
360 $settings = get_option('_fluentform_mailchimp_details');
361
362 try {
363 $MailChimp = new MailChimp($settings['apiKey']);
364
365 $list = $MailChimp->get('lists/' . $listId . '/merge-fields', ['count' => 9999]);
366
367 if (! $MailChimp->success()) {
368 return false;
369 }
370 } catch (\Exception $exception) {
371 return false;
372 }
373
374 return $list['merge_fields'];
375 }
376
377 public function fetchInterestGroups()
378 {
379 // SECURITY (FINDING-04): this AJAX action reads the site's global Mailchimp API key and
380 // issues an authenticated request on the caller's behalf; it had no capability/nonce check.
381 // Acl::verify enforces both the capability and the fluent_forms_admin_nonce for AJAX.
382 $formId = Acl::verifyFormId($this->app->request->get('form_id'));
383 Acl::verify('fluentform_forms_manager', $formId);
384
385 $settings = $this->app->request->get('settings', []);
386 $settings = is_array($settings) ? wp_unslash($settings) : [];
387
388 $listId = sanitize_text_field((string) ArrayHelper::get($settings, 'list_id'));
389 if (! $listId) {
390 wp_send_json_success([
391 'categories' => [],
392 'subcategories' => [],
393 'reset_values' => true,
394 ]);
395 }
396
397 $categoryId = sanitize_text_field((string) ArrayHelper::get($settings, 'interest_group.category'));
398 $categories = $this->getInterestCategories($listId);
399
400 $subCategories = [];
401 if ($categoryId) {
402 $subCategories = $this->getInterestSubCategories($listId, $categoryId);
403 }
404
405 wp_send_json_success([
406 'categories' => $categories,
407 'subcategories' => $subCategories,
408 'reset_values' => ! $categories && ! $subCategories,
409 ]);
410 }
411
412 private function getInterestCategories($listId)
413 {
414 $settings = get_option('_fluentform_mailchimp_details');
415 try {
416 $MailChimp = new MailChimp($settings['apiKey']);
417 $categories = $MailChimp->get('/lists/' . $listId . '/interest-categories', [
418 'count' => 9999,
419 'fields' => 'categories.id,categories.title',
420 ]);
421 if (! $MailChimp->success()) {
422 return [];
423 }
424 } catch (\Exception $exception) {
425 return [];
426 }
427 $categories = ArrayHelper::get($categories, 'categories', []);
428 $formattedLists = [];
429 foreach ($categories as $list) {
430 $formattedLists[] = [
431 'value' => $list['id'],
432 'label' => $list['title'],
433 ];
434 }
435 return $formattedLists;
436 }
437
438 private function getInterestSubCategories($listId, $categoryId)
439 {
440 $settings = get_option('_fluentform_mailchimp_details');
441 try {
442 $MailChimp = new MailChimp($settings['apiKey']);
443 $categories = $MailChimp->get('/lists/' . $listId . '/interest-categories/' . $categoryId . '/interests', [
444 'count' => 9999,
445 'fields' => 'interests.id,interests.name',
446 ]);
447 if (! $MailChimp->success()) {
448 return [];
449 }
450 } catch (\Exception $exception) {
451 return [];
452 }
453 $categories = ArrayHelper::get($categories, 'interests', []);
454 $formattedLists = [];
455 foreach ($categories as $list) {
456 $formattedLists[] = [
457 'value' => $list['id'],
458 'label' => $list['name'],
459 ];
460 }
461 return $formattedLists;
462 }
463
464 public function sanitizeSettings($integration, $integrationId, $formId)
465 {
466 if (fluentformCanUnfilteredHTML()) {
467 return $integration;
468 }
469 $sanitizeMap = [
470 'status' => 'rest_sanitize_boolean',
471 'enabled' => 'rest_sanitize_boolean',
472 'type' => 'sanitize_text_field',
473 'list_id' => 'sanitize_text_field',
474 'list_name' => 'sanitize_text_field',
475 'name' => 'sanitize_text_field',
476 'tags' => 'sanitize_text_field',
477 'tag_ids_selection_type' => 'sanitize_text_field',
478 'fieldEmailAddress' => 'sanitize_text_field',
479 'doubleOptIn' => 'rest_sanitize_boolean',
480 'resubscribe' => 'rest_sanitize_boolean',
481 'note' => 'sanitize_text_field',
482 ];
483 return fluentform_backend_sanitizer($integration, $sanitizeMap);
484 }
485
486 /*
487 * For Handling Notifications broadcast
488 */
489 public function notify($feed, $formData, $entry, $form)
490 {
491 $response = $this->subscribe($feed, $formData, $entry, $form);
492
493 if (true == $response && !is_wp_error($response)) {
494 $message = __('Mailchimp feed has been successfully initialed and pushed data', 'fluentform');
495 do_action('fluentform/integration_action_result', $feed, 'success', $message);
496 } else {
497 $message = __('Mailchimp feed has been failed to deliver feed', 'fluentform');
498 if (is_wp_error($response)) {
499 $message = $response->get_error_message();
500 if (is_array($message)) {
501 $messageArray = $message;
502 $message = '';
503 foreach ($messageArray as $error) {
504 $message .= ArrayHelper::get($error, 'message');
505 }
506 }
507 }
508 do_action('fluentform/integration_action_result', $feed, 'failed', $message);
509 }
510 }
511 }
512