MailChimp for WooCommerce - Version 2.1.12

Version Description

  • adds error handling for blocked admin-ajax.php files
  • adds support for customer merge variables
  • removes global variable overwrite of REMOTE_ADDR
  • fixes signup form not adding customers to Mailchimp
  • support for rate limiting
  • PHP 7.0 requirement messaging
  • support for WooCommerce 3.5.0
  • ignores amazon marketplace addresses
  • fixes cart entries never being removed
Download this release

Release Info

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

Code changes from version 2.1.11 to 2.1.12

README.txt CHANGED
@@ -3,10 +3,10 @@ Contributors: ryanhungate, Mailchimp
3
  Tags: ecommerce,email,workflows,mailchimp
4
  Donate link: https://mailchimp.com
5
  Requires at least: 4.3
6
- Tested up to: 4.9.8
7
- Stable tag: 2.1.11
8
- Requires PHP: 5.6
9
- WC tested up to: 3.4.5
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
  Connect your store to your Mailchimp list to track sales, create targeted emails, send abandoned cart emails, and more.
@@ -61,6 +61,16 @@ The Mailchimp for WooCommerce supports Wordpress Multi Sites and below are a few
61
  - Deleting removes the connection between Mailchimp and WooCommerce, and uninstalls the plugin from your site.
