MailChimp for WooCommerce - Version 2.7

Version Description

Download this release

Release Info

Developer ryanhungate
Plugin Icon wp plugin MailChimp for WooCommerce
Version 2.7
Comparing to
See all releases

Code changes from version 2.6.2 to 2.7

Files changed (47) hide show
  1. CHANGELOG.txt +40 -30
  2. README.txt +13 -13
  3. admin/class-mailchimp-woocommerce-admin.php +182 -99
  4. admin/css/mailchimp-woocommerce-admin-settings.css +8 -0
  5. admin/js/mailchimp-woocommerce-admin.js +28 -0
  6. admin/partials/tabs/plugin_settings.php +27 -0
  7. admin/user-profile/mailchimp-user-profile.php +17 -0
  8. blocks/assets/js/checkout-newsletter-subscription-block/block.js +23 -1
  9. blocks/assets/js/checkout-newsletter-subscription-block/edit.js +1 -6
  10. blocks/assets/js/checkout-newsletter-subscription-block/gdpr.js +0 -5
  11. blocks/assets/js/checkout-newsletter-subscription-block/index.js +1 -5
  12. blocks/build/newsletter-block-frontend.asset.php +1 -1
  13. blocks/build/newsletter-block-frontend.js +1 -267
  14. blocks/build/newsletter-block-frontend.js.map +0 -1
  15. blocks/build/newsletter-block.asset.php +1 -1
  16. blocks/build/newsletter-block.js +1 -487
  17. blocks/build/newsletter-block.js.map +0 -1
  18. blocks/build/style-newsletter-block.css +1 -17
  19. blocks/build/style-newsletter-block.css.map +0 -1
  20. blocks/{newsletter-test.php → newsletter.php} +0 -0
  21. blocks/package-lock.json +17 -7
  22. blocks/package.json +3 -3
  23. blocks/sample.json +0 -45
  24. blocks/woocommerce-blocks-integration.php +37 -7
  25. bootstrap.php +93 -15
  26. includes/api/assets/class-mailchimp-order.php +130 -4
  27. includes/api/class-mailchimp-api.php +288 -22
  28. includes/api/class-mailchimp-woocommerce-fix-duplicate-store.php +91 -0
  29. includes/api/class-mailchimp-woocommerce-log-viewer.php +184 -0
  30. includes/api/class-mailchimp-woocommerce-logs.php +90 -0
  31. includes/api/class-mailchimp-woocommerce-tower.php +570 -0
  32. includes/api/class-mailchimp-woocommerce-transform-orders-wc3.php +7 -0
  33. includes/class-mailchimp-woocommerce-rest-api.php +480 -2
  34. includes/class-mailchimp-woocommerce-service.php +183 -25
  35. includes/class-mailchimp-woocommerce.php +50 -8
  36. includes/processes/class-mailchimp-woocommerce-abstract-sync.php +8 -0
  37. includes/processes/class-mailchimp-woocommerce-process-coupons.php +11 -0
  38. includes/processes/class-mailchimp-woocommerce-process-orders.php +12 -0
  39. includes/processes/class-mailchimp-woocommerce-process-products.php +7 -3
  40. includes/processes/class-mailchimp-woocommerce-single-order.php +16 -4
  41. includes/processes/class-mailchimp-woocommerce-subscriber-sync.php +24 -7
  42. includes/processes/class-mailchimp-woocommerce-user-submit.php +31 -7
  43. includes/processes/class-mailchimp-woocommerce-webhooks-sync.php +66 -0
  44. languages/mc-woocommerce-newsletter.pot +10 -6
  45. mailchimp-woocommerce.php +8 -9
  46. public/class-mailchimp-woocommerce-public.php +89 -1
  47. public/partials/mailchimp-woocommerce-my-account.php +13 -0
CHANGELOG.txt CHANGED
@@ -1,4 +1,14 @@
1
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
2
  = 2.6.2 =
3
  * compatibility for woocommerce 6.3
4
  * UI/UX updates for situations where Action Scheduler is missing during composer installs (via .gitignore)
@@ -8,8 +18,8 @@
8
  * better error handling with Google Analytics
9
  * fixed bug related to Mailchimp API submission when someone was already a list member
10
  = 2.6 =
11
- * adds support for selectively syncing subscribers only
12
- * updates to action scheduler dependency
13
  = 2.5.4 =
14
  * enhanced api error parsing
15
  * adds site transient for tracking cart
@@ -25,7 +35,7 @@
25
  * tested for wordpress v5.7
26
  * fix for cookies.js samesite error
27
  * adds sync completion email sent to admin
28
- * resolves php error for mailchimp_set_user_by_email on checkout page
29
  * additional database error handling
30
  = 2.5 =
31
  * interface reskin
@@ -37,7 +47,7 @@
37
  * fix for errors on installs with RTL Site Languages
38
  * adds GDPR fields for GDPR enabled audiences
39
  * locale settings from WooCommerce or WP are now auto-selected
40
- * support for notices in the wc-admin inbox
41
  * moves Mailchimp plugin link to bottom of Woocommerce sub navigation
42
  = 2.4.5 =
43
  * fixed disconnect/reconnect list issue
@@ -66,11 +76,11 @@
66
  * adds Mailchimp support form
67
  * moves navigation to WooCommerce nav as a sub-item
68
  * removes bubble h1 title element
69
- * log tab ui enhancements
70
  * next button for setup wizard moved to bottom of page
71
- * required field ui enhancement
72
  * adds a banner for setup completion in Wordpress
73
- * overview tab ui enhancements
74
  * audience settings tab ux improvements
75
  * fix for cart non-numeric error
76
  * fix for woocommerce setup wizard redirect
@@ -84,10 +94,10 @@
84
  * update for latest version of Action Scheduler v3.1.4
85
  * documentation updates
86
  * fix for errors on activation following deactivation
87
- * fix for PHP notice on Woocommerce Import Tax rate page
88
- * adds error handling on store add/update
89
- * use denormalized order items values in initial sync
90
- * adds function allowing tags for specific users
91
  * adds include/exclude Mailchimp script
92
  * fix for double opt-in issues on saved settings
93
  * fixes transactionals on guest checkout
@@ -121,9 +131,9 @@
121
  * fix for orders with deleted products
122
  * support for orders with 0 line items
123
  = 2.3.1 =
124
- * adds fallback for mb_strpos if extension is not installed
125
  * implements communications box on sync page
126
- * adds account create for Mailchimp
127
  * fixes Pending Payment and On-hold status orders passed to Mailchimp
128
  * fixes for WooCommerce Fatal-errors
129
  * support for WooCommerce vendor feature
@@ -132,40 +142,40 @@
132
  * adds banner to review plugin after audience is synced
133
  * support for user language based on wp get_locale() at order placement
134
  = 2.3 =
135
- * adds action scheduler queue system
136
- * documentation for Custom Merge Tags
137
- * adds more specific installation requirements
138
  * fixes PHP Error in class-mailchimp-order.php
139
  * fixes pop up blocks on connection
140
  * fixes unable to sync without accepting to auto subscribe existing customers
141
  * documentation for wp-cli class queue-command
142
  = 2.2 =
143
- * plugin reskin
144
- * support for oauth to Mailchimp
145
  * fixes sync issues with altered order IDs
146
- * fixes issues with trashed coupons
147
  = 2.1.17 =
148
  * re add resync button to sync tab, after sync finishes
149
  * renamed 'merge_vars' to 'merge_fields' as per new Mailchimp naming convention
150
  * fixes issues with cloudflare
151
- * honors woo currency settings
152
  * fix for failing custom coupon type
153
  = 2.1.16 =
154
  * support for HTML in opt-in checkbox
155
- * support for language translation
156
  * fixes abandoned_cart.error
157
- * support for audience tags
158
  * adds responsive checkboxes for newsletter settings
159
  * adds sanitizing function to order ids
160
  * copy change from List terminology to Audience
161
  = 2.1.15 =
162
- * adds optional feedback survey on deactivate
163
- * updates syncing engine to use REST API
164
- * fixes edited orders syncing old and new products into Mailchimp
165
- * adds support for remove_action
166
  = 2.1.14 =
167
- * Adds support for filter on newsletter field
168
- * fixes inactive log delete button
169
  * fixes Mailchimp option page flow and displays list defaults tab
170
  * fixes resource not found error on logs
171
  * fixes API Key Request errors
@@ -193,8 +203,8 @@
193
  * Add Initial sync label on Sync Tab
194
  * Multisite Delete and deactivate improvements
195
  * Mailchimp Order Notification issues support for downloadable and virtual products
196
- * http worker lock improvement
197
- * Add documentation about Multisite setup
198
  * Add documentaiton for on-demand syncing
199
  = 2.1.9 =
200
  * Improved UI feedback when API key is invalid
1
  == Changelog ==
2
+ = 2.7 =
3
+ * adds support for WooCommerce Checkout block
4
+ * adds support for the tracking url from Mailchimp API
5
+ * adds update function to register webhook for store
6
+ * support for new WooCommerce admin navigation
7
+ * adds opt-in preference on My Account page
8
+ * adds subscriber status to user (customer) in Wordpress
9
+ * now assigns double opt-in to all re-subscribers
10
+ * now support for loading plugin files from absolute path
11
+ * adds two way sync check for webhooks on unsubscribes to and from Mailchimp
12
  = 2.6.2 =
13
  * compatibility for woocommerce 6.3
14
  * UI/UX updates for situations where Action Scheduler is missing during composer installs (via .gitignore)
18
  * better error handling with Google Analytics
19
  * fixed bug related to Mailchimp API submission when someone was already a list member
20
  = 2.6 =
21
+ * adds support for selectively syncing subscribers only
22
+ * updates to action scheduler dependency
23
  = 2.5.4 =
24
  * enhanced api error parsing
25
  * adds site transient for tracking cart
35
  * tested for wordpress v5.7
36
  * fix for cookies.js samesite error
37
  * adds sync completion email sent to admin
38
+ * resolves php error for mailchimp_set_user_by_email on checkout page
39
  * additional database error handling
40
  = 2.5 =
41
  * interface reskin
47
  * fix for errors on installs with RTL Site Languages
48
  * adds GDPR fields for GDPR enabled audiences
49
  * locale settings from WooCommerce or WP are now auto-selected
50
+ * support for notices in the wc-admin inbox
51
  * moves Mailchimp plugin link to bottom of Woocommerce sub navigation
52
  = 2.4.5 =
53
  * fixed disconnect/reconnect list issue
76
  * adds Mailchimp support form
77
  * moves navigation to WooCommerce nav as a sub-item
78
  * removes bubble h1 title element
79
+ * log tab ui enhancements
80
  * next button for setup wizard moved to bottom of page
81
+ * required field ui enhancement
82
  * adds a banner for setup completion in Wordpress
83
+ * overview tab ui enhancements
84
  * audience settings tab ux improvements
85
  * fix for cart non-numeric error
86
  * fix for woocommerce setup wizard redirect
94
  * update for latest version of Action Scheduler v3.1.4
95
  * documentation updates
96
  * fix for errors on activation following deactivation
97
+ * fix for PHP notice on Woocommerce Import Tax rate page
98
+ * adds error handling on store add/update
99
+ * use denormalized order items values in initial sync
100
+ * adds function allowing tags for specific users
101
  * adds include/exclude Mailchimp script
102
  * fix for double opt-in issues on saved settings
103
  * fixes transactionals on guest checkout
131
  * fix for orders with deleted products
132
  * support for orders with 0 line items
133
  = 2.3.1 =
134
+ * adds fallback for mb_strpos if extension is not installed
135
  * implements communications box on sync page
136
+ * adds account create for Mailchimp
137
  * fixes Pending Payment and On-hold status orders passed to Mailchimp
138
  * fixes for WooCommerce Fatal-errors
139
  * support for WooCommerce vendor feature
142
  * adds banner to review plugin after audience is synced
143
  * support for user language based on wp get_locale() at order placement
144
  = 2.3 =
145
+ * adds action scheduler queue system
146
+ * documentation for Custom Merge Tags
147
+ * adds more specific installation requirements
148
  * fixes PHP Error in class-mailchimp-order.php
149
  * fixes pop up blocks on connection
150
  * fixes unable to sync without accepting to auto subscribe existing customers
151
  * documentation for wp-cli class queue-command
152
  = 2.2 =
153
+ * plugin reskin
154
+ * support for oauth to Mailchimp
155
  * fixes sync issues with altered order IDs
156
+ * fixes issues with trashed coupons
157
  = 2.1.17 =
158
  * re add resync button to sync tab, after sync finishes
159
  * renamed 'merge_vars' to 'merge_fields' as per new Mailchimp naming convention
160
  * fixes issues with cloudflare
161
+ * honors woo currency settings
162
  * fix for failing custom coupon type
163
  = 2.1.16 =
164
  * support for HTML in opt-in checkbox
165
+ * support for language translation
166
  * fixes abandoned_cart.error
167
+ * support for audience tags
168
  * adds responsive checkboxes for newsletter settings
169
  * adds sanitizing function to order ids
170
  * copy change from List terminology to Audience
171
  = 2.1.15 =
172
+ * adds optional feedback survey on deactivate
173
+ * updates syncing engine to use REST API
174
+ * fixes edited orders syncing old and new products into Mailchimp
175
+ * adds support for remove_action
176
  = 2.1.14 =
177
+ * Adds support for filter on newsletter field
178
+ * fixes inactive log delete button
179
  * fixes Mailchimp option page flow and displays list defaults tab
180
  * fixes resource not found error on logs
181
  * fixes API Key Request errors
203
  * Add Initial sync label on Sync Tab
204
  * Multisite Delete and deactivate improvements
205
  * Mailchimp Order Notification issues support for downloadable and virtual products
206
+ * http worker lock improvement
207
+ * Add documentation about Multisite setup
208
  * Add documentaiton for on-demand syncing
209
  = 2.1.9 =
210
  * Improved UI feedback when API key is invalid
README.txt CHANGED
@@ -3,11 +3,11 @@ Contributors: ryanhungate, Mailchimp
3
  Tags: ecommerce,email,workflows,mailchimp
4
  Donate link: https://mailchimp.com
5
  Requires at least: 4.9
6
- Tested up to: 5.9
7
- Stable tag: 2.6.2
8
  Requires PHP: 7.0
9
  WC requires at least: 3.5
10
- WC tested up to: 6.3
11
  License: GPLv2 or later
12
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
13
  Connect your store to your Mailchimp audience to track sales, create targeted emails, send abandoned cart emails, and more.
@@ -78,15 +78,15 @@ At this time, the synchronization of product categories from WooCommerce to Mail
78
  If you are unable to sync or connect with Mailchimp, you can open a ticket on our [Github plugin page](https://github.com/mailchimp/mc-woocommerce/issues). Please provide the version of the plugin and PHP you're using, any fatal errors in the WooCommerce logs (WooCommerce -> Status -> Logs) you're seeing, along with relevant information to the problem you're experiencing.
79
 
80
  == Changelog ==
81
- = 2.6.2 =
82
- * compatibility for woocommerce 6.3
83
- * UI/UX updates for situations where Action Scheduler is missing during composer installs (via .gitignore)
84
- * trigger double opt-in messages for customers who previously unsubscribed
85
- * improved minification of mailchimp-woocommerce-public.min.js file
86
- * mailchimp_woocommerce_landing_site URL improvements to reflect which page the customer entered on for the first time
87
- * better error handling with Google Analytics
88
- * fixed bug related to Mailchimp API submission when someone was already a list member
89
-
 
90
 
91
  [Historical Changelog](https://raw.githubusercontent.com/mailchimp/mc-woocommerce/master/CHANGELOG.txt)
92
-
3
  Tags: ecommerce,email,workflows,mailchimp
4
  Donate link: https://mailchimp.com
5
  Requires at least: 4.9
6
+ Tested up to: 6.0
7
+ Stable tag: 2.7
8
  Requires PHP: 7.0
9
  WC requires at least: 3.5
10
+ WC tested up to: 6.6
11
  License: GPLv2 or later
12
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
13
  Connect your store to your Mailchimp audience to track sales, create targeted emails, send abandoned cart emails, and more.
78
  If you are unable to sync or connect with Mailchimp, you can open a ticket on our [Github plugin page](https://github.com/mailchimp/mc-woocommerce/issues). Please provide the version of the plugin and PHP you're using, any fatal errors in the WooCommerce logs (WooCommerce -> Status -> Logs) you're seeing, along with relevant information to the problem you're experiencing.
79
 
80
  == Changelog ==
81
+ = 2.7 =
82
+ * adds support for WooCommerce Checkout block
83
+ * adds support for the tracking url from Mailchimp API
84
+ * adds update function to register webhook for store
85
+ * support for new WooCommerce admin navigation
86
+ * adds opt-in preference on My Account page
87
+ * adds subscriber status to user (customer) in Wordpress
88
+ * now assigns double opt-in to all re-subscribers
89
+ * now support for loading plugin files from absolute path
90
+ * adds two way sync check for webhooks on unsubscribes to and from Mailchimp
91
 
92
  [Historical Changelog](https://raw.githubusercontent.com/mailchimp/mc-woocommerce/master/CHANGELOG.txt)
 
admin/class-mailchimp-woocommerce-admin.php CHANGED
@@ -9,7 +9,7 @@
9
  * @package MailChimp_WooCommerce
10
  * @subpackage MailChimp_WooCommerce/admin
11
  */
12
-
13
  /**
14
  * The admin-specific functionality of the plugin.
15
  *
@@ -129,7 +129,7 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
129
  if ($label == '') $label = __('Subscribe to our newsletter', 'mailchimp-for-woocommerce');
130
  $options = get_option($this->plugin_name, array());
131
  $checkbox_default_settings = (array_key_exists('mailchimp_checkbox_defaults', $options) && !is_null($options['mailchimp_checkbox_defaults'])) ? $options['mailchimp_checkbox_defaults'] : 'check';
132
- wp_register_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/mailchimp-woocommerce-admin.js', array( 'jquery', 'swal' ), $this->version.'.05', false );
133
  wp_localize_script(
134
  $this->plugin_name,
135
  'phpVars',
@@ -168,6 +168,7 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
168
  * @since 1.0.0
169
  */
170
  public function add_plugin_admin_menu() {
 
171
  // Add woocommerce menu subitem
172
  add_submenu_page(
173
  'woocommerce',
@@ -177,6 +178,20 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
177
  $this->plugin_name,
178
  array($this, 'display_plugin_setup_page')
179
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
181
 
182
  /**
@@ -246,6 +261,36 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
246
  include_once( 'partials/mailchimp-woocommerce-admin-tabs.php' );
247
  }
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  /**
250
  *
251
  */
@@ -259,6 +304,13 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
259
  $this->handle_abandoned_cart_table();
260
  $this->update_db_check();
261
 
 
 
 
 
 
 
 
262
  /// this is where we need to cache this data for a longer period of time and only during admin page views.
263
  /// https://wordpress.org/support/topic/the-plugin-slows-down-the-website-because-of-slow-api/#post-14339311
264
  if (mailchimp_is_configured() && ($list_id = mailchimp_get_list_id())) {
@@ -326,7 +378,27 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
326
  }
327
  }
328
 
329
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  /**
331
  * Depending on the version we're on we may need to run some sort of migrations.
332
  */
@@ -593,12 +665,12 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
593
 
594
  case 'newsletter_settings':
595
  $data = $this->validatePostNewsletterSettings($input);
 
596
  break;
597
 
598
  case 'sync':
599
  //case sync
600
  if ($this->is_resyncing()) {
601
-
602
  // remove all the pointers to be sure
603
  $service = new MailChimp_Service();
604
  $service->removePointers(true, true);
@@ -626,7 +698,6 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
626
 
627
  break;
628
  case 'plugin_settings':
629
-
630
  // case disconnect
631
  if ($this->is_disconnecting()) {
632
  // Disconnect store!
@@ -636,11 +707,9 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
636
  'mailchimp_api_key' => null,
637
  'mailchimp_list' => null,
638
  );
639
- add_settings_error('mailchimp_store_settings', '', __('Store Disconnected', 'mailchimp-for-woocommerce'), 'info');
640
- } else {
641
- $data['active_tab'] = 'plugin_settings';
642
- add_settings_error('mailchimp_store_settings', '', __('Store Disconnect Failed', 'mailchimp-for-woocommerce'), 'warning');
643
- }
644
  }
645
  break;
646
  }
@@ -719,6 +788,12 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
719
  );
720
 
721
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/start', $pload);
 
 
 
 
 
 
722
  if ($response['response']['code'] == 201 ){
723
  set_site_transient('mailchimp-woocommerce-oauth-secret', $secret, 60*60);
724
  wp_send_json_success($response);
@@ -741,6 +816,11 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
741
  );
742
 
743
  $response = wp_remote_post($url, $pload);
 
 
 
 
 
744
 
745
  if ($response['response']['code'] == 200 && isset($response['body'])){
746
  wp_send_json_success(json_decode($response['body']));
@@ -767,6 +847,12 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
767
  );
768
 
769
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/finish', $pload);
 
 
 
 
 
 
770
  if ($response['response']['code'] == 200 ){
771
  delete_site_transient('mailchimp-woocommerce-oauth-secret');
772
  // save api_key? If yes, we can skip api key validation for validatePostApiKey();
@@ -780,19 +866,23 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
780
  public function mailchimp_woocommerce_ajax_create_account_check_username () {
781
  $user = $_POST['username'];
782
  $response = wp_remote_get( 'https://woocommerce.mailchimpapp.com/api/usernames/available/' . $_POST['username']);
 
 
 
 
783
  $response_body = json_decode($response['body']);
784
  if ($response['response']['code'] == 200 && $response_body->success == true ){
785
  wp_send_json_success($response);
786
- }
787
-
788
- else if ($response['response']['code'] == 404 ){
789
  wp_send_json_error(array(
790
  'success' => false,
791
  ));
792
- }
793
-
794
- else {
795
  $suggestion = wp_remote_get( 'https://woocommerce.mailchimpapp.com/api/usernames/suggestions/' . preg_replace('/[^A-Za-z0-9\-\@\.]/', '', $_POST['username']));
 
 
 
 
796
  $suggested_username = json_decode($suggestion['body'])->data;
797
  wp_send_json_error( array(
798
  'success' => false,
@@ -821,6 +911,10 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
821
  );
822
 
823
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/support', $pload);
 
 
 
 
824
  $response_body = json_decode($response['body']);
825
  if ($response['response']['code'] == 200 && $response_body->success == true ) {
826
  wp_send_json_success($response_body);
@@ -861,6 +955,10 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
861
  'timeout' => 30,
862
  );
863
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/support', $pload);
 
 
 
 
864
  $response_body = json_decode($response['body']);
865
  return $response_body;
866
  }
@@ -885,6 +983,10 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
885
  );
886
 
887
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/signup/', $pload);
 
 
 
 
888
  $response_body = json_decode($response['body']);
889
  if ($response['response']['code'] == 200 && $response_body->success == true) {
890
  wp_send_json_success($response_body);
@@ -1539,7 +1641,7 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1539
  * @param null $data
1540
  * @return bool
1541
  */
1542
- private function syncStore($data = null)
1543
  {
1544
  if (empty($data)) {
1545
  $data = $this->getOptions();
@@ -1707,8 +1809,8 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1707
  // make sure the storeeId saved on DB is the same on Mailchimp
1708
  try {
1709
  $this->syncStore();
1710
- }
1711
- catch (\Exception $e) {
1712
  mailchimp_log('error.sync', 'Store cannot be synced :: ' . $e->getMessage());
1713
  add_settings_error('mailchimp_sync_error', '', __('Cannot create or update Store at Mailchimp.', 'mailchimp-for-woocommerce') . ' Mailchimp says: ' . $e->getMessage());
1714
  return false;
@@ -1763,7 +1865,8 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1763
  /**
1764
  * set Communications status via sync page.
1765
  */
1766
- public function mailchimp_woocommerce_communication_status() {
 
1767
  $original_opt = $this->getData('comm.opt',0);
1768
  $opt = $_POST['opt'];
1769
  $admin_email = $this->getOptions()['admin_email'];
@@ -1781,19 +1884,46 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1781
  $this->setData('comm.opt', $opt);
1782
  wp_send_json_success(__('Saved', 'mailchimp-for-woocommerce'));
1783
  }
1784
- }
1785
- else {
1786
  //if error, keep option to original value
1787
  wp_send_json_error(array('error' => __('Error setting communications status', 'mailchimp-for-woocommerce'), 'opt' => $original_opt));
1788
  }
1789
 
1790
  wp_die();
1791
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1792
 
1793
  /**
1794
  * set Communications box status.
1795
  */
1796
- public function mailchimp_set_communications_status_on_server($opt, $admin_email, $remove = false) {
 
1797
  $env = mailchimp_environment_variables();
1798
  $audience = !empty(mailchimp_get_list_id()) ? 1 : 0;
1799
  $synced = get_option('mailchimp-woocommerce-sync.completed_at') > 0 ? 1 : 0;
@@ -1806,8 +1936,8 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1806
  'audience' => $audience,
1807
  'synced' => $synced,
1808
  'plugin_version' => "MailChimp for WooCommerce/{$env->version}; PHP/{$env->php_version}; WordPress/{$env->wp_version}; Woo/{$env->wc_version};",
1809
-
1810
  );
 
1811
  if ($remove) {
1812
  $post_data['remove_email'] = true;
1813
  }
@@ -1825,27 +1955,32 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1825
  ));
1826
  }
1827
 
1828
- public function mailchimp_woocommerce_ajax_delete_log_file() {
1829
- if (isset($_POST['log_file']) && !empty($_POST['log_file'])) {
1830
- $requested_log_file = $_POST['log_file'];
1831
- }
1832
- else {
1833
- return wp_send_json_error( __('No log file provided', 'mailchimp-for-woocommerce'));
 
 
1834
  }
 
1835
  $log_handler = new WC_Log_Handler_File();
1836
  $removed = $log_handler->remove(str_replace('-log', '.log', $requested_log_file));
1837
  wp_send_json_success(array('success' => $removed));
1838
  }
1839
 
1840
- public function mailchimp_woocommerce_ajax_load_log_file() {
1841
- if (isset($_POST['log_file']) && !empty($_POST['log_file'])) {
1842
- $requested_log_file = $_POST['log_file'];
1843
- }
1844
- else {
1845
- return wp_send_json_error( __('No log file provided', 'mailchimp-for-woocommerce'));
1846
- }
1847
-
1848
- $files = defined('WC_LOG_DIR') ? @scandir( WC_LOG_DIR ) : array();
 
 
1849
 
1850
  $logs = array();
1851
  if (!empty($files)) {
@@ -1860,70 +1995,18 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
1860
 
1861
  if (!empty($requested_log_file) && isset($logs[sanitize_title($requested_log_file)])) {
1862
  $viewed_log = $logs[sanitize_title($requested_log_file)];
1863
- } else {
1864
- return wp_send_json_error( __('Error loading log file contents', 'mailchimp-for-woocommerce'));
1865
  }
1866
 
1867
- return wp_send_json_success( esc_html( file_get_contents( WC_LOG_DIR . $viewed_log ) ) );
1868
-
1869
  }
1870
 
1871
- public function save()
1872
  {
1873
- if (MC_Flag::isOn(MC_FlagNames::FIX_ECOMMERCE_CUSTOMER_STATS)) {
1874
- $existing_order_record = null;
1875
- $is_existing_order = $this->existsInDatabase();
1876
- $no_customer_for_existing_order = false;
1877
- if ($is_existing_order) {
1878
- $existing_order_record = MC::userDB()->queryOne('from Ecommerce_Order where store_id = ? and order_id = ? limit 1', [$this->store_id, $this->order_id]);
1879
- $no_customer_for_existing_order = $existing_order_record ? $existing_order_record->getCustomer() === null : true;
1880
- }
1881
- $result = parent::save();
1882
- $customer = $this->getCustomer();
1883
- if ($customer !== null) {
1884
- // Did we just save a new line item record?
1885
- if (!$is_existing_order) {
1886
- // Is this line item a completely new order or some addition to an existing order?
1887
- $has_another_line_item = (bool)MC::userDB()->querySqlOne('select 1 from ecommerce_orders where store_id = ? and order_foreign_id = ? and order_id != ? and is_deleted = ? limit 1', [$this->store_id, $this->order_foreign_id, $this->order_id, 'N']);
1888
- if (!$has_another_line_item) {
1889
- $customer->incrementOrdersCount();
1890
- $customer->addOrderToTotalSpent($this);
1891
- }
1892
- // Did we just make an update to an existing line item?
1893
- } elseif ($existing_order_record) {
1894
- $is_order_total_mismatched_with_other_line_items = (bool)MC::userDB()->querySqlOne('select 1 from ecommerce_orders where store_id = ? and order_foreign_id = ? and order_total != ? and is_deleted = ? limit 1', [$this->store_id, $this->order_foreign_id, $this->order_total, 'N']);
1895
- // Only update if all the line items say the same order_total
1896
- if (!$is_order_total_mismatched_with_other_line_items) {
1897
- $customer->total_spent = $customer->total_spent - $existing_order_record->order_total + $this->order_total;
1898
- }
1899
- if ($no_customer_for_existing_order) {
1900
- $customer->incrementOrdersCount();
1901
- }
1902
- }
1903
- $customer->save();
1904
- $this->customer = $customer;
1905
- }
1906
- return $result;
1907
  }
1908
- // Non-flagged behavior
1909
- return parent::save();
1910
  }
1911
-
1912
- public function onDelete()
1913
- {
1914
- parent::onDelete();
1915
- if (MC_Flag::isOn(MC_FlagNames::FIX_ECOMMERCE_CUSTOMER_STATS)) {
1916
- $has_another_line_item = MC::userDB()->querySqlOne('select 1 from ecommerce_orders where store_id = ? and order_foreign_id != ? and is_deleted = ? limit 1', [$this->store_id, $this->order_foreign_id, 'N']);
1917
- if (!$has_another_line_item) {
1918
- $customer = $this->getCustomer();
1919
- if ($customer !== null) {
1920
- $customer->total_spent -= $this->order_total;
1921
- $customer->decrementOrdersCount();
1922
- $customer->save();
1923
- $this->customer = $customer;
1924
- }
1925
- }
1926
- }
1927
- }
1928
-
1929
- }
9
  * @package MailChimp_WooCommerce
10
  * @subpackage MailChimp_WooCommerce/admin
11
  */
12
+ use \Automattic\WooCommerce\Admin\Features\Navigation\Menu;
13
  /**
14
  * The admin-specific functionality of the plugin.
15
  *
129
  if ($label == '') $label = __('Subscribe to our newsletter', 'mailchimp-for-woocommerce');
130
  $options = get_option($this->plugin_name, array());
131
  $checkbox_default_settings = (array_key_exists('mailchimp_checkbox_defaults', $options) && !is_null($options['mailchimp_checkbox_defaults'])) ? $options['mailchimp_checkbox_defaults'] : 'check';
132
+ wp_register_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/mailchimp-woocommerce-admin.js', array( 'jquery', 'swal' ), $this->version, false );
133
  wp_localize_script(
134
  $this->plugin_name,
135
  'phpVars',
168
  * @since 1.0.0
169
  */
170
  public function add_plugin_admin_menu() {
171
+
172
  // Add woocommerce menu subitem
173
  add_submenu_page(
174
  'woocommerce',
178
  $this->plugin_name,
179
  array($this, 'display_plugin_setup_page')
180
  );
181
+
182
+ // Add the WooCommerce navigation items if the feauture exists.
183
+ if ( ! class_exists( '\Automattic\WooCommerce\Admin\Features\Navigation\Menu' ) ) {
184
+ return;
185
+ }
186
+
187
+ Menu::add_plugin_item(
188
+ array(
189
+ 'id' => 'mailchimp-for-woocommerce',
190
+ 'title' => __( 'Mailchimp', 'mailchimp-for-woocommerce' ),
191
+ 'capability' => mailchimp_get_allowed_capability(),
192
+ 'url' => $this->plugin_name,
193
+ )
194
+ );
195
  }
196
 
197
  /**
261
  include_once( 'partials/mailchimp-woocommerce-admin-tabs.php' );
262
  }
263
 
264
+ public function display_user_profile_info( $user ) {
265
+ $gdpr_fields = mailchimp_render_gdpr_fields() ?
266
+ MailChimp_WooCommerce_Public::gdpr_fields($user) :
267
+ array();
268
+ $this->syncUserStatus($user);
269
+ include_once( 'user-profile/mailchimp-user-profile.php' );
270
+ }
271
+
272
+ /**
273
+ * @param \WP_User $user
274
+ * @return bool
275
+ */
276
+ protected function syncUserStatus($user)
277
+ {
278
+ try {
279
+ if (empty($user) || !is_email($user->user_email) || !mailchimp_is_configured()) {
280
+ return false;
281
+ }
282
+ if (($status = mailchimp_get_api()->getCachedSubscriberStatusForAdminProfileView(mailchimp_get_list_id(), $user->user_email))) {
283
+ $subscribed = is_string($status) && in_array($status, array('subscribed', 'pending')) ? '1' : '0';
284
+ $saved = (bool) get_user_meta($user->ID, 'mailchimp_woocommerce_is_subscribed', true);
285
+ if ((bool) $subscribed !== $saved) {
286
+ update_user_meta($user->ID, 'mailchimp_woocommerce_is_subscribed', $subscribed);
287
+ }
288
+ }
289
+ } catch (\Exception $e) {
290
+ return false;
291
+ }
292
+ }
293
+
294
  /**
295
  *
296
  */
304
  $this->handle_abandoned_cart_table();
305
  $this->update_db_check();
306
 
307
+ // if we don't have the server address set, let's save it to be used with curl requests
308
+ if (!mailchimp_get_data('SERVER_ADDR')) {
309
+ if (isset($_SERVER) && isset($_SERVER['SERVER_ADDR']) && !empty($_SERVER['SERVER_ADDR'])) {
310
+ mailchimp_set_data('SERVER_ADDR', $_SERVER['SERVER_ADDR']);
311
+ }
312
+ }
313
+
314
  /// this is where we need to cache this data for a longer period of time and only during admin page views.
315
  /// https://wordpress.org/support/topic/the-plugin-slows-down-the-website-because-of-slow-api/#post-14339311
316
  if (mailchimp_is_configured() && ($list_id = mailchimp_get_list_id())) {
378
  }
379
  }
380
 
381
+ /**
382
+ * Displays notice when plugin is installed but not yet configured / connected to Mailchimp.
383
+ */
384
+ public function webook_initial_notice() {
385
+ if( mailchimp_is_configured() && !mailchimp_get_webhook_url() ){
386
+ $class = 'notice notice-warning';
387
+ $message = sprintf(
388
+ /* translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag */
389
+ esc_html__(
390
+ '%1$sMailchimp for Woocommerce%2$s has not added the webhook to Mailchimp, %3$svisit the plugin settings page and synchronize your store%4$s.',
391
+ 'mailchimp-for-woocommerce'
392
+ ),
393
+ '<strong>',
394
+ '</strong>',
395
+ '<a href="' . admin_url( 'admin.php?page=') . $this->plugin_name . '">',
396
+ '</a>'
397
+ );
398
+ printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message );
399
+ }
400
+ }
401
+
402
  /**
403
  * Depending on the version we're on we may need to run some sort of migrations.
404
  */
665
 
666
  case 'newsletter_settings':
667
  $data = $this->validatePostNewsletterSettings($input);
668
+ $this->defineWebHooks();
669
  break;
670
 
671
  case 'sync':
672
  //case sync
673
  if ($this->is_resyncing()) {
 
674
  // remove all the pointers to be sure
675
  $service = new MailChimp_Service();
676
  $service->removePointers(true, true);
698
 
699
  break;
700
  case 'plugin_settings':
 
701
  // case disconnect
702
  if ($this->is_disconnecting()) {
703
  // Disconnect store!
707
  'mailchimp_api_key' => null,
708
  'mailchimp_list' => null,
709
  );
710
+ }
711
+ $data['active_tab'] = 'plugin_settings';
712
+ add_settings_error('mailchimp_store_settings', '', __('Store Disconnect Failed', 'mailchimp-for-woocommerce'), 'warning');
 
 
713
  }
714
  break;
715
  }
788
  );
789
 
790
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/start', $pload);
791
+
792
+ // need to return the error message if this is the problem.
793
+ if ($response instanceof WP_Error) {
794
+ wp_send_json_error( $response );
795
+ }
796
+
797
  if ($response['response']['code'] == 201 ){
798
  set_site_transient('mailchimp-woocommerce-oauth-secret', $secret, 60*60);
799
  wp_send_json_success($response);
816
  );
817
 
818
  $response = wp_remote_post($url, $pload);
819
+
820
+ // need to return the error message if this is the problem.
821
+ if ($response instanceof WP_Error) {
822
+ wp_send_json_error( $response );
823
+ }
824
 
825
  if ($response['response']['code'] == 200 && isset($response['body'])){
826
  wp_send_json_success(json_decode($response['body']));
847
  );
848
 
849
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/finish', $pload);
850
+
851
+ // need to return the error message if this is the problem.
852
+ if ($response instanceof WP_Error) {
853
+ wp_send_json_error( $response );
854
+ }
855
+
856
  if ($response['response']['code'] == 200 ){
857
  delete_site_transient('mailchimp-woocommerce-oauth-secret');
858
  // save api_key? If yes, we can skip api key validation for validatePostApiKey();
866
  public function mailchimp_woocommerce_ajax_create_account_check_username () {
867
  $user = $_POST['username'];
868
  $response = wp_remote_get( 'https://woocommerce.mailchimpapp.com/api/usernames/available/' . $_POST['username']);
869
+ // need to return the error message if this is the problem.
870
+ if ($response instanceof WP_Error) {
871
+ wp_send_json_error( $response );
872
+ }
873
  $response_body = json_decode($response['body']);
874
  if ($response['response']['code'] == 200 && $response_body->success == true ){
875
  wp_send_json_success($response);
876
+ } else if ($response['response']['code'] == 404 ){
 
 
877
  wp_send_json_error(array(
878
  'success' => false,
879
  ));
880
+ } else {
 
 
881
  $suggestion = wp_remote_get( 'https://woocommerce.mailchimpapp.com/api/usernames/suggestions/' . preg_replace('/[^A-Za-z0-9\-\@\.]/', '', $_POST['username']));
882
+ // need to return the error message if this is the problem.
883
+ if ($suggestion instanceof WP_Error) {
884
+ wp_send_json_error( $suggestion );
885
+ }
886
  $suggested_username = json_decode($suggestion['body'])->data;
887
  wp_send_json_error( array(
888
  'success' => false,
911
  );
912
 
913
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/support', $pload);
914
+ // need to return the error message if this is the problem.
915
+ if ($response instanceof WP_Error) {
916
+ wp_send_json_error( $response );
917
+ }
918
  $response_body = json_decode($response['body']);
919
  if ($response['response']['code'] == 200 && $response_body->success == true ) {
920
  wp_send_json_success($response_body);
955
  'timeout' => 30,
956
  );
957
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/support', $pload);
958
+ // need to return the error message if this is the problem.
959
+ if ($response instanceof WP_Error) {
960
+ wp_send_json_error( $response );
961
+ }
962
  $response_body = json_decode($response['body']);
963
  return $response_body;
964
  }
983
  );
984
 
985
  $response = wp_remote_post( 'https://woocommerce.mailchimpapp.com/api/signup/', $pload);
986
+ // need to return the error message if this is the problem.
987
+ if ($response instanceof WP_Error) {
988
+ wp_send_json_error( $response );
989
+ }
990
  $response_body = json_decode($response['body']);
991
  if ($response['response']['code'] == 200 && $response_body->success == true) {
992
  wp_send_json_success($response_body);
1641
  * @param null $data
1642
  * @return bool
1643
  */
1644
+ public function syncStore($data = null)
1645
  {
1646
  if (empty($data)) {
1647
  $data = $this->getOptions();
1809
  // make sure the storeeId saved on DB is the same on Mailchimp
1810
  try {
1811
  $this->syncStore();
1812
+ $this->defineWebHooks();
1813
+ } catch (\Exception $e) {
1814
  mailchimp_log('error.sync', 'Store cannot be synced :: ' . $e->getMessage());
1815
  add_settings_error('mailchimp_sync_error', '', __('Cannot create or update Store at Mailchimp.', 'mailchimp-for-woocommerce') . ' Mailchimp says: ' . $e->getMessage());
1816
  return false;
1865
  /**
1866
  * set Communications status via sync page.
1867
  */
1868
+ public function mailchimp_woocommerce_communication_status()
1869
+ {
1870
  $original_opt = $this->getData('comm.opt',0);
1871
  $opt = $_POST['opt'];
1872
  $admin_email = $this->getOptions()['admin_email'];
1884
  $this->setData('comm.opt', $opt);
1885
  wp_send_json_success(__('Saved', 'mailchimp-for-woocommerce'));
1886
  }
1887
+ } else {
 
1888
  //if error, keep option to original value
1889
  wp_send_json_error(array('error' => __('Error setting communications status', 'mailchimp-for-woocommerce'), 'opt' => $original_opt));
1890
  }
1891
 
1892
  wp_die();
1893
  }
1894
+
1895
+ /**
1896
+ * set Communications status via sync page.
1897
+ */
1898
+ public function mailchimp_woocommerce_tower_status()
1899
+ {
1900
+ $original_opt = $this->getData('tower.opt',0);
1901
+ $opt = $_POST['opt'];
1902
+
1903
+ mailchimp_debug('tower_status', "setting to {$opt}");
1904
+
1905
+ // try to set the info on the server
1906
+ // post to communications api
1907
+ $job = new MailChimp_WooCommerce_Tower(mailchimp_get_store_id());
1908
+ $response_body = $job->toggle($opt);
1909
+
1910
+ // if success, set internal option to check for opt and display on sync page
1911
+ if ($response_body && $response_body->success == true) {
1912
+ $this->setData('tower.opt', $opt);
1913
+ wp_send_json_success(__('Saved', 'mailchimp-for-woocommerce'));
1914
+ } else {
1915
+ //if error, keep option to original value
1916
+ wp_send_json_error(array('error' => __('Error setting tower support status', 'mailchimp-for-woocommerce'), 'opt' => $original_opt));
1917
+ }
1918
+
1919
+ wp_die();
1920
+ }
1921
 
1922
  /**
1923
  * set Communications box status.
1924
  */
1925
+ public function mailchimp_set_communications_status_on_server($opt, $admin_email, $remove = false)
1926
+ {
1927
  $env = mailchimp_environment_variables();
1928
  $audience = !empty(mailchimp_get_list_id()) ? 1 : 0;
1929
  $synced = get_option('mailchimp-woocommerce-sync.completed_at') > 0 ? 1 : 0;
1936
  'audience' => $audience,
1937
  'synced' => $synced,
1938
  'plugin_version' => "MailChimp for WooCommerce/{$env->version}; PHP/{$env->php_version}; WordPress/{$env->wp_version}; Woo/{$env->wc_version};",
 
1939
  );
1940
+
1941
  if ($remove) {
1942
  $post_data['remove_email'] = true;
1943
  }
1955
  ));
1956
  }
1957
 
1958
+ /**
1959
+ *
1960
+ */
1961
+ public function mailchimp_woocommerce_ajax_delete_log_file()
1962
+ {
1963
+ if (!isset($_POST['log_file']) || empty($_POST['log_file'])) {
1964
+ wp_send_json_error(__('No log file provided', 'mailchimp-for-woocommerce'));
1965
+ return;
1966
  }
1967
+ $requested_log_file = $_POST['log_file'];
1968
  $log_handler = new WC_Log_Handler_File();
1969
  $removed = $log_handler->remove(str_replace('-log', '.log', $requested_log_file));
1970
  wp_send_json_success(array('success' => $removed));
1971
  }
1972
 
1973
+ /**
1974
+ * @return void
1975
+ */
1976
+ public function mailchimp_woocommerce_ajax_load_log_file()
1977
+ {
1978
+ if (!isset($_POST['log_file']) || empty($_POST['log_file'])) {
1979
+ wp_send_json_error(__('No log file provided', 'mailchimp-for-woocommerce'));
1980
+ return;
1981
+ }
1982
+ $requested_log_file = $_POST['log_file'];
1983
+ $files = defined('WC_LOG_DIR') ? @scandir( WC_LOG_DIR ) : array();
1984
 
1985
  $logs = array();
1986
  if (!empty($files)) {
1995
 
1996
  if (!empty($requested_log_file) && isset($logs[sanitize_title($requested_log_file)])) {
1997
  $viewed_log = $logs[sanitize_title($requested_log_file)];
1998
+ wp_send_json_success(esc_html( file_get_contents( WC_LOG_DIR . $viewed_log )));
1999
+ return;
2000
  }
2001
 
2002
+ wp_send_json_error(__('Error loading log file contents', 'mailchimp-for-woocommerce'));
 
2003
  }
2004
 
2005
+ public function defineWebHooks()
2006
  {
2007
+ // run this every time the store is saved to be sure we've got the hooks enabled.
2008
+ if (mailchimp_is_configured()) {
2009
+ mailchimp_handle_or_queue(new MailChimp_WooCommerce_WebHooks_Sync());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2010
  }
 
 
2011
  }
2012
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/css/mailchimp-woocommerce-admin-settings.css CHANGED
@@ -512,6 +512,14 @@ a.button.create-account {
512
  color: #628735;
513
  }
514
 
 
 
 
 
 
 
 
 
515
  .sync-content-wrapper .sync-stats-wrapper {
516
  position:relative;
517
  background-color: white;
512
  color: #628735;
513
  }
514
 
515
+ .mc-tower-save {
516
+ position: absolute;
517
+ display: none;
518
+ font-size: 0.8em;
519
+ font-weight: 100 !important;
520
+ color: #628735;
521
+ }
522
+
523
  .sync-content-wrapper .sync-stats-wrapper {
524
  position:relative;
525
  background-color: white;
admin/js/mailchimp-woocommerce-admin.js CHANGED
@@ -369,6 +369,34 @@
369
  });
370
  });
371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  $('#comm_box_switch').change(function (e){
373
  var switch_button = this;
374
  var opt = this.checked ? 1 : 0;
369
  });
370
  });
371
 
372
+ $('#tower_box_switch').change(function (e){
373
+ var switch_button = this;
374
+ var opt = this.checked ? 1 : 0;
375
+
376
+ var data = {
377
+ action: 'mailchimp_woocommerce_tower_status',
378
+ opt: opt
379
+ }
380
+
381
+ $('.tower_box_status').hide();
382
+ $('#tower_box_status_' + opt).show();
383
+
384
+ $.post(ajaxurl, data, function(response) {
385
+ if (response.success) {
386
+ $('#mc-tower-save').html(response.data);
387
+ $('#mc-tower-save').css('color', '#628735').show().fadeOut(3000);
388
+ switch_button.checked = opt;
389
+ }
390
+ else {
391
+ $('#mc-tower-save').html(response.data.error);
392
+ $('#mc-tower-save').css('color', 'red').show().fadeOut(3000);
393
+ switch_button.checked = 1 - opt;
394
+ $('.tower_box_status').hide();
395
+ $('#tower_box_status_' + (1 - opt)).show();
396
+ }
397
+ });
398
+ });
399
+
400
  $('#comm_box_switch').change(function (e){
401
  var switch_button = this;
402
  var opt = this.checked ? 1 : 0;
admin/partials/tabs/plugin_settings.php CHANGED
@@ -4,14 +4,41 @@
4
  $store_id = mailchimp_get_store_id();
5
 
6
  $opt = get_option('mailchimp-woocommerce-comm.opt');
 
7
  $admin_email = mailchimp_get_option('admin_email', get_option('admin_email'));
8
  $comm_enabled = $opt != null ? $opt : '0';
 
9
  ?>
10
  <fieldset>
11
  <legend class="screen-reader-text">
12
  <span><?php esc_html_e('Plugin Settings', 'mailchimp-for-woocommerce');?></span>
13
  </legend>
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  <div class="box ">
16
  <label for="<?php echo $this->plugin_name; ?>-newsletter-checkbox-label">
17
  <h4><?php esc_html_e('Communication', 'mailchimp-for-woocommerce'); ?></h4>
4
  $store_id = mailchimp_get_store_id();
5
 
6
  $opt = get_option('mailchimp-woocommerce-comm.opt');
7
+ $tower_opt = get_option('mailchimp-woocommerce-tower.opt');
8
  $admin_email = mailchimp_get_option('admin_email', get_option('admin_email'));
9
  $comm_enabled = $opt != null ? $opt : '0';
10
+ $tower_enabled = $tower_opt != null ? $tower_opt : '0';
11
  ?>
12
  <fieldset>
13
  <legend class="screen-reader-text">
14
  <span><?php esc_html_e('Plugin Settings', 'mailchimp-for-woocommerce');?></span>
15
  </legend>
16
 
17
+ <div class="box ">
18
+ <label for="<?php echo $this->plugin_name; ?>-tower-support-checkbox-label">
19
+ <h4><?php esc_html_e('Remote Diagnostics', 'mailchimp-for-woocommerce'); ?></h4>
20
+ <p>
21
+ <?php
22
+ echo sprintf(
23
+ /* translators: Placeholders %1$s - admin email address */
24
+ __('Remote diagnostics for the Mailchimp for WooCommerce plugin allows our development team to troubleshoot syncing issues.', 'mailchimp-for-woocommerce'),
25
+ $admin_email
26
+ );?>
27
+ </p>
28
+ </label>
29
+ <br/>
30
+ <fieldset>
31
+ <p id="mc-comm-wrapper">
32
+ <label class="el-switch el-checkbox-green">
33
+ <input id="tower_box_switch" type="checkbox" name="switch" <?php if($tower_enabled === '1') echo ' checked="checked" '; ?> value="1">
34
+ <span><?= __('Enable support', 'mailchimp-for-woocommerce'); ?></span>
35
+ <br/>
36
+ <span class="mc-tower-save" id="mc-tower-save">Saved</span>
37
+ </label>
38
+ </p>
39
+ </fieldset>
40
+ </div>
41
+
42
  <div class="box ">
43
  <label for="<?php echo $this->plugin_name; ?>-newsletter-checkbox-label">
44
  <h4><?php esc_html_e('Communication', 'mailchimp-for-woocommerce'); ?></h4>
admin/user-profile/mailchimp-user-profile.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $mailchimp_user_is_subscribed = get_user_meta($user->ID, 'mailchimp_woocommerce_is_subscribed', true); ?>
2
+
3
+ <h2>Mailchimp</h2>
4
+ <table class="form-table">
5
+ <tr>
6
+ <th><label for="mailchimp_woocommerce_is_subscribed"><?php esc_html_e('User Subscribed', 'mailchimp-for-woocommerce')?></label></th>
7
+ <td>
8
+ <input type="checkbox"
9
+ name="mailchimp_woocommerce_is_subscribed_checkbox"
10
+ id="mailchimp_woocommerce_is_subscribed"
11
+ <?php echo !empty($mailchimp_user_is_subscribed) ? esc_attr('checked') : ''; ?>>
12
+ </td>
13
+ </tr>
14
+ </table>
15
+ <?php if (isset($gdpr_fields) && !empty($gdpr_fields)): ?>
16
+ <?php echo $gdpr_fields ?>
17
+ <?php endif; ?>
blocks/assets/js/checkout-newsletter-subscription-block/block.js CHANGED
@@ -3,9 +3,18 @@
3
  */
4
  import { useEffect, useState } from '@wordpress/element';
5
  import { CheckboxControl } from '@woocommerce/blocks-checkout';
 
6
 
7
- const Block = ( { cart, extensions, text, checkoutExtensionData } ) => {
 
 
 
 
 
 
 
8
  const [ checked, setChecked ] = useState( false );
 
9
  const { setExtensionData } = checkoutExtensionData;
10
 
11
  useEffect( () => {
@@ -21,6 +30,19 @@ const Block = ( { cart, extensions, text, checkoutExtensionData } ) => {
21
  >
22
  <span dangerouslySetInnerHTML={ {__html: text} }/>
23
  </CheckboxControl>
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  </>
25
  );
26
  };
3
  */
4
  import { useEffect, useState } from '@wordpress/element';
5
  import { CheckboxControl } from '@woocommerce/blocks-checkout';
6
+ import {__} from "@wordpress/i18n";
7
 
8
+ const Block = ( { cart, extensions, text, gdprHeadline, gdpr, checkoutExtensionData } ) => {
9
+
10
+ let defaultGDPR = {};
11
+ if (gdpr && gdpr.length) {
12
+ gdpr.forEach((item) => {
13
+ defaultGDPR[item.marketing_permission_id] = false;
14
+ });
15
+ }
16
  const [ checked, setChecked ] = useState( false );
17
+ const [ gdprFields ] = useState({});
18
  const { setExtensionData } = checkoutExtensionData;
19
 
20
  useEffect( () => {
30
  >
31
  <span dangerouslySetInnerHTML={ {__html: text} }/>
32
  </CheckboxControl>
33
+ {gdpr && gdpr.length ? __(gdprHeadline, 'mailchimp-for-woocommerce') : ''}
34
+ {gdpr && gdpr.length ? gdpr.map((gdprItem) => {
35
+ return (<CheckboxControl
36
+ id={'gdpr_'+gdprItem.marketing_permission_id}
37
+ checked={ gdprFields[gdprItem.marketing_permission_id] }
38
+ onChange={ (e) => {
39
+ gdprFields[gdprItem.marketing_permission_id] = !gdprFields[gdprItem.marketing_permission_id];
40
+ setExtensionData( 'mailchimp-newsletter', 'gdprFields', gdprFields);
41
+ }}
42
+ >
43
+ <span dangerouslySetInnerHTML={ {__html: gdprItem.text} }/>
44
+ </CheckboxControl>);
45
+ }) : ''}
46
  </>
47
  );
48
  };
blocks/assets/js/checkout-newsletter-subscription-block/edit.js CHANGED
@@ -19,11 +19,6 @@ export const Edit = ( { attributes, setAttributes } ) => {
19
  const { text, gdprHeadline, gdpr } = attributes;
20
  const blockProps = useBlockProps();
21
 
22
- console.log('edit', {
23
- text: text,
24
- gdprHeadline: gdprHeadline,
25
- gdpr: gdpr,
26
- });
27
 
28
  return (
29
  <div { ...blockProps }>
@@ -81,4 +76,4 @@ export const Edit = ( { attributes, setAttributes } ) => {
81
  // not sure
82
  export const Save = () => {
83
  return <div { ...useBlockProps.save() } />;
84
- };
19
  const { text, gdprHeadline, gdpr } = attributes;
20
  const blockProps = useBlockProps();
21
 
 
 
 
 
 
22
 
23
  return (
24
  <div { ...blockProps }>
76
  // not sure
77
  export const Save = () => {
78
  return <div { ...useBlockProps.save() } />;
79
+ };
blocks/assets/js/checkout-newsletter-subscription-block/gdpr.js CHANGED
@@ -1,11 +1,6 @@
1
  import {Header} from "@wordpress/components/build/box-control/styles/box-control-styles";
2
  import {__} from "@wordpress/i18n";
3
 
4
- console.log('gdpr.js', {
5
- headline: gdprHeadline,
6
- fields: gdpr,
7
- });
8
-
9
  {gdpr.length &&
10
  <div>
11
  <Header>
1
  import {Header} from "@wordpress/components/build/box-control/styles/box-control-styles";
2
  import {__} from "@wordpress/i18n";
3
 
 
 
 
 
 
4
  {gdpr.length &&
5
  <div>
6
  <Header>
blocks/assets/js/checkout-newsletter-subscription-block/index.js CHANGED
@@ -11,10 +11,6 @@ import { Edit, Save } from './edit';
11
  import metadata from './block.json';
12
  import attributes from './attributes';
13
 
14
- console.log('index.js', {
15
- metadata: metadata,
16
- attributes: attributes,
17
- });
18
 
19
  registerBlockType( metadata, {
20
  icon: {
@@ -51,4 +47,4 @@ registerBlockType( metadata, {
51
  ...metadata.attributes,
52
  ...attributes,
53
  },
54
- } );
11
  import metadata from './block.json';
12
  import attributes from './attributes';
13
 
 
 
 
 
14
 
15
  registerBlockType( metadata, {
16
  icon: {
47
  ...metadata.attributes,
48
  ...attributes,
49
  },
50
+ } );
blocks/build/newsletter-block-frontend.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wc-blocks-checkout', 'wc-blocks-shared-hocs', 'wc-settings', 'wp-element', 'wp-polyfill'), 'version' => '61a7dedef24e6fd0ce09ed832aac89fa');
1
+ <?php return array('dependencies' => array('wc-blocks-checkout', 'wc-blocks-shared-hocs', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '998971e6ec3abdc4c40883b0f4edce57');
blocks/build/newsletter-block-frontend.js CHANGED
@@ -1,267 +1 @@
1
- /******/ (function(modules) { // webpackBootstrap
2
- /******/ // The module cache
3
- /******/ var installedModules = {};
4
- /******/
5
- /******/ // The require function
6
- /******/ function __webpack_require__(moduleId) {
7
- /******/
8
- /******/ // Check if module is in cache
9
- /******/ if(installedModules[moduleId]) {
10
- /******/ return installedModules[moduleId].exports;
11
- /******/ }
12
- /******/ // Create a new module (and put it into the cache)
13
- /******/ var module = installedModules[moduleId] = {
14
- /******/ i: moduleId,
15
- /******/ l: false,
16
- /******/ exports: {}
17
- /******/ };
18
- /******/
19
- /******/ // Execute the module function
20
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21
- /******/
22
- /******/ // Flag the module as loaded
23
- /******/ module.l = true;
24
- /******/
25
- /******/ // Return the exports of the module
26
- /******/ return module.exports;
27
- /******/ }
28
- /******/
29
- /******/
30
- /******/ // expose the modules object (__webpack_modules__)
31
- /******/ __webpack_require__.m = modules;
32
- /******/
33
- /******/ // expose the module cache
34
- /******/ __webpack_require__.c = installedModules;
35
- /******/
36
- /******/ // define getter function for harmony exports
37
- /******/ __webpack_require__.d = function(exports, name, getter) {
38
- /******/ if(!__webpack_require__.o(exports, name)) {
39
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
40
- /******/ }
41
- /******/ };
42
- /******/
43
- /******/ // define __esModule on exports
44
- /******/ __webpack_require__.r = function(exports) {
45
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
46
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
47
- /******/ }
48
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
49
- /******/ };
50
- /******/
51
- /******/ // create a fake namespace object
52
- /******/ // mode & 1: value is a module id, require it
53
- /******/ // mode & 2: merge all properties of value into the ns
54
- /******/ // mode & 4: return value when already ns object
55
- /******/ // mode & 8|1: behave like require
56
- /******/ __webpack_require__.t = function(value, mode) {
57
- /******/ if(mode & 1) value = __webpack_require__(value);
58
- /******/ if(mode & 8) return value;
59
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
60
- /******/ var ns = Object.create(null);
61
- /******/ __webpack_require__.r(ns);
62
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
63
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
64
- /******/ return ns;
65
- /******/ };
66
- /******/
67
- /******/ // getDefaultExport function for compatibility with non-harmony modules
68
- /******/ __webpack_require__.n = function(module) {
69
- /******/ var getter = module && module.__esModule ?
70
- /******/ function getDefault() { return module['default']; } :
71
- /******/ function getModuleExports() { return module; };
72
- /******/ __webpack_require__.d(getter, 'a', getter);
73
- /******/ return getter;
74
- /******/ };
75
- /******/
76
- /******/ // Object.prototype.hasOwnProperty.call
77
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
78
- /******/
79
- /******/ // __webpack_public_path__
80
- /******/ __webpack_require__.p = "";
81
- /******/
82
- /******/
83
- /******/ // Load entry module and return exports
84
- /******/ return __webpack_require__(__webpack_require__.s = "./assets/js/checkout-newsletter-subscription-block/frontend.js");
85
- /******/ })
86
- /************************************************************************/
87
- /******/ ({
88
-
89
- /***/ "./assets/js/checkout-newsletter-subscription-block/attributes.js":
90
- /*!************************************************************************!*\
91
- !*** ./assets/js/checkout-newsletter-subscription-block/attributes.js ***!
92
- \************************************************************************/
93
- /*! exports provided: default */
94
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
95
-
96
- "use strict";
97
- __webpack_require__.r(__webpack_exports__);
98
- /* harmony import */ var _woocommerce_settings__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @woocommerce/settings */ "@woocommerce/settings");
99
- /* harmony import */ var _woocommerce_settings__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_woocommerce_settings__WEBPACK_IMPORTED_MODULE_0__);
100
- /**
101
- * External dependencies
102
- */
103
-
104
- const {
105
- optinDefaultText,
106
- gdprHeadline,
107
- gdprFields
108
- } = Object(_woocommerce_settings__WEBPACK_IMPORTED_MODULE_0__["getSetting"])('mailchimp-newsletter_data', '');
109
- /* harmony default export */ __webpack_exports__["default"] = ({
110
- text: {
111
- type: 'string',
112
- default: optinDefaultText
113
- },
114
- gdprHeadline: {
115
- type: 'string',
116
- default: gdprHeadline
117
- },
118
- gdpr: {
119
- type: 'array',
120
- default: gdprFields
121
- }
122
- });
123
-
124
- /***/ }),
125
-
126
- /***/ "./assets/js/checkout-newsletter-subscription-block/block.js":
127
- /*!*******************************************************************!*\
128
- !*** ./assets/js/checkout-newsletter-subscription-block/block.js ***!
129
- \*******************************************************************/
130
- /*! exports provided: default */
131
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
132
-
133
- "use strict";
134
- __webpack_require__.r(__webpack_exports__);
135
- /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
136
- /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);
137
- /* harmony import */ var _woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @woocommerce/blocks-checkout */ "@woocommerce/blocks-checkout");
138
- /* harmony import */ var _woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_1__);
139
-
140
-
141
- /**
142
- * External dependencies
143
- */
144
-
145
-
146
-
147
- const Block = ({
148
- cart,
149
- extensions,
150
- text,
151
- checkoutExtensionData
152
- }) => {
153
- const [checked, setChecked] = Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["useState"])(false);
154
- const {
155
- setExtensionData
156
- } = checkoutExtensionData;
157
- Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["useEffect"])(() => {
158
- setExtensionData('mailchimp-newsletter', 'optin', checked);
159
- }, [checked, setExtensionData]);
160
- return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["Fragment"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_1__["CheckboxControl"], {
161
- id: "subscribe-to-newsletter",
162
- checked: checked,
163
- onChange: setChecked
164
- }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("span", {
165
- dangerouslySetInnerHTML: {
166
- __html: text
167
- }
168
- })));
169
- };
170
-
171
- /* harmony default export */ __webpack_exports__["default"] = (Block);
172
-
173
- /***/ }),
174
-
175
- /***/ "./assets/js/checkout-newsletter-subscription-block/block.json":
176
- /*!*********************************************************************!*\
177
- !*** ./assets/js/checkout-newsletter-subscription-block/block.json ***!
178
- \*********************************************************************/
179
- /*! exports provided: apiVersion, name, version, title, category, description, supports, parent, attributes, textdomain, editorStyle, default */
180
- /***/ (function(module) {
181
-
182
- module.exports = JSON.parse("{\"apiVersion\":2,\"name\":\"woocommerce/mailchimp-newsletter-subscription\",\"version\":\"1.0.0\",\"title\":\"Mailchimp Newsletter!\",\"category\":\"woocommerce\",\"description\":\"Adds a newsletter subscription checkbox to the checkout.\",\"supports\":{\"html\":true,\"align\":false,\"multiple\":false,\"reusable\":false},\"parent\":[\"woocommerce/checkout-contact-information-block\"],\"attributes\":{\"lock\":{\"type\":\"object\",\"default\":{\"remove\":true,\"move\":true}}},\"textdomain\":\"mailchimp-woocommerce\",\"editorStyle\":\"file:../../../build/style-newsletter-block.css\"}");
183
-
184
- /***/ }),
185
-
186
- /***/ "./assets/js/checkout-newsletter-subscription-block/frontend.js":
187
- /*!**********************************************************************!*\
188
- !*** ./assets/js/checkout-newsletter-subscription-block/frontend.js ***!
189
- \**********************************************************************/
190
- /*! no exports provided */
191
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
192
-
193
- "use strict";
194
- __webpack_require__.r(__webpack_exports__);
195
- /* harmony import */ var _woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @woocommerce/blocks-checkout */ "@woocommerce/blocks-checkout");
196
- /* harmony import */ var _woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_0__);
197
- /* harmony import */ var _woocommerce_shared_hocs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @woocommerce/shared-hocs */ "@woocommerce/shared-hocs");
198
- /* harmony import */ var _woocommerce_shared_hocs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_woocommerce_shared_hocs__WEBPACK_IMPORTED_MODULE_1__);
199
- /* harmony import */ var _block__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./block */ "./assets/js/checkout-newsletter-subscription-block/block.js");
200
- /* harmony import */ var _attributes__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./attributes */ "./assets/js/checkout-newsletter-subscription-block/attributes.js");
201
- /* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./assets/js/checkout-newsletter-subscription-block/block.json");
202
- var _block_json__WEBPACK_IMPORTED_MODULE_4___namespace = /*#__PURE__*/__webpack_require__.t(/*! ./block.json */ "./assets/js/checkout-newsletter-subscription-block/block.json", 1);
203
- /**
204
- * External dependencies
205
- */
206
-
207
-
208
- /**
209
- * Internal dependencies
210
- */
211
-
212
-
213
-
214
-
215
- Object(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_0__["registerCheckoutBlock"])({
216
- metadata: _block_json__WEBPACK_IMPORTED_MODULE_4__,
217
- component: Object(_woocommerce_shared_hocs__WEBPACK_IMPORTED_MODULE_1__["withFilteredAttributes"])(_attributes__WEBPACK_IMPORTED_MODULE_3__["default"])(_block__WEBPACK_IMPORTED_MODULE_2__["default"])
218
- });
219
-
220
- /***/ }),
221
-
222
- /***/ "@woocommerce/blocks-checkout":
223
- /*!****************************************!*\
224
- !*** external ["wc","blocksCheckout"] ***!
225
- \****************************************/
226
- /*! no static exports found */
227
- /***/ (function(module, exports) {
228
-
229
- (function() { module.exports = window["wc"]["blocksCheckout"]; }());
230
-
231
- /***/ }),
232
-
233
- /***/ "@woocommerce/settings":
234
- /*!************************************!*\
235
- !*** external ["wc","wcSettings"] ***!
236
- \************************************/
237
- /*! no static exports found */
238
- /***/ (function(module, exports) {
239
-
240
- (function() { module.exports = window["wc"]["wcSettings"]; }());
241
-
242
- /***/ }),
243
-
244
- /***/ "@woocommerce/shared-hocs":
245
- /*!********************************************!*\
246
- !*** external ["wc","wcBlocksSharedHocs"] ***!
247
- \********************************************/
248
- /*! no static exports found */
249
- /***/ (function(module, exports) {
250
-
251
- (function() { module.exports = window["wc"]["wcBlocksSharedHocs"]; }());
252
-
253
- /***/ }),
254
-
255
- /***/ "@wordpress/element":
256
- /*!*********************************!*\
257
- !*** external ["wp","element"] ***!
258
- \*********************************/
259
- /*! no static exports found */
260
- /***/ (function(module, exports) {
261
-
262
- (function() { module.exports = window["wp"]["element"]; }());
263
-
264
- /***/ })
265
-
266
- /******/ });
267
- //# sourceMappingURL=newsletter-block-frontend.js.map
1
+ !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=12)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wc.blocksCheckout},function(e,t){e.exports=window.wp.i18n},function(e){e.exports=JSON.parse('{"apiVersion":2,"name":"woocommerce/mailchimp-newsletter-subscription","version":"1.0.0","title":"Mailchimp Newsletter!","category":"woocommerce","description":"Adds a newsletter subscription checkbox to the checkout.","supports":{"html":true,"align":false,"multiple":false,"reusable":false},"parent":["woocommerce/checkout-contact-information-block"],"attributes":{"lock":{"type":"object","default":{"remove":true,"move":true}}},"textdomain":"mailchimp-woocommerce","editorStyle":"file:../../../build/style-newsletter-block.css"}')},,function(e,t,n){"use strict";var r=n(6);const{optinDefaultText:o,gdprHeadline:i,gdprFields:c}=Object(r.getSetting)("mailchimp-newsletter_data","");t.a={text:{type:"string",default:o},gdprHeadline:{type:"string",default:i},gdpr:{type:"array",default:c}}},function(e,t){e.exports=window.wc.wcSettings},,,function(e,t){e.exports=window.wc.wcBlocksSharedHocs},,,function(e,t,n){"use strict";n.r(t);var r=n(1),o=n(9),i=n(0),c=n(2),a=n(5),l=n(3);Object(r.registerCheckoutBlock)({metadata:l,component:Object(o.withFilteredAttributes)(a.a)(({cart:e,extensions:t,text:n,gdprHeadline:o,gdpr:a,checkoutExtensionData:l})=>{let s={};a&&a.length&&a.forEach(e=>{s[e.marketing_permission_id]=!1});const[u,p]=Object(i.useState)(!1),[d]=Object(i.useState)({}),{setExtensionData:m}=l;return Object(i.useEffect)(()=>{m("mailchimp-newsletter","optin",u)},[u,m]),Object(i.createElement)(i.Fragment,null,Object(i.createElement)(r.CheckboxControl,{id:"subscribe-to-newsletter",checked:u,onChange:p},Object(i.createElement)("span",{dangerouslySetInnerHTML:{__html:n}})),a&&a.length?Object(c.__)(o,"mailchimp-for-woocommerce"):"",a&&a.length?a.map(e=>Object(i.createElement)(r.CheckboxControl,{id:"gdpr_"+e.marketing_permission_id,checked:d[e.marketing_permission_id],onChange:t=>{d[e.marketing_permission_id]=!d[e.marketing_permission_id],m("mailchimp-newsletter","gdprFields",d)}},Object(i.createElement)("span",{dangerouslySetInnerHTML:{__html:e.text}}))):"")})})}]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
blocks/build/newsletter-block-frontend.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./assets/js/checkout-newsletter-subscription-block/attributes.js","webpack:///./assets/js/checkout-newsletter-subscription-block/block.js","webpack:///./assets/js/checkout-newsletter-subscription-block/frontend.js","webpack:///external [\"wc\",\"blocksCheckout\"]","webpack:///external [\"wc\",\"wcSettings\"]","webpack:///external [\"wc\",\"wcBlocksSharedHocs\"]","webpack:///external [\"wp\",\"element\"]"],"names":["optinDefaultText","gdprHeadline","gdprFields","getSetting","text","type","default","gdpr","Block","cart","extensions","checkoutExtensionData","checked","setChecked","useState","setExtensionData","useEffect","__html","registerCheckoutBlock","metadata","component","withFilteredAttributes","attributes"],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;AClFA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAEA,MAAM;AACLA,kBADK;AAELC,cAFK;AAGLC;AAHK,IAIFC,wEAAU,CAAE,2BAAF,EAA+B,EAA/B,CAJd;AAMe;AACdC,MAAI,EAAE;AACLC,QAAI,EAAE,QADD;AAELC,WAAO,EAAEN;AAFJ,GADQ;AAKdC,cAAY,EAAE;AACbI,QAAI,EAAE,QADO;AAEbC,WAAO,EAAEL;AAFI,GALA;AASdM,MAAI,EAAE;AACLF,QAAI,EAAE,OADD;AAELC,WAAO,EAAEJ;AAFJ;AATQ,CAAf,E;;;;;;;;;;;;;;;;;;;ACXA;AACA;AACA;AACA;AACA;;AAEA,MAAMM,KAAK,GAAG,CAAE;AAAEC,MAAF;AAAQC,YAAR;AAAoBN,MAApB;AAA0BO;AAA1B,CAAF,KAAyD;AACtE,QAAM,CAAEC,OAAF,EAAWC,UAAX,IAA0BC,mEAAQ,CAAE,KAAF,CAAxC;AACA,QAAM;AAAEC;AAAF,MAAuBJ,qBAA7B;AAEAK,sEAAS,CAAE,MAAM;AAChBD,oBAAgB,CAAE,sBAAF,EAA0B,OAA1B,EAAmCH,OAAnC,CAAhB;AACA,GAFQ,EAEN,CAAEA,OAAF,EAAWG,gBAAX,CAFM,CAAT;AAIA,SACC,4IACC,yEAAC,4EAAD;AACC,MAAE,EAAC,yBADJ;AAEC,WAAO,EAAGH,OAFX;AAGC,YAAQ,EAAGC;AAHZ,KAKC;AAAM,2BAAuB,EAAG;AAACI,YAAM,EAAEb;AAAT;AAAhC,IALD,CADD,CADD;AAWA,CAnBD;;AAqBeI,oEAAf,E;;;;;;;;;;;;;;;;;;;;;;;AC3BA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA;AACA;AACA;AAEAU,0FAAqB,CAAE;AACtBC,oDADsB;AAEtBC,WAAS,EAAEC,uFAAsB,CAAEC,mDAAF,CAAtB,CAAsCd,8CAAtC;AAFW,CAAF,CAArB,C;;;;;;;;;;;ACZA,aAAa,iDAAiD,EAAE,I;;;;;;;;;;;ACAhE,aAAa,6CAA6C,EAAE,I;;;;;;;;;;;ACA5D,aAAa,qDAAqD,EAAE,I;;;;;;;;;;;ACApE,aAAa,0CAA0C,EAAE,I","file":"newsletter-block-frontend.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./assets/js/checkout-newsletter-subscription-block/frontend.js\");\n","/**\n * External dependencies\n */\nimport { getSetting } from '@woocommerce/settings';\n\nconst {\n\toptinDefaultText,\n\tgdprHeadline,\n\tgdprFields,\n} = getSetting( 'mailchimp-newsletter_data', '' );\n\nexport default {\n\ttext: {\n\t\ttype: 'string',\n\t\tdefault: optinDefaultText,\n\t},\n\tgdprHeadline: {\n\t\ttype: 'string',\n\t\tdefault: gdprHeadline,\n\t},\n\tgdpr: {\n\t\ttype: 'array',\n\t\tdefault: gdprFields\n\t}\n};\n","/**\n * External dependencies\n */\nimport { useEffect, useState } from '@wordpress/element';\nimport { CheckboxControl } from '@woocommerce/blocks-checkout';\n\nconst Block = ( { cart, extensions, text, checkoutExtensionData } ) => {\n\tconst [ checked, setChecked ] = useState( false );\n\tconst { setExtensionData } = checkoutExtensionData;\n\n\tuseEffect( () => {\n\t\tsetExtensionData( 'mailchimp-newsletter', 'optin', checked );\n\t}, [ checked, setExtensionData ] );\n\n\treturn (\n\t\t<>\n\t\t\t<CheckboxControl\n\t\t\t\tid=\"subscribe-to-newsletter\"\n\t\t\t\tchecked={ checked }\n\t\t\t\tonChange={ setChecked }\n\t\t\t>\n\t\t\t\t<span dangerouslySetInnerHTML={ {__html: text} }/>\n\t\t\t</CheckboxControl>\n\t\t</>\n\t);\n};\n\nexport default Block;\n","/**\n * External dependencies\n */\nimport { registerCheckoutBlock } from '@woocommerce/blocks-checkout';\nimport { withFilteredAttributes } from '@woocommerce/shared-hocs';\n/**\n * Internal dependencies\n */\nimport Block from './block';\nimport attributes from './attributes';\nimport metadata from './block.json';\n\nregisterCheckoutBlock( {\n\tmetadata,\n\tcomponent: withFilteredAttributes( attributes )( Block ),\n} );\n","(function() { module.exports = window[\"wc\"][\"blocksCheckout\"]; }());","(function() { module.exports = window[\"wc\"][\"wcSettings\"]; }());","(function() { module.exports = window[\"wc\"][\"wcBlocksSharedHocs\"]; }());","(function() { module.exports = window[\"wp\"][\"element\"]; }());"],"sourceRoot":""}
 
blocks/build/newsletter-block.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wc-blocks-checkout', 'wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'e0c2a4ce85cd127b74e23152b7a33f5f');
1
+ <?php return array('dependencies' => array('wc-blocks-checkout', 'wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '2c2cf2a5f2e005f397c70011778c7313');
blocks/build/newsletter-block.js CHANGED
@@ -1,487 +1 @@
1
- (window["webpackJsonp_woocommerce_mailchimp_newsletter"] = window["webpackJsonp_woocommerce_mailchimp_newsletter"] || []).push([["style-newsletter-block"],{
2
-
3
- /***/ "./assets/js/checkout-newsletter-subscription-block/style.scss":
4
- /*!*********************************************************************!*\
5
- !*** ./assets/js/checkout-newsletter-subscription-block/style.scss ***!
6
- \*********************************************************************/
7
- /*! no exports provided */
8
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
9
-
10
- "use strict";
11
- __webpack_require__.r(__webpack_exports__);
12
- // extracted by mini-css-extract-plugin
13
-
14
-
15
- /***/ })
16
-
17
- }]);
18
-
19
- /******/ (function(modules) { // webpackBootstrap
20
- /******/ // install a JSONP callback for chunk loading
21
- /******/ function webpackJsonpCallback(data) {
22
- /******/ var chunkIds = data[0];
23
- /******/ var moreModules = data[1];
24
- /******/ var executeModules = data[2];
25
- /******/
26
- /******/ // add "moreModules" to the modules object,
27
- /******/ // then flag all "chunkIds" as loaded and fire callback
28
- /******/ var moduleId, chunkId, i = 0, resolves = [];
29
- /******/ for(;i < chunkIds.length; i++) {
30
- /******/ chunkId = chunkIds[i];
31
- /******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
32
- /******/ resolves.push(installedChunks[chunkId][0]);
33
- /******/ }
34
- /******/ installedChunks[chunkId] = 0;
35
- /******/ }
36
- /******/ for(moduleId in moreModules) {
37
- /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
38
- /******/ modules[moduleId] = moreModules[moduleId];
39
- /******/ }
40
- /******/ }
41
- /******/ if(parentJsonpFunction) parentJsonpFunction(data);
42
- /******/
43
- /******/ while(resolves.length) {
44
- /******/ resolves.shift()();
45
- /******/ }
46
- /******/
47
- /******/ // add entry modules from loaded chunk to deferred list
48
- /******/ deferredModules.push.apply(deferredModules, executeModules || []);
49
- /******/
50
- /******/ // run deferred modules when all chunks ready
51
- /******/ return checkDeferredModules();
52
- /******/ };
53
- /******/ function checkDeferredModules() {
54
- /******/ var result;
55
- /******/ for(var i = 0; i < deferredModules.length; i++) {
56
- /******/ var deferredModule = deferredModules[i];
57
- /******/ var fulfilled = true;
58
- /******/ for(var j = 1; j < deferredModule.length; j++) {
59
- /******/ var depId = deferredModule[j];
60
- /******/ if(installedChunks[depId] !== 0) fulfilled = false;
61
- /******/ }
62
- /******/ if(fulfilled) {
63
- /******/ deferredModules.splice(i--, 1);
64
- /******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
65
- /******/ }
66
- /******/ }
67
- /******/
68
- /******/ return result;
69
- /******/ }
70
- /******/
71
- /******/ // The module cache
72
- /******/ var installedModules = {};
73
- /******/
74
- /******/ // object to store loaded and loading chunks
75
- /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
76
- /******/ // Promise = chunk loading, 0 = chunk loaded
77
- /******/ var installedChunks = {
78
- /******/ "newsletter-block": 0
79
- /******/ };
80
- /******/
81
- /******/ var deferredModules = [];
82
- /******/
83
- /******/ // The require function
84
- /******/ function __webpack_require__(moduleId) {
85
- /******/
86
- /******/ // Check if module is in cache
87
- /******/ if(installedModules[moduleId]) {
88
- /******/ return installedModules[moduleId].exports;
89
- /******/ }
90
- /******/ // Create a new module (and put it into the cache)
91
- /******/ var module = installedModules[moduleId] = {
92
- /******/ i: moduleId,
93
- /******/ l: false,
94
- /******/ exports: {}
95
- /******/ };
96
- /******/
97
- /******/ // Execute the module function
98
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
99
- /******/
100
- /******/ // Flag the module as loaded
101
- /******/ module.l = true;
102
- /******/
103
- /******/ // Return the exports of the module
104
- /******/ return module.exports;
105
- /******/ }
106
- /******/
107
- /******/
108
- /******/ // expose the modules object (__webpack_modules__)
109
- /******/ __webpack_require__.m = modules;
110
- /******/
111
- /******/ // expose the module cache
112
- /******/ __webpack_require__.c = installedModules;
113
- /******/
114
- /******/ // define getter function for harmony exports
115
- /******/ __webpack_require__.d = function(exports, name, getter) {
116
- /******/ if(!__webpack_require__.o(exports, name)) {
117
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
118
- /******/ }
119
- /******/ };
120
- /******/
121
- /******/ // define __esModule on exports
122
- /******/ __webpack_require__.r = function(exports) {
123
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
124
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
125
- /******/ }
126
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
127
- /******/ };
128
- /******/
129
- /******/ // create a fake namespace object
130
- /******/ // mode & 1: value is a module id, require it
131
- /******/ // mode & 2: merge all properties of value into the ns
132
- /******/ // mode & 4: return value when already ns object
133
- /******/ // mode & 8|1: behave like require
134
- /******/ __webpack_require__.t = function(value, mode) {
135
- /******/ if(mode & 1) value = __webpack_require__(value);
136
- /******/ if(mode & 8) return value;
137
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
138
- /******/ var ns = Object.create(null);
139
- /******/ __webpack_require__.r(ns);
140
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
141
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
142
- /******/ return ns;
143
- /******/ };
144
- /******/
145
- /******/ // getDefaultExport function for compatibility with non-harmony modules
146
- /******/ __webpack_require__.n = function(module) {
147
- /******/ var getter = module && module.__esModule ?
148
- /******/ function getDefault() { return module['default']; } :
149
- /******/ function getModuleExports() { return module; };
150
- /******/ __webpack_require__.d(getter, 'a', getter);
151
- /******/ return getter;
152
- /******/ };
153
- /******/
154
- /******/ // Object.prototype.hasOwnProperty.call
155
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
156
- /******/
157
- /******/ // __webpack_public_path__
158
- /******/ __webpack_require__.p = "";
159
- /******/
160
- /******/ var jsonpArray = window["webpackJsonp_woocommerce_mailchimp_newsletter"] = window["webpackJsonp_woocommerce_mailchimp_newsletter"] || [];
161
- /******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
162
- /******/ jsonpArray.push = webpackJsonpCallback;
163
- /******/ jsonpArray = jsonpArray.slice();
164
- /******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
165
- /******/ var parentJsonpFunction = oldJsonpFunction;
166
- /******/
167
- /******/
168
- /******/ // add entry module to deferred list
169
- /******/ deferredModules.push(["./assets/js/checkout-newsletter-subscription-block/index.js","style-newsletter-block"]);
170
- /******/ // run deferred modules when ready
171
- /******/ return checkDeferredModules();
172
- /******/ })
173
- /************************************************************************/
174
- /******/ ({
175
-
176
- /***/ "./assets/js/checkout-newsletter-subscription-block/attributes.js":
177
- /*!************************************************************************!*\
178
- !*** ./assets/js/checkout-newsletter-subscription-block/attributes.js ***!
179
- \************************************************************************/
180
- /*! exports provided: default */
181
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
182
-
183
- "use strict";
184
- __webpack_require__.r(__webpack_exports__);
185
- /* harmony import */ var _woocommerce_settings__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @woocommerce/settings */ "@woocommerce/settings");
186
- /* harmony import */ var _woocommerce_settings__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_woocommerce_settings__WEBPACK_IMPORTED_MODULE_0__);
187
- /**
188
- * External dependencies
189
- */
190
-
191
- const {
192
- optinDefaultText,
193
- gdprHeadline,
194
- gdprFields
195
- } = Object(_woocommerce_settings__WEBPACK_IMPORTED_MODULE_0__["getSetting"])('mailchimp-newsletter_data', '');
196
- /* harmony default export */ __webpack_exports__["default"] = ({
197
- text: {
198
- type: 'string',
199
- default: optinDefaultText
200
- },
201
- gdprHeadline: {
202
- type: 'string',
203
- default: gdprHeadline
204
- },
205
- gdpr: {
206
- type: 'array',
207
- default: gdprFields
208
- }
209
- });
210
-
211
- /***/ }),
212
-
213
- /***/ "./assets/js/checkout-newsletter-subscription-block/block.json":
214
- /*!*********************************************************************!*\
215
- !*** ./assets/js/checkout-newsletter-subscription-block/block.json ***!
216
- \*********************************************************************/
217
- /*! exports provided: apiVersion, name, version, title, category, description, supports, parent, attributes, textdomain, editorStyle, default */
218
- /***/ (function(module) {
219
-
220
- module.exports = JSON.parse("{\"apiVersion\":2,\"name\":\"woocommerce/mailchimp-newsletter-subscription\",\"version\":\"1.0.0\",\"title\":\"Mailchimp Newsletter!\",\"category\":\"woocommerce\",\"description\":\"Adds a newsletter subscription checkbox to the checkout.\",\"supports\":{\"html\":true,\"align\":false,\"multiple\":false,\"reusable\":false},\"parent\":[\"woocommerce/checkout-contact-information-block\"],\"attributes\":{\"lock\":{\"type\":\"object\",\"default\":{\"remove\":true,\"move\":true}}},\"textdomain\":\"mailchimp-woocommerce\",\"editorStyle\":\"file:../../../build/style-newsletter-block.css\"}");
221
-
222
- /***/ }),
223
-
224
- /***/ "./assets/js/checkout-newsletter-subscription-block/edit.js":
225
- /*!******************************************************************!*\
226
- !*** ./assets/js/checkout-newsletter-subscription-block/edit.js ***!
227
- \******************************************************************/
228
- /*! exports provided: Edit, Save */
229
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
230
-
231
- "use strict";
232
- __webpack_require__.r(__webpack_exports__);
233
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Edit", function() { return Edit; });
234
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Save", function() { return Save; });
235
- /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
236
- /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);
237
- /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
238
- /* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__);
239
- /* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
240
- /* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__);
241
- /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
242
- /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__);
243
- /* harmony import */ var _woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @woocommerce/blocks-checkout */ "@woocommerce/blocks-checkout");
244
- /* harmony import */ var _woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_4__);
245
- /* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./style.scss */ "./assets/js/checkout-newsletter-subscription-block/style.scss");
246
-
247
-
248
- /**
249
- * External dependencies
250
- */
251
-
252
-
253
-
254
-
255
- /**
256
- * Internal dependencies
257
- */
258
-
259
-
260
- const Edit = ({
261
- attributes,
262
- setAttributes
263
- }) => {
264
- const {
265
- text,
266
- gdprHeadline,
267
- gdpr
268
- } = attributes;
269
- const blockProps = Object(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__["useBlockProps"])();
270
- console.log('edit', {
271
- text: text,
272
- gdprHeadline: gdprHeadline,
273
- gdpr: gdpr
274
- });
275
- return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", blockProps, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__["InspectorControls"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__["PanelBody"], {
276
- title: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__["__"])('Block options', 'mailchimp-for-woocommerce')
277
- }, "Options for the block go here.")), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
278
- style: {
279
- display: 'flex'
280
- }
281
- }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_4__["CheckboxControl"], {
282
- id: "newsletter-text",
283
- checked: false,
284
- disabled: true
285
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__["RichText"], {
286
- value: text,
287
- help: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__["__"])('Set the newsletter confirmation text.', 'mailchimp-for-woocommerce'),
288
- onChange: value => setAttributes({
289
- text: value
290
- })
291
- })), gdpr && gdpr.length && Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["Fragment"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
292
- style: {
293
- display: 'flex',
294
- marginTop: '2rem'
295
- }
296
- }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__["RichText"], {
297
- value: gdprHeadline,
298
- help: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_1__["__"])('Set the GDPR headline.', 'mailchimp-for-woocommerce'),
299
- onChange: value => setAttributes({
300
- gdprHeadline: value
301
- })
302
- })), gdpr.map((gdprItem, index) => {
303
- return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
304
- style: {
305
- display: 'flex',
306
- marginTop: '1rem'
307
- }
308
- }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_woocommerce_blocks_checkout__WEBPACK_IMPORTED_MODULE_4__["CheckboxControl"], {
309
- id: 'gdpr_' + gdprItem.marketing_permission_id,
310
- checked: gdpr[index].enabled,
311
- onChange: () => {
312
- gdpr[index].enabled = !gdpr[index].enabled;
313
- setAttributes({
314
- gdpr: gdpr
315
- });
316
- }
317
- }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("span", {
318
- dangerouslySetInnerHTML: {
319
- __html: gdprItem.text
320
- }
321
- })));
322
- })));
323
- }; // not sure
324
-
325
- const Save = () => {
326
- return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__["useBlockProps"].save());
327
- };
328
-
329
- /***/ }),
330
-
331
- /***/ "./assets/js/checkout-newsletter-subscription-block/index.js":
332
- /*!*******************************************************************!*\
333
- !*** ./assets/js/checkout-newsletter-subscription-block/index.js ***!
334
- \*******************************************************************/
335
- /*! no exports provided */
336
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
337
-
338
- "use strict";
339
- __webpack_require__.r(__webpack_exports__);
340
- /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
341
- /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);
342
- /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
343
- /* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__);
344
- /* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
345
- /* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_2__);
346
- /* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./edit */ "./assets/js/checkout-newsletter-subscription-block/edit.js");
347
- /* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./assets/js/checkout-newsletter-subscription-block/block.json");
348
- var _block_json__WEBPACK_IMPORTED_MODULE_4___namespace = /*#__PURE__*/__webpack_require__.t(/*! ./block.json */ "./assets/js/checkout-newsletter-subscription-block/block.json", 1);
349
- /* harmony import */ var _attributes__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./attributes */ "./assets/js/checkout-newsletter-subscription-block/attributes.js");
350
-
351
-
352
- /**
353
- * External dependencies
354
- */
355
-
356
-
357
- /**
358
- * Internal dependencies
359
- */
360
-
361
-
362
-
363
-
364
- console.log('index.js', {
365
- metadata: _block_json__WEBPACK_IMPORTED_MODULE_4__,
366
- attributes: _attributes__WEBPACK_IMPORTED_MODULE_5__["default"]
367
- });
368
- Object(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_2__["registerBlockType"])(_block_json__WEBPACK_IMPORTED_MODULE_4__, {
369
- icon: {
370
- src: Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__["SVG"], {
371
- xmlns: "http://www.w3.org/2000/svg",
372
- width: "60",
373
- height: "60",
374
- viewBox: "0 0 46 49",
375
- fill: "none"
376
- }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
377
- d: "M34.5458 23.5193C34.8988 23.4778 35.2361 23.4759 35.5457 23.5193C35.7252 23.107 35.7568 22.397 35.5951 21.6239C35.3544 20.4741 35.029 19.7778 34.3584 19.8863C33.6859 19.9948 33.6622 20.8271 33.9028 21.9769C34.037 22.6238 34.2776 23.1761 34.5458 23.5193Z",
378
- fill: "black"
379
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
380
- d: "M28.7763 24.4284C29.2575 24.6394 29.5534 24.7795 29.6678 24.6572C29.7427 24.5803 29.719 24.4363 29.6046 24.2489C29.368 23.8624 28.8788 23.4679 28.3621 23.249C27.303 22.7934 26.0407 22.9453 25.0664 23.6454C24.745 23.8801 24.4393 24.2075 24.4826 24.4047C24.4965 24.4698 24.5458 24.5172 24.6582 24.5329C24.9225 24.5625 25.8494 24.0951 26.9164 24.03C27.6718 23.9827 28.295 24.2174 28.7763 24.4284Z",
381
- fill: "black"
382
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
383
- d: "M27.8105 24.9806C27.1852 25.0793 26.8381 25.2863 26.6172 25.4777C26.4279 25.6433 26.3115 25.8267 26.3115 25.9549C26.3115 26.0161 26.3391 26.0516 26.3589 26.0693C26.3865 26.095 26.422 26.1088 26.4614 26.1088C26.6034 26.1088 26.919 25.9826 26.919 25.9826C27.7907 25.6709 28.3647 25.7084 28.9346 25.7735C29.2502 25.809 29.3981 25.8287 29.4672 25.7202C29.4869 25.6887 29.5125 25.6216 29.4494 25.521C29.3054 25.2804 28.6723 24.8781 27.8105 24.9806Z",
384
- fill: "black"
385
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
386
- d: "M32.5975 27.0061C33.0235 27.2152 33.4909 27.1324 33.6428 26.8227C33.7946 26.5131 33.5737 26.093 33.1497 25.8839C32.7237 25.6749 32.2563 25.7577 32.1044 26.0673C31.9506 26.377 32.1734 26.7971 32.5975 27.0061Z",
387
- fill: "black"
388
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
389
- d: "M35.3306 24.6177C34.9854 24.6118 34.6995 24.9905 34.6916 25.4638C34.6837 25.9372 34.9578 26.3257 35.303 26.3317C35.6481 26.3376 35.9341 25.9589 35.942 25.4855C35.9499 25.0122 35.6757 24.6237 35.3306 24.6177Z",
390
- fill: "black"
391
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
392
- d: "M12.1324 33.1577C12.0456 33.0492 11.9056 33.0827 11.7695 33.1143C11.6749 33.136 11.5664 33.1616 11.448 33.1596C11.1936 33.1557 10.9786 33.0452 10.8583 32.8598C10.7006 32.6192 10.7104 32.2583 10.884 31.8461C10.9076 31.7909 10.9353 31.7297 10.9648 31.6607C11.241 31.0394 11.7064 30 11.1857 29.008C10.7932 28.2625 10.1542 27.797 9.38702 27.7004C8.64939 27.6077 7.89006 27.8798 7.40685 28.4143C6.64358 29.2565 6.52328 30.4044 6.6712 30.8087C6.72445 30.9566 6.80925 30.998 6.87237 31.0059C7.00254 31.0237 7.19385 30.929 7.31416 30.6055C7.32205 30.5819 7.33388 30.5464 7.34769 30.501C7.40094 30.3294 7.50152 30.0099 7.66522 29.7555C7.86245 29.4478 8.17012 29.2348 8.53105 29.1579C8.89789 29.079 9.2746 29.15 9.58819 29.3551C10.1227 29.7062 10.3298 30.361 10.101 30.9862C9.98264 31.3096 9.79133 31.9289 9.83275 32.4378C9.91756 33.4673 10.5507 33.8795 11.1206 33.9249C11.6729 33.9466 12.0594 33.6349 12.1581 33.4081C12.2133 33.274 12.164 33.1932 12.1324 33.1577Z",
393
- fill: "black"
394
- }), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("path", {
395
- d: "M44.044 31.2761C44.0223 31.2012 43.8862 30.7002 43.6969 30.0967C43.5075 29.4932 43.3142 29.0672 43.3142 29.0672C44.0696 27.9351 44.0834 26.9233 43.9828 26.3514C43.8763 25.6414 43.5805 25.0359 42.9829 24.4107C42.3873 23.7854 41.1684 23.1445 39.4545 22.6632C39.2593 22.608 38.6123 22.4305 38.5551 22.4127C38.5512 22.3753 38.5078 20.2945 38.4684 19.3991C38.4408 18.7522 38.3836 17.7444 38.0719 16.7504C37.6992 15.4053 37.0483 14.2298 36.2377 13.4764C38.4763 11.157 39.8726 8.60091 39.8707 6.40774C39.8647 2.19102 34.6855 0.914962 28.3033 3.55781C28.2974 3.55978 26.9602 4.1278 26.9503 4.13174C26.9444 4.12582 24.5066 1.73346 24.4692 1.7019C17.1954 -4.64488 -5.55475 20.6436 1.71899 26.7853L3.30864 28.1323C2.89644 29.2013 2.73471 30.4241 2.86685 31.7396C3.03647 33.4299 3.90822 35.0511 5.32234 36.3015C6.66348 37.4908 8.42669 38.2422 10.1386 38.2402C12.9688 44.7626 19.4359 48.7643 27.0193 48.9891C35.153 49.2317 41.981 45.4134 44.8428 38.5578C45.0301 38.0765 45.825 35.909 45.825 33.9939C45.825 32.0729 44.7382 31.2761 44.044 31.2761ZM10.7638 36.41C10.5173 36.4514 10.2649 36.4691 10.0104 36.4632C7.55298 36.3981 4.90027 34.1852 4.63598 31.5621C4.34409 28.6629 5.82527 26.4322 8.44839 25.9017C8.76198 25.8386 9.14066 25.8011 9.54892 25.8228C11.0183 25.9037 13.1838 27.0318 13.6789 30.2328C14.1187 33.0689 13.4225 35.9564 10.7638 36.41ZM8.02041 24.1681C6.38736 24.4856 4.9476 25.4106 4.06797 26.6886C3.54137 26.2508 2.56115 25.4007 2.38956 25.0694C0.985306 22.4009 3.92202 17.2138 5.97516 14.285C11.0478 7.04676 18.9922 1.56581 22.6705 2.55984C23.2681 2.72945 25.2482 5.02518 25.2482 5.02518C25.2482 5.02518 21.5719 7.06451 18.1618 9.90853C13.5704 13.4468 10.0992 18.5885 8.02041 24.1681ZM33.8079 35.3252C33.8611 35.3035 33.8986 35.2424 33.8927 35.1812C33.8848 35.1063 33.8177 35.0531 33.7448 35.0609C33.7448 35.0609 29.8969 35.6309 26.26 34.2996C26.6564 33.0117 27.7096 33.4772 29.3012 33.6054C32.1709 33.777 34.7408 33.3569 36.642 32.8125C38.2889 32.3392 40.4505 31.4083 42.1309 30.0829C42.6969 31.3274 42.8981 32.6962 42.8981 32.6962C42.8981 32.6962 43.3359 32.6173 43.7028 32.8441C44.0499 33.0571 44.3024 33.5009 44.1288 34.6448C43.7758 36.7847 42.8665 38.5223 41.338 40.1198C40.4071 41.1217 39.277 41.9935 37.9852 42.6266C37.2988 42.9875 36.5671 43.2991 35.7959 43.5516C30.033 45.4331 24.1339 43.3642 22.2326 38.9207C22.0807 38.5874 21.9525 38.2363 21.852 37.8714C21.0414 34.9426 21.7297 31.43 23.8795 29.2171C23.8795 29.2171 23.8795 29.2171 23.8795 29.2151C24.0116 29.0751 24.1477 28.9094 24.1477 28.7004C24.1477 28.5248 24.0372 28.3414 23.9406 28.2112C23.1892 27.1206 20.5818 25.2607 21.1045 21.6613C21.4792 19.0757 23.7414 17.2553 25.8498 17.3637C26.0273 17.3736 26.2067 17.3834 26.3842 17.3953C27.2974 17.4485 28.0942 17.5669 28.8476 17.5984C30.1059 17.6537 31.238 17.4702 32.5792 16.3519C33.0308 15.9752 33.3937 15.6478 34.0071 15.5453C34.0722 15.5335 34.2319 15.4763 34.5534 15.492C34.8808 15.5098 35.1924 15.5985 35.4725 15.7859C36.5474 16.5018 36.6992 18.2335 36.7545 19.4997C36.786 20.2235 36.8728 21.9729 36.9044 22.4759C36.9734 23.6237 37.2751 23.7874 37.8846 23.9886C38.2278 24.101 38.5473 24.1858 39.0167 24.318C40.4387 24.7183 41.2828 25.1227 41.8153 25.6433C42.1329 25.9688 42.2808 26.3139 42.3261 26.6433C42.4938 27.8661 41.3755 29.3788 38.4171 30.7515C35.1826 32.2524 31.2577 32.6331 28.5459 32.3313C28.3388 32.3076 27.5992 32.2248 27.5952 32.2248C25.4257 31.9329 24.1891 34.7355 25.4908 36.6565C26.329 37.8951 28.6149 38.6998 30.9008 38.6998C36.1431 38.6998 40.1724 36.4613 41.6713 34.5284C41.7167 34.4712 41.7206 34.4633 41.7916 34.3568C41.8646 34.2464 41.8055 34.1852 41.7128 34.2464C40.488 35.0846 35.0484 38.4099 29.2322 37.4099C29.2322 37.4099 28.5261 37.2936 27.8792 37.0431C27.3664 36.8439 26.2935 36.3508 26.1634 35.2483C30.8514 36.6979 33.8079 35.3252 33.8079 35.3252ZM26.3704 34.4476C26.3704 34.4476 26.3724 34.4476 26.3704 34.4476C26.3724 34.4495 26.3724 34.4495 26.3724 34.4515C26.3724 34.4495 26.3724 34.4476 26.3704 34.4476ZM17.3887 14.2554C19.1914 12.1707 21.4121 10.3602 23.4002 9.34249C23.4692 9.30699 23.5422 9.38193 23.5047 9.44899C23.3469 9.73497 23.0432 10.3464 22.9466 10.8118C22.9308 10.8848 23.0097 10.9381 23.0708 10.8966C24.3074 10.0525 26.4612 9.14921 28.3486 9.03284C28.4295 9.02693 28.4689 9.13146 28.4039 9.18076C28.1159 9.40166 27.8023 9.70539 27.5735 10.0131C27.5341 10.0663 27.5716 10.1413 27.6366 10.1413C28.962 10.1511 30.8317 10.6146 32.0486 11.297C32.1315 11.3424 32.0723 11.5021 31.9796 11.4824C30.1375 11.0603 27.1199 10.7389 23.986 11.5041C21.1893 12.1865 19.0533 13.2397 17.4952 14.3738C17.4203 14.4329 17.3256 14.3304 17.3887 14.2554Z",
396
- fill: "black"
397
- })),
398
- foreground: '#874FB9'
399
- },
400
- edit: _edit__WEBPACK_IMPORTED_MODULE_3__["Edit"],
401
- save: _edit__WEBPACK_IMPORTED_MODULE_3__["Save"],
402
- attributes: { ..._block_json__WEBPACK_IMPORTED_MODULE_4__.attributes,
403
- ..._attributes__WEBPACK_IMPORTED_MODULE_5__["default"]
404
- }
405
- });
406
-
407
- /***/ }),
408
-
409
- /***/ "@woocommerce/blocks-checkout":
410
- /*!****************************************!*\
411
- !*** external ["wc","blocksCheckout"] ***!
412
- \****************************************/
413
- /*! no static exports found */
414
- /***/ (function(module, exports) {
415
-
416
- (function() { module.exports = window["wc"]["blocksCheckout"]; }());
417
-
418
- /***/ }),
419
-
420
- /***/ "@woocommerce/settings":
421
- /*!************************************!*\
422
- !*** external ["wc","wcSettings"] ***!
423
- \************************************/
424
- /*! no static exports found */
425
- /***/ (function(module, exports) {
426
-
427
- (function() { module.exports = window["wc"]["wcSettings"]; }());
428
-
429
- /***/ }),
430
-
431
- /***/ "@wordpress/block-editor":
432
- /*!*************************************!*\
433
- !*** external ["wp","blockEditor"] ***!
434
- \*************************************/
435
- /*! no static exports found */
436
- /***/ (function(module, exports) {
437
-
438
- (function() { module.exports = window["wp"]["blockEditor"]; }());
439
-
440
- /***/ }),
441
-
442
- /***/ "@wordpress/blocks":
443
- /*!********************************!*\
444
- !*** external ["wp","blocks"] ***!
445
- \********************************/
446
- /*! no static exports found */
447
- /***/ (function(module, exports) {
448
-
449
- (function() { module.exports = window["wp"]["blocks"]; }());
450
-
451
- /***/ }),
452
-
453
- /***/ "@wordpress/components":
454
- /*!************************************!*\
455
- !*** external ["wp","components"] ***!
456
- \************************************/
457
- /*! no static exports found */
458
- /***/ (function(module, exports) {
459
-
460
- (function() { module.exports = window["wp"]["components"]; }());
461
-
462
- /***/ }),
463
-
464
- /***/ "@wordpress/element":
465
- /*!*********************************!*\
466
- !*** external ["wp","element"] ***!
467
- \*********************************/
468
- /*! no static exports found */
469
- /***/ (function(module, exports) {
470
-
471
- (function() { module.exports = window["wp"]["element"]; }());
472
-
473
- /***/ }),
474
-
475
- /***/ "@wordpress/i18n":
476
- /*!******************************!*\
477
- !*** external ["wp","i18n"] ***!
478
- \******************************/
479
- /*! no static exports found */
480
- /***/ (function(module, exports) {
481
-
482
- (function() { module.exports = window["wp"]["i18n"]; }());
483
-
484
- /***/ })
485
-
486
- /******/ });
487
- //# sourceMappingURL=newsletter-block.js.map
1
+ (window.webpackJsonp_woocommerce_mailchimp_newsletter=window.webpackJsonp_woocommerce_mailchimp_newsletter||[]).push([[2],{10:function(e,t,n){}}]),function(e){function t(t){for(var r,l,C=t[0],i=t[1],a=t[2],s=0,m=[];s<C.length;s++)l=C[s],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&m.push(o[l][0]),o[l]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);for(p&&p(t);m.length;)m.shift()();return c.push.apply(c,a||[]),n()}function n(){for(var e,t=0;t<c.length;t++){for(var n=c[t],r=!0,C=1;C<n.length;C++){var i=n[C];0!==o[i]&&(r=!1)}r&&(c.splice(t--,1),e=l(l.s=n[0]))}return e}var r={},o={0:0},c=[];function l(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,l),n.l=!0,n.exports}l.m=e,l.c=r,l.d=function(e,t,n){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(l.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)l.d(n,r,function(t){return e[t]}.bind(null,r));return n},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="";var C=window.webpackJsonp_woocommerce_mailchimp_newsletter=window.webpackJsonp_woocommerce_mailchimp_newsletter||[],i=C.push.bind(C);C.push=t,C=C.slice();for(var a=0;a<C.length;a++)t(C[a]);var p=i;c.push([11,2]),n()}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wc.blocksCheckout},function(e,t){e.exports=window.wp.i18n},function(e){e.exports=JSON.parse('{"apiVersion":2,"name":"woocommerce/mailchimp-newsletter-subscription","version":"1.0.0","title":"Mailchimp Newsletter!","category":"woocommerce","description":"Adds a newsletter subscription checkbox to the checkout.","supports":{"html":true,"align":false,"multiple":false,"reusable":false},"parent":["woocommerce/checkout-contact-information-block"],"attributes":{"lock":{"type":"object","default":{"remove":true,"move":true}}},"textdomain":"mailchimp-woocommerce","editorStyle":"file:../../../build/style-newsletter-block.css"}')},function(e,t){e.exports=window.wp.blockEditor},function(e,t,n){"use strict";var r=n(6);const{optinDefaultText:o,gdprHeadline:c,gdprFields:l}=Object(r.getSetting)("mailchimp-newsletter_data","");t.a={text:{type:"string",default:o},gdprHeadline:{type:"string",default:c},gdpr:{type:"array",default:l}}},function(e,t){e.exports=window.wc.wcSettings},function(e,t){e.exports=window.wp.components},function(e,t){e.exports=window.wp.blocks},,,function(e,t,n){"use strict";n.r(t);var r=n(0),o=n(7),c=n(8),l=n(2),C=n(4),i=n(1);n(10);var a=n(3),p=n(5);Object(c.registerBlockType)(a,{icon:{src:Object(r.createElement)(o.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"60",height:"60",viewBox:"0 0 46 49",fill:"none"},Object(r.createElement)("path",{d:"M34.5458 23.5193C34.8988 23.4778 35.2361 23.4759 35.5457 23.5193C35.7252 23.107 35.7568 22.397 35.5951 21.6239C35.3544 20.4741 35.029 19.7778 34.3584 19.8863C33.6859 19.9948 33.6622 20.8271 33.9028 21.9769C34.037 22.6238 34.2776 23.1761 34.5458 23.5193Z",fill:"black"}),Object(r.createElement)("path",{d:"M28.7763 24.4284C29.2575 24.6394 29.5534 24.7795 29.6678 24.6572C29.7427 24.5803 29.719 24.4363 29.6046 24.2489C29.368 23.8624 28.8788 23.4679 28.3621 23.249C27.303 22.7934 26.0407 22.9453 25.0664 23.6454C24.745 23.8801 24.4393 24.2075 24.4826 24.4047C24.4965 24.4698 24.5458 24.5172 24.6582 24.5329C24.9225 24.5625 25.8494 24.0951 26.9164 24.03C27.6718 23.9827 28.295 24.2174 28.7763 24.4284Z",fill:"black"}),Object(r.createElement)("path",{d:"M27.8105 24.9806C27.1852 25.0793 26.8381 25.2863 26.6172 25.4777C26.4279 25.6433 26.3115 25.8267 26.3115 25.9549C26.3115 26.0161 26.3391 26.0516 26.3589 26.0693C26.3865 26.095 26.422 26.1088 26.4614 26.1088C26.6034 26.1088 26.919 25.9826 26.919 25.9826C27.7907 25.6709 28.3647 25.7084 28.9346 25.7735C29.2502 25.809 29.3981 25.8287 29.4672 25.7202C29.4869 25.6887 29.5125 25.6216 29.4494 25.521C29.3054 25.2804 28.6723 24.8781 27.8105 24.9806Z",fill:"black"}),Object(r.createElement)("path",{d:"M32.5975 27.0061C33.0235 27.2152 33.4909 27.1324 33.6428 26.8227C33.7946 26.5131 33.5737 26.093 33.1497 25.8839C32.7237 25.6749 32.2563 25.7577 32.1044 26.0673C31.9506 26.377 32.1734 26.7971 32.5975 27.0061Z",fill:"black"}),Object(r.createElement)("path",{d:"M35.3306 24.6177C34.9854 24.6118 34.6995 24.9905 34.6916 25.4638C34.6837 25.9372 34.9578 26.3257 35.303 26.3317C35.6481 26.3376 35.9341 25.9589 35.942 25.4855C35.9499 25.0122 35.6757 24.6237 35.3306 24.6177Z",fill:"black"}),Object(r.createElement)("path",{d:"M12.1324 33.1577C12.0456 33.0492 11.9056 33.0827 11.7695 33.1143C11.6749 33.136 11.5664 33.1616 11.448 33.1596C11.1936 33.1557 10.9786 33.0452 10.8583 32.8598C10.7006 32.6192 10.7104 32.2583 10.884 31.8461C10.9076 31.7909 10.9353 31.7297 10.9648 31.6607C11.241 31.0394 11.7064 30 11.1857 29.008C10.7932 28.2625 10.1542 27.797 9.38702 27.7004C8.64939 27.6077 7.89006 27.8798 7.40685 28.4143C6.64358 29.2565 6.52328 30.4044 6.6712 30.8087C6.72445 30.9566 6.80925 30.998 6.87237 31.0059C7.00254 31.0237 7.19385 30.929 7.31416 30.6055C7.32205 30.5819 7.33388 30.5464 7.34769 30.501C7.40094 30.3294 7.50152 30.0099 7.66522 29.7555C7.86245 29.4478 8.17012 29.2348 8.53105 29.1579C8.89789 29.079 9.2746 29.15 9.58819 29.3551C10.1227 29.7062 10.3298 30.361 10.101 30.9862C9.98264 31.3096 9.79133 31.9289 9.83275 32.4378C9.91756 33.4673 10.5507 33.8795 11.1206 33.9249C11.6729 33.9466 12.0594 33.6349 12.1581 33.4081C12.2133 33.274 12.164 33.1932 12.1324 33.1577Z",fill:"black"}),Object(r.createElement)("path",{d:"M44.044 31.2761C44.0223 31.2012 43.8862 30.7002 43.6969 30.0967C43.5075 29.4932 43.3142 29.0672 43.3142 29.0672C44.0696 27.9351 44.0834 26.9233 43.9828 26.3514C43.8763 25.6414 43.5805 25.0359 42.9829 24.4107C42.3873 23.7854 41.1684 23.1445 39.4545 22.6632C39.2593 22.608 38.6123 22.4305 38.5551 22.4127C38.5512 22.3753 38.5078 20.2945 38.4684 19.3991C38.4408 18.7522 38.3836 17.7444 38.0719 16.7504C37.6992 15.4053 37.0483 14.2298 36.2377 13.4764C38.4763 11.157 39.8726 8.60091 39.8707 6.40774C39.8647 2.19102 34.6855 0.914962 28.3033 3.55781C28.2974 3.55978 26.9602 4.1278 26.9503 4.13174C26.9444 4.12582 24.5066 1.73346 24.4692 1.7019C17.1954 -4.64488 -5.55475 20.6436 1.71899 26.7853L3.30864 28.1323C2.89644 29.2013 2.73471 30.4241 2.86685 31.7396C3.03647 33.4299 3.90822 35.0511 5.32234 36.3015C6.66348 37.4908 8.42669 38.2422 10.1386 38.2402C12.9688 44.7626 19.4359 48.7643 27.0193 48.9891C35.153 49.2317 41.981 45.4134 44.8428 38.5578C45.0301 38.0765 45.825 35.909 45.825 33.9939C45.825 32.0729 44.7382 31.2761 44.044 31.2761ZM10.7638 36.41C10.5173 36.4514 10.2649 36.4691 10.0104 36.4632C7.55298 36.3981 4.90027 34.1852 4.63598 31.5621C4.34409 28.6629 5.82527 26.4322 8.44839 25.9017C8.76198 25.8386 9.14066 25.8011 9.54892 25.8228C11.0183 25.9037 13.1838 27.0318 13.6789 30.2328C14.1187 33.0689 13.4225 35.9564 10.7638 36.41ZM8.02041 24.1681C6.38736 24.4856 4.9476 25.4106 4.06797 26.6886C3.54137 26.2508 2.56115 25.4007 2.38956 25.0694C0.985306 22.4009 3.92202 17.2138 5.97516 14.285C11.0478 7.04676 18.9922 1.56581 22.6705 2.55984C23.2681 2.72945 25.2482 5.02518 25.2482 5.02518C25.2482 5.02518 21.5719 7.06451 18.1618 9.90853C13.5704 13.4468 10.0992 18.5885 8.02041 24.1681ZM33.8079 35.3252C33.8611 35.3035 33.8986 35.2424 33.8927 35.1812C33.8848 35.1063 33.8177 35.0531 33.7448 35.0609C33.7448 35.0609 29.8969 35.6309 26.26 34.2996C26.6564 33.0117 27.7096 33.4772 29.3012 33.6054C32.1709 33.777 34.7408 33.3569 36.642 32.8125C38.2889 32.3392 40.4505 31.4083 42.1309 30.0829C42.6969 31.3274 42.8981 32.6962 42.8981 32.6962C42.8981 32.6962 43.3359 32.6173 43.7028 32.8441C44.0499 33.0571 44.3024 33.5009 44.1288 34.6448C43.7758 36.7847 42.8665 38.5223 41.338 40.1198C40.4071 41.1217 39.277 41.9935 37.9852 42.6266C37.2988 42.9875 36.5671 43.2991 35.7959 43.5516C30.033 45.4331 24.1339 43.3642 22.2326 38.9207C22.0807 38.5874 21.9525 38.2363 21.852 37.8714C21.0414 34.9426 21.7297 31.43 23.8795 29.2171C23.8795 29.2171 23.8795 29.2171 23.8795 29.2151C24.0116 29.0751 24.1477 28.9094 24.1477 28.7004C24.1477 28.5248 24.0372 28.3414 23.9406 28.2112C23.1892 27.1206 20.5818 25.2607 21.1045 21.6613C21.4792 19.0757 23.7414 17.2553 25.8498 17.3637C26.0273 17.3736 26.2067 17.3834 26.3842 17.3953C27.2974 17.4485 28.0942 17.5669 28.8476 17.5984C30.1059 17.6537 31.238 17.4702 32.5792 16.3519C33.0308 15.9752 33.3937 15.6478 34.0071 15.5453C34.0722 15.5335 34.2319 15.4763 34.5534 15.492C34.8808 15.5098 35.1924 15.5985 35.4725 15.7859C36.5474 16.5018 36.6992 18.2335 36.7545 19.4997C36.786 20.2235 36.8728 21.9729 36.9044 22.4759C36.9734 23.6237 37.2751 23.7874 37.8846 23.9886C38.2278 24.101 38.5473 24.1858 39.0167 24.318C40.4387 24.7183 41.2828 25.1227 41.8153 25.6433C42.1329 25.9688 42.2808 26.3139 42.3261 26.6433C42.4938 27.8661 41.3755 29.3788 38.4171 30.7515C35.1826 32.2524 31.2577 32.6331 28.5459 32.3313C28.3388 32.3076 27.5992 32.2248 27.5952 32.2248C25.4257 31.9329 24.1891 34.7355 25.4908 36.6565C26.329 37.8951 28.6149 38.6998 30.9008 38.6998C36.1431 38.6998 40.1724 36.4613 41.6713 34.5284C41.7167 34.4712 41.7206 34.4633 41.7916 34.3568C41.8646 34.2464 41.8055 34.1852 41.7128 34.2464C40.488 35.0846 35.0484 38.4099 29.2322 37.4099C29.2322 37.4099 28.5261 37.2936 27.8792 37.0431C27.3664 36.8439 26.2935 36.3508 26.1634 35.2483C30.8514 36.6979 33.8079 35.3252 33.8079 35.3252ZM26.3704 34.4476C26.3704 34.4476 26.3724 34.4476 26.3704 34.4476C26.3724 34.4495 26.3724 34.4495 26.3724 34.4515C26.3724 34.4495 26.3724 34.4476 26.3704 34.4476ZM17.3887 14.2554C19.1914 12.1707 21.4121 10.3602 23.4002 9.34249C23.4692 9.30699 23.5422 9.38193 23.5047 9.44899C23.3469 9.73497 23.0432 10.3464 22.9466 10.8118C22.9308 10.8848 23.0097 10.9381 23.0708 10.8966C24.3074 10.0525 26.4612 9.14921 28.3486 9.03284C28.4295 9.02693 28.4689 9.13146 28.4039 9.18076C28.1159 9.40166 27.8023 9.70539 27.5735 10.0131C27.5341 10.0663 27.5716 10.1413 27.6366 10.1413C28.962 10.1511 30.8317 10.6146 32.0486 11.297C32.1315 11.3424 32.0723 11.5021 31.9796 11.4824C30.1375 11.0603 27.1199 10.7389 23.986 11.5041C21.1893 12.1865 19.0533 13.2397 17.4952 14.3738C17.4203 14.4329 17.3256 14.3304 17.3887 14.2554Z",fill:"black"})),foreground:"#874FB9"},edit:({attributes:e,setAttributes:t})=>{const{text:n,gdprHeadline:c,gdpr:a}=e,p=Object(C.useBlockProps)();return Object(r.createElement)("div",p,Object(r.createElement)(C.InspectorControls,null,Object(r.createElement)(o.PanelBody,{title:Object(l.__)("Block options","mailchimp-for-woocommerce")},"Options for the block go here.")),Object(r.createElement)("div",{style:{display:"flex"}},Object(r.createElement)(i.CheckboxControl,{id:"newsletter-text",checked:!1,disabled:!0}),Object(r.createElement)(C.RichText,{value:n,help:Object(l.__)("Set the newsletter confirmation text.","mailchimp-for-woocommerce"),onChange:e=>t({text:e})})),a&&a.length&&Object(r.createElement)(r.Fragment,null,Object(r.createElement)("div",{style:{display:"flex",marginTop:"2rem"}},Object(r.createElement)(C.RichText,{value:c,help:Object(l.__)("Set the GDPR headline.","mailchimp-for-woocommerce"),onChange:e=>t({gdprHeadline:e})})),a.map((e,n)=>Object(r.createElement)("div",{style:{display:"flex",marginTop:"1rem"}},Object(r.createElement)(i.CheckboxControl,{id:"gdpr_"+e.marketing_permission_id,checked:a[n].enabled,onChange:()=>{a[n].enabled=!a[n].enabled,t({gdpr:a})}},Object(r.createElement)("span",{dangerouslySetInnerHTML:{__html:e.text}}))))))},save:()=>Object(r.createElement)("div",C.useBlockProps.save()),attributes:{...a.attributes,...p.a}})}]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
blocks/build/newsletter-block.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./assets/js/checkout-newsletter-subscription-block/attributes.js","webpack:///./assets/js/checkout-newsletter-subscription-block/edit.js","webpack:///./assets/js/checkout-newsletter-subscription-block/index.js","webpack:///external [\"wc\",\"blocksCheckout\"]","webpack:///external [\"wc\",\"wcSettings\"]","webpack:///external [\"wp\",\"blockEditor\"]","webpack:///external [\"wp\",\"blocks\"]","webpack:///external [\"wp\",\"components\"]","webpack:///external [\"wp\",\"element\"]","webpack:///external [\"wp\",\"i18n\"]"],"names":["optinDefaultText","gdprHeadline","gdprFields","getSetting","text","type","default","gdpr","Edit","attributes","setAttributes","blockProps","useBlockProps","console","log","__","display","value","length","marginTop","map","gdprItem","index","marketing_permission_id","enabled","__html","Save","save","metadata","registerBlockType","icon","src","foreground","edit"],"mappings":";;;;;;;;;;;;;;;;;;;QAAA;QACA;QACA;QACA;QACA;;QAEA;QACA;QACA;QACA,QAAQ,oBAAoB;QAC5B;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA,iBAAiB,4BAA4B;QAC7C;QACA;QACA,kBAAkB,2BAA2B;QAC7C;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;;QAEA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;QAEA;QACA;QACA;QACA;QACA,gBAAgB,uBAAuB;QACvC;;;QAGA;QACA;QACA;QACA;;;;;;;;;;;;;ACvJA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAEA,MAAM;AACLA,kBADK;AAELC,cAFK;AAGLC;AAHK,IAIFC,wEAAU,CAAE,2BAAF,EAA+B,EAA/B,CAJd;AAMe;AACdC,MAAI,EAAE;AACLC,QAAI,EAAE,QADD;AAELC,WAAO,EAAEN;AAFJ,GADQ;AAKdC,cAAY,EAAE;AACbI,QAAI,EAAE,QADO;AAEbC,WAAO,EAAEL;AAFI,GALA;AASdM,MAAI,EAAE;AACLF,QAAI,EAAE,OADD;AAELC,WAAO,EAAEJ;AAFJ;AATQ,CAAf,E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACXA;AACA;AACA;AACA;AACA;AAKA;AACA;AAEA;AACA;AACA;;AACA;AAEO,MAAMM,IAAI,GAAG,CAAE;AAAEC,YAAF;AAAcC;AAAd,CAAF,KAAqC;AACxD,QAAM;AAAEN,QAAF;AAAQH,gBAAR;AAAsBM;AAAtB,MAA+BE,UAArC;AACA,QAAME,UAAU,GAAGC,6EAAa,EAAhC;AAEAC,SAAO,CAACC,GAAR,CAAY,MAAZ,EAAoB;AACnBV,QAAI,EAAEA,IADa;AAEnBH,gBAAY,EAAEA,YAFK;AAGnBM,QAAI,EAAEA;AAHa,GAApB;AAMA,SACC,gFAAUI,UAAV,EACC,yEAAC,yEAAD,QACC,yEAAC,+DAAD;AAAW,SAAK,EAAGI,0DAAE,CAAE,eAAF,EAAmB,2BAAnB;AAArB,sCADD,CADD,EAMC;AAAK,SAAK,EAAE;AAACC,aAAO,EAAE;AAAV;AAAZ,KACC,yEAAC,4EAAD;AACC,MAAE,EAAC,iBADJ;AAEC,WAAO,EAAG,KAFX;AAGC,YAAQ,EAAG;AAHZ,IADD,EAMC,yEAAC,gEAAD;AACC,SAAK,EAAGZ,IADT;AAEC,QAAI,EAAEW,0DAAE,CAAE,uCAAF,EAA2C,2BAA3C,CAFT;AAGC,YAAQ,EAAKE,KAAF,IAAaP,aAAa,CAAE;AAAEN,UAAI,EAAEa;AAAR,KAAF;AAHtC,IAND,CAND,EAmBEV,IAAI,IAAIA,IAAI,CAACW,MAAb,IAEC,4IACC;AAAK,SAAK,EAAE;AAACF,aAAO,EAAE,MAAV;AAAkBG,eAAS,EAAE;AAA7B;AAAZ,KACC,yEAAC,gEAAD;AACC,SAAK,EAAGlB,YADT;AAEC,QAAI,EAAEc,0DAAE,CAAE,wBAAF,EAA4B,2BAA5B,CAFT;AAGC,YAAQ,EAAKE,KAAF,IAAaP,aAAa,CAAE;AAAET,kBAAY,EAAEgB;AAAhB,KAAF;AAHtC,IADD,CADD,EAQEV,IAAI,CAACa,GAAL,CAAS,CAACC,QAAD,EAAWC,KAAX,KAAqB;AAC9B,WACC;AAAK,WAAK,EAAE;AAACN,eAAO,EAAE,MAAV;AAAkBG,iBAAS,EAAE;AAA7B;AAAZ,OACC,yEAAC,4EAAD;AACC,QAAE,EAAE,UAAQE,QAAQ,CAACE,uBADtB;AAEC,aAAO,EAAGhB,IAAI,CAACe,KAAD,CAAJ,CAAYE,OAFvB;AAGC,cAAQ,EAAG,MAAM;AAChBjB,YAAI,CAACe,KAAD,CAAJ,CAAYE,OAAZ,GAAsB,CAACjB,IAAI,CAACe,KAAD,CAAJ,CAAYE,OAAnC;AACAd,qBAAa,CAAC;AAACH,cAAI,EAAEA;AAAP,SAAD,CAAb;AACA;AANF,OAQC;AAAM,6BAAuB,EAAG;AAACkB,cAAM,EAAEJ,QAAQ,CAACjB;AAAlB;AAAhC,MARD,CADD,CADD;AAcA,GAfA,CARF,CArBH,CADD;AAmDA,CA7DM,C,CA+DP;;AACO,MAAMsB,IAAI,GAAG,MAAM;AACzB,SAAO,gFAAUd,qEAAa,CAACe,IAAd,EAAV,CAAP;AACA,CAFM,C;;;;;;;;;;;;;;;;;;;;;;;;;ACjFP;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;AACA;AACA;AACA;AAEAd,OAAO,CAACC,GAAR,CAAY,UAAZ,EAAwB;AACvBc,UAAQ,EAAEA,wCADa;AAEvBnB,YAAU,EAAEA,mDAAUA;AAFC,CAAxB;AAKAoB,2EAAiB,CAAED,wCAAF,EAAY;AAC5BE,MAAI,EAAE;AACLC,OAAG,EACF,yEAAC,yDAAD;AAAK,WAAK,EAAC,4BAAX;AAAwC,WAAK,EAAC,IAA9C;AAAmD,YAAM,EAAC,IAA1D;AAA+D,aAAO,EAAC,WAAvE;AAAmF,UAAI,EAAC;AAAxF,OACC;AACC,OAAC,EAAC,+PADH;AAEC,UAAI,EAAC;AAFN,MADD,EAIC;AACC,OAAC,EAAC,2YADH;AAEC,UAAI,EAAC;AAFN,MAJD,EAOC;AACC,OAAC,EAAC,6bADH;AAEC,UAAI,EAAC;AAFN,MAPD,EAUC;AACC,OAAC,EAAC,iNADH;AAEC,UAAI,EAAC;AAFN,MAVD,EAaC;AACC,OAAC,EAAC,iNADH;AAEC,UAAI,EAAC;AAFN,MAbD,EAgBC;AACC,OAAC,EAAC,47BADH;AAEC,UAAI,EAAC;AAFN,MAhBD,EAmBC;AACC,OAAC,EAAC,s/IADH;AAEC,UAAI,EAAC;AAFN,MAnBD,CAFI;AA0BLC,cAAU,EAAE;AA1BP,GADsB;AA6B5BC,MAAI,EAAEzB,0CA7BsB;AA8B5BmB,MAAI,EAAED,0CA9BsB;AA+B5BjB,YAAU,EAAE,EACX,GAAGmB,wCAAQ,CAACnB,UADD;AAEX,OAAGA,mDAAUA;AAFF;AA/BgB,CAAZ,CAAjB,C;;;;;;;;;;;AClBA,aAAa,iDAAiD,EAAE,I;;;;;;;;;;;ACAhE,aAAa,6CAA6C,EAAE,I;;;;;;;;;;;ACA5D,aAAa,8CAA8C,EAAE,I;;;;;;;;;;;ACA7D,aAAa,yCAAyC,EAAE,I;;;;;;;;;;;ACAxD,aAAa,6CAA6C,EAAE,I;;;;;;;;;;;ACA5D,aAAa,0CAA0C,EAAE,I;;;;;;;;;;;ACAzD,aAAa,uCAAuC,EAAE,I","file":"newsletter-block.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t\"newsletter-block\": 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp_woocommerce_mailchimp_newsletter\"] = window[\"webpackJsonp_woocommerce_mailchimp_newsletter\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([\"./assets/js/checkout-newsletter-subscription-block/index.js\",\"style-newsletter-block\"]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","/**\n * External dependencies\n */\nimport { getSetting } from '@woocommerce/settings';\n\nconst {\n\toptinDefaultText,\n\tgdprHeadline,\n\tgdprFields,\n} = getSetting( 'mailchimp-newsletter_data', '' );\n\nexport default {\n\ttext: {\n\t\ttype: 'string',\n\t\tdefault: optinDefaultText,\n\t},\n\tgdprHeadline: {\n\t\ttype: 'string',\n\t\tdefault: gdprHeadline,\n\t},\n\tgdpr: {\n\t\ttype: 'array',\n\t\tdefault: gdprFields\n\t}\n};\n","/**\n * External dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport {\n\tuseBlockProps,\n\tRichText,\n\tInspectorControls,\n} from '@wordpress/block-editor';\nimport { PanelBody } from '@wordpress/components';\nimport { CheckboxControl } from '@woocommerce/blocks-checkout';\n\n/**\n * Internal dependencies\n */\nimport './style.scss';\n\nexport const Edit = ( { attributes, setAttributes } ) => {\n\tconst { text, gdprHeadline, gdpr } = attributes;\n\tconst blockProps = useBlockProps();\n\n\tconsole.log('edit', {\n\t\ttext: text,\n\t\tgdprHeadline: gdprHeadline,\n\t\tgdpr: gdpr,\n\t});\n\n\treturn (\n\t\t<div { ...blockProps }>\n\t\t\t<InspectorControls>\n\t\t\t\t<PanelBody title={ __( 'Block options', 'mailchimp-for-woocommerce' ) }>\n\t\t\t\t\tOptions for the block go here.\n\t\t\t\t</PanelBody>\n\t\t\t</InspectorControls>\n\t\t\t<div style={{display: 'flex'}}>\n\t\t\t\t<CheckboxControl\n\t\t\t\t\tid=\"newsletter-text\"\n\t\t\t\t\tchecked={ false }\n\t\t\t\t\tdisabled={ true }\n\t\t\t\t/>\n\t\t\t\t<RichText\n\t\t\t\t\tvalue={ text }\n\t\t\t\t\thelp={__( 'Set the newsletter confirmation text.', 'mailchimp-for-woocommerce' )}\n\t\t\t\t\tonChange={ ( value ) => setAttributes( { text: value } ) }\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t{\n\t\t\t\tgdpr && gdpr.length &&\n\t\t\t\t(\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div style={{display: 'flex', marginTop: '2rem'}}>\n\t\t\t\t\t\t\t<RichText\n\t\t\t\t\t\t\t\tvalue={ gdprHeadline }\n\t\t\t\t\t\t\t\thelp={__( 'Set the GDPR headline.', 'mailchimp-for-woocommerce' )}\n\t\t\t\t\t\t\t\tonChange={ ( value ) => setAttributes( { gdprHeadline: value } ) }\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{gdpr.map((gdprItem, index) => {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div style={{display: 'flex', marginTop: '1rem'}}>\n\t\t\t\t\t\t\t\t\t<CheckboxControl\n\t\t\t\t\t\t\t\t\t\tid={'gdpr_'+gdprItem.marketing_permission_id}\n\t\t\t\t\t\t\t\t\t\tchecked={ gdpr[index].enabled }\n\t\t\t\t\t\t\t\t\t\tonChange={ () => {\n\t\t\t\t\t\t\t\t\t\t\tgdpr[index].enabled = !gdpr[index].enabled;\n\t\t\t\t\t\t\t\t\t\t\tsetAttributes({gdpr: gdpr});\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span dangerouslySetInnerHTML={ {__html: gdprItem.text} }/>\n\t\t\t\t\t\t\t\t\t</CheckboxControl>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</>\n\t\t\t\t)\n\t\t\t}\n\t\t</div>\n\t);\n};\n\n// not sure\nexport const Save = () => {\n\treturn <div { ...useBlockProps.save() } />;\n};\n","/**\n * External dependencies\n */\nimport { SVG } from '@wordpress/components';\nimport { registerBlockType } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { Edit, Save } from './edit';\nimport metadata from './block.json';\nimport attributes from './attributes';\n\nconsole.log('index.js', {\n\tmetadata: metadata,\n\tattributes: attributes,\n});\n\nregisterBlockType( metadata, {\n\ticon: {\n\t\tsrc: (\n\t\t\t<SVG xmlns=\"http://www.w3.org/2000/svg\" width=\"60\" height=\"60\" viewBox=\"0 0 46 49\" fill=\"none\">\n\t\t\t\t<path\n\t\t\t\t\td=\"M34.5458 23.5193C34.8988 23.4778 35.2361 23.4759 35.5457 23.5193C35.7252 23.107 35.7568 22.397 35.5951 21.6239C35.3544 20.4741 35.029 19.7778 34.3584 19.8863C33.6859 19.9948 33.6622 20.8271 33.9028 21.9769C34.037 22.6238 34.2776 23.1761 34.5458 23.5193Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M28.7763 24.4284C29.2575 24.6394 29.5534 24.7795 29.6678 24.6572C29.7427 24.5803 29.719 24.4363 29.6046 24.2489C29.368 23.8624 28.8788 23.4679 28.3621 23.249C27.303 22.7934 26.0407 22.9453 25.0664 23.6454C24.745 23.8801 24.4393 24.2075 24.4826 24.4047C24.4965 24.4698 24.5458 24.5172 24.6582 24.5329C24.9225 24.5625 25.8494 24.0951 26.9164 24.03C27.6718 23.9827 28.295 24.2174 28.7763 24.4284Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M27.8105 24.9806C27.1852 25.0793 26.8381 25.2863 26.6172 25.4777C26.4279 25.6433 26.3115 25.8267 26.3115 25.9549C26.3115 26.0161 26.3391 26.0516 26.3589 26.0693C26.3865 26.095 26.422 26.1088 26.4614 26.1088C26.6034 26.1088 26.919 25.9826 26.919 25.9826C27.7907 25.6709 28.3647 25.7084 28.9346 25.7735C29.2502 25.809 29.3981 25.8287 29.4672 25.7202C29.4869 25.6887 29.5125 25.6216 29.4494 25.521C29.3054 25.2804 28.6723 24.8781 27.8105 24.9806Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M32.5975 27.0061C33.0235 27.2152 33.4909 27.1324 33.6428 26.8227C33.7946 26.5131 33.5737 26.093 33.1497 25.8839C32.7237 25.6749 32.2563 25.7577 32.1044 26.0673C31.9506 26.377 32.1734 26.7971 32.5975 27.0061Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M35.3306 24.6177C34.9854 24.6118 34.6995 24.9905 34.6916 25.4638C34.6837 25.9372 34.9578 26.3257 35.303 26.3317C35.6481 26.3376 35.9341 25.9589 35.942 25.4855C35.9499 25.0122 35.6757 24.6237 35.3306 24.6177Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M12.1324 33.1577C12.0456 33.0492 11.9056 33.0827 11.7695 33.1143C11.6749 33.136 11.5664 33.1616 11.448 33.1596C11.1936 33.1557 10.9786 33.0452 10.8583 32.8598C10.7006 32.6192 10.7104 32.2583 10.884 31.8461C10.9076 31.7909 10.9353 31.7297 10.9648 31.6607C11.241 31.0394 11.7064 30 11.1857 29.008C10.7932 28.2625 10.1542 27.797 9.38702 27.7004C8.64939 27.6077 7.89006 27.8798 7.40685 28.4143C6.64358 29.2565 6.52328 30.4044 6.6712 30.8087C6.72445 30.9566 6.80925 30.998 6.87237 31.0059C7.00254 31.0237 7.19385 30.929 7.31416 30.6055C7.32205 30.5819 7.33388 30.5464 7.34769 30.501C7.40094 30.3294 7.50152 30.0099 7.66522 29.7555C7.86245 29.4478 8.17012 29.2348 8.53105 29.1579C8.89789 29.079 9.2746 29.15 9.58819 29.3551C10.1227 29.7062 10.3298 30.361 10.101 30.9862C9.98264 31.3096 9.79133 31.9289 9.83275 32.4378C9.91756 33.4673 10.5507 33.8795 11.1206 33.9249C11.6729 33.9466 12.0594 33.6349 12.1581 33.4081C12.2133 33.274 12.164 33.1932 12.1324 33.1577Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M44.044 31.2761C44.0223 31.2012 43.8862 30.7002 43.6969 30.0967C43.5075 29.4932 43.3142 29.0672 43.3142 29.0672C44.0696 27.9351 44.0834 26.9233 43.9828 26.3514C43.8763 25.6414 43.5805 25.0359 42.9829 24.4107C42.3873 23.7854 41.1684 23.1445 39.4545 22.6632C39.2593 22.608 38.6123 22.4305 38.5551 22.4127C38.5512 22.3753 38.5078 20.2945 38.4684 19.3991C38.4408 18.7522 38.3836 17.7444 38.0719 16.7504C37.6992 15.4053 37.0483 14.2298 36.2377 13.4764C38.4763 11.157 39.8726 8.60091 39.8707 6.40774C39.8647 2.19102 34.6855 0.914962 28.3033 3.55781C28.2974 3.55978 26.9602 4.1278 26.9503 4.13174C26.9444 4.12582 24.5066 1.73346 24.4692 1.7019C17.1954 -4.64488 -5.55475 20.6436 1.71899 26.7853L3.30864 28.1323C2.89644 29.2013 2.73471 30.4241 2.86685 31.7396C3.03647 33.4299 3.90822 35.0511 5.32234 36.3015C6.66348 37.4908 8.42669 38.2422 10.1386 38.2402C12.9688 44.7626 19.4359 48.7643 27.0193 48.9891C35.153 49.2317 41.981 45.4134 44.8428 38.5578C45.0301 38.0765 45.825 35.909 45.825 33.9939C45.825 32.0729 44.7382 31.2761 44.044 31.2761ZM10.7638 36.41C10.5173 36.4514 10.2649 36.4691 10.0104 36.4632C7.55298 36.3981 4.90027 34.1852 4.63598 31.5621C4.34409 28.6629 5.82527 26.4322 8.44839 25.9017C8.76198 25.8386 9.14066 25.8011 9.54892 25.8228C11.0183 25.9037 13.1838 27.0318 13.6789 30.2328C14.1187 33.0689 13.4225 35.9564 10.7638 36.41ZM8.02041 24.1681C6.38736 24.4856 4.9476 25.4106 4.06797 26.6886C3.54137 26.2508 2.56115 25.4007 2.38956 25.0694C0.985306 22.4009 3.92202 17.2138 5.97516 14.285C11.0478 7.04676 18.9922 1.56581 22.6705 2.55984C23.2681 2.72945 25.2482 5.02518 25.2482 5.02518C25.2482 5.02518 21.5719 7.06451 18.1618 9.90853C13.5704 13.4468 10.0992 18.5885 8.02041 24.1681ZM33.8079 35.3252C33.8611 35.3035 33.8986 35.2424 33.8927 35.1812C33.8848 35.1063 33.8177 35.0531 33.7448 35.0609C33.7448 35.0609 29.8969 35.6309 26.26 34.2996C26.6564 33.0117 27.7096 33.4772 29.3012 33.6054C32.1709 33.777 34.7408 33.3569 36.642 32.8125C38.2889 32.3392 40.4505 31.4083 42.1309 30.0829C42.6969 31.3274 42.8981 32.6962 42.8981 32.6962C42.8981 32.6962 43.3359 32.6173 43.7028 32.8441C44.0499 33.0571 44.3024 33.5009 44.1288 34.6448C43.7758 36.7847 42.8665 38.5223 41.338 40.1198C40.4071 41.1217 39.277 41.9935 37.9852 42.6266C37.2988 42.9875 36.5671 43.2991 35.7959 43.5516C30.033 45.4331 24.1339 43.3642 22.2326 38.9207C22.0807 38.5874 21.9525 38.2363 21.852 37.8714C21.0414 34.9426 21.7297 31.43 23.8795 29.2171C23.8795 29.2171 23.8795 29.2171 23.8795 29.2151C24.0116 29.0751 24.1477 28.9094 24.1477 28.7004C24.1477 28.5248 24.0372 28.3414 23.9406 28.2112C23.1892 27.1206 20.5818 25.2607 21.1045 21.6613C21.4792 19.0757 23.7414 17.2553 25.8498 17.3637C26.0273 17.3736 26.2067 17.3834 26.3842 17.3953C27.2974 17.4485 28.0942 17.5669 28.8476 17.5984C30.1059 17.6537 31.238 17.4702 32.5792 16.3519C33.0308 15.9752 33.3937 15.6478 34.0071 15.5453C34.0722 15.5335 34.2319 15.4763 34.5534 15.492C34.8808 15.5098 35.1924 15.5985 35.4725 15.7859C36.5474 16.5018 36.6992 18.2335 36.7545 19.4997C36.786 20.2235 36.8728 21.9729 36.9044 22.4759C36.9734 23.6237 37.2751 23.7874 37.8846 23.9886C38.2278 24.101 38.5473 24.1858 39.0167 24.318C40.4387 24.7183 41.2828 25.1227 41.8153 25.6433C42.1329 25.9688 42.2808 26.3139 42.3261 26.6433C42.4938 27.8661 41.3755 29.3788 38.4171 30.7515C35.1826 32.2524 31.2577 32.6331 28.5459 32.3313C28.3388 32.3076 27.5992 32.2248 27.5952 32.2248C25.4257 31.9329 24.1891 34.7355 25.4908 36.6565C26.329 37.8951 28.6149 38.6998 30.9008 38.6998C36.1431 38.6998 40.1724 36.4613 41.6713 34.5284C41.7167 34.4712 41.7206 34.4633 41.7916 34.3568C41.8646 34.2464 41.8055 34.1852 41.7128 34.2464C40.488 35.0846 35.0484 38.4099 29.2322 37.4099C29.2322 37.4099 28.5261 37.2936 27.8792 37.0431C27.3664 36.8439 26.2935 36.3508 26.1634 35.2483C30.8514 36.6979 33.8079 35.3252 33.8079 35.3252ZM26.3704 34.4476C26.3704 34.4476 26.3724 34.4476 26.3704 34.4476C26.3724 34.4495 26.3724 34.4495 26.3724 34.4515C26.3724 34.4495 26.3724 34.4476 26.3704 34.4476ZM17.3887 14.2554C19.1914 12.1707 21.4121 10.3602 23.4002 9.34249C23.4692 9.30699 23.5422 9.38193 23.5047 9.44899C23.3469 9.73497 23.0432 10.3464 22.9466 10.8118C22.9308 10.8848 23.0097 10.9381 23.0708 10.8966C24.3074 10.0525 26.4612 9.14921 28.3486 9.03284C28.4295 9.02693 28.4689 9.13146 28.4039 9.18076C28.1159 9.40166 27.8023 9.70539 27.5735 10.0131C27.5341 10.0663 27.5716 10.1413 27.6366 10.1413C28.962 10.1511 30.8317 10.6146 32.0486 11.297C32.1315 11.3424 32.0723 11.5021 31.9796 11.4824C30.1375 11.0603 27.1199 10.7389 23.986 11.5041C21.1893 12.1865 19.0533 13.2397 17.4952 14.3738C17.4203 14.4329 17.3256 14.3304 17.3887 14.2554Z\"\n\t\t\t\t\tfill=\"black\"/>\n\t\t\t</SVG>\n\t\t),\n\t\tforeground: '#874FB9',\n\t},\n\tedit: Edit,\n\tsave: Save,\n\tattributes: {\n\t\t...metadata.attributes,\n\t\t...attributes,\n\t},\n} );\n","(function() { module.exports = window[\"wc\"][\"blocksCheckout\"]; }());","(function() { module.exports = window[\"wc\"][\"wcSettings\"]; }());","(function() { module.exports = window[\"wp\"][\"blockEditor\"]; }());","(function() { module.exports = window[\"wp\"][\"blocks\"]; }());","(function() { module.exports = window[\"wp\"][\"components\"]; }());","(function() { module.exports = window[\"wp\"][\"element\"]; }());","(function() { module.exports = window[\"wp\"][\"i18n\"]; }());"],"sourceRoot":""}
 
blocks/build/style-newsletter-block.css CHANGED
@@ -1,17 +1 @@
1
- .wp-block-woocommerce-checkout-newsletter-subscription {
2
- margin: 20px 0;
3
- padding-top: 4px;
4
- padding-bottom: 4px;
5
- display: flex;
6
- align-items: flex-start;
7
- }
8
- .wp-block-woocommerce-checkout-newsletter-subscription .block-editor-rich-text__editable {
9
- vertical-align: middle;
10
- line-height: 24px;
11
- }
12
- .wp-block-woocommerce-checkout-newsletter-subscription .wc-block-components-checkbox {
13
- margin-right: 16px;
14
- margin-top: 0;
15
- }
16
-
17
- /*# sourceMappingURL=style-newsletter-block.css.map*/
1
+ .wp-block-woocommerce-checkout-newsletter-subscription{margin:20px 0;padding-top:4px;padding-bottom:4px;display:flex;align-items:flex-start}.wp-block-woocommerce-checkout-newsletter-subscription .block-editor-rich-text__editable{vertical-align:middle;line-height:24px}.wp-block-woocommerce-checkout-newsletter-subscription .wc-block-components-checkbox{margin-right:16px;margin-top:0}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
blocks/build/style-newsletter-block.css.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["webpack:///./assets/js/checkout-newsletter-subscription-block/style.scss"],"names":[],"mappings":"AAAA;EACC;EACA;EACA;EACA;EACA;AACD;AACC;EACC;EACA;AACF;AAEC;EACC;EACA;AAAF,C","file":"style-newsletter-block.css","sourcesContent":[".wp-block-woocommerce-checkout-newsletter-subscription {\n\tmargin: 20px 0;\n\tpadding-top: 4px;\n\tpadding-bottom: 4px;\n\tdisplay: flex;\n\talign-items: flex-start;\n\n\t.block-editor-rich-text__editable {\n\t\tvertical-align: middle;\n\t\tline-height: 24px;\n\t}\n\n\t.wc-block-components-checkbox {\n\t\tmargin-right: 16px;\n\t\tmargin-top: 0;\n\t}\n}"],"sourceRoot":""}
 
blocks/{newsletter-test.php → newsletter.php} RENAMED
File without changes
blocks/package-lock.json CHANGED
@@ -7430,10 +7430,20 @@
7430
  }
7431
  },
7432
  "node_modules/caniuse-lite": {
7433
- "version": "1.0.30001251",
7434
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz",
7435
- "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==",
7436
- "dev": true
 
 
 
 
 
 
 
 
 
 
7437
  },
7438
  "node_modules/capture-exit": {
7439
  "version": "2.0.0",
@@ -30051,9 +30061,9 @@
30051
  }
30052
  },
30053
  "caniuse-lite": {
30054
- "version": "1.0.30001251",
30055
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz",
30056
- "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==",
30057
  "dev": true
30058
  },
30059
  "capture-exit": {
7430
  }
7431
  },
7432
  "node_modules/caniuse-lite": {
7433
+ "version": "1.0.30001341",
7434
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001341.tgz",
7435
+ "integrity": "sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA==",
7436
+ "dev": true,
7437
+ "funding": [
7438
+ {
7439
+ "type": "opencollective",
7440
+ "url": "https://opencollective.com/browserslist"
7441
+ },
7442
+ {
7443
+ "type": "tidelift",
7444
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
7445
+ }
7446
+ ]
7447
  },
7448
  "node_modules/capture-exit": {
7449
  "version": "2.0.0",
30061
  }
30062
  },
30063
  "caniuse-lite": {
30064
+ "version": "1.0.30001341",
30065
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001341.tgz",
30066
+ "integrity": "sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA==",
30067
  "dev": true
30068
  },
30069
  "capture-exit": {
blocks/package.json CHANGED
@@ -28,11 +28,11 @@
28
  "scripts": {
29
  "prebuild": "rm -rf ./vendor",
30
  "build": "npm run build:js && npm run makepot && npm run archive",
31
- "build:dev": "pm run makepot",
32
  "build:js": "wp-scripts build",
33
  "archive": "composer archive --file=$npm_package_name --format=zip",
34
  "postarchive": "rm -rf $npm_package_name && unzip $npm_package_name.zip -d $npm_package_name && rm $npm_package_name.zip && zip -r $npm_package_name.zip $npm_package_name && rm -rf $npm_package_name",
35
- "check-engines": "wp-scripts che ck-engines",
36
  "check-licenses": "wp-scripts check-licenses",
37
  "format:js": "wp-scripts format-js",
38
  "lint:css": "wp-scripts lint-style assets/js",
@@ -40,7 +40,7 @@
40
  "lint:js-fix": "eslint assets/js --ext=js,jsx,ts,tsx --fix",
41
  "start": "wp-scripts start",
42
  "test:unit": "wp-scripts test-unit-js",
43
- "makepot": "wpi18n makepot --domain-path ../languages --pot-file mc-woocommerce-newsletter.pot --type plugin --main-file newsletter-test.php --exclude node_modules,tests,docs"
44
  },
45
  "engines": {
46
  "node": ">=8.9.3",
28
  "scripts": {
29
  "prebuild": "rm -rf ./vendor",
30
  "build": "npm run build:js && npm run makepot && npm run archive",
31
+ "build:dev": "npm run makepot",
32
  "build:js": "wp-scripts build",
33
  "archive": "composer archive --file=$npm_package_name --format=zip",
34
  "postarchive": "rm -rf $npm_package_name && unzip $npm_package_name.zip -d $npm_package_name && rm $npm_package_name.zip && zip -r $npm_package_name.zip $npm_package_name && rm -rf $npm_package_name",
35
+ "check-engines": "wp-scripts check-engines",
36
  "check-licenses": "wp-scripts check-licenses",
37
  "format:js": "wp-scripts format-js",
38
  "lint:css": "wp-scripts lint-style assets/js",
40
  "lint:js-fix": "eslint assets/js --ext=js,jsx,ts,tsx --fix",
41
  "start": "wp-scripts start",
42
  "test:unit": "wp-scripts test-unit-js",
43
+ "makepot": "wpi18n makepot --domain-path ../languages --pot-file mc-woocommerce-newsletter.pot --type plugin --main-file newsletter-blocks-integration.php --exclude node_modules,tests,docs"
44
  },
45
  "engines": {
46
  "node": ">=8.9.3",
blocks/sample.json DELETED
@@ -1,45 +0,0 @@
1
- {
2
- "billing_address": {
3
- "first_name": "Ryan",
4
- "last_name": "Hungate",
5
- "company": "",
6
- "address_1": "10754 N CHAPIN CT",
7
- "address_2": "",
8
- "city": "ORO VALLEY",
9
- "state": "AZ",
10
- "postcode": "85737-6634",
11
- "country": "US",
12
- "email": "ryanhungate@icloud.com",
13
- "phone": "15203057061"
14
- },
15
- "shipping_address": {
16
- "first_name": "Ryan",
17
- "last_name": "Hungate",
18
- "company": "",
19
- "address_1": "10754 N CHAPIN CT",
20
- "address_2": "",
21
- "city": "ORO VALLEY",
22
- "state": "AZ",
23
- "postcode": "85737-6634",
24
- "country": "US",
25
- "phone": "15203057061"
26
- },
27
- "customer_note": "",
28
- "should_create_account": false,
29
- "payment_method": "cod",
30
- "payment_data": [
31
- {
32
- "key": "payment_method",
33
- "value": ""
34
- },
35
- {
36
- "key": "wc-cod-new-payment-method",
37
- "value": false
38
- }
39
- ],
40
- "extensions": {
41
- "mailchimp-newsletter": {
42
- "optin": true
43
- }
44
- }
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
blocks/woocommerce-blocks-integration.php CHANGED
@@ -190,6 +190,16 @@ class Mailchimp_Woocommerce_Newsletter_Blocks_Integration implements Integration
190
  },
191
  ),
192
  ),
 
 
 
 
 
 
 
 
 
 
193
  );
194
  },
195
  )
@@ -231,10 +241,15 @@ class Mailchimp_Woocommerce_Newsletter_Blocks_Integration implements Integration
231
  {
232
  $meta_key = 'mailchimp_woocommerce_is_subscribed';
233
  $optin = $request['extensions']['mailchimp-newsletter']['optin'];
234
- //$email = $request['billing_address']['email'];
 
235
 
236
  // update the order meta for the subscription status to support legacy functions
237
  update_post_meta($order->get_id(), $meta_key, $optin);
 
 
 
 
238
 
239
  // if the user id exists
240
  if (($user_id = $order->get_user_id())) {
@@ -244,7 +259,6 @@ class Mailchimp_Woocommerce_Newsletter_Blocks_Integration implements Integration
244
  if ((bool) $optin) {
245
  // probably need to add the GDPR fields and language in to this submission next.
246
  $language = null;
247
- $gdpr_fields = null;
248
  mailchimp_handle_or_queue(
249
  new MailChimp_WooCommerce_User_Submit(
250
  $user_id,
@@ -257,10 +271,25 @@ class Mailchimp_Woocommerce_Newsletter_Blocks_Integration implements Integration
257
  }
258
  }
259
 
260
- // maybe add the filter to only submit orders from subscribers?
261
- $service = MailChimp_Service::instance();
262
- $tracking = $service->onNewOrder($order->get_id());
263
- $service->onOrderSave($order->get_id(), $tracking, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  }
265
 
266
  /**
@@ -285,7 +314,8 @@ class Mailchimp_Woocommerce_Newsletter_Blocks_Integration implements Integration
285
  if (!($list_id = mailchimp_get_list_id())) {
286
  return array();
287
  }
288
- return mailchimp_get_api()->getCachedGDPRFields($list_id);
 
289
  }
290
 
291
  /**
190
  },
191
  ),
192
  ),
193
+ 'gdprFields' => array(
194
+ 'description' => __( 'GDPR marketing opt-in.', 'mailchimp-newsletter' ),
195
+ 'type' => 'object',
196
+ 'context' => array(),
197
+ 'arg_options' => array(
198
+ 'validate_callback' => function( $value ) {
199
+ return true;
200
+ },
201
+ ),
202
+ ),
203
  );
204
  },
205
  )
241
  {
242
  $meta_key = 'mailchimp_woocommerce_is_subscribed';
243
  $optin = $request['extensions']['mailchimp-newsletter']['optin'];
244
+ $gdpr_fields = isset($request['extensions']['mailchimp-newsletter']['gdprFields']) ?
245
+ (array) $request['extensions']['mailchimp-newsletter']['gdprFields'] : null;
246
 
247
  // update the order meta for the subscription status to support legacy functions
248
  update_post_meta($order->get_id(), $meta_key, $optin);
249
+ // let's set the GDPR fields here just in case we need to pull them again.
250
+ if (!empty($gdpr_fields)) {
251
+ update_post_meta($order->get_id(), "mailchimp_woocommerce_gdpr_fields", $gdpr_fields);
252
+ }
253
 
254
  // if the user id exists
255
  if (($user_id = $order->get_user_id())) {
259
  if ((bool) $optin) {
260
  // probably need to add the GDPR fields and language in to this submission next.
261
  $language = null;
 
262
  mailchimp_handle_or_queue(
263
  new MailChimp_WooCommerce_User_Submit(
264
  $user_id,
271
  }
272
  }
273
 
274
+ $tracking = MailChimp_Service::instance()->onNewOrder($order->get_id());
275
+ // queue up the single order to be processed.
276
+ $campaign_id = isset($tracking) && isset($tracking['campaign_id']) ? $tracking['campaign_id'] : null;
277
+ $landing_site = isset($tracking) && isset($tracking['landing_site']) ? $tracking['landing_site'] : null;
278
+ $language = substr( get_locale(), 0, 2 );
279
+
280
+ // update the post meta with campaign tracking details for future sync
281
+ if (!empty($campaign_id)) {
282
+ update_post_meta($order->get_id(), 'mailchimp_woocommerce_campaign_id', $campaign_id);
283
+ }
284
+ if (!empty($landing_site)) {
285
+ update_post_meta($order->get_id(), 'mailchimp_woocommerce_landing_site', $landing_site);
286
+ }
287
+
288
+ $handler = new MailChimp_WooCommerce_Single_Order($order->get_id(), null, $campaign_id, $landing_site, $language, $gdpr_fields);
289
+ $handler->is_update = false;
290
+ $handler->is_admin_save = is_admin();
291
+
292
+ mailchimp_handle_or_queue($handler, 15);
293
  }
294
 
295
  /**
314
  if (!($list_id = mailchimp_get_list_id())) {
315
  return array();
316
  }
317
+ $fields = mailchimp_get_api()->getCachedGDPRFields($list_id);
318
+ return is_array($fields) ? $fields : array();
319
  }
320
 
321
  /**
bootstrap.php CHANGED
@@ -65,9 +65,15 @@ spl_autoload_register(function($class) {
65
  'MailChimp_WooCommerce_User_Submit' => 'includes/processes/class-mailchimp-woocommerce-user-submit.php',
66
  'MailChimp_WooCommerce_Process_Full_Sync_Manager' => 'includes/processes/class-mailchimp-woocommerce-full-sync-manager.php',
67
  'MailChimp_WooCommerce_Subscriber_Sync' => 'includes/processes/class-mailchimp-woocommerce-subscriber-sync.php',
 
68
 
69
  'MailChimp_WooCommerce_Public' => 'public/class-mailchimp-woocommerce-public.php',
70
  'MailChimp_WooCommerce_Admin' => 'admin/class-mailchimp-woocommerce-admin.php',
 
 
 
 
 
71
  );
72
 
73
  // if the file exists, require it
@@ -88,7 +94,7 @@ function mailchimp_environment_variables() {
88
  return (object) array(
89
  'repo' => 'master',
90
  'environment' => 'production', // staging or production
91
- 'version' => '2.6.2',
92
  'php_version' => phpversion(),
93
  'wp_version' => (empty($wp_version) ? 'Unknown' : $wp_version),
94
  'wc_version' => function_exists('WC') ? WC()->version : null,
@@ -187,10 +193,11 @@ function mailchimp_as_push( Mailchimp_Woocommerce_Job $job, $delay = 0 ) {
187
  * @param bool $force_now
188
  */
189
  function mailchimp_handle_or_queue(Mailchimp_Woocommerce_Job $job, $delay = 0)
190
- {
191
- if ($job instanceof \MailChimp_WooCommerce_Single_Order && isset($job->id)) {
192
  // if this is a order process already queued - just skip this
193
  if (get_site_transient("mailchimp_order_being_processed_{$job->id}") == true) {
 
194
  return;
195
  }
196
  // tell the system the order is already queued for processing in this saving process - and we don't need to process it again.
@@ -305,7 +312,51 @@ function mailchimp_get_api_key() {
305
  function mailchimp_get_list_id() {
306
  return mailchimp_get_option('mailchimp_list', false);
307
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
 
 
 
309
  /**
310
  * @return string
311
  */
@@ -1167,7 +1218,7 @@ function mailchimp_update_member_with_double_opt_in(MailChimp_WooCommerce_Order
1167
  } catch (\Exception $e) {
1168
  // if the error code is 404 - need to subscribe them because it means they were not on the list.
1169
  if ($e->getCode() == 404) {
1170
- $api->subscribe($list_id, $email, false, $merge_fields);
1171
  mailchimp_tell_system_about_user_submit($email, mailchimp_get_subscriber_status_options(false), 60);
1172
  mailchimp_log('double_opt_in', "Subscribed {$email} Using Double Opt In", $merge_fields);
1173
  } else {
@@ -1193,8 +1244,10 @@ function mailchimp_update_communication_status() {
1193
  $original_opt = $plugin_admin->getData('comm.opt',0);
1194
  $options = $plugin_admin->getOptions();
1195
  if (is_array($options) && array_key_exists('admin_email', $options)) {
1196
- $plugin_admin->mailchimp_set_communications_status_on_server($original_opt, $options['admin_email']);
1197
  }
 
 
1198
  }
1199
 
1200
  // call server to update comm status
@@ -1258,6 +1311,7 @@ function mailchimp_member_data_update($user_email = null, $language = null, $cal
1258
  'user_language' => $language,
1259
  'caller' => $caller,
1260
  'status_if_new' => $status_if_new,
 
1261
  ));
1262
  if (!$user_email) return;
1263
 
@@ -1272,14 +1326,11 @@ function mailchimp_member_data_update($user_email = null, $language = null, $cal
1272
  // update member with new data
1273
  // if the member's subscriber status was transactional - and if we're passing in either one of these options below,
1274
  // we can attach the new status to the member.
1275
-
1276
-
1277
  if ($member['status'] === 'transactional' && in_array($status_if_new, array('subscribed', 'pending'))) {
1278
  $member['status'] = $status_if_new;
1279
  }
1280
-
1281
  if (($member['status'] === 'transactional' && in_array($status_if_new, array('subscribed', 'pending'))) || $member['status'] === 'subscribed') {
1282
- if (!empty($gdpr_fields)) {
1283
  $gdpr_fields_to_save = [];
1284
  foreach ($gdpr_fields as $id => $value) {
1285
  $gdpr_field['marketing_permission_id'] = $id;
@@ -1290,27 +1341,32 @@ function mailchimp_member_data_update($user_email = null, $language = null, $cal
1290
  }
1291
  $merge_fields = $order ? apply_filters('mailchimp_get_ecommerce_merge_tags', array(), $order) : array();
1292
  if (!is_array($merge_fields)) $merge_fields = array();
1293
-
1294
  if ($update_status && in_array($member['status'], array('unsubscribed', 'cleaned'))) {
1295
  $member['status'] = $status_if_new;
1296
  }
1297
-
1298
  $result = mailchimp_get_api()->update($list_id, $user_email, $member['status'], $merge_fields, null, $language, $gdpr_fields_to_save);
1299
  // set transient to prevent too many calls to update language
1300
  mailchimp_set_transient($caller . ".member.{$hash}", true, 3600);
1301
-
1302
  mailchimp_log($caller . '.member.updated', "Updated {$user_email} subscriber status to {$result['status']} and language to {$language}");
1303
  } catch (\Exception $e) {
1304
  if ($e->getCode() == 404) {
1305
  $merge_fields = $order ? apply_filters('mailchimp_get_ecommerce_merge_tags', array(), $order) : array();
1306
  if (!is_array($merge_fields)) $merge_fields = array();
 
 
 
 
 
 
 
 
1307
  // member doesn't exist yet, create as transactional ( or what was passed in the function args )
1308
- mailchimp_get_api()->subscribe($list_id, $user_email, $status_if_new, $merge_fields, array(), $language);
1309
  // set transient to prevent too many calls to update language
1310
  mailchimp_set_transient($caller . ".member.{$hash}", true, 3600);
1311
  mailchimp_log($caller . '.member.created', "Added {$user_email} as transactional, setting language to [{$language}]");
1312
  } else {
1313
- mailchimp_error($caller . '.member.sync.error', $e->getMessage(), $user_email);
1314
  }
1315
  }
1316
  }
@@ -1357,7 +1413,29 @@ function mailchimp_allowed_to_use_cookie($cookie) {
1357
  // return the $cookie_name if you will allow it -
1358
  // otherwise it is going to turn this feature off.
1359
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1360
 
 
 
 
 
 
 
 
 
1361
 
1362
  // Add WP CLI commands
1363
  if (defined( 'WP_CLI' ) && WP_CLI) {
@@ -1403,4 +1481,4 @@ if (defined( 'WP_CLI' ) && WP_CLI) {
1403
  WP_CLI::add_command( 'mailchimp_push', 'mailchimp_cli_push_command');
1404
  WP_CLI::add_command( 'queue', 'Mailchimp_Wocoomerce_CLI' );
1405
  } catch (\Exception $e) {}
1406
- }
65
  'MailChimp_WooCommerce_User_Submit' => 'includes/processes/class-mailchimp-woocommerce-user-submit.php',
66
  'MailChimp_WooCommerce_Process_Full_Sync_Manager' => 'includes/processes/class-mailchimp-woocommerce-full-sync-manager.php',
67
  'MailChimp_WooCommerce_Subscriber_Sync' => 'includes/processes/class-mailchimp-woocommerce-subscriber-sync.php',
68
+ 'MailChimp_WooCommerce_WebHooks_Sync' => 'includes/processes/class-mailchimp-woocommerce-webhooks-sync.php',
69
 
70
  'MailChimp_WooCommerce_Public' => 'public/class-mailchimp-woocommerce-public.php',
71
  'MailChimp_WooCommerce_Admin' => 'admin/class-mailchimp-woocommerce-admin.php',
72
+
73
+ 'MailChimp_WooCommerce_Fix_Duplicate_Store' => 'includes/api/class-mailchimp-woocommerce-fix-duplicate-store.php',
74
+ 'MailChimp_WooCommerce_Logs' => 'includes/api/class-mailchimp-woocommerce-logs.php',
75
+ 'MailChimp_WooCommerce_Tower' => 'includes/api/class-mailchimp-woocommerce-tower.php',
76
+ 'MailChimp_WooCommerce_Log_Viewer' => 'includes/api/class-mailchimp-woocommerce-log-viewer.php',
77
  );
78
 
79
  // if the file exists, require it
94
  return (object) array(
95
  'repo' => 'master',
96
  'environment' => 'production', // staging or production
97
+ 'version' => '2.7',
98
  'php_version' => phpversion(),
99
  'wp_version' => (empty($wp_version) ? 'Unknown' : $wp_version),
100
  'wc_version' => function_exists('WC') ? WC()->version : null,
193
  * @param bool $force_now
194
  */
195
  function mailchimp_handle_or_queue(Mailchimp_Woocommerce_Job $job, $delay = 0)
196
+ {
197
+ if ($job instanceof \MailChimp_WooCommerce_Single_Order && isset($job->id) && empty($job->gdpr_fields)) {
198
  // if this is a order process already queued - just skip this
199
  if (get_site_transient("mailchimp_order_being_processed_{$job->id}") == true) {
200
+ mailchimp_debug('queue', "Not queuing up order {$job->id} because it's already queued");
201
  return;
202
  }
203
  // tell the system the order is already queued for processing in this saving process - and we don't need to process it again.
312
  function mailchimp_get_list_id() {
313
  return mailchimp_get_option('mailchimp_list', false);
314
  }
315
+ /**
316
+ * Build mailchimp webhook url
317
+ * @param string $key Encripted randome script
318
+ * @return string $url Webhook url
319
+ */
320
+ function mailchimp_build_webhook_url( $key ) {
321
+ $key = base64_encode($key);
322
+ $url = MailChimp_WooCommerce_Rest_Api::url('member-sync') . '?auth=' . $key;
323
+ return $url;
324
+ }
325
+ /**
326
+ * Generate random string
327
+ * @return string
328
+ */
329
+ function mailchimp_create_webhook_token(){
330
+ return md5( trim( strtolower(get_bloginfo('url') . '|' . time() . '|' . mailchimp_get_list_id() . '|' . wp_salt() ) ) );
331
+ }
332
+ /**
333
+ * Updates webhookurl option
334
+ * @param string $url Webhook url
335
+ * @return void
336
+ */
337
+ function mailchimp_set_webhook_url( $url ) {
338
+ update_option('mc-mailchimp_webhook_url', $url);
339
+ }
340
+ /**
341
+ * Returns webhookurl option
342
+ * @return string
343
+ */
344
+ function mailchimp_get_webhook_url() {
345
+ return get_option('mc-mailchimp_webhook_url', false);
346
+ }
347
+ /**
348
+ * Returns webhook url
349
+ * @return array Common localhost ips
350
+ */
351
+ function mailchimp_common_loopback_ips(){
352
+ $common_loopback_ips = array(
353
+ '127.0.0.1',
354
+ '0:0:0:0:0:0:0:1',
355
+ '::1'
356
+ );
357
 
358
+ return $common_loopback_ips;
359
+ }
360
  /**
361
  * @return string
362
  */
1218
  } catch (\Exception $e) {
1219
  // if the error code is 404 - need to subscribe them because it means they were not on the list.
1220
  if ($e->getCode() == 404) {
1221
+ $api->subscribe($list_id, $email, 'pending', $merge_fields);
1222
  mailchimp_tell_system_about_user_submit($email, mailchimp_get_subscriber_status_options(false), 60);
1223
  mailchimp_log('double_opt_in', "Subscribed {$email} Using Double Opt In", $merge_fields);
1224
  } else {
1244
  $original_opt = $plugin_admin->getData('comm.opt',0);
1245
  $options = $plugin_admin->getOptions();
1246
  if (is_array($options) && array_key_exists('admin_email', $options)) {
1247
+ $plugin_admin->mailchimp_set_communications_status_on_server($original_opt, $options['admin_email']);
1248
  }
1249
+ // communication is ready lets define the webhooks
1250
+ $plugin_admin->defineWebhooks();
1251
  }
1252
 
1253
  // call server to update comm status
1311
  'user_language' => $language,
1312
  'caller' => $caller,
1313
  'status_if_new' => $status_if_new,
1314
+ 'gdpr_fields' => $gdpr_fields,
1315
  ));
1316
  if (!$user_email) return;
1317
 
1326
  // update member with new data
1327
  // if the member's subscriber status was transactional - and if we're passing in either one of these options below,
1328
  // we can attach the new status to the member.
 
 
1329
  if ($member['status'] === 'transactional' && in_array($status_if_new, array('subscribed', 'pending'))) {
1330
  $member['status'] = $status_if_new;
1331
  }
 
1332
  if (($member['status'] === 'transactional' && in_array($status_if_new, array('subscribed', 'pending'))) || $member['status'] === 'subscribed') {
1333
+ if (!empty($gdpr_fields) && is_array($gdpr_fields)) {
1334
  $gdpr_fields_to_save = [];
1335
  foreach ($gdpr_fields as $id => $value) {
1336
  $gdpr_field['marketing_permission_id'] = $id;
1341
  }
1342
  $merge_fields = $order ? apply_filters('mailchimp_get_ecommerce_merge_tags', array(), $order) : array();
1343
  if (!is_array($merge_fields)) $merge_fields = array();
 
1344
  if ($update_status && in_array($member['status'], array('unsubscribed', 'cleaned'))) {
1345
  $member['status'] = $status_if_new;
1346
  }
 
1347
  $result = mailchimp_get_api()->update($list_id, $user_email, $member['status'], $merge_fields, null, $language, $gdpr_fields_to_save);
1348
  // set transient to prevent too many calls to update language
1349
  mailchimp_set_transient($caller . ".member.{$hash}", true, 3600);
 
1350
  mailchimp_log($caller . '.member.updated', "Updated {$user_email} subscriber status to {$result['status']} and language to {$language}");
1351
  } catch (\Exception $e) {
1352
  if ($e->getCode() == 404) {
1353
  $merge_fields = $order ? apply_filters('mailchimp_get_ecommerce_merge_tags', array(), $order) : array();
1354
  if (!is_array($merge_fields)) $merge_fields = array();
1355
+ if (!empty($gdpr_fields) && is_array($gdpr_fields)) {
1356
+ $gdpr_fields_to_save = [];
1357
+ foreach ($gdpr_fields as $id => $value) {
1358
+ $gdpr_field['marketing_permission_id'] = $id;
1359
+ $gdpr_field['enabled'] = (bool) $value;
1360
+ $gdpr_fields_to_save[] = $gdpr_field;
1361
+ }
1362
+ }
1363
  // member doesn't exist yet, create as transactional ( or what was passed in the function args )
1364
+ mailchimp_get_api()->subscribe($list_id, $user_email, $status_if_new, $merge_fields, array(), $language, $gdpr_fields_to_save);
1365
  // set transient to prevent too many calls to update language
1366
  mailchimp_set_transient($caller . ".member.{$hash}", true, 3600);
1367
  mailchimp_log($caller . '.member.created', "Added {$user_email} as transactional, setting language to [{$language}]");
1368
  } else {
1369
+ mailchimp_error($caller . '.member.sync.error', $e->getMessage());
1370
  }
1371
  }
1372
  }
1413
  // return the $cookie_name if you will allow it -
1414
  // otherwise it is going to turn this feature off.
1415
 
1416
+ /**
1417
+ * @return mixed|null
1418
+ */
1419
+ function mailchimp_get_outbound_ip() {
1420
+ // if we have a dedicated IP address, and have set a configuration for it, we'll use it here.
1421
+ if (defined('MAILCHIMP_USE_OUTBOUND_IP')) {
1422
+ return MAILCHIMP_USE_OUTBOUND_IP;
1423
+ } elseif (($server_address = mailchimp_get_data('SERVER_ADDR')) && !empty($server_address)) {
1424
+ return $server_address;
1425
+ } elseif (isset($_SERVER) && isset($_SERVER['SERVER_ADDR']) && !empty($_SERVER['SERVER_ADDR'])) {
1426
+ return $_SERVER['SERVER_ADDR'];
1427
+ }
1428
+ return null;
1429
+ }
1430
 
1431
+ /**
1432
+ * @return bool
1433
+ */
1434
+ function mailchimp_render_gdpr_fields() {
1435
+ return true;
1436
+ return defined('MAILCHIMP_RENDER_GDPR_FIELDS') &&
1437
+ MAILCHIMP_RENDER_GDPR_FIELDS;
1438
+ }
1439
 
1440
  // Add WP CLI commands
1441
  if (defined( 'WP_CLI' ) && WP_CLI) {
1481
  WP_CLI::add_command( 'mailchimp_push', 'mailchimp_cli_push_command');
1482
  WP_CLI::add_command( 'queue', 'Mailchimp_Wocoomerce_CLI' );
1483
  } catch (\Exception $e) {}
1484
+ }
includes/api/assets/class-mailchimp-order.php CHANGED
@@ -34,6 +34,9 @@ class MailChimp_WooCommerce_Order
34
  protected $is_privacy_protected = false;
35
  protected $original_woo_status = null;
36
  protected $ignore_if_new = false;
 
 
 
37
 
38
  /**
39
  * @param $bool
@@ -552,14 +555,73 @@ class MailChimp_WooCommerce_Order
552
  }
553
  return $this->billing_address;
554
  }
555
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556
  /**
557
  * @return array
558
  */
559
  public function toArray()
560
  {
561
  $campaign_id = (string) $this->getCampaignId();
562
-
563
  return mailchimp_array_remove_empty(array(
564
  'id' => (string) $this->getId(),
565
  'landing_site' => (string) $this->getLandingSite(),
@@ -580,6 +642,9 @@ class MailChimp_WooCommerce_Order
580
  'shipping_address' => $this->getShippingAddress()->toArray(),
581
  'billing_address' => $this->getBillingAddress()->toArray(),
582
  'promos' => !empty($this->promos) ? $this->promos : null,
 
 
 
583
  'lines' => array_map(function ($item) {
584
  /** @var MailChimp_WooCommerce_LineItem $item */
585
  return $item->toArray();
@@ -596,7 +661,7 @@ class MailChimp_WooCommerce_Order
596
  $singles = array(
597
  'id', 'landing_site', 'campaign_id', 'financial_status', 'fulfillment_status',
598
  'currency_code', 'order_total', 'order_url', 'tax_total', 'discount_total', 'processed_at_foreign',
599
- 'cancelled_at_foreign', 'updated_at_foreign'
600
  );
601
 
602
  foreach ($singles as $key) {
@@ -627,6 +692,67 @@ class MailChimp_WooCommerce_Order
627
  }
628
  }
629
 
 
 
 
 
 
630
  return $this;
631
  }
632
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  protected $is_privacy_protected = false;
35
  protected $original_woo_status = null;
36
  protected $ignore_if_new = false;
37
+ protected $tracking_url = '';
38
+ protected $tracking_number = '';
39
+ protected $tracking_carrier = '';
40
 
41
  /**
42
  * @param $bool
555
  }
556
  return $this->billing_address;
557
  }
558
+ /**
559
+ * Set Tracking url if exists
560
+ */
561
+ public function setTrackingUrl($url = ''){
562
+
563
+ if(!empty($url)){ return $this->tracking_url = $url; }
564
+
565
+ $tracking_url = '';
566
+ //Taken from woocommercer-services plugin example
567
+ if( !empty($this->tracking_number) && !empty($this->tracking_carrier) ){
568
+ switch ( $this->tracking_carrier ) {
569
+ case 'fedex':
570
+ $tracking_url = 'https://www.fedex.com/apps/fedextrack/?action=track&tracknumbers=' . $this->tracking_number;
571
+ break;
572
+ case 'usps':
573
+ $tracking_url = 'https://tools.usps.com/go/TrackConfirmAction.action?tLabels=' . $this->tracking_number;
574
+ break;
575
+ case 'ups':
576
+ $tracking_url = 'https://www.ups.com/track?tracknum=' . $this->tracking_number;
577
+ break;
578
+ case 'dhlexpress':
579
+ $tracking_url = 'https://www.dhl.com/en/express/tracking.html?AWB=' . $this->tracking_number . '&brand=DHL';
580
+ break;
581
+ }
582
+ }
583
+
584
+ $this->tracking_url = $tracking_url;
585
+ }
586
+ /**
587
+ * @return string Tracking url
588
+ */
589
+ public function getTrackingUrl(){
590
+ return $this->tracking_url;
591
+ }
592
+ /**
593
+ * Set Tracking number if exists
594
+ * @param string $tracking_number Tracking number from first-party plugin
595
+ */
596
+ public function setTrackingNumber( $tracking_number ){
597
+ $this->tracking_number = $tracking_number;
598
+ }
599
+ /**
600
+ * @return string Tracking number
601
+ */
602
+ public function getTrackingNumber(){
603
+ return $this->tracking_number;
604
+ }
605
+ /**
606
+ * Set Tracking url if exists
607
+ * @param string $tracking_carrier Tracking carrier from first-party plugin
608
+ */
609
+ public function setTrackingCarrier( $tracking_carrier ){
610
+ $this->tracking_carrier = $tracking_carrier;
611
+ }
612
+ /**
613
+ * @return string Tracking carrier
614
+ */
615
+ public function getTrackingCarrier(){
616
+ return $this->tracking_carrier;
617
+ }
618
  /**
619
  * @return array
620
  */
621
  public function toArray()
622
  {
623
  $campaign_id = (string) $this->getCampaignId();
624
+ $this->setTrackingInfo();
625
  return mailchimp_array_remove_empty(array(
626
  'id' => (string) $this->getId(),
627
  'landing_site' => (string) $this->getLandingSite(),
642
  'shipping_address' => $this->getShippingAddress()->toArray(),
643
  'billing_address' => $this->getBillingAddress()->toArray(),
644
  'promos' => !empty($this->promos) ? $this->promos : null,
645
+ 'tracking_number' => $this->getTrackingNumber(),
646
+ 'tracking_url' => $this->getTrackingUrl(),
647
+ 'tracking_carrier' => $this->getTrackingCarrier(),
648
  'lines' => array_map(function ($item) {
649
  /** @var MailChimp_WooCommerce_LineItem $item */
650
  return $item->toArray();
661
  $singles = array(
662
  'id', 'landing_site', 'campaign_id', 'financial_status', 'fulfillment_status',
663
  'currency_code', 'order_total', 'order_url', 'tax_total', 'discount_total', 'processed_at_foreign',
664
+ 'cancelled_at_foreign', 'updated_at_foreign', 'tracking_carrier', 'tracking_number', 'tracking_url'
665
  );
666
 
667
  foreach ($singles as $key) {
692
  }
693
  }
694
 
695
+ if (array_key_exists('customer', $data)) {
696
+ $customer_object = new MailChimp_WooCommerce_Customer();
697
+ $this->setCustomer($customer_object->fromArray($data['customer']));
698
+ }
699
+
700
  return $this;
701
  }
702
+ /**
703
+ * Set Tracking info before the job gets executed
704
+ */
705
+ public function setTrackingInfo()
706
+ {
707
+ // Support for woocomemrce shipment tracking plugin (https://woocommerce.com/products/shipment-tracking)
708
+ if (function_exists('wc_st_add_tracking_number' )){
709
+ $trackings = get_post_meta( (int) $this->getId(), '_wc_shipment_tracking_items', true );
710
+
711
+ if ( empty($trackings) ) {
712
+ return ;
713
+ }
714
+ foreach($trackings as $tracking){
715
+ // carrier
716
+ if(!empty($tracking['custom_tracking_provider'])){
717
+ $this->setTrackingCarrier($tracking['custom_tracking_provider']);
718
+ }elseif(!empty($tracking['tracking_provider'])){
719
+ $this->setTrackingCarrier($tracking['tracking_provider']);
720
+ }
721
+
722
+ // tracking url
723
+ $ship = WC_Shipment_Tracking_Actions::get_instance();
724
+ $url = $ship->get_formatted_tracking_item($this->getId(), $tracking);
725
+ $this->setTrackingUrl($url['formatted_tracking_link']);
726
+
727
+ // tracking number
728
+ $this->setTrackingNumber($tracking['tracking_number']);
729
+ return;
730
+ }
731
+ }
732
+
733
+ // Support for woocoomerce shipping plugin (https://woocommerce.com/woocommerce-shipping/)
734
+ if( class_exists( 'WC_Connect_Loader' ) ){
735
+ $label_data = get_post_meta( (int) $this->getId(), 'wc_connect_labels', true );
736
+ // return an empty array if the data doesn't exist.
737
+ if ( empty($label_data) ) {
738
+ return ;
739
+ }
740
+ if( !is_array($label_data) && is_string( $label_data ) ){
741
+ $label_data = json_decode( $label_data, true );
742
+ }
743
+ // labels stored as an array, return.
744
+ if ( is_array( $label_data ) ){
745
+ foreach ($label_data as $label) {
746
+ if (!empty($label['tracking']) && !empty($label['carrier_id']) ){
747
+ $this->setTrackingNumber( $label['tracking'] );
748
+ $this->setTrackingCarrier( $label['carrier_id'] );
749
+ $this->setTrackingUrl();
750
+ }
751
+ }
752
+ }
753
+ return;
754
+ }
755
+
756
+
757
+ }
758
+ }
includes/api/class-mailchimp-api.php CHANGED
@@ -200,15 +200,12 @@ class MailChimp_WooCommerce_MailChimpApi
200
  {
201
  if (is_string($subscribed)) {
202
  $status = $subscribed;
 
 
203
  } else {
204
- if ($subscribed === true) {
205
- $status = 'subscribed';
206
- } elseif ($subscribed === false) {
207
- $status = 'pending';
208
- } else {
209
- $status = 'transactional';
210
- }
211
  }
 
212
  $data = array(
213
  'email_type' => 'html',
214
  'email_address' => $email,
@@ -235,6 +232,8 @@ class MailChimp_WooCommerce_MailChimpApi
235
  unset($data['marketing_permissions']);
236
  }
237
 
 
 
238
  mailchimp_debug('api.subscribe', "Subscribing {$email}", $data);
239
 
240
  try {
@@ -270,7 +269,7 @@ class MailChimp_WooCommerce_MailChimpApi
270
  if ($subscribed === true) {
271
  $status = 'subscribed';
272
  } elseif ($subscribed === false) {
273
- $status = 'unsubscribed';
274
  } elseif ($subscribed === null) {
275
  $status = 'cleaned';
276
  } else {
@@ -302,21 +301,27 @@ class MailChimp_WooCommerce_MailChimpApi
302
  unset($data['marketing_permissions']);
303
  }
304
 
 
 
305
  mailchimp_debug('api.update_member', "Updating {$email}", $data);
306
 
307
  try {
308
  return $this->patch("lists/$list_id/members/$hash?skip_merge_validation=true", $data);
309
  } catch (\Exception $e) {
 
310
  // If mailchimp says is already a member lets send the update by PUT
311
  if (mailchimp_string_contains($e->getMessage(), 'is already a list member')) {
312
  return $this->applyPutRequestOnSubscriber($list_id, $email, $data);
313
  } elseif ($data['status'] !== 'subscribed' || !mailchimp_string_contains($e->getMessage(), 'compliance state')) {
314
  throw $e;
315
- }
 
316
  $data['status'] = 'pending';
317
  $result = $this->patch("lists/$list_id/members/$hash?skip_merge_validation=true", $data);
318
  mailchimp_log('api', "{$email} was in compliance state, sending the double opt in message");
319
- return $result;
 
 
320
  }
321
  }
322
 
@@ -429,7 +434,7 @@ class MailChimp_WooCommerce_MailChimpApi
429
  $status = 'subscribed';
430
  $status_if_new = 'subscribed';
431
  } elseif ($subscribed === false) {
432
- $status = 'unsubscribed';
433
  $status_if_new = 'pending';
434
  } elseif ($subscribed === null) {
435
  $status = 'cleaned';
@@ -459,7 +464,9 @@ class MailChimp_WooCommerce_MailChimpApi
459
  if (empty($data['language'])) {
460
  unset($data['language']);
461
  }
462
-
 
 
463
  mailchimp_debug('api.update_or_create', "Update Or Create {$email}", $data);
464
 
465
  return $this->put("lists/$list_id/members/$hash", $data);
@@ -675,6 +682,36 @@ class MailChimp_WooCommerce_MailChimpApi
675
  return $data['total_items'];
676
  }
677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
678
  /**
679
  * @param $store_id
680
  * @param bool $throw
@@ -952,6 +989,8 @@ class MailChimp_WooCommerce_MailChimpApi
952
  return false;
953
  }
954
 
 
 
955
  mailchimp_debug('api.addCart', "Adding Cart :: {$email}", $data = $cart->toArray());
956
 
957
  $data = $this->post("ecommerce/stores/$store_id/carts", $data);
@@ -984,6 +1023,8 @@ class MailChimp_WooCommerce_MailChimpApi
984
  return false;
985
  }
986
 
 
 
987
  mailchimp_debug('api.updateCart', "Updating Cart :: {$email}", $data = $cart->toArrayForUpdate());
988
 
989
  $data = $this->patch("ecommerce/stores/$store_id/carts/{$cart->getId()}", $data);
@@ -1531,6 +1572,34 @@ class MailChimp_WooCommerce_MailChimpApi
1531
  }
1532
  }
1533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1534
  /**
1535
  * @param $store_id
1536
  * @param MailChimp_WooCommerce_PromoRule $rule
@@ -1598,8 +1667,10 @@ class MailChimp_WooCommerce_MailChimpApi
1598
  protected function validateStoreSubmission($target)
1599
  {
1600
  if ($target instanceof MailChimp_WooCommerce_Order) {
 
1601
  return $this->validateStoreOrder($target);
1602
  } else if ($target instanceof MailChimp_WooCommerce_Customer) {
 
1603
  return $this->validateStoreCustomer($target);
1604
  }
1605
  return true;
@@ -1674,14 +1745,46 @@ class MailChimp_WooCommerce_MailChimpApi
1674
  return $fields;
1675
  }
1676
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1677
  /**
1678
  * @param $list_id
1679
  * @return array|bool
1680
  * @throws \Throwable
1681
  */
1682
- public function getWebHooks($list_id)
1683
  {
1684
- return $this->get("lists/{$list_id}/webhooks");
 
 
 
1685
  }
1686
 
1687
  /**
@@ -1723,8 +1826,9 @@ class MailChimp_WooCommerce_MailChimpApi
1723
  $deleted = 0;
1724
  $hooks = $this->getWebHooks($list_id);
1725
  foreach ($hooks['webhooks'] as $hook) {
1726
- $href = $hook['href'] ?? $hook['url'] ?? null;
1727
- if ($href && $href === $url) {
 
1728
  $this->delete("lists/{$list_id}/webhooks/{$hook['id']}");
1729
  $deleted++;
1730
  }
@@ -1732,6 +1836,168 @@ class MailChimp_WooCommerce_MailChimpApi
1732
  return $deleted;
1733
  }
1734
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1735
  /**
1736
  * @param $url
1737
  * @param null $params
@@ -1878,7 +2144,6 @@ class MailChimp_WooCommerce_MailChimpApi
1878
  protected function applyCurlOptions($method, $url, $params = array(), $headers = array())
1879
  {
1880
  $env = mailchimp_environment_variables();
1881
-
1882
  $curl_options = array(
1883
  CURLOPT_USERPWD => "mailchimp:{$this->api_key}",
1884
  CURLOPT_CUSTOMREQUEST => strtoupper($method),
@@ -1896,9 +2161,9 @@ class MailChimp_WooCommerce_MailChimpApi
1896
  ), $headers)
1897
  );
1898
 
1899
- // if we have a dedicated IP address, and have set a configuration for it, we'll use it here.
1900
- if (defined('MAILCHIMP_USE_OUTBOUND_IP')) {
1901
- $curl_options[CURLOPT_INTERFACE] = MAILCHIMP_USE_OUTBOUND_IP;
1902
  }
1903
 
1904
  // if we need to define a specific http version being used for curl requests, we can override this here.
@@ -1954,7 +2219,8 @@ class MailChimp_WooCommerce_MailChimpApi
1954
  return $data;
1955
  }
1956
 
1957
- $error_status = isset($data['status']) ? (int) $data['status'] : (int) $http_code;
 
1958
 
1959
  if ($http_code >= 400 && $http_code <= 500) {
1960
  if ($http_code == 403) {
@@ -1995,7 +2261,7 @@ class MailChimp_WooCommerce_MailChimpApi
1995
  }
1996
 
1997
  // make sure the response is correct from the data in the response array
1998
- if (isset($data['status']) && $data['status'] >= 400) {
1999
  if (isset($data['http_code']) && $data['http_code'] == 403) {
2000
  throw new MailChimp_WooCommerce_RateLimitError();
2001
  }
200
  {
201
  if (is_string($subscribed)) {
202
  $status = $subscribed;
203
+ } else if ($subscribed === true) {
204
+ $status = 'subscribed';
205
  } else {
206
+ $status = 'transactional';
 
 
 
 
 
 
207
  }
208
+
209
  $data = array(
210
  'email_type' => 'html',
211
  'email_address' => $email,
232
  unset($data['marketing_permissions']);
233
  }
234
 
235
+ $this->validateNaughtyListEmail($email);
236
+
237
  mailchimp_debug('api.subscribe', "Subscribing {$email}", $data);
238
 
239
  try {
269
  if ($subscribed === true) {
270
  $status = 'subscribed';
271
  } elseif ($subscribed === false) {
272
+ $status = 'transactional';
273
  } elseif ($subscribed === null) {
274
  $status = 'cleaned';
275
  } else {
301
  unset($data['marketing_permissions']);
302
  }
303
 
304
+ $this->validateNaughtyListEmail($email);
305
+
306
  mailchimp_debug('api.update_member', "Updating {$email}", $data);
307
 
308
  try {
309
  return $this->patch("lists/$list_id/members/$hash?skip_merge_validation=true", $data);
310
  } catch (\Exception $e) {
311
+
312
  // If mailchimp says is already a member lets send the update by PUT
313
  if (mailchimp_string_contains($e->getMessage(), 'is already a list member')) {
314
  return $this->applyPutRequestOnSubscriber($list_id, $email, $data);
315
  } elseif ($data['status'] !== 'subscribed' || !mailchimp_string_contains($e->getMessage(), 'compliance state')) {
316
  throw $e;
317
+ }
318
+
319
  $data['status'] = 'pending';
320
  $result = $this->patch("lists/$list_id/members/$hash?skip_merge_validation=true", $data);
321
  mailchimp_log('api', "{$email} was in compliance state, sending the double opt in message");
322
+ return $result;
323
+
324
+
325
  }
326
  }
327
 
434
  $status = 'subscribed';
435
  $status_if_new = 'subscribed';
436
  } elseif ($subscribed === false) {
437
+ $status = 'transactional';
438
  $status_if_new = 'pending';
439
  } elseif ($subscribed === null) {
440
  $status = 'cleaned';
464
  if (empty($data['language'])) {
465
  unset($data['language']);
466
  }
467
+
468
+ $this->validateNaughtyListEmail($email);
469
+
470
  mailchimp_debug('api.update_or_create', "Update Or Create {$email}", $data);
471
 
472
  return $this->put("lists/$list_id/members/$hash", $data);
682
  return $data['total_items'];
683
  }
684
 
685
+ /**
686
+ * @param $store_id
687
+ * @return int|mixed
688
+ * @throws MailChimp_WooCommerce_Error
689
+ * @throws MailChimp_WooCommerce_ServerError
690
+ */
691
+ public function getProductCount($store_id)
692
+ {
693
+ $data = $this->get("ecommerce/stores/{$store_id}/products?count=1");
694
+ if (!is_array($data)) {
695
+ return 0;
696
+ }
697
+ return $data['total_items'];
698
+ }
699
+
700
+ /**
701
+ * @param $store_id
702
+ * @return int|mixed
703
+ * @throws MailChimp_WooCommerce_Error
704
+ * @throws MailChimp_WooCommerce_ServerError
705
+ */
706
+ public function getCustomerCount($store_id)
707
+ {
708
+ $data = $this->get("ecommerce/stores/{$store_id}/customers?count=1");
709
+ if (!is_array($data)) {
710
+ return 0;
711
+ }
712
+ return $data['total_items'];
713
+ }
714
+
715
  /**
716
  * @param $store_id
717
  * @param bool $throw
989
  return false;
990
  }
991
 
992
+ $this->validateNaughtyList($cart->getCustomer());
993
+
994
  mailchimp_debug('api.addCart', "Adding Cart :: {$email}", $data = $cart->toArray());
995
 
996
  $data = $this->post("ecommerce/stores/$store_id/carts", $data);
1023
  return false;
1024
  }
1025
 
1026
+ $this->validateNaughtyList($cart->getCustomer());
1027
+
1028
  mailchimp_debug('api.updateCart', "Updating Cart :: {$email}", $data = $cart->toArrayForUpdate());
1029
 
1030
  $data = $this->patch("ecommerce/stores/$store_id/carts/{$cart->getId()}", $data);
1572
  }
1573
  }
1574
 
1575
+ /**
1576
+ * @param $store_id
1577
+ * @param $rule_id
1578
+ * @return object
1579
+ * @throws \Exception
1580
+ */
1581
+ public function getPromoRuleWithCodes($store_id, $rule_id)
1582
+ {
1583
+ $rule = new MailChimp_WooCommerce_PromoCode();
1584
+ $rule = $rule->fromArray($this->get("ecommerce/stores/{$store_id}/promo-rules/{$rule_id}"));
1585
+ try {
1586
+ $promo_codes = $this->getPromoCodesForRule($store_id, $rule->getId(), 1, 100);
1587
+ $codes = array();
1588
+ foreach ($promo_codes as $item) {
1589
+ $codes[] = $item->toArray();
1590
+ }
1591
+ return (object) [
1592
+ 'rule' => $rule->toArray(),
1593
+ 'codes' => $codes,
1594
+ ];
1595
+ } catch (\Exception $e) {
1596
+ return (object) [
1597
+ 'rule' => $rule,
1598
+ 'error' => $e->getMessage()
1599
+ ];
1600
+ }
1601
+ }
1602
+
1603
  /**
1604
  * @param $store_id
1605
  * @param MailChimp_WooCommerce_PromoRule $rule
1667
  protected function validateStoreSubmission($target)
1668
  {
1669
  if ($target instanceof MailChimp_WooCommerce_Order) {
1670
+ $this->validateNaughtyList($target->getCustomer());
1671
  return $this->validateStoreOrder($target);
1672
  } else if ($target instanceof MailChimp_WooCommerce_Customer) {
1673
+ $this->validateNaughtyList($target);
1674
  return $this->validateStoreCustomer($target);
1675
  }
1676
  return true;
1745
  return $fields;
1746
  }
1747
 
1748
+ /**
1749
+ * @param string $list_id
1750
+ * @param string $email
1751
+ * @param int $minutes
1752
+ * @return false|mixed
1753
+ */
1754
+ public function getCachedSubscriberStatusForAdminProfileView($list_id, $email, $minutes = 5)
1755
+ {
1756
+ if (!is_email($email) || !mailchimp_is_configured()) return null;
1757
+ $email_hash = md5(strtolower(trim($email)));
1758
+ $transient = "mailchimp-woocommerce-subscribed.{$list_id}.{$email_hash}";
1759
+ $status = get_site_transient($transient);
1760
+
1761
+ if (!empty($status)) {
1762
+ return $status;
1763
+ }
1764
+
1765
+ try {
1766
+ $member = mailchimp_get_api()->member($list_id, $email);
1767
+ $status = $member['status'];
1768
+ } catch (\Exception $e) {
1769
+ $status = 'not_found';
1770
+ }
1771
+
1772
+ set_site_transient($transient, $status, 60 * $minutes);
1773
+
1774
+ return $status;
1775
+ }
1776
+
1777
  /**
1778
  * @param $list_id
1779
  * @return array|bool
1780
  * @throws \Throwable
1781
  */
1782
+ public function getWebHooks($list_id = false)
1783
  {
1784
+ if( empty($list_id) ){
1785
+ $list_id = mailchimp_get_list_id();
1786
+ }
1787
+ return $this->get("lists/{$list_id}/webhooks", array('count' => 1000));
1788
  }
1789
 
1790
  /**
1826
  $deleted = 0;
1827
  $hooks = $this->getWebHooks($list_id);
1828
  foreach ($hooks['webhooks'] as $hook) {
1829
+ $href = isset($hook['url']) ? $hook['url'] : (isset($hook['href']) ? $hook['href'] : null);
1830
+ if ($href && $href === $url || ($href && !empty($url) && mailchimp_string_contains($href, $url))) {
1831
+ mailchimp_log('admin', "deleting webhook id {$hook['id']} - {$href}");
1832
  $this->delete("lists/{$list_id}/webhooks/{$hook['id']}");
1833
  $deleted++;
1834
  }
1836
  return $deleted;
1837
  }
1838
 
1839
+ /**
1840
+ * @param $list_id
1841
+ * @param $url
1842
+ * @return bool
1843
+ * @throws Throwable
1844
+ */
1845
+ public function hasWebhook($list_id, $url)
1846
+ {
1847
+ $hooks = $this->getWebHooks($list_id);
1848
+ foreach ($hooks['webhooks'] as $hook) {
1849
+ $href = isset($hook['url']) ? $hook['url'] : (isset($hook['href']) ? $hook['href'] : null);
1850
+ if ($href && $href === $url) {
1851
+ return true;
1852
+ }
1853
+ }
1854
+ return false;
1855
+ }
1856
+
1857
+ /**
1858
+ * @param MailChimp_WooCommerce_Customer $customer
1859
+ * @return false
1860
+ * @throws MailChimp_WooCommerce_Error
1861
+ */
1862
+ public function validateNaughtyList(MailChimp_WooCommerce_Customer $customer)
1863
+ {
1864
+ $this->validateNaughtyListEmail($customer->getEmailAddress());
1865
+ $this->validateNaughtyListNames($customer->getFirstName(), $customer->getLastName());
1866
+ return false;
1867
+ }
1868
+
1869
+ /**
1870
+ * @param $email
1871
+ * @return false
1872
+ * @throws MailChimp_WooCommerce_Error
1873
+ */
1874
+ public function validateNaughtyListEmail($email)
1875
+ {
1876
+ if (!empty($email) && mailchimp_string_contains($email, $this->getNaughtyList())) {
1877
+ $this->reportSpamToTower($email);
1878
+ throw new MailChimp_WooCommerce_Error("Email [{$email}] has been blocked due to spam reports.");
1879
+ }
1880
+ return false;
1881
+ }
1882
+
1883
+ /**
1884
+ * @return array|mixed
1885
+ */
1886
+ public function getNaughtyList()
1887
+ {
1888
+ try {
1889
+ $domains = mailchimp_get_transient('naughty_list_domains');
1890
+ if (is_array($domains) && isset($domains['value'])) {
1891
+ return $domains['value'];
1892
+ }
1893
+ $domains = json_decode(file_get_contents('https://tower.vextras.com/naughty-domains'), true);
1894
+ mailchimp_set_transient('naughty_list_domains', $domains, 1440);
1895
+ return $domains;
1896
+ } catch (\Throwable $e) {
1897
+ $domains = [];
1898
+ mailchimp_set_transient('naughty_list_domains', $domains, 300);
1899
+ return $domains;
1900
+ }
1901
+ }
1902
+
1903
+ /**
1904
+ * @return bool
1905
+ */
1906
+ private function allowedToSubmitSpam()
1907
+ {
1908
+ // check to see if we've already set the transient.
1909
+ $status = mailchimp_get_transient('tower');
1910
+
1911
+ // if we've got it - just return it now.
1912
+ if (!empty($status)) {
1913
+ return $status === 'green';
1914
+ }
1915
+
1916
+ // call the API to see if we need to block traffic or not
1917
+ // this only impacts reporting spam metrics, does not impact local site blocking
1918
+ $response = wp_remote_get('https://tower.vextras.com/api/traffic');
1919
+ $body = json_decode($response['body']);
1920
+ $status = $body ? $body->status : 'red';
1921
+
1922
+ // set this for 5 minutes.
1923
+ mailchimp_set_transient('tower', $status, 120);
1924
+
1925
+ return $status === 'green';
1926
+ }
1927
+
1928
+ /**
1929
+ * @param $email
1930
+ * @return mixed|null
1931
+ */
1932
+ private function reportSpamToTower($email)
1933
+ {
1934
+ try {
1935
+ if (!$this->allowedToSubmitSpam()) {
1936
+ return null;
1937
+ }
1938
+
1939
+ $payload = array(
1940
+ 'headers' => array(
1941
+ 'Content-type' => 'application/json',
1942
+ 'Accept' => 'application/json',
1943
+ 'X-Store-Platform' => 'woocommerce',
1944
+ 'X-List-Id' => mailchimp_get_list_id(),
1945
+ 'X-Store-Key' => base64_encode(mailchimp_get_store_id().':'.mailchimp_get_api_key()),
1946
+ ),
1947
+ 'body' => json_encode(array(
1948
+ 'store_id' => mailchimp_get_store_id(),
1949
+ 'list_id' => mailchimp_get_list_id(),
1950
+ 'email' => $email
1951
+ )),
1952
+ 'timeout' => 30,
1953
+ );
1954
+ $response = wp_remote_post('https://tower.vextras.com/admin-api/woocommerce/report-spam', $payload);
1955
+ return json_decode($response['body']);
1956
+ } catch (\Throwable $e) {
1957
+ return null;
1958
+ }
1959
+ }
1960
+
1961
+ /**
1962
+ * @param $first_name
1963
+ * @param $last_name
1964
+ * @return false
1965
+ * @throws MailChimp_WooCommerce_Error
1966
+ */
1967
+ public function validateNaughtyListNames($first_name, $last_name)
1968
+ {
1969
+ // add a list of naughty list customer names. Seems a little destructive though.
1970
+ $naughty_list_names = [
1971
+ 'mark mustermann',
1972
+ ];
1973
+ $name = "{$first_name} {$last_name}";
1974
+ if (mailchimp_string_contains(strtolower($name), $naughty_list_names)) {
1975
+ throw new MailChimp_WooCommerce_Error("Name [{$name}] has been blocked due to spam reports.");
1976
+ }
1977
+ return false;
1978
+ }
1979
+
1980
+ /**
1981
+ * @param $list_id
1982
+ * @return array
1983
+ * @throws MailChimp_WooCommerce_Error
1984
+ * @throws MailChimp_WooCommerce_ServerError
1985
+ */
1986
+ public function getAutomations($list_id)
1987
+ {
1988
+ $automations = $this->get('automations', array('limit' => 1000));
1989
+ if (!is_array($automations) || !array_key_exists('automations', $automations)) {
1990
+ return array();
1991
+ }
1992
+ $response = array();
1993
+ foreach ($automations['automations'] as $automation) {
1994
+ if ($list_id === $automation['recipients']['list_id']) {
1995
+ $response[] = $automation;
1996
+ }
1997
+ }
1998
+ return $response;
1999
+ }
2000
+
2001
  /**
2002
  * @param $url
2003
  * @param null $params
2144
  protected function applyCurlOptions($method, $url, $params = array(), $headers = array())
2145
  {
2146
  $env = mailchimp_environment_variables();
 
2147
  $curl_options = array(
2148
  CURLOPT_USERPWD => "mailchimp:{$this->api_key}",
2149
  CURLOPT_CUSTOMREQUEST => strtoupper($method),
2161
  ), $headers)
2162
  );
2163
 
2164
+ // automatically set the proper outbound IP address
2165
+ if ( ( $outbound_ip = mailchimp_get_outbound_ip() ) && !in_array( $outbound_ip, mailchimp_common_loopback_ips() ) ) {
2166
+ $curl_options[CURLOPT_INTERFACE] = $outbound_ip;
2167
  }
2168
 
2169
  // if we need to define a specific http version being used for curl requests, we can override this here.
2219
  return $data;
2220
  }
2221
 
2222
+ $error_status = isset($data['status']) && is_numeric($data['status']) ?
2223
+ (int) $data['status'] : (int) $http_code;
2224
 
2225
  if ($http_code >= 400 && $http_code <= 500) {
2226
  if ($http_code == 403) {
2261
  }
2262
 
2263
  // make sure the response is correct from the data in the response array
2264
+ if (isset($data['status']) && is_numeric($data['status']) && $data['status'] >= 400) {
2265
  if (isset($data['http_code']) && $data['http_code'] == 403) {
2266
  throw new MailChimp_WooCommerce_RateLimitError();
2267
  }
includes/api/class-mailchimp-woocommerce-fix-duplicate-store.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MailChimp_WooCommerce_Fix_Duplicate_Store
4
+ {
5
+ protected $store;
6
+ protected $has_old_integration = false;
7
+ protected $duplicate_store_problem = false;
8
+ protected $deleted_stores = [];
9
+ protected $should_delete_duplicate = false;
10
+ protected $should_delete_legacy = false;
11
+
12
+ /**
13
+ * FixDuplicatMailChimp_WooCommerce_Fix_Duplicate_StoreeStore constructor.
14
+ * @param $store_id
15
+ * @param bool $delete_duplicate
16
+ * @param false $delete_legacy
17
+ */
18
+ public function __construct($store_id, bool $delete_duplicate = false, $delete_legacy = false)
19
+ {
20
+ $this->store = $store_id;
21
+ $this->should_delete_duplicate = $delete_duplicate;
22
+ $this->should_delete_legacy = $delete_legacy;
23
+ }
24
+
25
+ /**
26
+ *
27
+ */
28
+ public function handle()
29
+ {
30
+ $this->deleted_stores = [];
31
+ $url = rtrim(get_option('siteurl'), '/');
32
+ $stores = mailchimp_get_api()->stores();
33
+ $compare_url = $this->domain($url);
34
+ $public_key = mailchimp_get_store_id();
35
+
36
+ if (is_array($stores) && !empty($stores)) {
37
+ foreach ($stores as $mc_store) {
38
+ /** @var MailChimp_WooCommerce_Store $mc_store */
39
+ $store_url = $this->domain($mc_store->getDomain());
40
+ $matched = strtolower($mc_store->getPlatform()) === 'woocommerce';
41
+ if ($store_url === $compare_url) {
42
+ if ($mc_store->getId() !== $public_key && $matched) {
43
+ $this->duplicate_store_problem = $mc_store;
44
+ if ($this->should_delete_duplicate) {
45
+ mailchimp_get_api()->deleteStore($mc_store->getId());
46
+ MailChimp_WooCommerce_Admin::instance()->syncStore();
47
+ $this->deleted_stores[] = $mc_store;
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * @return array
57
+ */
58
+ public function getDeletedStores()
59
+ {
60
+ return $this->deleted_stores;
61
+ }
62
+
63
+ /**
64
+ * @return bool|MailChimp_WooCommerce_Store
65
+ */
66
+ public function hasDuplicateStoreProblem()
67
+ {
68
+ return $this->duplicate_store_problem;
69
+ }
70
+
71
+ /**
72
+ * @return bool|MailChimp_WooCommerce_Store
73
+ */
74
+ public function hasOldIntegration()
75
+ {
76
+ return $this->has_old_integration;
77
+ }
78
+
79
+ /**
80
+ * @param $url
81
+ * @return string|string[]
82
+ */
83
+ public function domain($url)
84
+ {
85
+ return str_replace(
86
+ ['http://', 'https://', 'www.'],
87
+ '',
88
+ rtrim(strtolower(trim($url)), '/')
89
+ );
90
+ }
91
+ }
includes/api/class-mailchimp-woocommerce-log-viewer.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MailChimp_WooCommerce_Log_Viewer
4
+ {
5
+ /**
6
+ * @var string file
7
+ */
8
+ private static $file = null;
9
+ public static $directory = '*';
10
+
11
+ private static $levels_classes = [
12
+ 'debug' => 'info',
13
+ 'info' => 'success',
14
+ 'notice' => 'info',
15
+ 'warning' => 'warning',
16
+ 'error' => 'error',
17
+ 'critical' => 'error',
18
+ 'alert' => 'error',
19
+ 'emergency' => 'error',
20
+ 'processed' => 'success',
21
+ ];
22
+
23
+ private static $levels_imgs = [
24
+ 'debug' => 'info',
25
+ 'info' => 'info',
26
+ 'notice' => 'info',
27
+ 'warning' => 'warning',
28
+ 'error' => 'warning',
29
+ 'critical' => 'warning',
30
+ 'alert' => 'warning',
31
+ 'emergency' => 'warning',
32
+ 'processed' => 'info'
33
+ ];
34
+
35
+ /**
36
+ * Log levels that are used
37
+ * @var array
38
+ */
39
+ private static $log_levels = [
40
+ 'emergency',
41
+ 'alert',
42
+ 'critical',
43
+ 'error',
44
+ 'warning',
45
+ 'notice',
46
+ 'info',
47
+ 'debug',
48
+ 'processed'
49
+ ];
50
+
51
+ const MAX_FILE_SIZE = 52428800;
52
+
53
+ /**
54
+ * @param string $file
55
+ */
56
+ public static function setFile($file)
57
+ {
58
+ $file = self::pathToLogFile($file);
59
+ if (file_exists($file)) {
60
+ self::$file = $file;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * @param $file
66
+ * @return string
67
+ * @throws \Exception
68
+ */
69
+ public static function pathToLogFile($file)
70
+ {
71
+ if (!strpos('/', $file)) {
72
+ $logsPath = static::getLogDirectory();
73
+ if (static::$directory !== '*') $logsPath.= '/'.static::$directory;
74
+ $file = $logsPath . '/' . $file;
75
+ }
76
+ return $file;
77
+ }
78
+
79
+ /**
80
+ * @return string
81
+ */
82
+ public static function getFileName()
83
+ {
84
+ return basename(self::$file);
85
+ }
86
+
87
+ /**
88
+ * @return array
89
+ */
90
+ public static function all()
91
+ {
92
+ $log = array();
93
+ $directory = static::getLogDirectory();
94
+ $pattern = '/\d{4}-\d{2}-\d{2}[T]\d{2}:\d{2}:\d{2}[+]\d\d[:]\d\d.*/';
95
+ if (!self::$file) {
96
+ $log_file = self::getFiles();
97
+ if (!count($log_file)) {
98
+ return [];
99
+ }
100
+ self::$file = $log_file[0];
101
+ if (self::$file === 'test-log.log' && isset($log_file[1])) {
102
+ self::$file = $log_file[1];
103
+ }
104
+ self::$file = $directory.'/'.self::$file;
105
+ }
106
+ $file_path = self::$file;
107
+ if (filesize($file_path) > self::MAX_FILE_SIZE) return null;
108
+ $file = file_get_contents($file_path);
109
+ preg_match_all($pattern, $file, $headings);
110
+ if (!is_array($headings) || empty($headings)) return $log;
111
+ $log_data = preg_split($pattern, $file);
112
+ if ($log_data[0] < 1) {
113
+ array_shift($log_data);
114
+ }
115
+ foreach ($headings as $h) {
116
+ for ($i = 0, $j = count($h); $i < $j; $i++) {
117
+ preg_match('/^(\d{4}-\d{2}-\d{2}[T]\d{2}:\d{2}:\d{2}[+]\d\d[:]\d\d) (EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG|PROCESSED) (.*)/', $h[$i], $current);
118
+ if (!isset($current[3])) continue;
119
+ $context = strtolower($current[2]);
120
+ if (!array_key_exists($context, self::$levels_classes)) continue;
121
+ $log[] = array(
122
+ 'context' => $context,
123
+ 'level' => $context,
124
+ 'level_class' => self::$levels_classes[$context],
125
+ 'level_img' => self::$levels_imgs[$context],
126
+ 'date' => $current[1],
127
+ 'text' => $current[3],
128
+ 'stack' => preg_replace("/^\n*/", '', $log_data[$i])
129
+ );
130
+ }
131
+ }
132
+ return array_reverse($log);
133
+ }
134
+
135
+ public static function setDirectory($dir)
136
+ {
137
+ static::$directory = "{$dir}";
138
+ }
139
+
140
+ /**
141
+ * @param bool $basename
142
+ * @return array
143
+ */
144
+ public static function getFiles($basename = false)
145
+ {
146
+ if (!($dir = static::getLogDirectory())) {
147
+ return array();
148
+ }
149
+ $files = @scandir($dir);
150
+ $files = array_reverse($files);
151
+ $files = array_filter($files, function($value) {
152
+ return static::stringEndsWith($value, '.log');
153
+ });
154
+ if ($basename && is_array($files)) {
155
+ foreach ($files as $k => $file) {
156
+ $files[$k] = basename($file);
157
+ }
158
+ }
159
+ return array_values($files);
160
+ }
161
+
162
+ /**
163
+ * @return null
164
+ */
165
+ public static function getLogDirectory()
166
+ {
167
+ return !defined('WC_LOG_DIR') ? null : rtrim(WC_LOG_DIR, '/');
168
+ }
169
+
170
+ /**
171
+ * @param $haystack
172
+ * @param $needles
173
+ * @return bool
174
+ */
175
+ public static function stringEndsWith($haystack, $needles)
176
+ {
177
+ foreach ((array) $needles as $needle) {
178
+ if (substr($haystack, -strlen($needle)) === (string) $needle) {
179
+ return true;
180
+ }
181
+ }
182
+ return false;
183
+ }
184
+ }
includes/api/class-mailchimp-woocommerce-logs.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MailChimp_WooCommerce_Logs
4
+ {
5
+ protected $view = null;
6
+ protected $limit = false;
7
+ protected $search_query = null;
8
+
9
+ /**
10
+ * @param $view
11
+ * @return $this
12
+ */
13
+ public function withView($view)
14
+ {
15
+ $this->view = $view;
16
+ return $this;
17
+ }
18
+
19
+ /**
20
+ * @param int $limit
21
+ * @return $this
22
+ */
23
+ public function limit(int $limit)
24
+ {
25
+ $this->limit = $limit;
26
+ return $this;
27
+ }
28
+
29
+ /**
30
+ * @param $value
31
+ * @return $this
32
+ */
33
+ public function searching($value)
34
+ {
35
+ $this->search_query = $value;
36
+ return $this;
37
+ }
38
+
39
+ /**
40
+ * @param null $view
41
+ * @return array
42
+ */
43
+ public function handle()
44
+ {
45
+ if ($this->view) {
46
+ MailChimp_WooCommerce_Log_Viewer::setFile(base64_decode($this->view));
47
+ }
48
+
49
+ $logs = array();
50
+
51
+ foreach (MailChimp_WooCommerce_Log_Viewer::all() as $item) {
52
+ $date = new \DateTime($item['date']);
53
+ $item['date'] = $date->format('D, M j, Y g:i A');
54
+ $item['datetime'] = $date->format('Y-m-d H:i:s A');
55
+ $item['text'] = strtolower(str_replace('[]', ' ', $item['text']));
56
+ if (!empty($this->search_query) && !mailchimp_string_contains($item['text'], $this->search_query)) {
57
+ continue;
58
+ }
59
+ $logs[] = $item;
60
+ }
61
+
62
+ if ($this->limit) {
63
+ $logs = array_slice($logs, 0, $this->limit, true);
64
+ }
65
+
66
+ $files = [];
67
+
68
+ foreach (MailChimp_WooCommerce_Log_Viewer::getFiles(true) as $key => $file) {
69
+ preg_match('/(.*)-(\d{4}-\d{2}-\d{2})-(.*).log/', $file, $matches);
70
+ // the date should be here
71
+ if (!isset($matches[2])) {
72
+ continue;
73
+ }
74
+ $files[] = array(
75
+ 'value' => base64_encode($file),
76
+ 'filename' => $file,
77
+ 'label' => $matches[1].' '.$matches[2],
78
+ );
79
+ }
80
+
81
+ return $this->items = [
82
+ 'view_file' => $this->view,
83
+ 'search' => $this->search_query,
84
+ 'dir' => MailChimp_WooCommerce_Log_Viewer::getLogDirectory(),
85
+ 'current' => base64_encode(MailChimp_WooCommerce_Log_Viewer::getFileName()),
86
+ 'files' => $files,
87
+ 'logs' => $logs,
88
+ ];
89
+ }
90
+ }
includes/api/class-mailchimp-woocommerce-tower.php ADDED
@@ -0,0 +1,570 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MailChimp_WooCommerce_Tower extends Mailchimp_Woocommerce_Job
4
+ {
5
+ protected $store_id;
6
+ protected $with_shop_sales = true;
7
+ protected $with_log_file = null;
8
+ protected $with_log_search = null;
9
+
10
+ /**
11
+ * OrderCreatedHook constructor.
12
+ * @param $store_id
13
+ */
14
+ public function __construct($store_id)
15
+ {
16
+ $this->store_id = $store_id;
17
+ }
18
+
19
+ public function withoutShopSales()
20
+ {
21
+ $this->with_shop_sales = false;
22
+ return $this;
23
+ }
24
+
25
+ public function withShopSales()
26
+ {
27
+ $this->with_shop_sales = true;
28
+ return $this;
29
+ }
30
+
31
+ public function withLogFile($file)
32
+ {
33
+ $this->with_log_file = $file;
34
+ return $this;
35
+ }
36
+
37
+ public function withLogSearch($search)
38
+ {
39
+ $this->with_log_search = $search;
40
+ return $this;
41
+ }
42
+
43
+ /**
44
+ * @return array
45
+ * @throws MailChimp_WooCommerce_Error
46
+ * @throws MailChimp_WooCommerce_ServerError
47
+ */
48
+ public function handle()
49
+ {
50
+ return $this->getData();
51
+ }
52
+
53
+ /**
54
+ * @return array
55
+ * @throws MailChimp_WooCommerce_Error
56
+ * @throws MailChimp_WooCommerce_ServerError
57
+ */
58
+ public function getData()
59
+ {
60
+ $product_count = $customer_count = $order_count = $mc_product_count = $mc_customer_count = $mc_order_count = 0;
61
+
62
+ $api = mailchimp_get_api();
63
+ $store_id = mailchimp_get_store_id();
64
+ $authenticated = mailchimp_is_configured();
65
+ $list_id = mailchimp_get_list_id();
66
+ $url = get_option('siteurl');
67
+ $options = (array) get_option('mailchimp-woocommerce');
68
+
69
+ try {
70
+ $product_count = mailchimp_get_product_count();
71
+ $customer_count = 0;
72
+ $order_count = mailchimp_get_order_count();
73
+ $plan = $plan_name = 'Woo';
74
+ $store_active = true;
75
+ } catch (\Throwable $e) {
76
+ $store_active = false;
77
+ $plan = null;
78
+ }
79
+
80
+ $has_mailchimp_script = false;
81
+ $has_old_integration = false;
82
+ $duplicate_store_problem = false;
83
+ $store_attached = false;
84
+ $syncing_mc = false;
85
+ $list_is_valid = false;
86
+ $account_info = [];
87
+ $shop = null;
88
+ $akamai_block = false;
89
+
90
+ if ($authenticated) {
91
+ try {
92
+ $account_info = $api->getProfile();
93
+ } catch (\Exception $e) {
94
+ $account_info = array();
95
+ if ($e->getCode() === 503) {
96
+ $akamai_block = true;
97
+ }
98
+ }
99
+ if (is_array($account_info)) {
100
+ // don't need these
101
+ unset($account_info['_links']);
102
+ }
103
+ $stores = $api->stores();
104
+ $compare_url = $this->baseDomain($url);
105
+ $list_name = $list_id ? $api->getList($list_id)['name'] : null;
106
+
107
+ if (is_array($stores) && !empty($stores)) {
108
+ foreach ($stores as $mc_store) {
109
+ $store_url = $this->baseDomain($mc_store->getDomain());
110
+ $public_key_matched = $mc_store->getId() === $store_id;
111
+ // make sure the current store in context is inside the Mailchimp array of stores.
112
+ if ($public_key_matched) {
113
+ $shop = $mc_store;
114
+ $syncing_mc = $mc_store->isSyncing();
115
+ $store_attached = true;
116
+ $list_is_valid = $mc_store->getListId() === $list_id;
117
+ $has_mailchimp_script = (bool) $mc_store->getConnectedSiteScriptFragment();
118
+ }
119
+ if ($store_url === $compare_url) {
120
+ if (!$public_key_matched && $mc_store->getPlatform() === 'Woocommerce') {
121
+ $duplicate_store_problem = true;
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ try {
128
+ if ($store_attached) {
129
+ $mc_product_count = $api->getProductCount($store_id);
130
+ $mc_customer_count = $api->getCustomerCount($store_id);
131
+ $mc_order_count = $api->getOrderCount($store_id);
132
+ }
133
+ } catch (\Throwable $e) {
134
+ if ($e->getCode() === 503) {
135
+ $akamai_block = true;
136
+ }
137
+ }
138
+
139
+ $automations = array();
140
+ $merge_fields = array();
141
+ try {
142
+ foreach ($api->getAutomations($list_id) as $automation) {
143
+ $created = new \DateTime($automation['create_time']);
144
+ $started = new \DateTime($automation['start_time']);
145
+ $automations[] = array(
146
+ 'created_at' => $created->format('Y-m-d H:i:s'),
147
+ 'start_at' => $started->format('Y-m-d H:i:s'),
148
+ 'status' => $automation['status'],
149
+ 'name' => $automation['settings']['title'],
150
+ 'type' => $automation['trigger_settings']['workflow_title'],
151
+ 'stats' => $automation['report_summary'],
152
+ );
153
+ }
154
+ $merge_fields = $api->mergeFields($list_id);
155
+ $merge_fields = $merge_fields['merge_fields'];
156
+ } catch (\Throwable $e) {
157
+ if ($e->getCode() === 503) {
158
+ $akamai_block = true;
159
+ }
160
+ }
161
+ }
162
+
163
+ $time = new \DateTime('now');
164
+
165
+ return [
166
+ 'store' => (object) array(
167
+ 'public_key' => $store_id,
168
+ 'domain' => $url,
169
+ 'secure_url' => $url,
170
+ 'user' => (object) array(
171
+ 'email' => isset($options['admin_email']) ? $options['admin_email'] : null,
172
+ ),
173
+ 'average_monthly_sales' => $this->getShopSales(),
174
+ 'address' => (object) array(
175
+ 'street' => isset($options['store_street']) && $options['store_street'] ? $options['store_street'] : '',
176
+ 'city' => isset($options['store_street']) && $options['store_street'] ? $options['store_street'] : '',
177
+ 'state' => isset($options['store_state']) && $options['store_state'] ? $options['store_state'] : '',
178
+ 'country' => isset($options['store_country']) && $options['store_country'] ? $options['store_country'] : '',
179
+ 'zip' => isset($options['store_postal_code']) && $options['store_postal_code'] ? $options['store_postal_code'] : '',
180
+ 'phone' => isset($options['store_phone']) && $options['store_phone'] ? $options['store_phone'] : '',
181
+ ),
182
+ 'metrics' => array_values([
183
+ 'shopify_hooks' => (object) array('key' => 'shopify_hooks', 'value' => true),
184
+ 'shop.products' => (object) array('key' => 'shop.products', 'value' => $product_count),
185
+ 'shop.customers' => (object) array('key' => 'shop.customers', 'value' => $customer_count),
186
+ 'shop.orders' => (object) array('key' => 'shop.orders', 'value' => $order_count),
187
+ 'mc.products' => (object) array('key' => 'mc.products', 'value' => $mc_product_count),
188
+ 'mc.orders' => (object) array('key' => 'mc.orders', 'value' => $mc_order_count),
189
+ 'mc.has_chimpstatic' => (object) array('key' => 'mc.has_chimpstatic', 'value' => true),
190
+ 'mc.has_duplicate_store' => (object) array('key' => 'mc.has_duplicate_store', 'value' => $duplicate_store_problem),
191
+ 'mc.store_attached' => (object) array('key' => 'mc.store_attached', 'value' => $store_attached),
192
+ 'mc.is_syncing' => (object) array('key' => 'mc.is_syncing', 'value' => $syncing_mc),
193
+ 'mailchimp_api_connected' => (object) array('key' => 'mailchimp_api_connected', 'value' => (bool) $account_info),
194
+ 'mc_list_id' => (object) array('key' => 'mc_list_id', 'value' => (bool) $list_id && $list_is_valid),
195
+ 'mc_list_valid' => (object) array('key' => 'mc_list_valid', 'value' => $list_is_valid),
196
+ 'mc.has_legacy_integration' => (object) array('key' => 'mc.has_legacy_integration', 'value' => $has_old_integration),
197
+ 'admin.updated_at' => (object) array('key' => 'admin.updated_at', 'value' => $time->format('Y-m-d H:i:s')),
198
+ 'product_sync_started' => (object) array('key' => 'product_sync_started', 'value' => get_option('mailchimp-woocommerce-sync.products.started_at')),
199
+ 'product_sync_completed' => (object) array('key' => 'product_sync_completed', 'value' => get_option('mailchimp-woocommerce-sync.products.completed_at')),
200
+ 'customer_sync_started' => (object) array('key' => 'customer_sync_started', 'value' => get_option('mailchimp-woocommerce-sync.customers.started_at')),
201
+ 'customer_sync_completed' => (object) array('key' => 'customer_sync_completed', 'value' => get_option('mailchimp-woocommerce-sync.customers.completed_at')),
202
+ 'order_sync_started' => (object) array('key' => 'order_sync_started', 'value' => get_option('mailchimp-woocommerce-sync.orders.started_at')),
203
+ 'order_sync_completed' => (object) array('key' => 'order_sync_completed', 'value' => get_option('mailchimp-woocommerce-sync.orders.completed_at')),
204
+ ]),
205
+ 'meta' => $this->getMeta(),
206
+ ),
207
+ 'meta' => [
208
+ 'timestamp' => $time->format('Y-m-d H:i:s'),
209
+ 'platform' => [
210
+ 'active' => $store_active,
211
+ 'plan' => $plan,
212
+ 'store_name' => get_option('blogname'),
213
+ 'domain' => $url,
214
+ 'secure_url' => $url,
215
+ 'user_email' => isset($options['admin_email']) ? $options['admin_email'] : null,
216
+ 'is_syncing' => $syncing_mc,
217
+ 'sync_started_at' => get_option('mailchimp-woocommerce-sync.started_at'),
218
+ 'sync_completed_at' => get_option('mailchimp-woocommerce-sync.completed_at'),
219
+ 'subscribed_to_hooks' => true,
220
+ 'uses_custom_rules' => false,
221
+ 'wp_cron_enabled' => $this->hasWPCronEnabled(),
222
+ 'ecomm_stats' => [
223
+ 'products' => $product_count,
224
+ 'customers' => $customer_count,
225
+ 'orders' => $order_count,
226
+ ],
227
+ 'shop' => [
228
+ 'phone' => isset($options['store_phone']) && $options['store_phone'] ? $options['store_phone'] : '',
229
+ ],
230
+ ],
231
+ 'mailchimp' => [
232
+ 'shop' => $shop ? $shop->toArray() : false,
233
+ 'chimpstatic_installed' => $has_mailchimp_script,
234
+ 'force_disconnect' => false,
235
+ 'duplicate_store_problem' => $duplicate_store_problem,
236
+ 'has_old_integration' => $has_old_integration,
237
+ 'store_attached' => $store_attached,
238
+ 'akamai_block' => $akamai_block,
239
+ 'ecomm_stats' => [
240
+ 'products' => $mc_product_count,
241
+ 'customers' => $mc_customer_count,
242
+ 'orders' => $mc_order_count,
243
+ ],
244
+ 'list' => [
245
+ 'id' => $list_id,
246
+ 'name' => $list_name,
247
+ 'double_opt_in' => mailchimp_list_has_double_optin(false),
248
+ 'valid' => $list_is_valid,
249
+ ],
250
+ 'account_info' => $account_info,
251
+ 'automations' => $automations,
252
+ 'merge_fields' => (object) $merge_fields,
253
+ ],
254
+ 'merge_tags' => [
255
+
256
+ ]
257
+ ],
258
+ 'logs' => static::logs($this->with_log_file, $this->with_log_search),
259
+ 'system_report' => $this->getSystemReport(),
260
+ ];
261
+ }
262
+
263
+ /**
264
+ * @param $domain
265
+ * @return string|string[]
266
+ */
267
+ protected function baseDomain($domain)
268
+ {
269
+ return str_replace(
270
+ ['http://', 'https://', 'www.'],
271
+ '',
272
+ rtrim(strtolower(trim($domain)), '/')
273
+ );
274
+ }
275
+
276
+ /**
277
+ * @param null $file
278
+ * @param null $search
279
+ * @return array
280
+ */
281
+ public function logs($file = null, $search = null)
282
+ {
283
+ $logs = new MailChimp_WooCommerce_Logs();
284
+ $logs->limit(200);
285
+ $logs->withView(!is_null($file) ? $file : $this->with_log_file);
286
+ $logs->searching(!is_null($search) ? $search : $this->with_log_search);
287
+ return $logs->handle();
288
+ }
289
+
290
+ public function getShopSales()
291
+ {
292
+ try {
293
+ global $woocommerce, $wpdb;
294
+ include_once($woocommerce->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php');
295
+
296
+ // WooCommerce Admin Report
297
+ $wc_report = new WC_Admin_Report();
298
+
299
+ // Set date parameters for the current month
300
+ $start_date = strtotime(date('Y-m', current_time('timestamp')) . '-01 midnight');
301
+ $end_date = strtotime('+1month', $start_date) - 86400;
302
+ $wc_report->start_date = $start_date;
303
+ $wc_report->end_date = $end_date;
304
+
305
+ // Avoid max join size error
306
+ $wpdb->query('SET SQL_BIG_SELECTS=1');
307
+
308
+ // Get data for current month sold products
309
+ $sold_products = $wc_report->get_order_report_data(array(
310
+ 'data' => array(
311
+ '_product_id' => array(
312
+ 'type' => 'order_item_meta',
313
+ 'order_item_type' => 'line_item',
314
+ 'function' => '',
315
+ 'name' => 'product_id'
316
+ ),
317
+ '_qty' => array(
318
+ 'type' => 'order_item_meta',
319
+ 'order_item_type' => 'line_item',
320
+ 'function' => 'SUM',
321
+ 'name' => 'quantity'
322
+ ),
323
+ '_line_subtotal' => array(
324
+ 'type' => 'order_item_meta',
325
+ 'order_item_type' => 'line_item',
326
+ 'function' => 'SUM',
327
+ 'name' => 'gross'
328
+ ),
329
+ '_line_total' => array(
330
+ 'type' => 'order_item_meta',
331
+ 'order_item_type' => 'line_item',
332
+ 'function' => 'SUM',
333
+ 'name' => 'gross_after_discount'
334
+ )
335
+ ),
336
+ 'query_type' => 'get_results',
337
+ 'group_by' => 'product_id',
338
+ 'where_meta' => '',
339
+ 'order_by' => 'quantity DESC',
340
+ 'order_types' => wc_get_order_types('order_count'),
341
+ 'filter_range' => TRUE,
342
+ 'order_status' => array('completed', 'complete'),
343
+ ));
344
+ $total = 0;
345
+ foreach ($sold_products as $product) {
346
+ $total += $product->gross;
347
+ }
348
+ return $total;
349
+ } catch (\Throwable $e) {
350
+ mailchimp_log('tower', $e->getMessage());
351
+ return 0;
352
+ }
353
+ }
354
+
355
+ public function getSystemReport()
356
+ {
357
+ global $wp_version;
358
+
359
+ $actions = $this->getLastActions();
360
+ $theme = wp_get_theme();
361
+
362
+ return array(
363
+ array('key' => 'PhpVersion', 'value' => phpversion()),
364
+ array('key' => 'Memory Limit', 'value' => ini_get('memory_limit')),
365
+ array('key' => 'WP CRON Enabled', 'value' => $this->hasWPCronEnabled()),
366
+ array('key' => 'Curl Enabled', 'value' => function_exists('curl_init')),
367
+ array('key' => 'Curl Version', 'value' => $this->getCurlVersion()),
368
+ array('key' => 'Wordpress Version', 'value' => $wp_version),
369
+ array('key' => 'WooCommerce Version', 'value' => defined('WC_VERSION') ? WC_VERSION : null),
370
+ array('key' => 'Theme Name', 'value' => esc_html($theme->get('Name'))),
371
+ array('key' => 'Theme URL', 'value' => esc_html($theme->get('ThemeURI'))),
372
+ array('key' => 'Outbound IP Address', 'value' => mailchimp_get_outbound_ip()),
373
+ array('key' => 'Active Plugins', 'value' => $this->getActivePlugins()),
374
+ array('key' => 'Actions', 'value' => $actions),
375
+ );
376
+ }
377
+
378
+ /**
379
+ * @return bool
380
+ */
381
+ public function hasWPCronEnabled()
382
+ {
383
+ return !defined( 'DISABLE_WP_CRON' ) ||
384
+ (defined( 'DISABLE_WP_CRON' ) && !DISABLE_WP_CRON);
385
+ }
386
+
387
+ public function getCurlVersion()
388
+ {
389
+ $version = function_exists('curl_version') ? curl_version() : null;
390
+ return is_array($version) ? $version['version'] : null;
391
+ }
392
+
393
+ public function getActivePlugins()
394
+ {
395
+ $active_plugins = "<ul>";
396
+ $plugins = wp_get_active_and_valid_plugins();
397
+ foreach ($plugins as $plugin) {
398
+ $plugin_data = get_plugin_data($plugin);
399
+ $active_plugins .= '<li><span class="font-bold">'.$plugin_data['Name'].'</span>: '.$plugin_data['Version'].'</li>';
400
+ }
401
+ $active_plugins .= "</ul>";
402
+ return print_r($active_plugins, true);
403
+ }
404
+
405
+ public function getLastActions()
406
+ {
407
+ global $wpdb;
408
+ if (!class_exists('ActionScheduler') || !ActionScheduler::is_initialized( 'store' ) ) {
409
+ return array();
410
+ }
411
+ if (!ActionScheduler::store()) {
412
+ return array();
413
+ }
414
+ $oldest_and_newest = '<ul>';
415
+
416
+ foreach (array_keys(ActionScheduler::store()->get_status_labels()) as $status) {
417
+ if ('in-progress' === $status) {
418
+ continue;
419
+ }
420
+ $newest = $this->get_action_status_date($status, 'newest' );
421
+ $status = ucfirst($status);
422
+ $oldest_and_newest .= "<li><span class='font-bold'>{$status}</span>: {$newest}</li>";
423
+ }
424
+
425
+ $oldest_and_newest .= '</ul>';
426
+
427
+ return $oldest_and_newest;
428
+ }
429
+
430
+ /**
431
+ * @return array|object|null
432
+ */
433
+ public function getMeta()
434
+ {
435
+ global $wpdb;
436
+ $results = $wpdb->get_results("SELECT * FROM $wpdb->options WHERE option_name LIKE 'mailchimp-woocommerce-%'");
437
+ $response = array();
438
+ $date = new \DateTime('now');
439
+ foreach ($results as $result) {
440
+ $response[] = array(
441
+ 'key' => str_replace('mailchimp-woocommerce-', '', $result->option_name),
442
+ 'value' => $result->option_value,
443
+ 'updated_at' => $date->format('Y-m-d H:i:s'),
444
+ );
445
+ }
446
+ return $response;
447
+ }
448
+
449
+ /**
450
+ * This is where we need to hook into tower from the store owner's support request.
451
+ * We can enable and disable this feature which will generate an API token specific to
452
+ * tower which will be used for authentication coming from our server to this specific store.
453
+ *
454
+ * @param bool $enable
455
+ * @return array|mixed|object|null
456
+ */
457
+ public function toggle($enable = true)
458
+ {
459
+ $command = (bool) $enable ? 'enable' : 'disable';
460
+ $store_id = mailchimp_get_store_id();
461
+ $key = mailchimp_get_api_key();
462
+ $list_id = mailchimp_get_list_id();
463
+ $is_connected = mailchimp_is_configured();
464
+ $post_url = "https://tower.vextras.com/admin-api/woocommerce/{$command}/{$store_id}";
465
+ $plugin_options = (array) get_option('mailchimp-woocommerce');
466
+ $akamai_block = false;
467
+
468
+ if ((bool) $enable) {
469
+ mailchimp_set_data('tower.token', $support_token = wp_generate_password());
470
+ } else {
471
+ $support_token = mailchimp_get_data('tower.token');
472
+ delete_option('mailchimp-woocommerce-tower.support_token');
473
+ }
474
+
475
+ if ($enable) {
476
+ $data = array(
477
+ 'list_id' => $list_id,
478
+ 'php_version' => phpversion(),
479
+ 'curl_enabled' => function_exists('curl_init'),
480
+ 'is_connected' => $is_connected,
481
+ 'sync_complete' => mailchimp_is_done_syncing(),
482
+ 'rest_url' => MailChimp_WooCommerce_Rest_Api::url(''),
483
+ );
484
+ if ($is_connected) {
485
+ try {
486
+ $api = mailchimp_get_api();
487
+ $account_info = $api->getProfile();
488
+ $list_info = !empty($list_id) ? $api->getList($list_id) : null;
489
+ $mc_store = $api->getStore($store_id);
490
+ $syncing_mc = $mc_store ? $mc_store->isSyncing() : false;
491
+ if (is_array($list_info)) {
492
+ unset($list_info['_links']);
493
+ }
494
+ if (is_array($account_info)) {
495
+ unset($account_info['_links']);
496
+ }
497
+ $job = new MailChimp_WooCommerce_Fix_Duplicate_Store($store_id, false, false);
498
+ $job->handle();
499
+ $dup_store = (bool) $job->hasDuplicateStoreProblem();
500
+ } catch (\Throwable $e) {
501
+ $list_info = false;
502
+ $syncing_mc = false;
503
+ $account_info = false;
504
+ if ($e->getCode() === 503) {
505
+ $akamai_block = true;
506
+ }
507
+ if (!isset($dup_store)) $dup_store = false;
508
+ }
509
+ $data['list_info'] = $list_info;
510
+ $data['is_syncing'] = $syncing_mc;
511
+ $data['account_info'] = $account_info;
512
+ $data['duplicate_mailchimp_store'] = $dup_store;
513
+ $data['akamai_block'] = $akamai_block;
514
+ }
515
+ } else {
516
+ $data = array();
517
+ }
518
+
519
+ try {
520
+ $payload = array(
521
+ 'headers' => array(
522
+ 'Content-type' => 'application/json',
523
+ 'Accept' => 'application/json',
524
+ 'X-Store-Platform' => 'woocommerce',
525
+ 'X-List-Id' => $list_id,
526
+ 'X-Store-Key' => base64_encode("{$store_id}:{$key}"),
527
+ ),
528
+ 'body' => json_encode(array(
529
+ 'name' => !empty($plugin_options) && isset($plugin_options['store_name']) ? $plugin_options['store_name'] : get_option('blogname'),
530
+ 'support_token' => $support_token,
531
+ 'domain' => get_option('siteurl'),
532
+ 'data' => $data,
533
+ )),
534
+ 'timeout' => 30,
535
+ );
536
+ $response = wp_remote_post($post_url, $payload);
537
+ return json_decode($response['body']);
538
+ } catch (\Throwable $e) {
539
+ return null;
540
+ }
541
+ }
542
+
543
+ /**
544
+ * Get oldest or newest scheduled date for a given status.
545
+ *
546
+ * @param string $status Action status label/name string.
547
+ * @param string $date_type Oldest or Newest.
548
+ * @return string
549
+ */
550
+ protected function get_action_status_date( $status, $date_type = 'oldest' )
551
+ {
552
+ $order = 'oldest' === $date_type ? 'ASC' : 'DESC';
553
+ $store = ActionScheduler::store();
554
+ $action = $store->query_actions(
555
+ array(
556
+ 'claimed' => false,
557
+ 'status' => $status,
558
+ 'per_page' => 1,
559
+ 'order' => $order,
560
+ )
561
+ );
562
+ if ( ! empty( $action ) ) {
563
+ $date_object = $store->get_date( $action[0] );
564
+ $action_date = $date_object->format( 'Y-m-d H:i:s O' );
565
+ } else {
566
+ $action_date = '&ndash;';
567
+ }
568
+ return $action_date;
569
+ }
570
+ }
includes/api/class-mailchimp-woocommerce-transform-orders-wc3.php CHANGED
@@ -59,6 +59,13 @@ class MailChimp_WooCommerce_Transform_Orders
59
  return $order;
60
  }
61
 
 
 
 
 
 
 
 
62
  // if the woo object does not have a "get_billing_email" method, then we need to skip this until
63
  // we know how to resolve these types of things.
64
  //mailchimp_log('get_billing_mail', method_exists($woo, 'get_billing_email'), array($order->toArray(), $woo));
59
  return $order;
60
  }
61
 
62
+ // this is a fallback safety check to make sure we're not submitting these orders.
63
+ if ($woo->get_status() === 'checkout-draft') {
64
+ $order->setOriginalWooStatus('checkout-draft');
65
+ $order->flagAsIgnoreIfNotInMailchimp(true);
66
+ return $order;
67
+ }
68
+
69
  // if the woo object does not have a "get_billing_email" method, then we need to skip this until
70
  // we know how to resolve these types of things.
71
  //mailchimp_log('get_billing_mail', method_exists($woo, 'get_billing_email'), array($order->toArray(), $woo));
includes/class-mailchimp-woocommerce-rest-api.php CHANGED
@@ -44,6 +44,51 @@ class MailChimp_WooCommerce_Rest_Api
44
  'callback' => array($this, 'dismiss_review_banner'),
45
  'permission_callback' => array($this, 'permission_callback'),
46
  ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
 
49
  /**
@@ -72,7 +117,7 @@ class MailChimp_WooCommerce_Rest_Api
72
  {
73
  // need to send a post request to
74
  $host = mailchimp_environment_variables()->environment === 'staging' ?
75
- 'https://staging.conduit.vextras.com' : 'https://conduit.mailchimpapp.com';
76
 
77
  $route = "{$host}/survey/woocommerce";
78
 
@@ -163,16 +208,449 @@ class MailChimp_WooCommerce_Rest_Api
163
  return $this->mailchimp_rest_response(array('success' => delete_option('mailchimp-woocommerce-sync.initial_sync')));
164
  }
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
  /**
168
  * @param array $data
169
  * @param int $status
170
  * @return WP_REST_Response
171
  */
172
- private function mailchimp_rest_response($data, $status = 200) {
 
173
  if (!is_array($data)) $data = array();
174
  $response = new WP_REST_Response($data);
175
  $response->set_status($status);
176
  return $response;
177
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  }
44
  'callback' => array($this, 'dismiss_review_banner'),
45
  'permission_callback' => array($this, 'permission_callback'),
46
  ));
47
+
48
+ //Member Sync
49
+ register_rest_route(static::$namespace, "/member-sync", array(
50
+ 'methods' => 'GET',
51
+ 'callback' => array($this, 'member_sync_alive_signal'),
52
+ 'permission_callback' => '__return_true',
53
+ ));
54
+ register_rest_route(static::$namespace, "/member-sync", array(
55
+ 'methods' => 'POST',
56
+ 'callback' => array($this, 'member_sync'),
57
+ 'permission_callback' => '__return_true',
58
+ ));
59
+
60
+ // Tower report
61
+ register_rest_route(static::$namespace, "/tower/report", array(
62
+ 'methods' => 'POST',
63
+ 'callback' => array($this, 'get_tower_report'),
64
+ 'permission_callback' => '__return_true',
65
+ ));
66
+
67
+ // tower logs
68
+ register_rest_route(static::$namespace, "/tower/logs", array(
69
+ 'methods' => 'POST',
70
+ 'callback' => array($this, 'get_tower_logs'),
71
+ 'permission_callback' => '__return_true',
72
+ ));
73
+
74
+ register_rest_route(static::$namespace, "/tower/resource", array(
75
+ 'methods' => 'POST',
76
+ 'callback' => array($this, 'get_tower_resource'),
77
+ 'permission_callback' => '__return_true',
78
+ ));
79
+
80
+ register_rest_route(static::$namespace, "/tower/action", array(
81
+ 'methods' => 'POST',
82
+ 'callback' => array($this, 'handle_tower_action'),
83
+ 'permission_callback' => '__return_true',
84
+ ));
85
+
86
+ register_rest_route(static::$namespace, "/tower/sync_stats", array(
87
+ 'methods' => 'POST',
88
+ 'callback' => array($this, 'get_tower_sync_stats'),
89
+ 'permission_callback' => '__return_true',
90
+ ));
91
+
92
  }
93
 
94
  /**
117
  {
118
  // need to send a post request to
119
  $host = mailchimp_environment_variables()->environment === 'staging' ?
120
+ 'https://staging.conduit.vextras.com' : 'https://conduit.mailchimpapp.com';
121
 
122
  $route = "{$host}/survey/woocommerce";
123
 
208
  return $this->mailchimp_rest_response(array('success' => delete_option('mailchimp-woocommerce-sync.initial_sync')));
209
  }
210
 
211
+ /**
212
+ * Syncs members with updated statuses on Mailchimp panel
213
+ * @param WP_REST_Request $request
214
+ * @return WP_Error|WP_REST_Response
215
+ */
216
+ public function member_sync(WP_REST_Request $request)
217
+ {
218
+ $this->authorize('webhook.token', $request);
219
+ $data = $request->get_params();
220
+ if (!empty($data['type']) && !empty($data['data']['list_id']) && mailchimp_get_list_id() == $data['data']['list_id'] ){
221
+ $job = new MailChimp_WooCommerce_Subscriber_Sync($data);
222
+ $job->handle();
223
+ return $this->mailchimp_rest_response(array('success' => true));
224
+ }
225
+ return $this->mailchimp_rest_response(array('success' => false));
226
+ }
227
+
228
+ /**
229
+ * Returns an alive signal to confirm url exists to mailchimp system
230
+ * @param WP_REST_Request $request
231
+ * @return WP_Error|WP_REST_Response
232
+ */
233
+ public function member_sync_alive_signal(WP_REST_Request $request)
234
+ {
235
+ $this->authorize('webhook.token', $request);
236
+ return $this->mailchimp_rest_response(array('success' => true));
237
+ }
238
+
239
+ /**
240
+ * @param WP_REST_Request $request
241
+ * @return WP_Error|WP_REST_Response
242
+ */
243
+ public function get_tower_report(WP_REST_Request $request)
244
+ {
245
+ $this->authorize('tower.token', $request);
246
+ return $this->mailchimp_rest_response(
247
+ $this->tower($request->get_query_params())->handle()
248
+ );
249
+ }
250
+
251
+ /**
252
+ * @param WP_REST_Request $request
253
+ * @return WP_Error|WP_REST_Response
254
+ */
255
+ public function handle_tower_action(WP_REST_Request $request)
256
+ {
257
+ $this->authorize('tower.token', $request);
258
+ $body = $request->get_json_params();
259
+
260
+ $action = isset($body['action']) ? $body['action'] : null;
261
+ $data = isset($body['data']) ? $body['data'] : null;
262
+ $response = null;
263
+
264
+ if (empty($action)) {
265
+ return $this->mailchimp_rest_response(array(
266
+ 'success' => false,
267
+ 'message' => 'invalid action'
268
+ ));
269
+ }
270
+
271
+ switch ($action) {
272
+ case 'emergency_stop_syncing':
273
+ mailchimp_set_data('emergency_stop', true);
274
+ $response = [
275
+ 'title' => "Successfully stopped the sync.",
276
+ 'description' => "Please note you'll need to have them reconnect.",
277
+ 'type' => 'success',
278
+ ];
279
+ break;
280
+ case 'update_feature':
281
+ $response = [
282
+ 'title' => "Features are not available for WooCommerce",
283
+ 'type' => 'error',
284
+ ];
285
+ break;
286
+ case 'resync_orders':
287
+ MailChimp_WooCommerce_Process_Orders::push();
288
+ $response = [
289
+ 'title' => "Successfully initiated the order resync",
290
+ 'description' => "Please note that it will take a couple minutes to start this process. Check the store logs for details.",
291
+ 'type' => 'success',
292
+ ];
293
+ break;
294
+ case 'resync_products':
295
+ MailChimp_WooCommerce_Process_Products::push();
296
+ $response = [
297
+ 'title' => "Successfully initiated product resync",
298
+ 'description' => "Please note that it will take a couple minutes to start this process. Check the store logs for details.",
299
+ 'type' => 'success',
300
+ ];
301
+ break;
302
+ case 'resync_customers':
303
+ $response = [
304
+ 'title' => "Customer resync",
305
+ 'description' => "WooCommerce does not have customers to sync. Only orders.",
306
+ 'type' => 'error',
307
+ ];
308
+ break;
309
+ case 'resync_promo_codes':
310
+ MailChimp_WooCommerce_Process_Coupons::push();
311
+ $response = [
312
+ 'title' => "Successfully initiated promo code resync",
313
+ 'description' => "Please note that it will take a couple minutes to start this process. Check the store logs for details.",
314
+ 'type' => 'success',
315
+ ];
316
+ break;
317
+ case 'resync_chimpstatic_script':
318
+ $response = [
319
+ 'title' => "Chimpstatic script",
320
+ 'description' => 'Scripts are automatically injected at runtime.',
321
+ 'type' => 'error',
322
+ ];
323
+ break;
324
+ case 'activate_webhooks':
325
+ $response = [
326
+ 'title' => "Store Webhooks",
327
+ 'description' => "No store webhooks to apply",
328
+ 'type' => 'error',
329
+ ];
330
+ break;
331
+ case 'resync_all':
332
+ $service = new MailChimp_Service();
333
+ $service->removePointers(true, true);
334
+ MailChimp_WooCommerce_Admin::instance()->startSync();
335
+ $service->setData('sync.config.resync', true);
336
+ $response = [
337
+ 'title' => "Successfully initiated the store resync",
338
+ 'description' => "Please note that it will take a couple minutes to start this process. Check the store logs for details.",
339
+ 'type' => 'success',
340
+ ];
341
+ break;
342
+ case 'resync_customer':
343
+ $response = [
344
+ 'title' => "Error syncing custome",
345
+ 'description' => "WooCommerce only works with orders.",
346
+ 'type' => 'error',
347
+ ];
348
+ break;
349
+ case 'resync_order':
350
+ $order = new WC_Order($data['id']);
351
+ if (!$order->get_date_created()) {
352
+ $response = [
353
+ 'title' => "Error syncing order",
354
+ 'description' => "This order id does not exist.",
355
+ 'type' => 'error',
356
+ ];
357
+ } else {
358
+ $job = new MailChimp_WooCommerce_Single_Order($order);
359
+ $data = $job->handle();
360
+ $response = [
361
+ 'title' => "Executed order resync",
362
+ 'description' => "Check the store logs for details.",
363
+ 'type' => 'success',
364
+ ];
365
+ }
366
+ break;
367
+ case 'resync_product':
368
+ $product = new WC_Product($data['id']);
369
+ if (!$product->get_date_created()) {
370
+ $response = [
371
+ 'title' => "Error syncing product",
372
+ 'description' => "This product id does not exist.",
373
+ 'type' => 'error',
374
+ ];
375
+ } else {
376
+ $job = new MailChimp_WooCommerce_Single_Product($product);
377
+ $data = $job->handle();
378
+ $response = [
379
+ 'title' => "Executed product resync",
380
+ 'description' => "Check the store logs for details.",
381
+ 'type' => 'success',
382
+ ];
383
+ }
384
+ break;
385
+ case 'resync_cart':
386
+ $response = [
387
+ 'title' => "Let's talk",
388
+ 'description' => "This isn't supported by our system yet. If you really need this, please say something.",
389
+ 'type' => 'error',
390
+ ];
391
+ break;
392
+ case 'fix_duplicate_store':
393
+ $job = new MailChimp_WooCommerce_Fix_Duplicate_Store(mailchimp_get_store_id(), true, false);
394
+ $job->handle();
395
+ $response = [
396
+ 'title' => "Successfully queued up store deletion.",
397
+ 'description' => "This process may take a couple minutes to complete. Please check back by reloading the page after a minute.",
398
+ 'type' => 'success',
399
+ ];
400
+ break;
401
+ case 'remove_legacy_app':
402
+ $response = [
403
+ 'title' => "Error removing legacy app",
404
+ 'description' => "WooCommerce doesn't have any legacy apps to delete.",
405
+ 'type' => 'error',
406
+ ];
407
+ break;
408
+ }
409
+
410
+ return $this->mailchimp_rest_response($response);
411
+ }
412
+
413
+ /**
414
+ * @param WP_REST_Request $request
415
+ * @return WP_Error|WP_REST_Response
416
+ */
417
+ public function get_tower_logs(WP_REST_Request $request)
418
+ {
419
+ $this->authorize('tower.token', $request);
420
+ return $this->mailchimp_rest_response(
421
+ $this->tower($request->get_query_params())->logs()
422
+ );
423
+ }
424
+
425
+ /**
426
+ * @param WP_REST_Request $request
427
+ * @return WP_Error|WP_REST_Response
428
+ */
429
+ public function get_tower_resource(WP_REST_Request $request)
430
+ {
431
+ $this->authorize('tower.token', $request);
432
+ $body = json_decode($request->get_body(), true);
433
+
434
+ if (!isset($body['resource']) || !isset($body['resource_id'])) {
435
+ return $this->mailchimp_rest_response(array(
436
+ 'resource' => null,
437
+ 'resource_error' => 'Resource not found because post request was wrong',
438
+ 'mailchimp' => null,
439
+ 'mailchimp_error' => 'Resource not found because post request was wrong',
440
+ ));
441
+ }
442
+
443
+ $store_id = mailchimp_get_store_id();
444
+
445
+ switch ($body['resource']) {
446
+ case 'order':
447
+ $platform = null;
448
+ $order = get_post($body['resource_id']);
449
+ $mc = !$order->ID ? null : mailchimp_get_api()->getStoreOrder($store_id, $order->ID);
450
+ if ($order->ID) {
451
+ $transformer = new MailChimp_WooCommerce_Transform_Orders();
452
+ $platform = $transformer->transform($order)->toArray();
453
+ }
454
+ if ($mc) $mc = $mc->toArray();
455
+ break;
456
+ case 'customer':
457
+ $body['resource_id'] = urldecode($body['resource_id']);
458
+ $field = is_email($body['resource_id']) ? 'email' : 'id';
459
+ $platform = get_user_by($field, $body['resource_id']);
460
+ if ($platform) {
461
+ $platform->mailchimp_woocommerce_is_subscribed = (bool) get_user_meta($platform->ID, 'mailchimp_woocommerce_is_subscribed', true);
462
+ }
463
+ $hashed = mailchimp_hash_trim_lower($platform->user_email);
464
+ if ($mc = mailchimp_get_api()->getCustomer($store_id, $hashed)) {
465
+ try {
466
+ $member = mailchimp_get_api()->member(mailchimp_get_list_id(), $mc->getEmailAddress());
467
+ } catch (\Exception $e) {
468
+ $member = null;
469
+ }
470
+ $mc = array(
471
+ 'customer' => $mc->toArray(),
472
+ 'member' => $member,
473
+ );
474
+ }
475
+ break;
476
+ case 'product':
477
+ $platform = get_post($body['resource_id']);
478
+ if ($platform) {
479
+ $transformer = new MailChimp_WooCommerce_Transform_Products();
480
+ $platform = $transformer->transform($platform)->toArray();
481
+ }
482
+ if ($mc = mailchimp_get_api()->getStoreProduct($store_id, $body['resource_id'])) {
483
+ $mc = $mc->toArray();
484
+ }
485
+ break;
486
+ case 'cart':
487
+ global $wpdb;
488
+ $uid = mailchimp_hash_trim_lower($body['resource_id']);
489
+ $table = "{$wpdb->prefix}mailchimp_carts";
490
+ $sql = $wpdb->prepare("SELECT * FROM $table WHERE id = %s", $uid);
491
+ $platform = $wpdb->get_row($sql);
492
+ if ($mc = mailchimp_get_api()->getCart($store_id, $uid)) {
493
+ $mc = $mc->toArray();
494
+ }
495
+ break;
496
+ case 'promo_code':
497
+ $platform = new WC_Coupon($body['resource_id']);
498
+ if ($mc = mailchimp_get_api()->getPromoRuleWithCodes($store_id, $body['resource_id'])) {
499
+ //$mc = $mc->toArray();
500
+ }
501
+ break;
502
+ }
503
+
504
+ return $this->mailchimp_rest_response(array(
505
+ 'resource' => $platform,
506
+ 'resource_error' => empty($platform) ? 'Resource not found' : false,
507
+ 'mailchimp' => $mc,
508
+ 'mailchimp_error' => empty($mc) ? 'Resource not found' : false,
509
+ ));
510
+ }
511
+
512
+ /**
513
+ * @param WP_REST_Request $request
514
+ * @return WP_REST_Response
515
+ */
516
+ public function get_tower_sync_stats(WP_REST_Request $request)
517
+ {
518
+ $this->authorize('tower.token', $request);
519
+
520
+ // if the queue is running in the console - we need to say tell the response why it's not going to fire this way.
521
+ if (!mailchimp_is_configured() || !($api = mailchimp_get_api())) {
522
+ return $this->mailchimp_rest_response(array('success' => false, 'reason' => 'not configured'));
523
+ }
524
+
525
+ $store_id = mailchimp_get_store_id();
526
+ $product_count = mailchimp_get_product_count();
527
+ $order_count = mailchimp_get_order_count();
528
+
529
+ try {
530
+ $products = $api->products($store_id, 1, 1);
531
+ $mailchimp_total_products = $products['total_items'];
532
+ if ($mailchimp_total_products > $product_count) {
533
+ $mailchimp_total_products = $product_count;
534
+ }
535
+ } catch (\Exception $e) { $mailchimp_total_products = 0; }
536
+ try {
537
+ $mailchimp_total_customers = $api->getCustomerCount($store_id);
538
+ } catch (\Exception $e) { $mailchimp_total_customers = 0; }
539
+ try {
540
+ $orders = $api->orders($store_id, 1, 1);
541
+ $mailchimp_total_orders = $orders['total_items'];
542
+ if ($mailchimp_total_orders > $order_count) {
543
+ $mailchimp_total_orders = $order_count;
544
+ }
545
+ } catch (\Exception $e) { $mailchimp_total_orders = 0; }
546
+
547
+ // but we need to do it just in case.
548
+ return $this->mailchimp_rest_response(array(
549
+ 'platform' => array(
550
+ 'products' => $product_count,
551
+ 'customers' => 0,
552
+ 'orders' => $order_count,
553
+ ),
554
+ 'mailchimp' => array(
555
+ 'products' => $mailchimp_total_products,
556
+ 'customers' => $mailchimp_total_customers,
557
+ 'orders' => $mailchimp_total_orders,
558
+ ),
559
+ ));
560
+ }
561
+
562
+ /**
563
+ * @param null $params
564
+ * @return MailChimp_WooCommerce_Tower
565
+ */
566
+ private function tower($params = null)
567
+ {
568
+ if (!is_array($params)) $params = array();
569
+ $job = new MailChimp_WooCommerce_Tower(mailchimp_get_store_id());
570
+ $job->withLogFile(!empty($params['log_view']) ? $params['log_view'] : null);
571
+ $job->withLogSearch(!empty($params['search']) ? $params['search'] : null);
572
+ return $job;
573
+ }
574
+
575
 
576
  /**
577
  * @param array $data
578
  * @param int $status
579
  * @return WP_REST_Response
580
  */
581
+ private function mailchimp_rest_response($data, $status = 200)
582
+ {
583
  if (!is_array($data)) $data = array();
584
  $response = new WP_REST_Response($data);
585
  $response->set_status($status);
586
  return $response;
587
  }
588
+
589
+ /**
590
+ * @param $key
591
+ * @param WP_REST_Request $request
592
+ * @return bool
593
+ * @throws WC_REST_Exception
594
+ */
595
+ private function authorize($key, WP_REST_Request $request)
596
+ {
597
+ $allowed_keys = array(
598
+ 'tower.token',
599
+ 'webhook.token',
600
+ );
601
+ // this is just a safeguard against people trying to do wonky things.
602
+ if (!in_array($key, $allowed_keys, true)) {
603
+ wp_send_json_error(array('message' => 'unauthorized token type'), 403);
604
+ }
605
+ // get the auth token from either a header, or the query string
606
+ $token = $this->getAuthToken($request);
607
+ // pull the saved data
608
+ $saved = mailchimp_get_data($key);
609
+
610
+ // if we don't have a token - or we don't have the saved comparison
611
+ // or the token doesn't equal the saved token, throw an error.
612
+ if (empty($token) || empty($saved) || base64_decode($token) !== $saved) {
613
+ wp_send_json_error(array('message' => 'unauthorized'), 403);
614
+ }
615
+ return true;
616
+ }
617
+
618
+ /**
619
+ * @param WP_REST_Request $request
620
+ * @return false|mixed|string
621
+ */
622
+ private function getAuthToken(WP_REST_Request $request)
623
+ {
624
+ if (($token = $this->getBearerTokenHeader($request))) {
625
+ return $token;
626
+ }
627
+ return $this->getAuthQueryStringParam($request);
628
+ }
629
+
630
+ /**
631
+ * @param WP_REST_Request $request
632
+ * @return false|string
633
+ */
634
+ private function getBearerTokenHeader(WP_REST_Request $request)
635
+ {
636
+ $header = $request->get_header('Authorization');
637
+ $position = strrpos($header, 'Bearer ');
638
+ if ($position !== false) {
639
+ $header = substr($header, $position + 7);
640
+ return strpos($header, ',') !== false ?
641
+ strstr(',', $header, true) :
642
+ $header;
643
+ }
644
+ return false;
645
+ }
646
+
647
+ /**
648
+ * @param WP_REST_Request $request
649
+ * @return false|mixed
650
+ */
651
+ private function getAuthQueryStringParam(WP_REST_Request $request)
652
+ {
653
+ $params = $request->get_query_params();
654
+ return empty($params['auth']) ? false : $params['auth'];
655
+ }
656
  }
includes/class-mailchimp-woocommerce-service.php CHANGED
@@ -154,12 +154,19 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
154
  $gdpr_fields = isset($_POST['mailchimp_woocommerce_gdpr']) ?
155
  $_POST['mailchimp_woocommerce_gdpr'] : false;
156
 
157
- if (isset($tracking)) {
158
- // update the post meta with campaing tracking details for future sync
159
  update_post_meta($order_id, 'mailchimp_woocommerce_campaign_id', $campaign_id);
 
 
160
  update_post_meta($order_id, 'mailchimp_woocommerce_landing_site', $landing_site);
161
  }
162
 
 
 
 
 
 
163
  $handler = new MailChimp_WooCommerce_Single_Order($order_id, null, $campaign_id, $landing_site, $language, $gdpr_fields);
164
  $handler->is_update = $newOrder ? !$newOrder : null;
165
  $handler->is_admin_save = is_admin();
@@ -196,7 +203,7 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
196
  public function handleCartUpdated($updated = null)
197
  {
198
  if (mailchimp_carts_disabled()) {
199
- return false;
200
  }
201
 
202
  if ($updated === false || $this->is_admin || $this->cart_was_submitted || !mailchimp_is_configured()) {
@@ -225,7 +232,7 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
225
  }
226
  if ($cached_status !== 'subscribed') {
227
  mailchimp_debug('filter', "preventing {$user_email} from submitting cart data due to subscriber settings.");
228
- return false;
229
  }
230
  }
231
 
@@ -323,27 +330,140 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
323
  }
324
 
325
  /**
326
- * Save post metadata when a post is saved.
327
  *
328
- * @param int $post_id The post ID.
329
- * @param WP_Post $post The post object.
330
- * @param bool $update Whether this is an existing post being updated or not.
 
331
  */
332
- public function handlePostSaved($post_id, $post, $update)
333
  {
334
- if (!mailchimp_is_configured()) return;
 
 
 
 
 
 
335
 
336
- // don't handle any of these statuses because they're not ready for the show
337
- if (!in_array($post->post_status, array('trash', 'auto-draft', 'draft', 'pending'))) {
338
- if ('product' == $post->post_type) {
339
- mailchimp_handle_or_queue(new MailChimp_WooCommerce_Single_Product($post_id), 5);
340
- } elseif ('shop_order' == $post->post_type) {
341
- $tracking = $this->onNewOrder($post_id);
342
- $this->onOrderSave($post_id, $tracking, !$update);
343
- }
344
  }
345
  }
346
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  /**
348
  * @param $post_id
349
  */
@@ -429,12 +549,17 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
429
 
430
  // only update this person if they were marked as subscribed before
431
  $is_subscribed = get_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', true);
432
-
433
- // if they don't have a meta set for is_subscribed, we will get a blank string, so just ignore this.
434
- if ($is_subscribed === '' || $is_subscribed === null) return;
435
-
 
 
 
 
 
436
  // only send this update if the user actually has a boolean value.
437
- mailchimp_handle_or_queue(new MailChimp_WooCommerce_User_Submit($user_id, (bool) $is_subscribed, $old_user_data));
438
  }
439
 
440
  /**
@@ -940,6 +1065,9 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
940
 
941
  global $wpdb;
942
 
 
 
 
943
  $table = "{$wpdb->prefix}mailchimp_carts";
944
 
945
  $statement = "SELECT * FROM $table WHERE id = %s";
@@ -1023,8 +1151,38 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
1023
  return false;
1024
  }
1025
 
1026
- public function mailchimp_process_sync_manager () {
 
1027
  $sync_stats_manager = new MailChimp_WooCommerce_Process_Full_Sync_Manager();
1028
  $sync_stats_manager->handle();
1029
  }
1030
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  $gdpr_fields = isset($_POST['mailchimp_woocommerce_gdpr']) ?
155
  $_POST['mailchimp_woocommerce_gdpr'] : false;
156
 
157
+ // update the post meta with campaign tracking and landing site details
158
+ if (!empty($campaign_id)) {
159
  update_post_meta($order_id, 'mailchimp_woocommerce_campaign_id', $campaign_id);
160
+ }
161
+ if (!empty($landing_site)) {
162
  update_post_meta($order_id, 'mailchimp_woocommerce_landing_site', $landing_site);
163
  }
164
 
165
+ // if we have gdpr fields in the post - let's save them to the order
166
+ if (!empty($gdpr_fields)) {
167
+ update_post_meta($order_id, "mailchimp_woocommerce_gdpr_fields", $gdpr_fields);
168
+ }
169
+
170
  $handler = new MailChimp_WooCommerce_Single_Order($order_id, null, $campaign_id, $landing_site, $language, $gdpr_fields);
171
  $handler->is_update = $newOrder ? !$newOrder : null;
172
  $handler->is_admin_save = is_admin();
203
  public function handleCartUpdated($updated = null)
204
  {
205
  if (mailchimp_carts_disabled()) {
206
+ return $updated;
207
  }
208
 
209
  if ($updated === false || $this->is_admin || $this->cart_was_submitted || !mailchimp_is_configured()) {
232
  }
233
  if ($cached_status !== 'subscribed') {
234
  mailchimp_debug('filter', "preventing {$user_email} from submitting cart data due to subscriber settings.");
235
+ return $updated;
236
  }
237
  }
238
 
330
  }
331
 
332
  /**
333
+ * When a product post has been updated, handle or queue syncing when key fields have changed.
334
  *
335
+ * @param int $post_ID The ID of the post/product being updated
336
+ * @param WP_Post $post_after The post object as it existed before the update
337
+ * @param WP_Post $post_before The post object as it exists after the update
338
+ * @return void
339
  */
340
+ public function handleProductUpdated( int $post_ID, WP_Post $post_after, WP_Post $post_before )
341
  {
342
+ // Only work with products that have certain statuses
343
+ if ('product' !== $post_after->post_type
344
+ || in_array($post_after->post_status, array('trash', 'auto-draft', 'draft', 'pending'))
345
+ || ! mailchimp_is_configured()
346
+ ) {
347
+ return;
348
+ }
349
 
350
+ // Check if product title or description has been altered
351
+ if ($post_after->post_title !== $post_before->post_title
352
+ || $post_after->post_content !== $post_before->post_content
353
+ ) {
354
+ mailchimp_handle_or_queue( new MailChimp_WooCommerce_Single_Product($post_ID), 5);
 
 
 
355
  }
356
  }
357
 
358
+ /**
359
+ * @param \WC_Product $product
360
+ * @param $data
361
+ */
362
+ public function handleProcessProductMeta($product, $data)
363
+ {
364
+ if (!is_array($data) || empty($data) || !$product) {
365
+ return;
366
+ }
367
+
368
+ $valid_keys = array(
369
+ '_thumbnail_id',
370
+ 'description',
371
+ 'image_id',
372
+ 'price',
373
+ 'sku',
374
+ 'regular_price',
375
+ 'sale_price',
376
+ '_stock_status',
377
+ 'stock_quantity',
378
+ '_stock',
379
+ 'stock_status',
380
+ 'manage_stock',
381
+ 'gallery_image_ids',
382
+ 'name',
383
+ 'status',
384
+ 'slug',
385
+ );
386
+
387
+ // if there's not a valid prop in the update, just skip this.
388
+ if (!array_intersect($valid_keys, $data)) {
389
+ return;
390
+ }
391
+
392
+ mailchimp_debug('action', "handleProcessProductMeta {$product->get_id()} update being queued", array(
393
+ 'data' => $data,
394
+ ));
395
+
396
+ mailchimp_handle_or_queue(new MailChimp_WooCommerce_Single_Product($product->post->ID), 5);
397
+ }
398
+
399
+ /**
400
+ * When the _stock, _thumbnail_id,
401
+ * meta is updated for a product, handle or queue syncing updates.
402
+ *
403
+ * @param int $meta_id The ID of the post meta entry that was updated
404
+ * @param int $object_id The ID of the object the post meta entry is attached to
405
+ * @param string $meta_key The key of the meta entry that was updated
406
+ * @param mixed $_meta_value The value of the meta entry that was updated
407
+ * @return void
408
+ */
409
+ public function handleProductMetaUpdated($meta_id, $object_id, $meta_key, $_meta_value)
410
+ {
411
+ // If we're not working with the meta key used to store stock quantity, bail
412
+ if (!in_array($meta_key, array('_thumbnail_id'), true)) {
413
+ return;
414
+ }
415
+
416
+ // Confirm that we're working with an object that is a WooCommerce product with a certain status
417
+ $product = wc_get_product($object_id);
418
+ if ($product instanceof WC_Product &&
419
+ !in_array($product->get_status(), array('trash', 'auto-draft', 'draft', 'pending'))
420
+ ) {
421
+ mailchimp_debug('queue', "handling meta update for meta [{$meta_key}] on product {$object_id}");
422
+ mailchimp_handle_or_queue(new MailChimp_WooCommerce_Single_Product($object_id), 5);
423
+ }
424
+ }
425
+
426
+ /**
427
+ * If a product has been updated and isn't an existing post, handle or queue syncing updates.
428
+ *
429
+ * @param int $post_ID The ID of the post that was updated/created
430
+ * @param WP_Post $post The post object that was updated/created
431
+ * @param bool $is_existing_post Whether the updated post existed before the update
432
+ * @return void
433
+ */
434
+ public function handleProductCreated($post_ID, WP_Post $post, $is_existing_post)
435
+ {
436
+ // Since the handleProductUpdated() function above handles product updates, bail for existing posts/products.
437
+ if ($is_existing_post || !mailchimp_is_configured()) {
438
+ return;
439
+ }
440
+
441
+ // If the product is of a certain status, process it.
442
+ if (!in_array($post->post_status, array('trash', 'auto-draft', 'draft', 'pending'))) {
443
+ mailchimp_handle_or_queue(new MailChimp_WooCommerce_Single_Product($post_ID), 5);
444
+ }
445
+ }
446
+
447
+ /**
448
+ * Fire new order and order save handling/queueing events when a shop_order post is saved.
449
+ *
450
+ * @param int $post_ID The ID of the order
451
+ * @param WP_Post $post The post object of the order
452
+ * @param bool $is_existing_post Whether the order existed before the update
453
+ * @return void
454
+ */
455
+ public function handleOrderSaved( $post_ID, WP_Post $post, $is_existing_post)
456
+ {
457
+ if (!mailchimp_is_configured()) {
458
+ return;
459
+ }
460
+
461
+ if (!in_array($post->post_status, array('trash', 'auto-draft', 'draft', 'pending'))) {
462
+ $tracking = $this->onNewOrder($post_ID);
463
+ $this->onOrderSave($post_ID, $tracking, !$is_existing_post);
464
+ }
465
+ }
466
+
467
  /**
468
  * @param $post_id
469
  */
549
 
550
  // only update this person if they were marked as subscribed before
551
  $is_subscribed = get_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', true);
552
+ $gdpr_fields = get_user_meta($user_id, 'mailchimp_woocommerce_gdpr_fields', true);
553
+
554
+ $job = new MailChimp_WooCommerce_User_Submit(
555
+ $user_id,
556
+ (bool) $is_subscribed,
557
+ $old_user_data,
558
+ null,
559
+ !empty($gdpr_fields) ? $gdpr_fields : null
560
+ );
561
  // only send this update if the user actually has a boolean value.
562
+ mailchimp_handle_or_queue($job);
563
  }
564
 
565
  /**
1065
 
1066
  global $wpdb;
1067
 
1068
+ // Some people don't want to see these logs when they're in debug mode
1069
+ $wpdb->suppress_errors();
1070
+
1071
  $table = "{$wpdb->prefix}mailchimp_carts";
1072
 
1073
  $statement = "SELECT * FROM $table WHERE id = %s";
1151
  return false;
1152
  }
1153
 
1154
+ public function mailchimp_process_sync_manager()
1155
+ {
1156
  $sync_stats_manager = new MailChimp_WooCommerce_Process_Full_Sync_Manager();
1157
  $sync_stats_manager->handle();
1158
  }
1159
+
1160
+ /**
1161
+ * Display the Mailchimp checkbox on the admin page
1162
+ * @param $user
1163
+ */
1164
+ public function user_subscribed_profile( $user )
1165
+ {
1166
+ $admin = MailChimp_WooCommerce_Admin::instance();
1167
+ $admin->display_user_profile_info( $user );
1168
+ }
1169
+
1170
+ /**
1171
+ * Update the user meta from the admin page
1172
+ * @param $user_id
1173
+ */
1174
+ public function user_update_subscribe_status( $user_id )
1175
+ {
1176
+ $subscribed = isset($_POST['mailchimp_woocommerce_is_subscribed_checkbox']) &&
1177
+ $_POST['mailchimp_woocommerce_is_subscribed_checkbox'] == 'on';
1178
+ $gdpr_fields = isset($_POST['mailchimp_woocommerce_gdpr']) ? $_POST['mailchimp_woocommerce_gdpr'] : null;
1179
+ mailchimp_log("profile", 'user_update_subscribe_status', array(
1180
+ 'subscribed' => $subscribed,
1181
+ 'user_id' => $user_id,
1182
+ 'gdpr_fields' => $gdpr_fields,
1183
+ ));
1184
+ update_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', $subscribed);
1185
+ update_user_meta($user_id, 'mailchimp_woocommerce_gdpr_fields', $gdpr_fields);
1186
+ mailchimp_set_transient("mailchimp_woocommerce_gdpr_fields_{$user_id}", $gdpr_fields, 300);
1187
+ }
1188
+ }
includes/class-mailchimp-woocommerce.php CHANGED
@@ -132,6 +132,9 @@ class MailChimp_WooCommerce
132
  $this->activateMailChimpNewsletter();
133
  $this->activateMailChimpService();
134
  $this->applyQueryStringOverrides();
 
 
 
135
  }
136
 
137
  /**
@@ -241,6 +244,8 @@ class MailChimp_WooCommerce
241
  // make sure we're listening for the admin init
242
  $this->loader->add_action('admin_init', $plugin_admin, 'options_update');
243
  $this->loader->add_action('admin_notices', $plugin_admin, 'initial_notice');
 
 
244
 
245
  // put the menu on the admin top bar.
246
  //$this->loader->add_action('admin_bar_menu', $plugin_admin, 'admin_bar', 100);
@@ -273,11 +278,15 @@ class MailChimp_WooCommerce
273
  // set communications box status
274
  $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_communication_status', $plugin_admin, 'mailchimp_woocommerce_communication_status' );
275
 
 
 
 
276
  // Load log file via ajax
277
  $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_load_log_file', $plugin_admin, 'mailchimp_woocommerce_ajax_load_log_file' );
278
 
279
  // delete log file via ajax
280
  $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_delete_log_file', $plugin_admin, 'mailchimp_woocommerce_ajax_delete_log_file' );
 
281
  }
282
 
283
  /**
@@ -295,6 +304,10 @@ class MailChimp_WooCommerce
295
 
296
  $this->loader->add_action('woocommerce_after_checkout_form', $plugin_public, 'add_JS_checkout', 10);
297
  $this->loader->add_action('woocommerce_register_form', $plugin_public, 'add_JS_checkout', 10);
 
 
 
 
298
  }
299
 
300
  /**
@@ -329,7 +342,6 @@ class MailChimp_WooCommerce
329
  private function activateMailChimpService()
330
  {
331
  $service = MailChimp_Service::instance();
332
-
333
  if ($service->isConfigured()) {
334
 
335
  $service->setEnvironment($this->environment);
@@ -350,17 +362,33 @@ class MailChimp_WooCommerce
350
 
351
  // refunds
352
  $this->loader->add_action('woocommerce_order_partially_refunded', $service, 'onPartiallyRefunded', 20, 1);
353
-
354
- // cart hooks
 
 
 
 
 
355
  $this->loader->add_filter('woocommerce_update_cart_action_cart_updated', $service, 'handleCartUpdated');
356
  $this->loader->add_action('woocommerce_add_to_cart', $service, 'handleCartUpdated');
357
  $this->loader->add_action('woocommerce_cart_item_removed', $service, 'handleCartUpdated');
358
 
359
  // save post hooks
360
- $this->loader->add_action('save_post', $service, 'handlePostSaved', 10, 3);
361
- $this->loader->add_action('wp_trash_post', $service, 'handlePostTrashed', 10, 1);
362
- $this->loader->add_action('untrashed_post', $service, 'handlePostRestored', 10, 1);
 
 
363
 
 
 
 
 
 
 
 
 
 
364
  //coupons
365
  $this->loader->add_action('woocommerce_new_coupon', $service, 'handleNewCoupon', 10, 1);
366
  $this->loader->add_action('woocommerce_coupon_options_save', $service, 'handleCouponSaved', 10, 2);
@@ -384,6 +412,8 @@ class MailChimp_WooCommerce
384
  $this->loader->add_action('wp_ajax_mailchimp_set_user_by_email', $service, 'set_user_by_email');
385
  $this->loader->add_action('wp_ajax_nopriv_mailchimp_set_user_by_email', $service, 'set_user_by_email');
386
 
 
 
387
  $jobs_classes = array(
388
  "MailChimp_WooCommerce_Single_Order",
389
  "MailChimp_WooCommerce_SingleCoupon",
@@ -392,11 +422,13 @@ class MailChimp_WooCommerce
392
  "MailChimp_WooCommerce_User_Submit",
393
  "MailChimp_WooCommerce_Process_Coupons",
394
  "MailChimp_WooCommerce_Process_Orders",
395
- "MailChimp_WooCommerce_Process_Products"
 
396
  );
397
  foreach ($jobs_classes as $job_class) {
398
  $this->loader->add_action($job_class, $service, 'mailchimp_process_single_job', 10, 1);
399
  }
 
400
  // sync stats manager
401
  $this->loader->add_action('MailChimp_WooCommerce_Process_Full_Sync_Manager', $service, 'mailchimp_process_sync_manager', 10, 1);
402
  }
@@ -441,4 +473,14 @@ class MailChimp_WooCommerce
441
  public function get_version() {
442
  return $this->version;
443
  }
444
- }
 
 
 
 
 
 
 
 
 
 
132
  $this->activateMailChimpNewsletter();
133
  $this->activateMailChimpService();
134
  $this->applyQueryStringOverrides();
135
+
136
+ // load webhooks
137
+ $this->registerWebhooks();
138
  }
139
 
140
  /**
244
  // make sure we're listening for the admin init
245
  $this->loader->add_action('admin_init', $plugin_admin, 'options_update');
246
  $this->loader->add_action('admin_notices', $plugin_admin, 'initial_notice');
247
+ $this->loader->add_action('admin_notices', $plugin_admin, 'webook_initial_notice');
248
+ $this->loader->add_action('admin_notices', $plugin_admin, 'action_scheduler_notice');
249
 
250
  // put the menu on the admin top bar.
251
  //$this->loader->add_action('admin_bar_menu', $plugin_admin, 'admin_bar', 100);
278
  // set communications box status
279
  $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_communication_status', $plugin_admin, 'mailchimp_woocommerce_communication_status' );
280
 
281
+ // set tower support status
282
+ $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_tower_status', $plugin_admin, 'mailchimp_woocommerce_tower_status' );
283
+
284
  // Load log file via ajax
285
  $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_load_log_file', $plugin_admin, 'mailchimp_woocommerce_ajax_load_log_file' );
286
 
287
  // delete log file via ajax
288
  $this->loader->add_action( 'wp_ajax_mailchimp_woocommerce_delete_log_file', $plugin_admin, 'mailchimp_woocommerce_ajax_delete_log_file' );
289
+
290
  }
291
 
292
  /**
304
 
305
  $this->loader->add_action('woocommerce_after_checkout_form', $plugin_public, 'add_JS_checkout', 10);
306
  $this->loader->add_action('woocommerce_register_form', $plugin_public, 'add_JS_checkout', 10);
307
+
308
+ // set my-account opt-in checkbox
309
+ $this->loader->add_action('woocommerce_edit_account_form', $plugin_public, 'user_my_account_opt_in', 100);
310
+ $this->loader->add_action('woocommerce_save_account_details', $plugin_public, 'user_my_account_opt_in_save', 100, 1);
311
  }
312
 
313
  /**
342
  private function activateMailChimpService()
343
  {
344
  $service = MailChimp_Service::instance();
 
345
  if ($service->isConfigured()) {
346
 
347
  $service->setEnvironment($this->environment);
362
 
363
  // refunds
364
  $this->loader->add_action('woocommerce_order_partially_refunded', $service, 'onPartiallyRefunded', 20, 1);
365
+
366
+ // set user profile info
367
+ $this->loader->add_action('show_user_profile', $service, 'user_subscribed_profile', 100);
368
+ $this->loader->add_action('edit_user_profile', $service, 'user_subscribed_profile', 100);
369
+ $this->loader->add_action('personal_options_update', $service, 'user_update_subscribe_status', 100);
370
+ $this->loader->add_action('edit_user_profile_update', $service, 'user_update_subscribe_status', 100);
371
+ // cart hooks
372
  $this->loader->add_filter('woocommerce_update_cart_action_cart_updated', $service, 'handleCartUpdated');
373
  $this->loader->add_action('woocommerce_add_to_cart', $service, 'handleCartUpdated');
374
  $this->loader->add_action('woocommerce_cart_item_removed', $service, 'handleCartUpdated');
375
 
376
  // save post hooks
377
+ $this->loader->add_action('save_post_shop_order', $service, 'handleOrderSaved', 10, 3);
378
+ $this->loader->add_action('save_post_product', $service, 'handleProductCreated', 10, 3);
379
+
380
+ // this needs to listen for the title and the description updates.
381
+ $this->loader->add_action('post_updated', $service, 'handleProductUpdated', 10, 3);
382
 
383
+ // here's the hook we need to check for "relevant fields" where we can see which property was updated.
384
+ $this->loader->add_action('woocommerce_product_object_updated_props', $service, 'handleProcessProductMeta', 10, 2);
385
+
386
+ // we need to listen for all 3 events because changes aren't the same as "new" or "deleted".
387
+ $this->loader->add_action('updated_post_meta', $service, 'handleProductMetaUpdated', 10, 4);
388
+ $this->loader->add_action('added_post_meta', $service, 'handleProductMetaUpdated', 10, 4);
389
+ $this->loader->add_action('deleted_post_meta', $service, 'handleProductMetaUpdated', 10, 4);
390
+ $this->loader->add_action('wp_trash_post', $service, 'handlePostTrashed', 10, 1);
391
+ $this->loader->add_action('untrashed_post', $service, 'handlePostRestored', 10, 1);
392
  //coupons
393
  $this->loader->add_action('woocommerce_new_coupon', $service, 'handleNewCoupon', 10, 1);
394
  $this->loader->add_action('woocommerce_coupon_options_save', $service, 'handleCouponSaved', 10, 2);
412
  $this->loader->add_action('wp_ajax_mailchimp_set_user_by_email', $service, 'set_user_by_email');
413
  $this->loader->add_action('wp_ajax_nopriv_mailchimp_set_user_by_email', $service, 'set_user_by_email');
414
 
415
+
416
+
417
  $jobs_classes = array(
418
  "MailChimp_WooCommerce_Single_Order",
419
  "MailChimp_WooCommerce_SingleCoupon",
422
  "MailChimp_WooCommerce_User_Submit",
423
  "MailChimp_WooCommerce_Process_Coupons",
424
  "MailChimp_WooCommerce_Process_Orders",
425
+ "MailChimp_WooCommerce_Process_Products",
426
+ "MailChimp_WooCommerce_WebHooks_Sync"
427
  );
428
  foreach ($jobs_classes as $job_class) {
429
  $this->loader->add_action($job_class, $service, 'mailchimp_process_single_job', 10, 1);
430
  }
431
+
432
  // sync stats manager
433
  $this->loader->add_action('MailChimp_WooCommerce_Process_Full_Sync_Manager', $service, 'mailchimp_process_sync_manager', 10, 1);
434
  }
473
  public function get_version() {
474
  return $this->version;
475
  }
476
+
477
+ private function registerWebhooks()
478
+ {
479
+ $defined = mailchimp_get_data('registered_webhooks');
480
+ if (empty($defined)) {
481
+ mailchimp_log('admin', 'syncing webhooks for existing plugin');
482
+ mailchimp_set_data('registered_webhooks', true);
483
+ MailChimp_WooCommerce_Admin::instance()->defineWebhooks();
484
+ }
485
+ }
486
+ }
includes/processes/class-mailchimp-woocommerce-abstract-sync.php CHANGED
@@ -134,6 +134,14 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends Mailchimp_Woocommerce
134
  return false;
135
  }
136
 
 
 
 
 
 
 
 
 
137
  if (!($this->store_id = $this->getStoreID())) {
138
  mailchimp_debug(get_called_class().'@handle', 'store id not loaded');
139
  return false;
134
  return false;
135
  }
136
 
137
+ /// if we set something for an emergency stop through our admin, honor this
138
+ if (mailchimp_get_data('emergency_stop')) {
139
+ mailchimp_log('tower', 'Emergency stop sync has been issued. Please contact support to re-enable', array(
140
+ 'class' => get_called_class(),
141
+ ));
142
+ return false;
143
+ }
144
+
145
  if (!($this->store_id = $this->getStoreID())) {
146
  mailchimp_debug(get_called_class().'@handle', 'store id not loaded');
147
  return false;
includes/processes/class-mailchimp-woocommerce-process-coupons.php CHANGED
@@ -15,6 +15,17 @@ class MailChimp_WooCommerce_Process_Coupons extends MailChimp_WooCommerce_Abstra
15
  */
16
  protected $action = 'mailchimp_woocommerce_process_coupons';
17
 
 
 
 
 
 
 
 
 
 
 
 
18
  /**
19
  * @return string
20
  */
15
  */
16
  protected $action = 'mailchimp_woocommerce_process_coupons';
17
 
18
+ /**
19
+ * Resync the products
20
+ */
21
+ public static function push()
22
+ {
23
+ $service = MailChimp_Service::instance();
24
+ $service->removePointers(true, false);
25
+ $coupons_sync = new MailChimp_WooCommerce_Process_Coupons();
26
+ $coupons_sync->createSyncManagers();
27
+ }
28
+
29
  /**
30
  * @return string
31
  */
includes/processes/class-mailchimp-woocommerce-process-orders.php CHANGED
@@ -16,6 +16,18 @@ class MailChimp_WooCommerce_Process_Orders extends MailChimp_WooCommerce_Abstrac
16
  protected $action = 'mailchimp_woocommerce_process_orders';
17
  public $items = array();
18
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  /**
20
  * @return string
21
  */
16
  protected $action = 'mailchimp_woocommerce_process_orders';
17
  public $items = array();
18
 
19
+ /**
20
+ * Resync just the orders
21
+ */
22
+ public static function push()
23
+ {
24
+ $service = MailChimp_Service::instance();
25
+ $service->removePointers(false, true);
26
+ $sync = new MailChimp_WooCommerce_Process_Orders();
27
+ $sync->createSyncManagers();
28
+ $service->setData('sync.config.resync', true);
29
+ }
30
+
31
  /**
32
  * @return string
33
  */
includes/processes/class-mailchimp-woocommerce-process-products.php CHANGED
@@ -15,11 +15,15 @@ class MailChimp_WooCommerce_Process_Products extends MailChimp_WooCommerce_Abstr
15
  */
16
  protected $action = 'mailchimp_woocommerce_process_products';
17
 
 
 
 
18
  public static function push()
19
  {
20
- $job = new MailChimp_WooCommerce_Process_Products();
21
- $job->flagStartSync();
22
- mailchimp_handle_or_queue($job, 0);
 
23
  }
24
 
25
 
15
  */
16
  protected $action = 'mailchimp_woocommerce_process_products';
17
 
18
+ /**
19
+ * Resync the products
20
+ */
21
  public static function push()
22
  {
23
+ $service = MailChimp_Service::instance();
24
+ $service->removePointers(true, false);
25
+ $sync = new MailChimp_WooCommerce_Process_Products();
26
+ $sync->createSyncManagers();
27
  }
28
 
29
 
includes/processes/class-mailchimp-woocommerce-single-order.php CHANGED
@@ -125,11 +125,17 @@ class MailChimp_WooCommerce_Single_Order extends Mailchimp_Woocommerce_Job
125
 
126
  // transform the order
127
  $order = $job->transform($order_post);
 
 
 
 
 
 
128
 
129
  // if the order is new, and has been flagged as a status that should not be pushed over to
130
  // Mailchimp - just ignore it and log it.
131
  if ($new_order && $order->shouldIgnoreIfNotInMailchimp()) {
132
- mailchimp_debug('filter', "order {$order->getId()} is in {$order->getOriginalWooStatus()} status, and is being skipped for now.");
133
  return false;
134
  }
135
 
@@ -233,7 +239,7 @@ class MailChimp_WooCommerce_Single_Order extends Mailchimp_Woocommerce_Job
233
  // if single sync and
234
  // if the order is in failed or cancelled status - and it's brand new, we shouldn't submit it.
235
  if (!$this->is_full_sync && in_array($order->getFinancialStatus(), array('failed', 'cancelled')) || $order->getOriginalWooStatus() === 'pending') {
236
- mailchimp_log('order_sumbit', "#{$order->getId()} has a financial status of {$order->getFinancialStatus()} and was skipped.");
237
  return false;
238
  }
239
  // if full sync and
@@ -241,7 +247,7 @@ class MailChimp_WooCommerce_Single_Order extends Mailchimp_Woocommerce_Job
241
  // it is probably happening due to 3rd party payment processing and it's still pending. These orders
242
  // don't always make it over because someone could be cancelling out of the payment there.
243
  if ($this->is_full_sync && !in_array(strtolower($order->getFinancialStatus()), array('processing', 'completed', 'paid'))) {
244
- mailchimp_log('order_sumbit', "#{$order->getId()} has a financial status of {$order->getFinancialStatus()} and was skipped.");
245
  return false;
246
  }
247
 
@@ -301,7 +307,7 @@ class MailChimp_WooCommerce_Single_Order extends Mailchimp_Woocommerce_Job
301
 
302
  $order->addItem($line_item);
303
 
304
- mailchimp_log('order_sumbit.error', "Order {$order->getId()} does not have any line items, so we are using 'empty_line_item_placeholder' instead.");
305
  }
306
  }
307
 
@@ -346,6 +352,12 @@ class MailChimp_WooCommerce_Single_Order extends Mailchimp_Woocommerce_Job
346
  $status_if_new = $order->getCustomer()->getOptInStatus() ? 'subscribed' : 'transactional';
347
  }
348
 
 
 
 
 
 
 
349
  // Maybe sync subscriber to set correct member.language
350
  mailchimp_member_data_update($email, $this->user_language, 'order', $status_if_new, $order, $this->gdpr_fields, !$this->is_full_sync);
351
 
125
 
126
  // transform the order
127
  $order = $job->transform($order_post);
128
+
129
+ // don't allow this to happen.
130
+ if ($order->getOriginalWooStatus() === 'checkout-draft') {
131
+ mailchimp_debug('filter', "Order {$woo_order_number} is in draft status and can not be submitted");
132
+ return false;
133
+ }
134
 
135
  // if the order is new, and has been flagged as a status that should not be pushed over to
136
  // Mailchimp - just ignore it and log it.
137
  if ($new_order && $order->shouldIgnoreIfNotInMailchimp()) {
138
+ mailchimp_debug('filter', "order {$woo_order_number} is in {$order->getOriginalWooStatus()} status, and is being skipped for now.");
139
  return false;
140
  }
141
 
239
  // if single sync and
240
  // if the order is in failed or cancelled status - and it's brand new, we shouldn't submit it.
241
  if (!$this->is_full_sync && in_array($order->getFinancialStatus(), array('failed', 'cancelled')) || $order->getOriginalWooStatus() === 'pending') {
242
+ mailchimp_log('order_submit', "#{$order->getId()} has a financial status of {$order->getFinancialStatus()} and was skipped.");
243
  return false;
244
  }
245
  // if full sync and
247
  // it is probably happening due to 3rd party payment processing and it's still pending. These orders
248
  // don't always make it over because someone could be cancelling out of the payment there.
249
  if ($this->is_full_sync && !in_array(strtolower($order->getFinancialStatus()), array('processing', 'completed', 'paid'))) {
250
+ mailchimp_log('order_submit', "#{$order->getId()} has a financial status of {$order->getFinancialStatus()} and was skipped.");
251
  return false;
252
  }
253
 
307
 
308
  $order->addItem($line_item);
309
 
310
+ mailchimp_log('order_submit.error', "Order {$order->getId()} does not have any line items, so we are using 'empty_line_item_placeholder' instead.");
311
  }
312
  }
313
 
352
  $status_if_new = $order->getCustomer()->getOptInStatus() ? 'subscribed' : 'transactional';
353
  }
354
 
355
+ // if this is not currently in mailchimp - and we have the saved GDPR fields from
356
+ // we can use the post meta for gdpr fields that were saved during checkout.
357
+ if (!$this->is_full_sync && $new_order && empty($this->gdpr_fields)) {
358
+ $this->gdpr_fields = get_post_meta($order->getId(), 'mailchimp_woocommerce_gdpr_fields', true);
359
+ }
360
+
361
  // Maybe sync subscriber to set correct member.language
362
  mailchimp_member_data_update($email, $this->user_language, 'order', $status_if_new, $order, $this->gdpr_fields, !$this->is_full_sync);
363
 
includes/processes/class-mailchimp-woocommerce-subscriber-sync.php CHANGED
@@ -5,7 +5,7 @@
5
  */
6
  class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
7
  {
8
- public $data = [];
9
 
10
  /**
11
  * SubscriberSync constructor.
@@ -24,13 +24,21 @@ class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
24
  {
25
  try {
26
  // if the store is not properly connected to Mailchimp - we need to skip this.
27
- if (!mailchimp_is_configured()) return null;
 
 
 
28
  // grab the hook type, and the new data
29
  list($hook_type, $data, $failed) = $this->parseInputData();
30
  // extract the service ids from the data we get
31
  list ($service_id, $email) = $this->extractServiceIDs($data);
32
  // ignore the empty submissions or certain events or emails
33
- if ($this->hasInvalidEvent($hook_type, $failed, $data) || $this->shouldIgnoreEmail($email)) {
 
 
 
 
 
34
  return false;
35
  }
36
  // if hook type is 'subscribe' that means we need ot subscribe them
@@ -39,7 +47,7 @@ class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
39
  if (!($user = get_user_by('email', $email))) {
40
  // if the user is not found and we should create new customers
41
  return ($subscribe && $this->shouldCreateNewCustomers()) ?
42
- $this->createNewCustomer($email) :
43
  false;
44
  }
45
  try {
@@ -47,7 +55,10 @@ class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
47
  // see if we've saved a service call in the last 30 minutes.
48
  $handled = mailchimp_get_transient($handled_key, null);
49
  // if we've got the subscriber sync id and it's the same as the previous submission, just skip out now.
50
- if ($handled === $subscribe) return true;
 
 
 
51
  // if they unsubscribed, we need to put a cache on this because it's causing issues in the
52
  // shopify webhooks for some reason being re-subscribed.
53
  if (!$subscribe) {
@@ -60,7 +71,11 @@ class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
60
  update_user_meta($user->ID, 'mailchimp_woocommerce_is_subscribed', $subscribe);
61
  // cache it for 90 seconds to be used above.
62
  mailchimp_set_transient($handled_key, $subscribe, 90);
63
- mailchimp_log('webhook', "Subscriber Sync :: {$hook_type} :: {$email}");
 
 
 
 
64
  } catch (\Exception $e) {
65
  $error = $e->getMessage();
66
  mailchimp_error('webhook', "Updating Subscriber Status :: MC service ID {$service_id} :: {$hook_type} :: {$error}");
@@ -79,7 +94,9 @@ class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
79
  private function extractServiceIDs($data)
80
  {
81
  if (is_object($data)) {
82
- $service_id = isset($data->web_id) ? $data->web_id : isset($data->id) ? $data->id : null;
 
 
83
  $email = isset($data->email) ? $data->email : null;
84
  return array($service_id, $email);
85
  } else {
5
  */
6
  class MailChimp_WooCommerce_Subscriber_Sync extends Mailchimp_Woocommerce_Job
7
  {
8
+ public $data = array();
9
 
10
  /**
11
  * SubscriberSync constructor.
24
  {
25
  try {
26
  // if the store is not properly connected to Mailchimp - we need to skip this.
27
+ if (!mailchimp_is_configured()) {
28
+ mailchimp_log('subscriber_sync', 'Mailchimp is not configured, can not process job.');
29
+ return null;
30
+ }
31
  // grab the hook type, and the new data
32
  list($hook_type, $data, $failed) = $this->parseInputData();
33
  // extract the service ids from the data we get
34
  list ($service_id, $email) = $this->extractServiceIDs($data);
35
  // ignore the empty submissions or certain events or emails
36
+ if ($this->hasInvalidEvent($hook_type, $failed, $data)) {
37
+ mailchimp_log('subscriber_sync', 'Webhook has invalid event', compact('email'));
38
+ return false;
39
+ }
40
+ if ($this->shouldIgnoreEmail($email)) {
41
+ mailchimp_log('subscriber_sync', 'Webhook is ignoring email', compact('email'));
42
  return false;
43
  }
44
  // if hook type is 'subscribe' that means we need ot subscribe them
47
  if (!($user = get_user_by('email', $email))) {
48
  // if the user is not found and we should create new customers
49
  return ($subscribe && $this->shouldCreateNewCustomers()) ?
50
+ (bool) $this->createNewCustomer($email) :
51
  false;
52
  }
53
  try {
55
  // see if we've saved a service call in the last 30 minutes.
56
  $handled = mailchimp_get_transient($handled_key, null);
57
  // if we've got the subscriber sync id and it's the same as the previous submission, just skip out now.
58
+ if ($handled === $subscribe) {
59
+ mailchimp_log('subscriber_sync', "didn't need to do anything");
60
+ return true;
61
+ }
62
  // if they unsubscribed, we need to put a cache on this because it's causing issues in the
63
  // shopify webhooks for some reason being re-subscribed.
64
  if (!$subscribe) {
71
  update_user_meta($user->ID, 'mailchimp_woocommerce_is_subscribed', $subscribe);
72
  // cache it for 90 seconds to be used above.
73
  mailchimp_set_transient($handled_key, $subscribe, 90);
74
+ mailchimp_log('webhook', "Subscriber Sync :: {$hook_type} :: {$email}", array(
75
+ 'subscribed' => $subscribe,
76
+ 'user_id' => $user->ID,
77
+ ));
78
+ return true;
79
  } catch (\Exception $e) {
80
  $error = $e->getMessage();
81
  mailchimp_error('webhook', "Updating Subscriber Status :: MC service ID {$service_id} :: {$hook_type} :: {$error}");
94
  private function extractServiceIDs($data)
95
  {
96
  if (is_object($data)) {
97
+ $service_id = isset($data->web_id) ?
98
+ $data->web_id :
99
+ (isset($data->id) ? $data->id : null);
100
  $email = isset($data->email) ? $data->email : null;
101
  return array($service_id, $email);
102
  } else {
includes/processes/class-mailchimp-woocommerce-user-submit.php CHANGED
@@ -18,6 +18,7 @@ class MailChimp_WooCommerce_User_Submit extends Mailchimp_Woocommerce_Job
18
  public $updated_data;
19
  public $language;
20
  public $should_ignore = false;
 
21
 
22
  /**
23
  * MailChimp_WooCommerce_User_Submit constructor.
@@ -59,6 +60,16 @@ class MailChimp_WooCommerce_User_Submit extends Mailchimp_Woocommerce_Job
59
  }
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * @return bool
64
  */
@@ -133,7 +144,7 @@ class MailChimp_WooCommerce_User_Submit extends Mailchimp_Woocommerce_Job
133
 
134
  // don't let anyone be unsubscribed from the list - that should only happen on email campaigns
135
  // and someone clicking the unsubscribe linkage.
136
- if (!$this->subscribed) {
137
  static::$handling_for = null;
138
  return false;
139
  }
@@ -209,9 +220,14 @@ class MailChimp_WooCommerce_User_Submit extends Mailchimp_Woocommerce_Job
209
 
210
  // if the member is unsubscribed or pending, we really can't do anything here.
211
  if (isset($member_data['status']) && in_array($member_data['status'], array('unsubscribed', 'pending'))) {
212
- mailchimp_log('member.sync', "Skipped Member Sync For {$email} because the current status is {$member_data['status']}", $merge_fields);
213
- static::$handling_for = null;
214
- return false;
 
 
 
 
 
215
  }
216
 
217
  // if the status is not === 'transactional' we can update them to subscribed or pending now.
@@ -226,13 +242,18 @@ class MailChimp_WooCommerce_User_Submit extends Mailchimp_Woocommerce_Job
226
  mailchimp_log('member.sync', "Updated Member {$email}", array(
227
  'previous_status' => $member_data['status'],
228
  'status' => $status_meta['updated'],
229
- 'merge_fields' => $merge_fields
 
 
230
  ));
231
  static::$handling_for = null;
232
  return true;
233
  }
234
 
235
  if (isset($member_data['status'])) {
 
 
 
236
  // ok let's update this member
237
  $api->update($list_id, $email, $member_data['status'], $merge_fields, null, $language, $gdpr_fields);
238
 
@@ -240,8 +261,11 @@ class MailChimp_WooCommerce_User_Submit extends Mailchimp_Woocommerce_Job
240
  $api->updateMemberTags(mailchimp_get_list_id(), $email, true);
241
 
242
  mailchimp_tell_system_about_user_submit($email, $status_meta, 60);
243
- mailchimp_log('member.sync', "Updated Member {$email} ( merge fields only )", array(
244
- 'merge_fields' => $merge_fields
 
 
 
245
  ));
246
  static::$handling_for = null;
247
  return true;
18
  public $updated_data;
19
  public $language;
20
  public $should_ignore = false;
21
+ public $submit_transactional = true;
22
 
23
  /**
24
  * MailChimp_WooCommerce_User_Submit constructor.
60
  }
61
  }
62
 
63
+ /**
64
+ * @param bool $bool
65
+ * @return $this
66
+ */
67
+ public function submittingTransactional($bool = true)
68
+ {
69
+ $this->submit_transactional = (bool) $bool;
70
+ return $this;
71
+ }
72
+
73
  /**
74
  * @return bool
75
  */
144
 
145
  // don't let anyone be unsubscribed from the list - that should only happen on email campaigns
146
  // and someone clicking the unsubscribe linkage.
147
+ if (!$this->subscribed && !$this->submit_transactional) {
148
  static::$handling_for = null;
149
  return false;
150
  }
220
 
221
  // if the member is unsubscribed or pending, we really can't do anything here.
222
  if (isset($member_data['status']) && in_array($member_data['status'], array('unsubscribed', 'pending'))) {
223
+ if ($this->subscribed && $member_data['status'] !== 'pending') {
224
+ mailchimp_log('member.sync', "pushing {$email} status as pending because they were previously unsubscribed, and must use the double opt in to make it back on the list.");
225
+ $member_data['status'] = 'pending';
226
+ } else {
227
+ mailchimp_log('member.sync', "Skipped Member Sync For {$email} because the current status is {$member_data['status']}", $merge_fields);
228
+ static::$handling_for = null;
229
+ return false;
230
+ }
231
  }
232
 
233
  // if the status is not === 'transactional' we can update them to subscribed or pending now.
242
  mailchimp_log('member.sync', "Updated Member {$email}", array(
243
  'previous_status' => $member_data['status'],
244
  'status' => $status_meta['updated'],
245
+ 'language' => $language,
246
+ 'merge_fields' => $merge_fields,
247
+ 'gdpr_fields' => $gdpr_fields,
248
  ));
249
  static::$handling_for = null;
250
  return true;
251
  }
252
 
253
  if (isset($member_data['status'])) {
254
+ if ($member_data['status'] === 'subscribed' && !$this->subscribed) {
255
+ $member_data['status'] = 'transactional';
256
+ }
257
  // ok let's update this member
258
  $api->update($list_id, $email, $member_data['status'], $merge_fields, null, $language, $gdpr_fields);
259
 
261
  $api->updateMemberTags(mailchimp_get_list_id(), $email, true);
262
 
263
  mailchimp_tell_system_about_user_submit($email, $status_meta, 60);
264
+ mailchimp_log('member.sync', "Updated Member {$email}", array(
265
+ 'status' => $member_data['status'],
266
+ 'language' => $language,
267
+ 'merge_fields' => $merge_fields,
268
+ 'gdpr_fields' => $gdpr_fields,
269
  ));
270
  static::$handling_for = null;
271
  return true;
includes/processes/class-mailchimp-woocommerce-webhooks-sync.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by Vextras.
5
+ *
6
+ * Name: Alejandro Giraldo
7
+ * Email: alejandro@vextras.com
8
+ * Date: 04/02/16
9
+ * Time: 10:55 PM
10
+ */
11
+ class MailChimp_WooCommerce_WebHooks_Sync extends Mailchimp_Woocommerce_Job
12
+ {
13
+ /**
14
+ * Handle job
15
+ * @return void
16
+ */
17
+ public function handle()
18
+ {
19
+ $this->subscribeWebhook();
20
+ }
21
+
22
+ /**
23
+ * Subscribe mailchimp webhook
24
+ * @return void|bool
25
+ */
26
+ public function subscribeWebhook()
27
+ {
28
+ try {
29
+ if (!mailchimp_is_configured()) {
30
+ return null;
31
+ }
32
+
33
+ $list = mailchimp_get_list_id();
34
+ $key = mailchimp_get_data('webhook.token');
35
+ $url = mailchimp_get_webhook_url();
36
+ $api = mailchimp_get_api();
37
+
38
+ // if we have a key, and we have a url, but the token is not in the url,
39
+ // we need to delete the webhook and re-attach it.
40
+ if (!empty($key) && !empty($url) && (!mailchimp_string_contains($url, $key) || !$api->hasWebhook($list, $url))) {
41
+ $match = MailChimp_WooCommerce_Rest_Api::url('member-sync');
42
+ mailchimp_log('webhooks', "found discrepancy on audience webhook - deleting invalid hooks");
43
+ $api->webHookDelete($list, $match);
44
+ $url = null;
45
+ $key = null;
46
+ }
47
+
48
+ // for some reason the webhook url does not work with ?rest_route style, permalinks should be defined also
49
+ if (!$url && get_option('permalink_structure') !== '') {
50
+ $key = mailchimp_create_webhook_token();
51
+ $url = mailchimp_build_webhook_url($key);
52
+ mailchimp_set_data('webhook.token', $key);
53
+ //requesting api webhooks subscription
54
+ $webhook = $api->webHookSubscribe($list, $url);
55
+ //if no errors let save the url
56
+ mailchimp_set_webhook_url($webhook['url']);
57
+ mailchimp_log('webhooks', "added webhook to audience");
58
+ }
59
+ } catch (\Throwable $e) {
60
+ mailchimp_set_data('webhook.token', false);
61
+ mailchimp_set_webhook_url(false);
62
+ mailchimp_error('webhook', $e->getMessage());
63
+ }
64
+ return false;
65
+ }
66
+ }
languages/mc-woocommerce-newsletter.pot CHANGED
@@ -1,26 +1,30 @@
1
- # Copyright (C) 2021
2
  # This file is distributed under the same license as the package.
3
  msgid ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/blocks\n"
7
- "POT-Creation-Date: 2021-11-19 15:51:17+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
- "PO-Revision-Date: 2021-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
  "X-Generator: node-wp-i18n 1.2.6\n"
15
 
16
- #: woocommerce-blocks-integration.php:123
17
  msgid "I want to receive updates about products and promotions."
18
  msgstr ""
19
 
20
- #: woocommerce-blocks-integration.php:124
21
  msgid "Please select all the ways you would like to hear from us"
22
  msgstr ""
23
 
24
- #: woocommerce-blocks-integration.php:167
25
  msgid "Subscribe to marketing opt-in."
 
 
 
 
26
  msgstr ""
1
+ # Copyright (C) 2022
2
  # This file is distributed under the same license as the package.
3
  msgid ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/blocks\n"
7
+ "POT-Creation-Date: 2022-05-17 19:32:24+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2022-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
  "X-Generator: node-wp-i18n 1.2.6\n"
15
 
16
+ #: woocommerce-blocks-integration.php:134
17
  msgid "I want to receive updates about products and promotions."
18
  msgstr ""
19
 
20
+ #: woocommerce-blocks-integration.php:138
21
  msgid "Please select all the ways you would like to hear from us"
22
  msgstr ""
23
 
24
+ #: woocommerce-blocks-integration.php:181
25
  msgid "Subscribe to marketing opt-in."
26
+ msgstr ""
27
+
28
+ #: woocommerce-blocks-integration.php:194
29
+ msgid "GDPR marketing opt-in."
30
  msgstr ""
mailchimp-woocommerce.php CHANGED
@@ -16,7 +16,7 @@
16
  * Plugin Name: Mailchimp for WooCommerce
17
  * Plugin URI: https://mailchimp.com/connect-your-store/
18
  * Description: Connects WooCommerce to Mailchimp to sync your store data, send targeted campaigns to your customers, and sell more stuff.
19
- * Version: 2.6.2
20
  * Author: Mailchimp
21
  * Author URI: https://mailchimp.com
22
  * License: GPL-2.0+
@@ -36,11 +36,11 @@ if (!defined( 'WPINC')) {
36
 
37
  if (!isset($mailchimp_woocommerce_spl_autoloader) || $mailchimp_woocommerce_spl_autoloader === false) {
38
  // require Action Scheduler
39
- if( file_exists( "includes/vendor/action-scheduler/action-scheduler.php") ){
40
- include_once "includes/vendor/action-scheduler/action-scheduler.php";
41
  }
42
  // bootstrapper
43
- include_once "bootstrap.php";
44
  }
45
 
46
  register_activation_hook( __FILE__, 'activate_mailchimp_woocommerce');
@@ -48,8 +48,7 @@ register_activation_hook( __FILE__, 'activate_mailchimp_woocommerce');
48
  // plugins loaded callback
49
  add_action('plugins_loaded', 'mailchimp_on_all_plugins_loaded', 12);
50
 
51
- //add_action('plugins_loaded', function() {
52
- // // make this a one liner for testing and code separation
53
- // include_once __DIR__.'/blocks/newsletter-test.php';
54
- //}, 1);
55
-
16
  * Plugin Name: Mailchimp for WooCommerce
17
  * Plugin URI: https://mailchimp.com/connect-your-store/
18
  * Description: Connects WooCommerce to Mailchimp to sync your store data, send targeted campaigns to your customers, and sell more stuff.
19
+ * Version: 2.7
20
  * Author: Mailchimp
21
  * Author URI: https://mailchimp.com
22
  * License: GPL-2.0+
36
 
37
  if (!isset($mailchimp_woocommerce_spl_autoloader) || $mailchimp_woocommerce_spl_autoloader === false) {
38
  // require Action Scheduler
39
+ if( file_exists( __DIR__ . "/includes/vendor/action-scheduler/action-scheduler.php" ) ){
40
+ include_once __DIR__ . "/includes/vendor/action-scheduler/action-scheduler.php";
41
  }
42
  // bootstrapper
43
+ include_once __DIR__ . "/bootstrap.php";
44
  }
45
 
46
  register_activation_hook( __FILE__, 'activate_mailchimp_woocommerce');
48
  // plugins loaded callback
49
  add_action('plugins_loaded', 'mailchimp_on_all_plugins_loaded', 12);
50
 
51
+ add_action('plugins_loaded', function() {
52
+ // make this a one liner for testing and code separation
53
+ include_once __DIR__ . '/blocks/newsletter.php';
54
+ }, 1);
 
public/class-mailchimp-woocommerce-public.php CHANGED
@@ -99,5 +99,93 @@ class MailChimp_WooCommerce_Public {
99
  wp_enqueue_script($this->plugin_name. '_gdpr', plugin_dir_url( __FILE__ ) .'js/mailchimp-woocommerce-checkout-gdpr.min.js', array(), $this->version, true);
100
  }
101
 
102
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
99
  wp_enqueue_script($this->plugin_name. '_gdpr', plugin_dir_url( __FILE__ ) .'js/mailchimp-woocommerce-checkout-gdpr.min.js', array(), $this->version, true);
100
  }
101
 
102
+ public function user_my_account_opt_in()
103
+ {
104
+ $gdpr_fields = $this->user_my_account_gdpr_fields();
105
+ include_once('partials/mailchimp-woocommerce-my-account.php');
106
+ }
107
+
108
+ public function user_my_account_opt_in_save($user_id)
109
+ {
110
+ $subscribed = isset($_POST['mailchimp_woocommerce_is_subscribed_checkbox']) &&
111
+ $_POST['mailchimp_woocommerce_is_subscribed_checkbox'] == 'on';
112
+ update_user_meta( $user_id, 'mailchimp_woocommerce_is_subscribed', $subscribed);
113
+ }
114
+
115
+ /**
116
+ * @return string
117
+ */
118
+ public function user_my_account_gdpr_fields()
119
+ {
120
+ return static::gdpr_fields();
121
+ }
122
+
123
+ /**
124
+ * @param null $user
125
+ * @return string
126
+ */
127
+ public static function gdpr_fields($user = null)
128
+ {
129
+ if (!mailchimp_is_configured()) {
130
+ return "";
131
+ }
132
+
133
+ $api = mailchimp_get_api();
134
+ $GDPRfields = $api->getCachedGDPRFields(mailchimp_get_list_id(), 5);
135
+
136
+ $checkbox = '';
137
+
138
+ if (!empty($GDPRfields) && is_array($GDPRfields)) {
139
+ $checkbox .= "<div id='mailchimp-gdpr-fields'><p>";
140
+ $checkbox .= __('Please select all the ways you would like to hear from us', 'mailchimp-for-woocommerce');
141
+ $checkbox .= "<div class='clear'></div>";
142
+
143
+ // if the user is logged in, we will pull the 'is_subscribed' property out of the meta for the value.
144
+ // otherwise we use the default settings.
145
+ //$saved_fields = get_user_meta(get_current_user_id(), 'mailchimp_woocommerce_gdpr_fields');
146
+
147
+ /// if the user is logged in - and is already subscribed - just ignore this checkbox.
148
+ $user = $user ? $user : wp_get_current_user();
149
+ $current_gdpr_fields = array();
150
+ if ($user && $cached_gdpr_fields = mailchimp_get_transient("mailchimp_woocommerce_gdpr_fields_{$user->ID}")) {
151
+ foreach ($cached_gdpr_fields['value'] as $permission_id => $permission_value) {
152
+ $current_gdpr_fields[] = array(
153
+ 'marketing_permission_id' => $permission_id,
154
+ 'enabled' => $permission_value,
155
+ );
156
+ }
157
+ }
158
+ if (empty($cached_gdpr_fields) && !empty($user) && $user->user_email) {
159
+ try {
160
+ $member = mailchimp_get_api()->member(mailchimp_get_list_id(), $user->user_email);
161
+ $current_gdpr_fields = isset($member['marketing_permissions']) ?
162
+ $member['marketing_permissions'] : array();
163
+ } catch (\Exception $e) {
164
+ //mailchimp_error("GDPR ERROR", $e->getMessage());
165
+ }
166
+ }
167
+
168
+ foreach ($GDPRfields as $key => $field) {
169
+ $marketing_permission_id = $field['marketing_permission_id'];
170
+ $text = $field['text'];
171
+ $status = false;
172
+
173
+ foreach ($current_gdpr_fields as $current_gdpr_field) {
174
+ if ($marketing_permission_id === $current_gdpr_field['marketing_permission_id']) {
175
+ $status = $current_gdpr_field['enabled'];
176
+ break;
177
+ }
178
+ }
179
+
180
+ // Add to the checkbox output
181
+ $checkbox .= "<input class='mailchimp_woocommerce_gdpr_option' type='hidden' value='0' name='mailchimp_woocommerce_gdpr[{$marketing_permission_id}]'>";
182
+ $checkbox .= "<input id='mailchimp_woocommerce_gdpr[{$marketing_permission_id}]' type='checkbox' name='mailchimp_woocommerce_gdpr[{$marketing_permission_id}]' value='1'".($status ? ' checked="checked"' : '').">";
183
+ $checkbox .= "<label class='mailchimp_woocommerce_gdpr_label' for='mailchimp_woocommerce_gdpr[{$marketing_permission_id}]' ><span>{$text}</span></label>";
184
+ $checkbox .= "<div class='clear'></div>";
185
+ }
186
+ $checkbox .= "</p></div>";
187
+ }
188
+
189
+ return $checkbox;
190
+ }
191
  }
public/partials/mailchimp-woocommerce-my-account.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $user = wp_get_current_user(); ?>
2
+ <?php $mailchimp_user_is_subscribed = get_user_meta($user->ID, 'mailchimp_woocommerce_is_subscribed', true); ?>
3
+
4
+ <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
5
+ <input type="checkbox"
6
+ class='woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'
7
+ name="mailchimp_woocommerce_is_subscribed_checkbox"
8
+ id="mailchimp_woocommerce_is_subscribed"
9
+ <?php echo !empty($mailchimp_user_is_subscribed) ? esc_attr('checked') : ''; ?>>
10
+ <?php esc_html_e('Subscribe Newsletter', 'mailchimp-for-woocommerce')?>
11
+ </p>
12
+
13
+ <?php echo $gdpr_fields ?>