62
  Refer to the Wordpress Codex for more information about [Multisite Network Administration](https://codex.wordpress.org/Multisite_Network_Administration)
63
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
64
  = 2.1.11 =
65
  * fix double opt in sending on transactional customers
66
  = 2.1.10 =
3
  Tags: ecommerce,email,workflows,mailchimp
4
  Donate link: https://mailchimp.com
5
  Requires at least: 4.3
6
+ Tested up to: 5.0
7
+ Stable tag: 2.1.12
8
+ Requires PHP: 7.0
9
+ WC tested up to: 3.5.2
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
  Connect your store to your Mailchimp list to track sales, create targeted emails, send abandoned cart emails, and more.
61
  - Deleting removes the connection between Mailchimp and WooCommerce, and uninstalls the plugin from your site.
62
  Refer to the Wordpress Codex for more information about [Multisite Network Administration](https://codex.wordpress.org/Multisite_Network_Administration)
63
  == Changelog ==
64
+ = 2.1.12 =
65
+ * adds error handling for blocked admin-ajax.php files
66
+ * adds support for customer merge variables
67
+ * removes global variable overwrite of REMOTE_ADDR
68
+ * fixes signup form not adding customers to Mailchimp
69
+ * support for rate limiting
70
+ * PHP 7.0 requirement messaging
71
+ * support for WooCommerce 3.5.0
72
+ * ignores amazon marketplace addresses
73
+ * fixes cart entries never being removed
74
  = 2.1.11 =
75
  * fix double opt in sending on transactional customers
76
  = 2.1.10 =
admin/class-mailchimp-woocommerce-admin.php CHANGED
@@ -247,6 +247,14 @@ class MailChimp_WooCommerce_Admin extends MailChimp_WooCommerce_Options {
247
  'mailchimp_account_info_username' => null,
248
  );
249
 
 
 
 
 
 
 
 
 
250
  $api = new MailChimp_WooCommerce_MailChimpApi($data['mailchimp_api_key']);
251
 
252
  try {
247
  'mailchimp_account_info_username' => null,
248
  );
249
 
250
+ if (($failure = mailchimp_woocommerce_check_if_http_worker_fails())) {
251
+ unset($data['mailchimp_api_key']);
252
+ $data['active_tab'] = 'api_key';
253
+ $data['api_ping_error'] = $failure;
254
+ mailchimp_error('admin@validateCanUseHttpWorker', $failure);
255
+ return $data;
256
+ }
257
+
258
  $api = new MailChimp_WooCommerce_MailChimpApi($data['mailchimp_api_key']);
259
 
260
  try {
admin/partials/mailchimp-woocommerce-admin-tabs.php CHANGED
@@ -22,11 +22,13 @@ if (isset($options['mailchimp_api_key'])) {
22
  try {
23
  if ($handler->hasValidApiKey(null, true)) {
24
  $has_valid_api_key = true;
 
25
  // if we don't have a valid api key we need to redirect back to the 'api_key' tab.
26
  if (($mailchimp_lists = $handler->getMailChimpLists()) && is_array($mailchimp_lists)) {
27
  $show_campaign_defaults = false;
28
  $allow_new_list = false;
29
  }
 
30
  // only display this button if the data is not syncing and we have a valid api key
31
  if ((bool) $this->getData('sync.started_at', false)) {
32
  $show_sync_tab = true;
22
  try {
23
  if ($handler->hasValidApiKey(null, true)) {
24
  $has_valid_api_key = true;
25
+
26
  // if we don't have a valid api key we need to redirect back to the 'api_key' tab.
27
  if (($mailchimp_lists = $handler->getMailChimpLists()) && is_array($mailchimp_lists)) {
28
  $show_campaign_defaults = false;
29
  $allow_new_list = false;
30
  }
31
+
32
  // only display this button if the data is not syncing and we have a valid api key
33
  if ((bool) $this->getData('sync.started_at', false)) {
34
  $show_sync_tab = true;
bootstrap.php CHANGED
@@ -34,6 +34,7 @@ spl_autoload_register(function($class) {
34
 
35
  // includes/api/errors
36
  'MailChimp_WooCommerce_Error' => 'includes/api/errors/class-mailchimp-error.php',
 
37
  'MailChimp_WooCommerce_ServerError' => 'includes/api/errors/class-mailchimp-server-error.php',
38
 
39
  // includes/api/helpers
@@ -87,7 +88,7 @@ function mailchimp_environment_variables() {
87
  return (object) array(
88
  'repo' => 'master',
89
  'environment' => 'production',
90
- 'version' => '2.1.11',
91
  'php_version' => phpversion(),
92
  'wp_version' => (empty($wp_version) ? 'Unknown' : $wp_version),
93
  'wc_version' => class_exists('WC') ? WC()->version : null,
@@ -99,7 +100,7 @@ function mailchimp_environment_variables() {
99
  if (defined( 'WP_CLI' ) && WP_CLI) {
100
  try {
101
  /**
102
- * Service push to Mailchimp
103
  *
104
  * <type>
105
  * : product_sync order_sync order product
@@ -288,14 +289,19 @@ function mailchimp_get_store_id() {
288
  return $store_id;
289
  }
290
 
291
-
292
  /**
293
  * @return bool|MailChimp_WooCommerce_MailChimpApi
294
  */
295
  function mailchimp_get_api() {
 
 
 
 
 
296
  if (($key = mailchimp_get_api_key())) {
297
- return new MailChimp_WooCommerce_MailChimpApi($key);
298
  }
 
299
  return false;
300
  }
301
 
@@ -460,33 +466,18 @@ function mailchimp_woocommerce_get_all_image_sizes_list() {
460
  }
461
 
462
  /**
463
- * @param null $network_wide
 
464
  */
465
- function activate_mailchimp_woocommerce($network_wide = null) {
466
- if (is_multisite() && $network_wide ) {
467
- global $wpdb;
468
- mailchimp_log('plugin.activation.multisite', "Installing Mailchimp Tables.");
469
- foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
470
- switch_to_blog($blog_id);
471
- if (mailchimp_check_woocommerce_plugin_status()) {
472
- MailChimp_WooCommerce_Activator::activate();
473
- }
474
- restore_current_blog();
475
- }
476
- } else {
477
- // if we don't have woocommerce we need to display a horrible error message before the plugin is installed.
478
- if (!mailchimp_check_woocommerce_plugin_status()) {
479
- // Deactivate the plugin
480
- deactivate_plugins(__FILE__);
481
- $error_message = __('The Mailchimp For WooCommerce plugin requires the <a href="http://wordpress.org/extend/plugins/woocommerce/">WooCommerce</a> plugin to be active!', 'woocommerce');
482
- wp_die($error_message);
483
- }
484
-
485
- $site_name = get_option('siteurl');
486
- mailchimp_log('plugin.activation.single_site', "Installing Mailchimp Tables For :: {$site_name}");
487
- MailChimp_WooCommerce_Activator::activate();
488
- mailchimp_log('plugin.activation.single_site', "Installed Mailchimp Tables For :: {$site_name}");
489
  }
 
490
  }
491
 
492
  /**
@@ -622,37 +613,91 @@ function mailchimp_update_connected_site_script() {
622
 
623
  // if the api is configured
624
  if ($store_id && ($api = mailchimp_get_api())) {
625
-
626
  // if we have a store
627
  if (($store = $api->getStore($store_id))) {
628
-
629
  // handle the coupon sync if we don't have a flag that says otherwise.
630
  $job = new MailChimp_WooCommerce_Process_Coupons();
631
  if ($job->getData('sync.coupons.completed_at', false) === false) {
632
  wp_queue($job);
633
  }
 
 
 
 
 
634
 
635
- // see if we have a connected site script url/fragment
636
- $url = $store->getConnectedSiteScriptUrl();
637
- $fragment = $store->getConnectedSiteScriptFragment();
 
 
 
 
 
 
 
 
 
 
 
638
 
639
- // if it's not empty we need to set the values
640
- if ($url && $fragment) {
 
 
 
 
 
641
 
642
- // update the options for script_url and script_fragment
643
- update_option('mailchimp-woocommerce-script_url', $url);
644
- update_option('mailchimp-woocommerce-script_fragment', $fragment);
 
 
 
 
645
 
646
- // check to see if the site is connected
647
- if (!$api->checkConnectedSite($store_id)) {
 
 
 
 
 
 
 
 
 
 
 
648
 
649
- // if it's not, connect it now.
650
- $api->connectSite($store_id);
651
- }
 
 
652
 
653
- return true;
654
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
  }
 
 
656
  }
657
  return false;
658
  }
@@ -732,7 +777,7 @@ function mailchimp_email_is_privacy_protected($email) {
732
  * @return bool
733
  */
734
  function mailchimp_email_is_amazon($email) {
735
- return mailchimp_string_contains($email, '@marketplace.amazon.com');
736
  }
737
 
738
  /**
@@ -744,18 +789,20 @@ function mailchimp_hash_trim_lower($str) {
744
  }
745
 
746
  /**
 
747
  * @return array|WP_Error
748
  */
749
- function mailchimp_call_http_worker_manually() {
750
  $action = 'http_worker';
751
  $query_args = apply_filters('http_worker_query_args', array(
752
  'action' => $action,
753
  'nonce' => wp_create_nonce($action),
 
754
  ));
755
  $query_url = apply_filters('http_worker_query_url', admin_url('admin-ajax.php'));
756
  $post_args = apply_filters('http_worker_post_args', array(
757
- 'timeout' => 0.01,
758
- 'blocking' => false,
759
  'cookies' => $_COOKIE,
760
  'sslverify' => apply_filters('https_local_ssl_verify', false),
761
  ));
@@ -763,6 +810,36 @@ function mailchimp_call_http_worker_manually() {
763
  return wp_remote_post(esc_url_raw($url), $post_args);
764
  }
765
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
766
  /**
767
  * @param $key
768
  * @param null $default
@@ -784,7 +861,7 @@ function mailchimp_set_transient($key, $value, $seconds = 60) {
784
  return set_site_transient("mailchimp-woocommerce.{$key}", array(
785
  'value' => $value,
786
  'expires' => time()+$seconds,
787
- ));
788
  }
789
 
790
  /**
@@ -909,3 +986,4 @@ function mailchimp_on_all_plugins_loaded() {
909
  run_mailchimp_woocommerce();
910
  }
911
  }
 
34
 
35
  // includes/api/errors
36
  'MailChimp_WooCommerce_Error' => 'includes/api/errors/class-mailchimp-error.php',
37
+ 'MailChimp_WooCommerce_RateLimitError' => 'includes/api/errors/class-mailchimp-rate-limit-error.php',
38
  'MailChimp_WooCommerce_ServerError' => 'includes/api/errors/class-mailchimp-server-error.php',
39
 
40
  // includes/api/helpers
88
  return (object) array(
89
  'repo' => 'master',
90
  'environment' => 'production',
91
+ 'version' => '2.1.12',
92
  'php_version' => phpversion(),
93
  'wp_version' => (empty($wp_version) ? 'Unknown' : $wp_version),
94
  'wc_version' => class_exists('WC') ? WC()->version : null,
100
  if (defined( 'WP_CLI' ) && WP_CLI) {
101
  try {
102
  /**
103
+ * Service push to MailChimp
104
  *
105
  * <type>
106
  * : product_sync order_sync order product
289
  return $store_id;
290
  }
291
 
 
292
  /**
293
  * @return bool|MailChimp_WooCommerce_MailChimpApi
294
  */
295
  function mailchimp_get_api() {
296
+
297
+ if (($api = MailChimp_WooCommerce_MailChimpApi::getInstance())) {
298
+ return $api;
299
+ }
300
+
301
  if (($key = mailchimp_get_api_key())) {
302
+ return MailChimp_WooCommerce_MailChimpApi::constructInstance($key);
303
  }
304
+
305
  return false;
306
  }
307
 
466
  }
467
 
468
  /**
469
+ * The code that runs during plugin activation.
470
+ * This action is documented in includes/class-mailchimp-woocommerce-activator.php
471
  */
472
+ function activate_mailchimp_woocommerce() {
473
+ // if we don't have woocommerce we need to display a horrible error message before the plugin is installed.
474
+ if (!mailchimp_check_woocommerce_plugin_status()) {
475
+ // Deactivate the plugin
476
+ deactivate_plugins(__FILE__);
477
+ $error_message = __('The MailChimp For WooCommerce plugin requires the <a href="http://wordpress.org/extend/plugins/woocommerce/">WooCommerce</a> plugin to be active!', 'woocommerce');
478
+ wp_die($error_message);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  }
480
+ MailChimp_WooCommerce_Activator::activate();
481
  }
482
 
483
  /**
613
 
614
  // if the api is configured
615
  if ($store_id && ($api = mailchimp_get_api())) {
 
616
  // if we have a store
617
  if (($store = $api->getStore($store_id))) {
 
618
  // handle the coupon sync if we don't have a flag that says otherwise.
619
  $job = new MailChimp_WooCommerce_Process_Coupons();
620
  if ($job->getData('sync.coupons.completed_at', false) === false) {
621
  wp_queue($job);
622
  }
623
+ return mailchimpi_refresh_connected_site_script($store);
624
+ }
625
+ }
626
+ return false;
627
+ }
628
 
629
+ /**
630
+ * @return bool|DateTime
631
+ */
632
+ function mailchimp_get_updated_connected_site_since_as_date_string() {
633
+ $updated_at = get_option('mailchimp-woocommerce-script_updated_at', false);
634
+ if (empty($updated_at)) return '';
635
+ try {
636
+ $date = new \DateTime();
637
+ $date->setTimestamp($updated_at);
638
+ return $date->format('D, M j, Y g:i A');
639
+ } catch (\Exception $e) {
640
+ return '';
641
+ }
642
+ }
643
 
644
+ /**
645
+ * @return int
646
+ */
647
+ function mailchimp_get_updated_connected_site_since() {
648
+ $updated_at = get_option('mailchimp-woocommerce-script_updated_at', false);
649
+ return empty($updated_at) ? 1000000 : (time() - $updated_at);
650
+ }
651
 
652
+ /**
653
+ * @param int $seconds
654
+ * @return bool
655
+ */
656
+ function mailchimp_should_update_connected_site_script($seconds = 600) {
657
+ return mailchimp_get_updated_connected_site_since() >= $seconds;
658
+ }
659
 
660
+ /**
661
+ *
662
+ */
663
+ function mailchimp_update_connected_site_script_from_cdn() {
664
+ if (mailchimp_is_configured() && mailchimp_should_update_connected_site_script() && ($store_id = mailchimp_get_store_id())) {
665
+ try {
666
+ // pull the store, refresh the connected site url
667
+ mailchimpi_refresh_connected_site_script(mailchimp_get_api()->getStore($store_id));
668
+ } catch (\Exception $e) {
669
+ mailchimp_error("admin.update_connected_site_script", $e->getMessage());
670
+ }
671
+ }
672
+ }
673
 
674
+ /**
675
+ * @param MailChimp_WooCommerce_Store $store
676
+ * @return bool
677
+ */
678
+ function mailchimpi_refresh_connected_site_script(MailChimp_WooCommerce_Store $store) {
679
 
680
+ $api = mailchimp_get_api();
681
+
682
+ $url = $store->getConnectedSiteScriptUrl();
683
+ $fragment = $store->getConnectedSiteScriptFragment();
684
+
685
+ // if it's not empty we need to set the values
686
+ if ($url && $fragment) {
687
+
688
+ // update the options for script_url and script_fragment
689
+ update_option('mailchimp-woocommerce-script_url', $url);
690
+ update_option('mailchimp-woocommerce-script_fragment', $fragment);
691
+ update_option('mailchimp-woocommerce-script_updated_at', time());
692
+
693
+ // check to see if the site is connected
694
+ if (!$api->checkConnectedSite($store->getId())) {
695
+
696
+ // if it's not, connect it now.
697
+ $api->connectSite($store->getId());
698
  }
699
+
700
+ return true;
701
  }
702
  return false;
703
  }
777
  * @return bool
778
  */
779
  function mailchimp_email_is_amazon($email) {
780
+ return mailchimp_string_contains($email, '@marketplace.amazon.');
781
  }
782
 
783
  /**
789
  }
790
 
791
  /**
792
+ * @param bool $block
793
  * @return array|WP_Error
794
  */
795
+ function mailchimp_call_http_worker_manually($block = false) {
796
  $action = 'http_worker';
797
  $query_args = apply_filters('http_worker_query_args', array(
798
  'action' => $action,
799
  'nonce' => wp_create_nonce($action),
800
+ 'test' => $block === true ? '1' : '0',
801
  ));
802
  $query_url = apply_filters('http_worker_query_url', admin_url('admin-ajax.php'));
803
  $post_args = apply_filters('http_worker_post_args', array(
804
+ 'timeout' => $block ? 60 : 0.01,
805
+ 'blocking' => $block,
806
  'cookies' => $_COOKIE,
807
  'sslverify' => apply_filters('https_local_ssl_verify', false),
808
  ));
810
  return wp_remote_post(esc_url_raw($url), $post_args);
811
  }
812
 
813
+ /**
814
+ * @return bool|string
815
+ */
816
+ function mailchimp_woocommerce_check_if_http_worker_fails() {
817
+ // if the function doesn't exist we can't do anything.
818
+ if (!function_exists('wp_remote_post')) {
819
+ mailchimp_set_data('test.can.remote_post', false);
820
+ mailchimp_set_data('test.can.remote_post.error', 'function "wp_remote_post" does not exist');
821
+ return 'function "wp_remote_post" does not exist';
822
+ }
823
+ // apply a blocking call to make sure we get the response back
824
+ $response = mailchimp_call_http_worker_manually(true);
825
+
826
+ if (is_wp_error($response)) {
827
+ // nope, we have problems
828
+ mailchimp_set_data('test.can.remote_post', false);
829
+ mailchimp_set_data('test.can.remote_post.error', $response->get_error_message());
830
+ return $response->get_error_message();
831
+ } elseif (is_array($response) && isset($response['http_response']) && ($r = $response['http_response'])){
832
+ /** @var \WP_HTTP_Requests_Response $r */
833
+ if ($r->get_status() >= 400) {
834
+ return 'admin-ajax.php seems to be disabled on this wordpress site. Please enable to sync data.';
835
+ }
836
+ }
837
+ // yep all good.
838
+ mailchimp_set_data('test.can.remote_post', true);
839
+ mailchimp_set_data('test.can.remote_post.error', false);
840
+ return false;
841
+ }
842
+
843
  /**
844
  * @param $key
845
  * @param null $default
861
  return set_site_transient("mailchimp-woocommerce.{$key}", array(
862
  'value' => $value,
863
  'expires' => time()+$seconds,
864
+ ), $seconds);
865
  }
866
 
867
  /**
986
  run_mailchimp_woocommerce();
987
  }
988
  }
989
+
includes/api/class-mailchimp-api.php CHANGED
@@ -10,6 +10,25 @@ class MailChimp_WooCommerce_MailChimpApi
10
  protected $api_key = null;
11
  protected $auth_type = 'key';
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  /**
14
  * MailChimpService constructor.
15
  * @param null $api_key
@@ -1467,6 +1486,9 @@ class MailChimp_WooCommerce_MailChimpApi
1467
  }
1468
 
1469
  if ($info['http_code'] >= 400 && $info['http_code'] <= 500) {
 
 
 
1470
  throw new MailChimp_WooCommerce_Error($data['title'] .' :: '.$data['detail'], $data['status']);
1471
  }
1472
 
@@ -1495,6 +1517,9 @@ class MailChimp_WooCommerce_MailChimpApi
1495
 
1496
  // make sure the response is correct from the data in the response array
1497
  if (isset($data['status']) && $data['status'] >= 400) {
 
 
 
1498
  throw new MailChimp_WooCommerce_Error($data['detail'], $data['status']);
1499
  }
1500
 
10
  protected $api_key = null;
11
  protected $auth_type = 'key';
12
 
13
+ protected static $instance = null;
14
+
15
+ /**
16
+ * @return null
17
+ */
18
+ public static function getInstance()
19
+ {
20
+ return static::$instance;
21
+ }
22
+
23
+ /**
24
+ * @param $api_key
25
+ * @return MailChimp_WooCommerce_MailChimpApi
26
+ */
27
+ public static function constructInstance($api_key)
28
+ {
29
+ return static::$instance = new MailChimp_WooCommerce_MailChimpApi($api_key);
30
+ }
31
+
32
  /**
33
  * MailChimpService constructor.
34
  * @param null $api_key
1486
  }
1487
 
1488
  if ($info['http_code'] >= 400 && $info['http_code'] <= 500) {
1489
+ if ($info['http_code'] == 403) {
1490
+ throw new MailChimp_WooCommerce_RateLimitError();
1491
+ }
1492
  throw new MailChimp_WooCommerce_Error($data['title'] .' :: '.$data['detail'], $data['status']);
1493
  }
1494
 
1517
 
1518
  // make sure the response is correct from the data in the response array
1519
  if (isset($data['status']) && $data['status'] >= 400) {
1520
+ if ($data['http_code'] == 403) {
1521
+ throw new MailChimp_WooCommerce_RateLimitError();
1522
+ }
1523
  throw new MailChimp_WooCommerce_Error($data['detail'], $data['status']);
1524
  }
1525
 
includes/api/class-mailchimp-woocommerce-transform-orders-wc3.php CHANGED
@@ -220,6 +220,7 @@ class MailChimp_WooCommerce_Transform_Orders
220
 
221
  if ($subscriber['status'] === 'transactional') {
222
  $customer->setOptInStatus(false);
 
223
  if ($doi) {
224
  $customer->requireDoubleOptIn(true);
225
  }
@@ -370,7 +371,8 @@ class MailChimp_WooCommerce_Transform_Orders
370
 
371
  foreach ($orders as $order) {
372
  $order = new WC_Order($order);
373
- if ($order->get_status() !== 'cancelled') {
 
374
  $stats->total += $order->get_total();
375
  $stats->count ++;
376
  }
220
 
221
  if ($subscriber['status'] === 'transactional') {
222
  $customer->setOptInStatus(false);
223
+ // when the list requires a double opt in - flag it here.
224
  if ($doi) {
225
  $customer->requireDoubleOptIn(true);
226
  }
371
 
372
  foreach ($orders as $order) {
373
  $order = new WC_Order($order);
374
+
375
+ if ($order->get_status() !== 'cancelled' && $order->is_paid()) {
376
  $stats->total += $order->get_total();
377
  $stats->count ++;
378
  }
includes/api/class-mailchimp-woocommerce-transform-products.php CHANGED
@@ -108,6 +108,7 @@ class MailChimp_WooCommerce_Transform_Products
108
  $variant = new MailChimp_WooCommerce_ProductVariation();
109
 
110
  if (!$woo) {
 
111
  return $variant;
112
  }
113
 
108
  $variant = new MailChimp_WooCommerce_ProductVariation();
109
 
110
  if (!$woo) {
111
+ //mailchimp_error("products.transform", "could not load product variant", array('post' => print_r($post, true)));
112
  return $variant;
113
  }
114
 
includes/api/errors/class-mailchimp-rate-limit-error.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class MailChimp_WooCommerce_RateLimitError
5
+ */
6
+ class MailChimp_WooCommerce_RateLimitError extends MailChimp_WooCommerce_Error
7
+ {
8
+
9
+ }
includes/class-mailchimp-woocommerce-newsletter.php CHANGED
@@ -90,15 +90,26 @@ class MailChimp_Newsletter extends MailChimp_WooCommerce_Options
90
  */
91
  protected function handleStatus($order_id = null)
92
  {
93
- $status = isset($_POST['mailchimp_woocommerce_newsletter']) ? (int)$_POST['mailchimp_woocommerce_newsletter'] : 0;
 
 
94
 
 
 
 
 
 
 
 
 
 
95
  if ($order_id) {
96
- update_post_meta($order_id, 'mailchimp_woocommerce_is_subscribed', $status);
97
  }
98
 
99
- if (is_user_logged_in()) {
100
- update_user_meta(get_current_user_id(), 'mailchimp_woocommerce_is_subscribed', $status);
101
-
102
  return $status;
103
  }
104
 
90
  */
91
  protected function handleStatus($order_id = null)
92
  {
93
+ $post_key = 'mailchimp_woocommerce_newsletter';
94
+ $meta_key = 'mailchimp_woocommerce_is_subscribed';
95
+ $logged_in = is_user_logged_in();
96
 
97
+ // if the post key is available we use it - otherwise we null it out.
98
+ $status = isset($_POST[$post_key]) ? (int) $_POST[$post_key] : null;
99
+
100
+ // if the status is null, we don't do anything
101
+ if ($status === null) {
102
+ return false;
103
+ }
104
+
105
+ // if we passed in an order id, we update it here.
106
  if ($order_id) {
107
+ update_post_meta($order_id, $meta_key, $status);
108
  }
109
 
110
+ // if the user is logged in, we will update the status correctly.
111
+ if ($logged_in) {
112
+ update_user_meta(get_current_user_id(), $meta_key, $status);
113
  return $status;
114
  }
115
 
includes/class-mailchimp-woocommerce-service.php CHANGED
@@ -127,7 +127,7 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
127
  public function clearCartData()
128
  {
129
  if ($user_email = $this->getCurrentUserEmail()) {
130
- $this->deleteCart($user_email);
131
  }
132
  }
133
 
@@ -377,7 +377,7 @@ class MailChimp_Service extends MailChimp_WooCommerce_Options
377
  public function getCartItems()
378
  {
379
  if (!($this->cart = $this->getWooSession('cart', false))) {
380
- $this->cart = function_exists('WC') ? false : WC()->cart->get_cart();
381
  } else {
382
  $cart_session = array();
383
  foreach ( $this->cart as $key => $values ) {
127
  public function clearCartData()
128
  {
129
  if ($user_email = $this->getCurrentUserEmail()) {
130
+ $this->deleteCart(mailchimp_hash_trim_lower($user_email));
131
  }
132
  }
133
 
377
  public function getCartItems()
378
  {
379
  if (!($this->cart = $this->getWooSession('cart', false))) {
380
+ $this->cart = !function_exists('WC') ? false : WC()->cart->get_cart();
381
  } else {
382
  $cart_session = array();
383
  foreach ( $this->cart as $key => $values ) {
includes/class-mailchimp-woocommerce.php CHANGED
@@ -132,6 +132,29 @@ class MailChimp_WooCommerce
132
 
133
  $this->activateMailChimpNewsletter();
134
  $this->activateMailChimpService();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
136
 
137
  /**
@@ -160,7 +183,10 @@ class MailChimp_WooCommerce
160
  // fire up the loader
161
  $this->loader = new MailChimp_WooCommerce_Loader();
162
 
163
- if (!mailchimp_running_in_console() && mailchimp_is_configured()) {
 
 
 
164
  // fire up the http worker container
165
  new WP_Http_Worker($wp_queue);
166
  }
@@ -178,7 +204,9 @@ class MailChimp_WooCommerce
178
  mailchimp_call_http_worker_manually();
179
  }
180
  }
181
- } catch (\Exception $e) {}
 
 
182
  }
183
  }
184
 
132
 
133
  $this->activateMailChimpNewsletter();
134
  $this->activateMailChimpService();
135
+ $this->applyQueryStringOverrides();
136
+ }
137
+
138
+ /**
139
+ *
140
+ */
141
+ private function applyQueryStringOverrides()
142
+ {
143
+ // if we need to refresh the double opt in for any reason - just do it here.
144
+ if ($this->queryStringEquals('mc_doi_refresh', '1')) {
145
+ $enabled_doi = mailchimp_list_has_double_optin(true);
146
+ mailchimp_log('mc.utils.doi_refresh', ($enabled_doi ? 'turned ON' : 'turned OFF'));
147
+ }
148
+ }
149
+
150
+ /**
151
+ * @param $key
152
+ * @param string $value
153
+ * @return bool
154
+ */
155
+ private function queryStringEquals($key, $value = '1')
156
+ {
157
+ return isset($_GET[$key]) && $_GET[$key] === $value;
158
  }
159
 
160
  /**
183
  // fire up the loader
184
  $this->loader = new MailChimp_WooCommerce_Loader();
185
 
186
+ $has_test = isset($_REQUEST['action']) && $_REQUEST['action'] === 'http_worker' &&
187
+ (isset($_REQUEST['test']) && $_REQUEST['test'] === '1');
188
+
189
+ if ($has_test || (!mailchimp_running_in_console() && mailchimp_is_configured())) {
190
  // fire up the http worker container
191
  new WP_Http_Worker($wp_queue);
192
  }
204
  mailchimp_call_http_worker_manually();
205
  }
206
  }
207
+ } catch (\Exception $e) {
208
+ mailchimp_error_trace($e, "loading dependencies");
209
+ }
210
  }
211
  }
212
 
includes/processes/class-mailchimp-woocommerce-abstract-sync.php CHANGED
@@ -30,6 +30,11 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
30
  */
31
  protected $store_id = '';
32
 
 
 
 
 
 
33
  /**
34
  * @return mixed
35
  */
@@ -76,8 +81,6 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
76
  */
77
  public function handle()
78
  {
79
- global $wpdb;
80
-
81
  if (!mailchimp_is_configured()) {
82
  mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
83
  return false;
@@ -89,6 +92,19 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
89
  return false;
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  // don't let recursion happen.
93
  if ($this->getResourceType() === 'orders' && $this->getResourceCompleteTime()) {
94
  mailchimp_log('sync.stop', "halting the sync for :: {$this->getResourceType()}");
@@ -128,20 +144,40 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
128
 
129
  // iterate through the items and send each one through the pipeline based on this class.
130
  foreach ($page->items as $resource) {
131
- $this->iterate($resource);
 
 
 
 
 
132
  }
133
 
134
- $this->delete();
135
-
136
- $class_name = get_called_class();
137
- $wpdb->query("DELETE FROM {$wpdb->prefix}queue WHERE job LIKE '%{$class_name}%'");
138
 
139
- // this will paginate through all records for the resource type until they return no records.
140
- mailchimp_handle_or_queue(new static());
141
- mailchimp_debug(get_called_class().'@handle', 'queuing up the next job');
142
  return false;
143
  }
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  /**
146
  * @return $this
147
  */
@@ -246,6 +282,9 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
246
  {
247
  if (empty($resource)) $resource = $this->getResourceType();
248
 
 
 
 
249
  return $this->setData('sync.'.$resource.'.current_page', $page);
250
  }
251
 
@@ -263,7 +302,8 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
263
  }
264
 
265
  /**
266
- * @return null
 
267
  */
268
  protected function setResourceCompleteTime($resource = null)
269
  {
@@ -392,4 +432,46 @@ abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
392
  }
393
  return $this->mc;
394
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  }
30
  */
31
  protected $store_id = '';
32
 
33
+ /**
34
+ * @var bool
35
+ */
36
+ protected $has_applied_pagination = false;
37
+
38
  /**
39
  * @return mixed
40
  */
81
  */
82
  public function handle()
83
  {
 
 
84
  if (!mailchimp_is_configured()) {
85
  mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
86
  return false;
92
  return false;
93
  }
94
 
95
+ // if we're being rate limited - we need to pause here.
96
+ if ($this->isBeingRateLimited()) {
97
+ // wait a few seconds
98
+ sleep(3);
99
+ // check this again
100
+ if ($this->isBeingRateLimited()) {
101
+ // ok - hold off for a few - let's re-queue the job.
102
+ mailchimp_debug(get_called_class().'@handle', 'being rate limited - pausing for a few seconds...');
103
+ $this->next();
104
+ return false;
105
+ }
106
+ }
107
+
108
  // don't let recursion happen.
109
  if ($this->getResourceType() === 'orders' && $this->getResourceCompleteTime()) {
110
  mailchimp_log('sync.stop', "halting the sync for :: {$this->getResourceType()}");
144
 
145
  // iterate through the items and send each one through the pipeline based on this class.
146
  foreach ($page->items as $resource) {
147
+ try {
148
+ $this->iterateCurrentResource($resource);
149
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
150
+ $this->applyRateLimitedScenario();
151
+ return false;
152
+ }
153
  }
154
 
155
+ $this->next();
 
 
 
156
 
 
 
 
157
  return false;
158
  }
159
 
160
+ /**
161
+ * @param $resource
162
+ * @return bool
163
+ * @throws MailChimp_WooCommerce_RateLimitError
164
+ */
165
+ protected function iterateCurrentResource($resource)
166
+ {
167
+ $attempts = 1;
168
+ while ($attempts <= 4) {
169
+ $attempts++;
170
+ try {
171
+ return $this->iterate($resource);
172
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
173
+ if ($attempts === 4) {
174
+ throw $e;
175
+ }
176
+ sleep(3);
177
+ }
178
+ }
179
+ }
180
+
181
  /**
182
  * @return $this
183
  */
282
  {
283
  if (empty($resource)) $resource = $this->getResourceType();
284
 
285
+ // tell the file that if we catch a rate limit error that we need to revert to the current page.
286
+ $this->has_applied_pagination = $page;
287
+
288
  return $this->setData('sync.'.$resource.'.current_page', $page);
289
  }
290
 
302
  }
303
 
304
  /**
305
+ * @param null $resource
306
+ * @return MailChimp_WooCommerce_Abstract_Sync
307
  */
308
  protected function setResourceCompleteTime($resource = null)
309
  {
432
  }
433
  return $this->mc;
434
  }
435
+
436
+ /**
437
+ * @return bool
438
+ */
439
+ protected function isBeingRateLimited()
440
+ {
441
+ return (bool) mailchimp_get_transient('api-rate-limited', false);
442
+ }
443
+
444
+ /**
445
+ * @return $this
446
+ */
447
+ protected function applyRateLimitedScenario()
448
+ {
449
+ mailchimp_set_transient('api-rate-limited', true, 60);
450
+
451
+ if ($this->has_applied_pagination) {
452
+ $this->setResourcePagePointer(($this->has_applied_pagination-1));
453
+ $this->has_applied_pagination = false;
454
+ }
455
+
456
+ $this->next();
457
+
458
+ return $this;
459
+ }
460
+
461
+ /**
462
+ *
463
+ */
464
+ protected function next()
465
+ {
466
+ global $wpdb;
467
+
468
+ $this->delete();
469
+
470
+ $class_name = get_called_class();
471
+ $wpdb->query("DELETE FROM {$wpdb->prefix}queue WHERE job LIKE '%{$class_name}%'");
472
+
473
+ // this will paginate through all records for the resource type until they return no records.
474
+ mailchimp_handle_or_queue(new static());
475
+ mailchimp_debug(get_called_class().'@handle', 'queuing up the next job');
476
+ }
477
  }
includes/processes/class-mailchimp-woocommerce-cart-update.php CHANGED
@@ -41,7 +41,22 @@ class MailChimp_WooCommerce_Cart_Update extends WP_Job
41
  $this->campaign_id = $campaign_id;
42
  }
43
 
 
 
 
 
 
 
 
 
44
  $this->ip_address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
 
 
 
 
 
 
 
45
  }
46
 
47
  /**
@@ -146,6 +161,10 @@ class MailChimp_WooCommerce_Cart_Update extends WP_Job
146
  mailchimp_log('abandoned_cart.success', "email: {$customer->getEmailAddress()}");
147
  }
148
 
 
 
 
 
149
  } catch (\Exception $e) {
150
  update_option('mailchimp-woocommerce-cart-error', $e->getMessage());
151
  mailchimp_error('abandoned_cart.error', $e);
41
  $this->campaign_id = $campaign_id;
42
  }
43
 
44
+ $this->assignIP();
45
+ }
46
+
47
+ /**
48
+ * @return null
49
+ */
50
+ public function assignIP()
51
+ {
52
  $this->ip_address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
53
+
54
+ if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
55
+ $forwarded_address = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
56
+ $this->ip_address = $forwarded_address[0];
57
+ }
58
+
59
+ return $this->ip_address;
60
  }
61
 
62
  /**
161
  mailchimp_log('abandoned_cart.success', "email: {$customer->getEmailAddress()}");
162
  }
163
 
164
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
165
+ sleep(3);
166
+ $this->release();
167
+ mailchimp_error('cart.error', mailchimp_error_trace($e, "RateLimited :: email {$this->email}"));
168
  } catch (\Exception $e) {
169
  update_option('mailchimp-woocommerce-cart-error', $e->getMessage());
170
  mailchimp_error('abandoned_cart.error', $e);
includes/processes/class-mailchimp-woocommerce-single-coupon.php CHANGED
@@ -49,6 +49,11 @@ class MailChimp_WooCommerce_SingleCoupon extends WP_Job
49
  $api->addPromoCodeForRule($store_id, $code->getAttachedPromoRule(), $code, true);
50
 
51
  mailchimp_log('promo_code.update', "updated promo code {$code->getCode()}");
 
 
 
 
 
52
  } catch (\Exception $e) {
53
  $promo_code = isset($code) ? "code {$code->getCode()}" : "id {$this->post_id}";
54
  mailchimp_error('promo_code.error', mailchimp_error_trace($e, "error updating promo {$promo_code}"));
49
  $api->addPromoCodeForRule($store_id, $code->getAttachedPromoRule(), $code, true);
50
 
51
  mailchimp_log('promo_code.update', "updated promo code {$code->getCode()}");
52
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
53
+ sleep(3);
54
+ $this->release();
55
+ $promo_code = isset($code) ? "code {$code->getCode()}" : "id {$this->post_id}";
56
+ mailchimp_error('promo_code.error', mailchimp_error_trace($e, "RateLimited :: #{$promo_code}"));
57
  } catch (\Exception $e) {
58
  $promo_code = isset($code) ? "code {$code->getCode()}" : "id {$this->post_id}";
59
  mailchimp_error('promo_code.error', mailchimp_error_trace($e, "error updating promo {$promo_code}"));
includes/processes/class-mailchimp-woocommerce-single-order.php CHANGED
@@ -196,6 +196,10 @@ class MailChimp_WooCommerce_Single_Order extends WP_Job
196
  }
197
 
198
  return $api_response;
 
 
 
 
199
  } catch (\Exception $e) {
200
  $message = strtolower($e->getMessage());
201
  mailchimp_error('order_submit.tracing_error', $e);
196
  }
197
 
198
  return $api_response;
199
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
200
+ sleep(3);
201
+ $this->release();
202
+ mailchimp_error('order_submit.error', mailchimp_error_trace($e, "RateLimited :: #{$this->order_id}"));
203
  } catch (\Exception $e) {
204
  $message = strtolower($e->getMessage());
205
  mailchimp_error('order_submit.tracing_error', $e);
includes/processes/class-mailchimp-woocommerce-single-product.php CHANGED
@@ -72,6 +72,10 @@ class MailChimp_WooCommerce_Single_Product extends WP_Job
72
 
73
  return $product;
74
 
 
 
 
 
75
  } catch (MailChimp_WooCommerce_ServerError $e) {
76
  mailchimp_error('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
77
  } catch (MailChimp_WooCommerce_Error $e) {
72
 
73
  return $product;
74
 
75
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
76
+ sleep(3);
77
+ $this->release();
78
+ mailchimp_error('product_submit.error', mailchimp_error_trace($e, "RateLimited :: #{$this->product_id}"));
79
  } catch (MailChimp_WooCommerce_ServerError $e) {
80
  mailchimp_error('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
81
  } catch (MailChimp_WooCommerce_Error $e) {
includes/processes/class-mailchimp-woocommerce-user-submit.php CHANGED
@@ -26,11 +26,12 @@ class MailChimp_WooCommerce_User_Submit extends WP_Job
26
  public function __construct($user_id = null, $subscribed = null, $updated_data = null)
27
  {
28
  if (!empty($user_id)) {
29
- if (static::$handling_for === $this->user_id) {
 
30
  $this->should_ignore = true;
31
  }
32
- $this->user_id = $user_id;
33
- static::$handling_for = $this->user_id;
34
  }
35
 
36
  if (is_bool($subscribed)) {
@@ -131,6 +132,15 @@ class MailChimp_WooCommerce_User_Submit extends WP_Job
131
  if (!empty($fn)) $merge_vars['FNAME'] = $fn;
132
  if (!empty($ln)) $merge_vars['LNAME'] = $ln;
133
 
 
 
 
 
 
 
 
 
 
134
  // pull the transient key for this job.
135
  $transient_id = mailchimp_get_transient_email_key($email);
136
  $status_meta = mailchimp_get_subscriber_status_options($this->subscribed);
@@ -171,20 +181,44 @@ class MailChimp_WooCommerce_User_Submit extends WP_Job
171
  return false;
172
  }
173
  }
 
 
174
  if (isset($member_data['status']) && in_array($member_data['status'], array('unsubscribed', 'pending'))) {
175
  mailchimp_log('member.sync', "Skipped Member Sync For {$email} because the current status is {$member_data['status']}", $merge_vars);
176
  static::$handling_for = null;
177
  return false;
178
  }
179
- // ok let's update this member
180
- $api->update($list_id, $email, $status_meta['updated'], $merge_vars);
181
- mailchimp_tell_system_about_user_submit($email, $status_meta, 60);
182
- mailchimp_log('member.sync', "Updated Member {$email}", array(
183
- 'previous_status' => isset($member_data['status']) ? $member_data['status'] : 'no status on customer',
184
- 'status' => $status_meta['updated'],
185
- 'merge_vars' => $merge_vars
186
- ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  static::$handling_for = null;
 
 
 
 
188
  } catch (\Exception $e) {
189
  // if we have a 404 not found, we can create the member
190
  if ($e->getCode() == 404) {
26
  public function __construct($user_id = null, $subscribed = null, $updated_data = null)
27
  {
28
  if (!empty($user_id)) {
29
+ // if we're passing in another user with the same id during the same php process we need to ignore it.
30
+ if (static::$handling_for === $user_id) {
31
  $this->should_ignore = true;
32
  }
33
+ // set the user id and the current 'handling_for' to this user id so we don't duplicate jobs.
34
+ static::$handling_for = $this->user_id = $user_id;
35
  }
36
 
37
  if (is_bool($subscribed)) {
132
  if (!empty($fn)) $merge_vars['FNAME'] = $fn;
133
  if (!empty($ln)) $merge_vars['LNAME'] = $ln;
134
 
135
+ // allow users to hook into the merge tag submission
136
+ $merge_vars = apply_filters('mailchimp_sync_user_mergetags', $user, $merge_vars);
137
+
138
+ // for whatever reason if this isn't an array we need to skip it.
139
+ if (!is_array($merge_vars)) {
140
+ mailchimp_error("custom.merge_tags", "the filter for mailchimp_sync_user_mergetags needs to return an array.");
141
+ return false;
142
+ }
143
+
144
  // pull the transient key for this job.
145
  $transient_id = mailchimp_get_transient_email_key($email);
146
  $status_meta = mailchimp_get_subscriber_status_options($this->subscribed);
181
  return false;
182
  }
183
  }
184
+
185
+ // if the member is unsubscribed or pending, we really can't do anything here.
186
  if (isset($member_data['status']) && in_array($member_data['status'], array('unsubscribed', 'pending'))) {
187
  mailchimp_log('member.sync', "Skipped Member Sync For {$email} because the current status is {$member_data['status']}", $merge_vars);
188
  static::$handling_for = null;
189
  return false;
190
  }
191
+
192
+ // if the status is not === 'transactional' we can update them to subscribed or pending now.
193
+ if (isset($member_data['status']) && $member_data['status'] === 'transactional' || $member_data['status'] === 'cleaned') {
194
+ // ok let's update this member
195
+ $api->update($list_id, $email, $status_meta['updated'], $merge_vars);
196
+ mailchimp_tell_system_about_user_submit($email, $status_meta, 60);
197
+ mailchimp_log('member.sync', "Updated Member {$email}", array(
198
+ 'previous_status' => $member_data['status'],
199
+ 'status' => $status_meta['updated'],
200
+ 'merge_vars' => $merge_vars
201
+ ));
202
+ static::$handling_for = null;
203
+ return true;
204
+ }
205
+
206
+ if (isset($member_data['status'])) {
207
+ // ok let's update this member
208
+ $api->update($list_id, $email, $member_data['status'], $merge_vars);
209
+ mailchimp_tell_system_about_user_submit($email, $status_meta, 60);
210
+ mailchimp_log('member.sync', "Updated Member {$email} ( merge tags only )", array(
211
+ 'merge_vars' => $merge_vars
212
+ ));
213
+ static::$handling_for = null;
214
+ return true;
215
+ }
216
+
217
  static::$handling_for = null;
218
+ } catch (MailChimp_WooCommerce_RateLimitError $e) {
219
+ sleep(3);
220
+ $this->release();
221
+ mailchimp_error('member.sync.error', mailchimp_error_trace($e, "RateLimited :: user #{$this->user_id}"));
222
  } catch (\Exception $e) {
223
  // if we have a 404 not found, we can create the member
224
  if ($e->getCode() == 404) {
includes/vendor/queue/classes/worker/wp-http-worker.php CHANGED
@@ -39,7 +39,7 @@ if ( ! class_exists( 'WP_Http_Worker' ) ) {
39
  add_action( 'wp_queue_job_pushed', array( $this, 'maybe_dispatch_worker' ) );
40
 
41
  if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'http_worker' && check_ajax_referer( 'http_worker', 'nonce', false)) {
42
- add_action('init', array($this, 'handle'));
43
  }
44
  }
45
 
39
  add_action( 'wp_queue_job_pushed', array( $this, 'maybe_dispatch_worker' ) );
40
 
41
  if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'http_worker' && check_ajax_referer( 'http_worker', 'nonce', false)) {
42
+ add_action('init', array($this, 'handle'));
43
  }
44
  }
45
 
includes/vendor/queue/classes/worker/wp-worker.php CHANGED
@@ -28,6 +28,7 @@ if ( ! class_exists( 'WP_Worker' ) ) {
28
  * @return bool
29
  */
30
  public function should_run() {
 
31
  if ( $this->queue->available_jobs() ) {
32
  return true;
33
  }
28
  * @return bool
29
  */
30
  public function should_run() {
31
+
32
  if ( $this->queue->available_jobs() ) {
33
  return true;
34
  }
includes/vendor/queue/classes/wp-queue.php CHANGED
@@ -48,8 +48,18 @@ if ( ! class_exists( 'WP_Queue' ) ) {
48
  $id = $wpdb->insert( $this->table, $data );
49
 
50
  if (!$id) {
51
- $name = get_class($job);
52
- mailchimp_error("queue.failure", "Could not queue job {$name}, your database tables might not be properly set!");
 
 
 
 
 
 
 
 
 
 
53
  }
54
 
55
  return $this;
48
  $id = $wpdb->insert( $this->table, $data );
49
 
50
  if (!$id) {
51
+ try {
52
+ if (mailchimp_string_contains($wpdb->last_error, 'Table')) {
53
+ mailchimp_debug('Queue Table Was Not Found!', 'Creating Tables');
54
+ MailChimp_WooCommerce_Activator::create_queue_tables();
55
+ $id = $wpdb->insert( $this->table, $data );
56
+ if (!$id) {
57
+ mailchimp_debug('Queue Job '.get_class($job), $wpdb->last_error);
58
+ }
59
+ }
60
+ } catch (\Exception $e) {
61
+ mailchimp_error_trace($e, 'trying to create queue tables');
62
+ }
63
  }
64
 
65
  return $this;
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: Mailchimp - WooCommerce plugin
19
- * Version: 2.1.11
20
  * Author: Mailchimp
21
  * Author URI: https://mailchimp.com
22
  * License: GPL-2.0+
@@ -38,9 +38,3 @@ if (!isset($mailchimp_woocommerce_spl_autoloader) || $mailchimp_woocommerce_spl_
38
 
39
  register_activation_hook( __FILE__, 'activate_mailchimp_woocommerce');
40
  add_action('plugins_loaded', 'mailchimp_on_all_plugins_loaded', 12);
41
-
42
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
43
- $forwarded_address = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
44
- $_SERVER['REMOTE_ADDR'] = $forwarded_address[0];
45
- }
46
-
16
  * Plugin Name: Mailchimp for WooCommerce
17
  * Plugin URI: https://mailchimp.com/connect-your-store/
18
  * Description: Mailchimp - WooCommerce plugin
19
+ * Version: 2.1.12
20
  * Author: Mailchimp
21
  * Author URI: https://mailchimp.com
22
  * License: GPL-2.0+
38
 
39
  register_activation_hook( __FILE__, 'activate_mailchimp_woocommerce');
40
  add_action('plugins_loaded', 'mailchimp_on_all_plugins_loaded', 12);
 
 
 
 
 
 
public/class-mailchimp-woocommerce-public.php CHANGED
@@ -77,7 +77,7 @@ class MailChimp_WooCommerce_Public {
77
  wp_enqueue_script($this->plugin_name, '', array(), $this->version, true);
78
  //if we have the connected_site script url saved, we need to inject it
79
  if (($site = mailchimp_get_connected_site_script_url()) && !empty($site)) {
80
- wp_enqueue_script($this->plugin_name.'_connected_site', $site, array(), $this->version, true);
81
  }
82
  }
83
  }
77
  wp_enqueue_script($this->plugin_name, '', array(), $this->version, true);
78
  //if we have the connected_site script url saved, we need to inject it
79
  if (($site = mailchimp_get_connected_site_script_url()) && !empty($site)) {
80
+ wp_enqueue_script($this->plugin_name.'_connected_site', $site, array(), $this->version, true);
81
  }
82
  }
83
  }