MailChimp for WooCommerce - Version 2.3.3

Version Description

  • fixes abandoned cart issues with Paypal
  • resolves Action Scheduler 3.0 compatiblity issues
  • Fixes missing product images
Download this release

Release Info

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

Code changes from version 2.3.2 to 2.3.3

Files changed (28) hide show
  1. README.txt +5 -1
  2. admin/js/mailchimp-woocommerce-admin.js +9 -3
  3. includes/api/class-mailchimp-woocommerce-transform-products.php +10 -11
  4. includes/processes/class-mailchimp-woocommerce-single-order.php +4 -2
  5. includes/vendor/action-scheduler/.travis.yml +17 -9
  6. includes/vendor/action-scheduler/action-scheduler.php +15 -8
  7. includes/vendor/action-scheduler/classes/ActionScheduler_AdminView.php +2 -1
  8. includes/vendor/action-scheduler/classes/ActionScheduler_AsyncRequest_QueueRunner.php +2 -1
  9. includes/vendor/action-scheduler/classes/ActionScheduler_ListTable.php +10 -5
  10. includes/vendor/action-scheduler/classes/ActionScheduler_QueueRunner.php +14 -1
  11. includes/vendor/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php +9 -2
  12. includes/vendor/action-scheduler/classes/ActionScheduler_wcSystemStatus.php +10 -0
  13. includes/vendor/action-scheduler/classes/abstracts/ActionScheduler.php +11 -1
  14. includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php +1 -0
  15. includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php +10 -2
  16. includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Logger.php +1 -1
  17. includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Store.php +6 -6
  18. includes/vendor/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php +46 -5
  19. includes/vendor/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php +32 -30
  20. includes/vendor/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_TaxonomyRegistrar.php +2 -2
  21. includes/vendor/action-scheduler/classes/schema/ActionScheduler_LoggerSchema.php +0 -1
  22. includes/vendor/action-scheduler/classes/schema/ActionScheduler_StoreSchema.php +2 -1
  23. includes/vendor/action-scheduler/composer.json +7 -0
  24. includes/vendor/action-scheduler/docs/_layouts/default.html +1 -1
  25. includes/vendor/action-scheduler/docs/api.md +1 -1
  26. includes/vendor/action-scheduler/docs/usage.md +1 -1
  27. includes/vendor/action-scheduler/docs/version3-0.md +48 -0
  28. mailchimp-woocommerce.php +1 -1
README.txt CHANGED
@@ -4,7 +4,7 @@ Tags: ecommerce,email,workflows,mailchimp
4
  Donate link: https://mailchimp.com
5
  Requires at least: 4.9
6
  Tested up to: 5.3.2
7
- Stable tag: 2.3.2
8
  Requires PHP: 7.0
9
  WC requires at least: 3.5
10
  WC tested up to: 3.9
@@ -63,6 +63,10 @@ The Mailchimp for WooCommerce supports Wordpress Multi Sites and below are a few
63
  - Deleting removes the connection between Mailchimp and WooCommerce, and uninstalls the plugin from your site.
64
  Refer to the Wordpress Codex for more information about [Multisite Network Administration](https://codex.wordpress.org/Multisite_Network_Administration)
65
  == Changelog ==
 
 
 
 
66
  = 2.3.2 =
67
  * update to action scheduler v3.0.1
68
  * adds low-bandwidth setting on sync
4
  Donate link: https://mailchimp.com
5
  Requires at least: 4.9
6
  Tested up to: 5.3.2
7
+ Stable tag: 2.3.3
8
  Requires PHP: 7.0
9
  WC requires at least: 3.5
10
  WC tested up to: 3.9
63
  - Deleting removes the connection between Mailchimp and WooCommerce, and uninstalls the plugin from your site.
64
  Refer to the Wordpress Codex for more information about [Multisite Network Administration](https://codex.wordpress.org/Multisite_Network_Administration)
65
  == Changelog ==
66
+ = 2.3.3 =
67
+ * fixes abandoned cart issues with Paypal
68
+ * resolves Action Scheduler 3.0 compatiblity issues
69
+ * Fixes missing product images
70
  = 2.3.2 =
71
  * update to action scheduler v3.0.1
72
  * adds low-bandwidth setting on sync
admin/js/mailchimp-woocommerce-admin.js CHANGED
@@ -57,7 +57,9 @@
57
  }
58
 
59
  e.preventDefault();
60
-
 
 
61
  const swalWithBootstrapButtons = Swal.mixin({
62
  customClass: {
63
  confirmButton: 'button button-primary tab-content-submit disconnect-button',
@@ -81,8 +83,12 @@
81
  history.replaceState({}, "", query[1]);
82
  $('input[name=_wp_http_referer]').val(query[1]);
83
  }
84
- mailchimp_woocommerce_disconnect_done = true;
85
- e.target.click();
 
 
 
 
86
  }
87
  })
88
  });
57
  }
58
 
59
  e.preventDefault();
60
+
61
+ var me = $(e.target);
62
+
63
  const swalWithBootstrapButtons = Swal.mixin({
64
  customClass: {
65
  confirmButton: 'button button-primary tab-content-submit disconnect-button',
83
  history.replaceState({}, "", query[1]);
84
  $('input[name=_wp_http_referer]').val(query[1]);
85
  }
86
+ try {
87
+ me.click();
88
+ mailchimp_woocommerce_disconnect_done = true;
89
+ } catch (e) {
90
+ console.error('clicking event for disconnect failed', e);
91
+ }
92
  }
93
  })
94
  });
includes/api/class-mailchimp-woocommerce-transform-products.php CHANGED
@@ -256,22 +256,21 @@ class MailChimp_WooCommerce_Transform_Products
256
  return $variants;
257
  }
258
 
259
- /**
260
- * @param $post_id
261
- * @return false|string
262
- */
263
- public function getProductImage($post_id)
264
  {
265
- $meta = get_post_meta($post_id);
266
  $key = '_thumbnail_id';
267
  $image_key = $this->getProductImageKey();
268
-
269
  if ($meta && is_array($meta) && array_key_exists($key, $meta) && isset($meta[$key][0])) {
270
- $img = wp_get_attachment_image($meta[$key][0], $image_key);
271
- if (!empty($img)) return $img;
 
 
 
 
 
272
  }
273
-
274
- return get_the_post_thumbnail_url($post_id, $image_key);
275
  }
276
 
277
  /**
256
  return $variants;
257
  }
258
 
259
+ public function getProductImage($post)
 
 
 
 
260
  {
261
+ $meta = get_post_meta($post->ID);
262
  $key = '_thumbnail_id';
263
  $image_key = $this->getProductImageKey();
 
264
  if ($meta && is_array($meta) && array_key_exists($key, $meta) && isset($meta[$key][0])) {
265
+ $img = wp_get_attachment_image_src($meta[$key][0], $image_key);
266
+ if (!empty($img[0])) {
267
+ if (substr($img[0], 0, 4) !== 'http') {
268
+ return rtrim(get_option('siteurl'), '/').'/'.ltrim($img[0], '/');
269
+ }
270
+ return $img[0];
271
+ }
272
  }
273
+ return get_the_post_thumbnail_url($post->ID, $image_key);
 
274
  }
275
 
276
  /**
includes/processes/class-mailchimp-woocommerce-single-order.php CHANGED
@@ -142,8 +142,10 @@ class MailChimp_WooCommerce_Single_Order extends Mailchimp_Woocommerce_Job
142
  }
143
  }
144
 
145
- // delete the AC cart record.
146
- $deleted_abandoned_cart = !empty($this->cart_session_id) && $api->deleteCartByID($store_id, $this->cart_session_id);
 
 
147
 
148
  // skip amazon orders and skip privacy protected orders.
149
  if ($order->isFlaggedAsAmazonOrder()) {
142
  }
143
  }
144
 
145
+ if ($order->getOriginalWooStatus() !== 'pending') {
146
+ // delete the AC cart record.
147
+ $deleted_abandoned_cart = !empty($this->cart_session_id) && $api->deleteCartByID($store_id, $this->cart_session_id);
148
+ }
149
 
150
  // skip amazon orders and skip privacy protected orders.
151
  if ($order->isFlaggedAsAmazonOrder()) {
includes/vendor/action-scheduler/.travis.yml CHANGED
@@ -9,29 +9,37 @@ dist: precise
9
  # Versions of PHP to test against
10
  php:
11
  - "5.3"
12
- - "5.4"
13
- - "5.5"
14
  - "5.6"
15
  - "7.0"
16
  - "7.1"
 
 
17
 
18
  # Specify versions of WordPress to test against
19
  # WP_VERSION = WordPress version number (use "master" for SVN trunk)
20
  # WP_MULTISITE = whether to test multisite (use either "0" or "1")
21
  env:
22
- - WP_VERSION=4.8 WP_MULTISITE=0
23
- - WP_VERSION=4.7 WP_MULTISITE=0
24
- - WP_VERSION=4.6 WP_MULTISITE=0
25
- - WP_VERSION=4.8 WP_MULTISITE=1
26
- - WP_VERSION=4.7 WP_MULTISITE=1
27
- - WP_VERSION=4.6 WP_MULTISITE=1
 
 
 
 
 
 
 
 
28
 
29
  # Grab the setup script and execute
30
  before_script:
31
  - source tests/travis/setup.sh $TRAVIS_PHP_VERSION
32
 
33
  script:
34
- - if [[ "$TRAVIS_PHP_VERSION" == "7.1" ]] && [[ "$WP_VERSION" == "4.8" ]] && [[ "$WP_MULTISITE" == "0" ]] && [[ "$TRAVIS_BRANCH" == "master" ]]; then phpunit --configuration tests/phpunit.xml.dist --coverage-clover clover.xml; else phpunit --configuration tests/phpunit.xml.dist; fi
35
 
36
  after_script:
37
  - bash <(curl -s https://codecov.io/bash)
9
  # Versions of PHP to test against
10
  php:
11
  - "5.3"
 
 
12
  - "5.6"
13
  - "7.0"
14
  - "7.1"
15
+ - "7.2"
16
+ - "7.3"
17
 
18
  # Specify versions of WordPress to test against
19
  # WP_VERSION = WordPress version number (use "master" for SVN trunk)
20
  # WP_MULTISITE = whether to test multisite (use either "0" or "1")
21
  env:
22
+ - WP_VERSION=5.3 WP_MULTISITE=0
23
+ - WP_VERSION=5.2 WP_MULTISITE=0
24
+ - WP_VERSION=5.1 WP_MULTISITE=0
25
+ - WP_VERSION=5.3 WP_MULTISITE=1
26
+ - WP_VERSION=5.2 WP_MULTISITE=1
27
+ - WP_VERSION=5.1 WP_MULTISITE=1
28
+
29
+ # WordPress 5.3 requires PHP 5.6. Exclude WP 5.3 + PHP 5.3
30
+ jobs:
31
+ exclude:
32
+ - php: "5.3"
33
+ env: WP_VERSION=5.3 WP_MULTISITE=0
34
+ - php: "5.3"
35
+ env: WP_VERSION=5.3 WP_MULTISITE=1
36
 
37
  # Grab the setup script and execute
38
  before_script:
39
  - source tests/travis/setup.sh $TRAVIS_PHP_VERSION
40
 
41
  script:
42
+ - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]] && [[ "$WP_VERSION" == "5.3" ]] && [[ "$WP_MULTISITE" == "0" ]] && [[ "$TRAVIS_BRANCH" == "master" ]]; then phpunit --configuration tests/phpunit.xml.dist --coverage-clover clover.xml; else phpunit --configuration tests/phpunit.xml.dist; fi
43
 
44
  after_script:
45
  - bash <(curl -s https://codecov.io/bash)
includes/vendor/action-scheduler/action-scheduler.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: A robust scheduling library for use in WordPress plugins.
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/
8
- * Version: 3.0.1
9
  * License: GPLv3
10
  *
11
  * Copyright 2019 Automattic, Inc. (https://automattic.com/contact/)
@@ -25,28 +25,35 @@
25
  *
26
  */
27
 
28
- if ( ! function_exists( 'action_scheduler_register_3_dot_0_dot_1' ) ) {
29
 
30
  if ( ! class_exists( 'ActionScheduler_Versions' ) ) {
31
  require_once( 'classes/ActionScheduler_Versions.php' );
32
  add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
33
  }
34
 
35
- add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_0_dot_1', 0, 0 );
36
 
37
- function action_scheduler_register_3_dot_0_dot_1() {
38
  $versions = ActionScheduler_Versions::instance();
39
- $versions->register( '3.0.1', 'action_scheduler_initialize_3_dot_0_dot_1' );
40
  }
41
 
42
- function action_scheduler_initialize_3_dot_0_dot_1() {
43
- require_once( 'classes/abstracts/ActionScheduler.php' );
 
 
 
 
 
 
 
44
  ActionScheduler::init( __FILE__ );
45
  }
46
 
47
  // Support usage in themes - load this version if no plugin has loaded a version yet.
48
  if ( did_action( 'plugins_loaded' ) && ! class_exists( 'ActionScheduler' ) ) {
49
- action_scheduler_register_3_dot_0_dot_1();
50
  do_action( 'action_scheduler_pre_theme_init' );
51
  ActionScheduler_Versions::initialize_latest_version();
52
  }
5
  * Description: A robust scheduling library for use in WordPress plugins.
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/
8
+ * Version: 3.1.0
9
  * License: GPLv3
10
  *
11
  * Copyright 2019 Automattic, Inc. (https://automattic.com/contact/)
25
  *
26
  */
27
 
28
+ if ( ! function_exists( 'action_scheduler_register_3_dot_1_dot_0' ) ) {
29
 
30
  if ( ! class_exists( 'ActionScheduler_Versions' ) ) {
31
  require_once( 'classes/ActionScheduler_Versions.php' );
32
  add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
33
  }
34
 
35
+ add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_1_dot_0', 0, 0 );
36
 
37
+ function action_scheduler_register_3_dot_1_dot_0() {
38
  $versions = ActionScheduler_Versions::instance();
39
+ $versions->register( '3.1.0', 'action_scheduler_initialize_3_dot_1_dot_0' );
40
  }
41
 
42
+ function action_scheduler_initialize_3_dot_1_dot_0() {
43
+ $autoloader = __DIR__ . '/vendor/autoload.php';
44
+ if ( is_readable( $autoloader ) ) {
45
+ require_once( $autoloader );
46
+ define( 'AS_COMPOSER_AUTOLOADING', true );
47
+ } else {
48
+ define( 'AS_COMPOSER_AUTOLOADING', false );
49
+ require_once( 'classes/abstracts/ActionScheduler.php' );
50
+ }
51
  ActionScheduler::init( __FILE__ );
52
  }
53
 
54
  // Support usage in themes - load this version if no plugin has loaded a version yet.
55
  if ( did_action( 'plugins_loaded' ) && ! class_exists( 'ActionScheduler' ) ) {
56
+ action_scheduler_register_3_dot_1_dot_0();
57
  do_action( 'action_scheduler_pre_theme_init' );
58
  ActionScheduler_Versions::initialize_latest_version();
59
  }
includes/vendor/action-scheduler/classes/ActionScheduler_AdminView.php CHANGED
@@ -104,12 +104,13 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
104
  return;
105
  }
106
 
 
107
  $screen->add_help_tab(
108
  array(
109
  'id' => 'action_scheduler_about',
110
  'title' => __( 'About', 'action-scheduler' ),
111
  'content' =>
112
- '<h2>' . __( 'About Action Scheduler', 'action-scheduler' ) . '</h2>' .
113
  '<p>' .
114
  __( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'action-scheduler' ) .
115
  '</p>',
104
  return;
105
  }
106
 
107
+ $as_version = ActionScheduler_Versions::instance()->latest_version();
108
  $screen->add_help_tab(
109
  array(
110
  'id' => 'action_scheduler_about',
111
  'title' => __( 'About', 'action-scheduler' ),
112
  'content' =>
113
+ '<h2>' . sprintf( __( 'About Action Scheduler %s', 'action-scheduler' ), $as_version ) . '</h2>' .
114
  '<p>' .
115
  __( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'action-scheduler' ) .
116
  '</p>',
includes/vendor/action-scheduler/classes/ActionScheduler_AsyncRequest_QueueRunner.php CHANGED
@@ -69,6 +69,7 @@ class ActionScheduler_AsyncRequest_QueueRunner extends WP_Async_Request {
69
  }
70
 
71
  $this->dispatch();
 
72
  }
73
 
74
  /**
@@ -91,6 +92,6 @@ class ActionScheduler_AsyncRequest_QueueRunner extends WP_Async_Request {
91
  * Chaining async requests can crash MySQL. A brief sleep call in PHP prevents that.
92
  */
93
  protected function get_sleep_seconds() {
94
- return apply_filters( 'action_scheduler_async_request_sleep_seconds', 1, $this );
95
  }
96
  }
69
  }
70
 
71
  $this->dispatch();
72
+ ActionScheduler_QueueRunner::instance()->unhook_dispatch_async_request();
73
  }
74
 
75
  /**
92
  * Chaining async requests can crash MySQL. A brief sleep call in PHP prevents that.
93
  */
94
  protected function get_sleep_seconds() {
95
+ return apply_filters( 'action_scheduler_async_request_sleep_seconds', 5, $this );
96
  }
97
  }
includes/vendor/action-scheduler/classes/ActionScheduler_ListTable.php CHANGED
@@ -252,7 +252,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
252
  */
253
  public function column_args( array $row ) {
254
  if ( empty( $row['args'] ) ) {
255
- return '';
256
  }
257
 
258
  $row_html = '<ul>';
@@ -319,17 +319,22 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
319
  *
320
  * Notifications:
321
  * 1. When the maximum number of tasks are being executed simultaneously
322
- * 2. Notifications when a task us manually executed
323
  */
324
  public function display_admin_notices() {
325
-
326
  if ( $this->runner->has_maximum_concurrent_batches() ) {
 
327
  $this->admin_notices[] = array(
328
  'class' => 'updated',
329
  'message' => sprintf(
330
  /* translators: %s: amount of claims */
331
- __( 'Maximum simultaneous queues already in progress (%s queues). No additional queues will begin processing until the current queues are complete.', 'action-scheduler' ),
332
- $this->store->get_claim_count()
 
 
 
 
 
333
  ),
334
  );
335
  } elseif ( $this->store->has_pending_actions_due() ) {
252
  */
253
  public function column_args( array $row ) {
254
  if ( empty( $row['args'] ) ) {
255
+ return apply_filters( 'action_scheduler_list_table_column_args', '', $row );
256
  }
257
 
258
  $row_html = '<ul>';
319
  *
320
  * Notifications:
321
  * 1. When the maximum number of tasks are being executed simultaneously
322
+ * 2. Notifications when a task is manually executed
323
  */
324
  public function display_admin_notices() {
 
325
  if ( $this->runner->has_maximum_concurrent_batches() ) {
326
+ $claim_count = $this->store->get_claim_count();
327
  $this->admin_notices[] = array(
328
  'class' => 'updated',
329
  'message' => sprintf(
330
  /* translators: %s: amount of claims */
331
+ _n(
332
+ 'Maximum simultaneous queues already in progress (%s queue). No additional queues will begin processing until the current queues are complete.',
333
+ 'Maximum simultaneous queues already in progress (%s queues). No additional queues will begin processing until the current queues are complete.',
334
+ $claim_count,
335
+ 'action-scheduler'
336
+ ),
337
+ $claim_count
338
  ),
339
  );
340
  } elseif ( $this->store->has_pending_actions_due() ) {
includes/vendor/action-scheduler/classes/ActionScheduler_QueueRunner.php CHANGED
@@ -65,8 +65,21 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
65
  }
66
 
67
  add_action( self::WP_CRON_HOOK, array( self::instance(), 'run' ) );
 
 
68
 
69
- add_filter( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) );
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
 
72
  /**
65
  }
66
 
67
  add_action( self::WP_CRON_HOOK, array( self::instance(), 'run' ) );
68
+ $this->hook_dispatch_async_request();
69
+ }
70
 
71
+ /**
72
+ * Hook check for dispatching an async request.
73
+ */
74
+ public function hook_dispatch_async_request() {
75
+ add_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) );
76
+ }
77
+
78
+ /**
79
+ * Unhook check for dispatching an async request.
80
+ */
81
+ public function unhook_dispatch_async_request() {
82
+ remove_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) );
83
  }
84
 
85
  /**
includes/vendor/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php CHANGED
@@ -46,8 +46,8 @@ class ActionScheduler_WPCommentCleaner {
46
  add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 );
47
 
48
  // Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
49
- add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'print_admin_notice' ) );
50
- add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'print_admin_notice' ) );
51
  }
52
 
53
  /**
@@ -84,6 +84,13 @@ class ActionScheduler_WPCommentCleaner {
84
  delete_option( self::$has_logs_option_key );
85
  }
86
 
 
 
 
 
 
 
 
87
  /**
88
  * Prints details about the orphaned action logs and includes information on where to learn more.
89
  */
46
  add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 );
47
 
48
  // Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
49
+ add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) );
50
+ add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) );
51
  }
52
 
53
  /**
84
  delete_option( self::$has_logs_option_key );
85
  }
86
 
87
+ /**
88
+ * Registers admin notices about the orphaned action logs.
89
+ */
90
+ public static function register_admin_notice() {
91
+ add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
92
+ }
93
+
94
  /**
95
  * Prints details about the orphaned action logs and includes information on where to learn more.
96
  */
includes/vendor/action-scheduler/classes/ActionScheduler_wcSystemStatus.php CHANGED
@@ -92,6 +92,8 @@ class ActionScheduler_wcSystemStatus {
92
  * @param array $oldest_and_newest Date of the oldest and newest action with each status.
93
  */
94
  protected function get_template( $status_labels, $action_counts, $oldest_and_newest ) {
 
 
95
  ?>
96
 
97
  <table class="wc_status_table widefat" cellspacing="0">
@@ -99,6 +101,14 @@ class ActionScheduler_wcSystemStatus {
99
  <tr>
100
  <th colspan="5" data-export-label="Action Scheduler"><h2><?php esc_html_e( 'Action Scheduler', 'action-scheduler' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows scheduled action counts.', 'action-scheduler' ) ); ?></h2></th>
101
  </tr>
 
 
 
 
 
 
 
 
102
  <tr>
103
  <td><strong><?php esc_html_e( 'Action Status', 'action-scheduler' ); ?></strong></td>
104
  <td class="help">&nbsp;</td>
92
  * @param array $oldest_and_newest Date of the oldest and newest action with each status.
93
  */
94
  protected function get_template( $status_labels, $action_counts, $oldest_and_newest ) {
95
+ $as_version = ActionScheduler_Versions::instance()->latest_version();
96
+ $autoloader = AS_COMPOSER_AUTOLOADING ? __( 'Composer', 'action-scheduler' ) : __( 'Internal', 'action-scheduler' );
97
  ?>
98
 
99
  <table class="wc_status_table widefat" cellspacing="0">
101
  <tr>
102
  <th colspan="5" data-export-label="Action Scheduler"><h2><?php esc_html_e( 'Action Scheduler', 'action-scheduler' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows scheduled action counts.', 'action-scheduler' ) ); ?></h2></th>
103
  </tr>
104
+ <tr>
105
+ <td colspan="2" data-export-label="Version"><?php esc_html_e( 'Version:', 'action-scheduler' ); ?></td>
106
+ <td colspan="3"><?php echo esc_html( $as_version ); ?></td>
107
+ </tr>
108
+ <tr>
109
+ <td colspan="2" data-export-label="Version"><?php esc_html_e( 'Autoloader:', 'action-scheduler' ); ?></td>
110
+ <td colspan="3"><?php echo esc_html( $autoloader ); ?></td>
111
+ </tr>
112
  <tr>
113
  <td><strong><?php esc_html_e( 'Action Status', 'action-scheduler' ); ?></strong></td>
114
  <td class="help">&nbsp;</td>
includes/vendor/action-scheduler/classes/abstracts/ActionScheduler.php CHANGED
@@ -130,7 +130,9 @@ abstract class ActionScheduler {
130
  */
131
  public static function init( $plugin_file ) {
132
  self::$plugin_file = $plugin_file;
133
- spl_autoload_register( array( __CLASS__, 'autoload' ) );
 
 
134
 
135
  /**
136
  * Fires in the early stages of Action Scheduler init hook.
@@ -152,6 +154,14 @@ abstract class ActionScheduler {
152
  $admin_view = self::admin_view();
153
  add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()
154
 
 
 
 
 
 
 
 
 
155
  if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
156
  require_once( self::plugin_path('deprecated/functions.php') );
157
  }
130
  */
131
  public static function init( $plugin_file ) {
132
  self::$plugin_file = $plugin_file;
133
+ if ( ! AS_COMPOSER_AUTOLOADING ) {
134
+ spl_autoload_register( array( __CLASS__, 'autoload' ) );
135
+ }
136
 
137
  /**
138
  * Fires in the early stages of Action Scheduler init hook.
154
  $admin_view = self::admin_view();
155
  add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()
156
 
157
+ // Ensure initialization on plugin activation.
158
+ if ( did_action( 'init' ) ) {
159
+ $store->init();
160
+ $logger->init();
161
+ $runner->init();
162
+ $admin_view->init();
163
+ }
164
+
165
  if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
166
  require_once( self::plugin_path('deprecated/functions.php') );
167
  }
includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php CHANGED
@@ -606,6 +606,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
606
  }
607
 
608
  $status_filter_url = ( 'all' === $status_name ) ? remove_query_arg( 'status' ) : add_query_arg( 'status', $status_name );
 
609
  $status_list_items[] = sprintf( $status_list_item, esc_attr( $status_name ), esc_url( $status_filter_url ), esc_html( ucfirst( $status_name ) ), absint( $count ) );
610
  }
611
 
606
  }
607
 
608
  $status_filter_url = ( 'all' === $status_name ) ? remove_query_arg( 'status' ) : add_query_arg( 'status', $status_name );
609
+ $status_filter_url = remove_query_arg( array( 'paged', 's' ), $status_filter_url );
610
  $status_list_items[] = sprintf( $status_list_item, esc_attr( $status_name ), esc_url( $status_filter_url ), esc_html( ucfirst( $status_name ) ), absint( $count ) );
611
  }
612
 
includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php CHANGED
@@ -49,6 +49,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
49
  */
50
  public function process_action( $action_id, $context = '' ) {
51
  try {
 
52
  do_action( 'action_scheduler_before_execute', $action_id, $context );
53
 
54
  if ( ActionScheduler_Store::STATUS_PENDING !== $this->store->get_status( $action_id ) ) {
@@ -56,14 +57,21 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
56
  return;
57
  }
58
 
 
 
 
59
  $action = $this->store->fetch_action( $action_id );
60
  $this->store->log_execution( $action_id );
61
  $action->execute();
62
  do_action( 'action_scheduler_after_execute', $action_id, $action, $context );
63
  $this->store->mark_complete( $action_id );
64
  } catch ( Exception $e ) {
65
- $this->store->mark_failure( $action_id );
66
- do_action( 'action_scheduler_failed_execution', $action_id, $e, $context );
 
 
 
 
67
  }
68
 
69
  if ( isset( $action ) && is_a( $action, 'ActionScheduler_Action' ) && $action->get_schedule()->is_recurring() ) {
49
  */
50
  public function process_action( $action_id, $context = '' ) {
51
  try {
52
+ $valid_action = false;
53
  do_action( 'action_scheduler_before_execute', $action_id, $context );
54
 
55
  if ( ActionScheduler_Store::STATUS_PENDING !== $this->store->get_status( $action_id ) ) {
57
  return;
58
  }
59
 
60
+ $valid_action = true;
61
+ do_action( 'action_scheduler_begin_execute', $action_id, $context );
62
+
63
  $action = $this->store->fetch_action( $action_id );
64
  $this->store->log_execution( $action_id );
65
  $action->execute();
66
  do_action( 'action_scheduler_after_execute', $action_id, $action, $context );
67
  $this->store->mark_complete( $action_id );
68
  } catch ( Exception $e ) {
69
+ if ( $valid_action ) {
70
+ $this->store->mark_failure( $action_id );
71
+ do_action( 'action_scheduler_failed_execution', $action_id, $e, $context );
72
+ } else {
73
+ do_action( 'action_scheduler_failed_validation', $action_id, $e, $context );
74
+ }
75
  }
76
 
77
  if ( isset( $action ) && is_a( $action, 'ActionScheduler_Action' ) && $action->get_schedule()->is_recurring() ) {
includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Logger.php CHANGED
@@ -48,7 +48,7 @@ abstract class ActionScheduler_Logger {
48
  public function init() {
49
  $this->hook_stored_action();
50
  add_action( 'action_scheduler_canceled_action', array( $this, 'log_canceled_action' ), 10, 1 );
51
- add_action( 'action_scheduler_before_execute', array( $this, 'log_started_action' ), 10, 2 );
52
  add_action( 'action_scheduler_after_execute', array( $this, 'log_completed_action' ), 10, 3 );
53
  add_action( 'action_scheduler_failed_execution', array( $this, 'log_failed_action' ), 10, 3 );
54
  add_action( 'action_scheduler_failed_action', array( $this, 'log_timed_out_action' ), 10, 2 );
48
  public function init() {
49
  $this->hook_stored_action();
50
  add_action( 'action_scheduler_canceled_action', array( $this, 'log_canceled_action' ), 10, 1 );
51
+ add_action( 'action_scheduler_begin_execute', array( $this, 'log_started_action' ), 10, 2 );
52
  add_action( 'action_scheduler_after_execute', array( $this, 'log_completed_action' ), 10, 3 );
53
  add_action( 'action_scheduler_failed_execution', array( $this, 'log_failed_action' ), 10, 3 );
54
  add_action( 'action_scheduler_failed_action', array( $this, 'log_timed_out_action' ), 10, 2 );
includes/vendor/action-scheduler/classes/abstracts/ActionScheduler_Store.php CHANGED
@@ -16,7 +16,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
16
  private static $store = NULL;
17
 
18
  /** @var int */
19
- private static $max_index_length = 191;
20
 
21
  /**
22
  * @param ActionScheduler_Action $action
@@ -217,14 +217,14 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
217
  * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
218
  *
219
  * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
220
- * as we prepare to move to custom tables, and can use an indexed VARCHAR column instead, we want to warn
221
- * developers of this impending requirement.
222
  *
223
- * @param ActionScheduler_Action $action
 
224
  */
225
  protected function validate_action( ActionScheduler_Action $action ) {
226
- if ( strlen( json_encode( $action->get_args() ) ) > self::$max_index_length ) {
227
- throw new InvalidArgumentException( __( 'ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than 191 characters when encoded as JSON.', 'action-scheduler' ) );
228
  }
229
  }
230
 
16
  private static $store = NULL;
17
 
18
  /** @var int */
19
+ protected static $max_args_length = 191;
20
 
21
  /**
22
  * @param ActionScheduler_Action $action
217
  * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
218
  *
219
  * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
220
+ * with custom tables, we use an indexed VARCHAR column instead.
 
221
  *
222
+ * @param ActionScheduler_Action $action Action to be validated.
223
+ * @throws InvalidArgumentException When json encoded args is too long.
224
  */
225
  protected function validate_action( ActionScheduler_Action $action ) {
226
+ if ( strlen( json_encode( $action->get_args() ) ) > static::$max_args_length ) {
227
+ throw new InvalidArgumentException( sprintf( __( 'ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than %d characters when encoded as JSON.', 'action-scheduler' ), static::$max_args_length ) );
228
  }
229
  }
230
 
includes/vendor/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php CHANGED
@@ -9,6 +9,12 @@
9
  */
10
  class ActionScheduler_DBStore extends ActionScheduler_Store {
11
 
 
 
 
 
 
 
12
  /**
13
  * Initialize the data store
14
  *
@@ -39,10 +45,17 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
39
  'status' => ( $action->is_finished() ? self::STATUS_COMPLETE : self::STATUS_PENDING ),
40
  'scheduled_date_gmt' => $this->get_scheduled_date_string( $action, $date ),
41
  'scheduled_date_local' => $this->get_scheduled_date_string_local( $action, $date ),
42
- 'args' => json_encode( $action->get_args() ),
43
  'schedule' => serialize( $action->get_schedule() ),
44
  'group_id' => $this->get_group_id( $action->get_group() ),
45
  ];
 
 
 
 
 
 
 
 
46
  $wpdb->insert( $wpdb->actionscheduler_actions, $data );
47
  $action_id = $wpdb->insert_id;
48
 
@@ -62,6 +75,29 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
62
  }
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  /**
66
  * Get a group's ID based on its name/slug.
67
  *
@@ -118,6 +154,11 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
118
  return $this->get_null_action();
119
  }
120
 
 
 
 
 
 
121
  try {
122
  $action = $this->make_action_from_db_record( $data );
123
  } catch ( ActionScheduler_InvalidActionException $exception ) {
@@ -188,7 +229,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
188
  $args[] = $hook;
189
  if ( ! is_null( $params[ 'args' ] ) ) {
190
  $query .= " AND a.args=%s";
191
- $args[] = json_encode( $params[ 'args' ] );
192
  }
193
 
194
  $order = 'ASC';
@@ -265,7 +306,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
265
  }
266
  if ( ! is_null( $query[ 'args' ] ) ) {
267
  $sql .= " AND a.args=%s";
268
- $sql_params[] = json_encode( $query[ 'args' ] );
269
  }
270
 
271
  if ( $query[ 'status' ] ) {
@@ -301,8 +342,8 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
301
  }
302
 
303
  if ( ! empty( $query['search'] ) ) {
304
- $sql .= " AND (a.hook LIKE %s OR a.args LIKE %s";
305
- for( $i = 0; $i < 2; $i++ ) {
306
  $sql_params[] = sprintf( '%%%s%%', $query['search'] );
307
  }
308
 
9
  */
10
  class ActionScheduler_DBStore extends ActionScheduler_Store {
11
 
12
+ /** @var int */
13
+ protected static $max_args_length = 8000;
14
+
15
+ /** @var int */
16
+ protected static $max_index_length = 191;
17
+
18
  /**
19
  * Initialize the data store
20
  *
45
  'status' => ( $action->is_finished() ? self::STATUS_COMPLETE : self::STATUS_PENDING ),
46
  'scheduled_date_gmt' => $this->get_scheduled_date_string( $action, $date ),
47
  'scheduled_date_local' => $this->get_scheduled_date_string_local( $action, $date ),
 
48
  'schedule' => serialize( $action->get_schedule() ),
49
  'group_id' => $this->get_group_id( $action->get_group() ),
50
  ];
51
+ $args = wp_json_encode( $action->get_args() );
52
+ if ( strlen( $args ) <= static::$max_index_length ) {
53
+ $data['args'] = $args;
54
+ } else {
55
+ $data['args'] = $this->hash_args( $args );
56
+ $data['extended_args'] = $args;
57
+ }
58
+
59
  $wpdb->insert( $wpdb->actionscheduler_actions, $data );
60
  $action_id = $wpdb->insert_id;
61
 
75
  }
76
  }
77
 
78
+ /**
79
+ * Generate a hash from json_encoded $args using MD5 as this isn't for security.
80
+ *
81
+ * @param string $args JSON encoded action args.
82
+ * @return string
83
+ */
84
+ protected function hash_args( $args ) {
85
+ return md5( $args );
86
+ }
87
+
88
+ /**
89
+ * Get action args query param value from action args.
90
+ *
91
+ * @param array $args Action args.
92
+ * @return string
93
+ */
94
+ protected function get_args_for_query( $args ) {
95
+ $encoded = wp_json_encode( $args );
96
+ if ( strlen( $encoded ) <= static::$max_index_length ) {
97
+ return $encoded;
98
+ }
99
+ return $this->hash_args( $encoded );
100
+ }
101
  /**
102
  * Get a group's ID based on its name/slug.
103
  *
154
  return $this->get_null_action();
155
  }
156
 
157
+ if ( ! empty( $data->extended_args ) ) {
158
+ $data->args = $data->extended_args;
159
+ unset( $data->extended_args );
160
+ }
161
+
162
  try {
163
  $action = $this->make_action_from_db_record( $data );
164
  } catch ( ActionScheduler_InvalidActionException $exception ) {
229
  $args[] = $hook;
230
  if ( ! is_null( $params[ 'args' ] ) ) {
231
  $query .= " AND a.args=%s";
232
+ $args[] = $this->get_args_for_query( $params[ 'args' ] );
233
  }
234
 
235
  $order = 'ASC';
306
  }
307
  if ( ! is_null( $query[ 'args' ] ) ) {
308
  $sql .= " AND a.args=%s";
309
+ $sql_params[] = $this->get_args_for_query( $query[ 'args' ] );
310
  }
311
 
312
  if ( $query[ 'status' ] ) {
342
  }
343
 
344
  if ( ! empty( $query['search'] ) ) {
345
+ $sql .= " AND (a.hook LIKE %s OR (a.extended_args IS NULL AND a.args LIKE %s) OR a.extended_args LIKE %s";
346
+ for( $i = 0; $i < 3; $i++ ) {
347
  $sql_params[] = sprintf( '%%%s%%', $query['search'] );
348
  }
349
 
includes/vendor/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php CHANGED
@@ -22,7 +22,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
22
  do_action( 'action_scheduler_stored_action', $post_id );
23
  return $post_id;
24
  } catch ( Exception $e ) {
25
- throw new RuntimeException( sprintf( __('Error saving action: %s', 'action-scheduler'), $e->getMessage() ), 0 );
26
  }
27
  }
28
 
@@ -59,7 +59,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
59
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
60
 
61
  if ( is_wp_error($post_id) || empty($post_id) ) {
62
- throw new RuntimeException(__('Unable to save action.', 'action-scheduler'));
63
  }
64
  return $post_id;
65
  }
@@ -280,7 +280,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
280
  protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
281
 
282
  if ( ! in_array( $select_or_count, array( 'select', 'count' ) ) ) {
283
- throw new InvalidArgumentException(__('Invalid schedule. Cannot save action.', 'action-scheduler'));
284
  }
285
 
286
  $query = wp_parse_args( $query, array(
@@ -452,20 +452,20 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
452
  * @throws InvalidArgumentException
453
  */
454
  public function cancel_action( $action_id ) {
455
- $post = get_post($action_id);
456
- if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
457
- throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
458
  }
459
  do_action( 'action_scheduler_canceled_action', $action_id );
460
  add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
461
- wp_trash_post($action_id);
462
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
463
  }
464
 
465
  public function delete_action( $action_id ) {
466
- $post = get_post($action_id);
467
- if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
468
- throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
469
  }
470
  do_action( 'action_scheduler_deleted_action', $action_id );
471
 
@@ -490,14 +490,14 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
490
  * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
491
  */
492
  public function get_date_gmt( $action_id ) {
493
- $post = get_post($action_id);
494
- if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
495
- throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
496
  }
497
  if ( $post->post_status == 'publish' ) {
498
- return as_get_datetime_object($post->post_modified_gmt);
499
  } else {
500
- return as_get_datetime_object($post->post_date_gmt);
501
  }
502
  }
503
 
@@ -675,18 +675,18 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
675
 
676
  public function release_claim( ActionScheduler_ActionClaim $claim ) {
677
  $action_ids = $this->find_actions_by_claim_id( $claim->get_id() );
678
- if ( empty($action_ids) ) {
679
  return; // nothing to do
680
  }
681
- $action_id_string = implode(',', array_map('intval', $action_ids));
682
  /** @var wpdb $wpdb */
683
  global $wpdb;
684
  $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s";
685
  $sql = $wpdb->prepare( $sql, array( $claim->get_id() ) );
686
- $result = $wpdb->query($sql);
687
  if ( $result === false ) {
688
  /* translators: %s: claim ID */
689
- throw new RuntimeException( sprintf( __('Unable to unlock claim %s. Database error.', 'action-scheduler'), $claim->get_id() ) );
690
  }
691
  }
692
 
@@ -698,10 +698,10 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
698
  global $wpdb;
699
  $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s";
700
  $sql = $wpdb->prepare( $sql, $action_id, self::POST_TYPE );
701
- $result = $wpdb->query($sql);
702
  if ( $result === false ) {
703
  /* translators: %s: action ID */
704
- throw new RuntimeException( sprintf( __('Unable to unlock claim on action %s. Database error.', 'action-scheduler'), $action_id ) );
705
  }
706
  }
707
 
@@ -710,10 +710,10 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
710
  global $wpdb;
711
  $sql = "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s";
712
  $sql = $wpdb->prepare( $sql, self::STATUS_FAILED, $action_id, self::POST_TYPE );
713
- $result = $wpdb->query($sql);
714
  if ( $result === false ) {
715
  /* translators: %s: action ID */
716
- throw new RuntimeException( sprintf( __('Unable to mark failure on action %s. Database error.', 'action-scheduler'), $action_id ) );
717
  }
718
  }
719
 
@@ -768,9 +768,9 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
768
  * @throws InvalidArgumentException|RuntimeException
769
  */
770
  public function mark_complete( $action_id ) {
771
- $post = get_post($action_id);
772
- if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
773
- throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
774
  }
775
  add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
776
  add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
@@ -780,8 +780,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
780
  ), TRUE);
781
  remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
782
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
783
- if ( is_wp_error($result) ) {
784
- throw new RuntimeException($result->get_error_message());
785
  }
786
  }
787
 
@@ -809,9 +809,11 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
809
 
810
  $dependencies_met = get_transient( self::DEPENDENCIES_MET );
811
  if ( empty( $dependencies_met ) ) {
812
- $found_action = $wpdb->get_var(
 
813
  $wpdb->prepare(
814
- "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND CHAR_LENGTH(post_content) > 191 LIMIT 1",
 
815
  self::POST_TYPE
816
  )
817
  );
22
  do_action( 'action_scheduler_stored_action', $post_id );
23
  return $post_id;
24
  } catch ( Exception $e ) {
25
+ throw new RuntimeException( sprintf( __( 'Error saving action: %s', 'action-scheduler' ), $e->getMessage() ), 0 );
26
  }
27
  }
28
 
59
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
60
 
61
  if ( is_wp_error($post_id) || empty($post_id) ) {
62
+ throw new RuntimeException( __( 'Unable to save action.', 'action-scheduler' ) );
63
  }
64
  return $post_id;
65
  }
280
  protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
281
 
282
  if ( ! in_array( $select_or_count, array( 'select', 'count' ) ) ) {
283
+ throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
284
  }
285
 
286
  $query = wp_parse_args( $query, array(
452
  * @throws InvalidArgumentException
453
  */
454
  public function cancel_action( $action_id ) {
455
+ $post = get_post( $action_id );
456
+ if ( empty( $post ) || ( $post->post_type != self::POST_TYPE ) ) {
457
+ throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
458
  }
459
  do_action( 'action_scheduler_canceled_action', $action_id );
460
  add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
461
+ wp_trash_post( $action_id );
462
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
463
  }
464
 
465
  public function delete_action( $action_id ) {
466
+ $post = get_post( $action_id );
467
+ if ( empty( $post ) || ( $post->post_type != self::POST_TYPE ) ) {
468
+ throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
469
  }
470
  do_action( 'action_scheduler_deleted_action', $action_id );
471
 
490
  * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
491
  */
492
  public function get_date_gmt( $action_id ) {
493
+ $post = get_post( $action_id );
494
+ if ( empty( $post ) || ( $post->post_type != self::POST_TYPE ) ) {
495
+ throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
496
  }
497
  if ( $post->post_status == 'publish' ) {
498
+ return as_get_datetime_object( $post->post_modified_gmt );
499
  } else {
500
+ return as_get_datetime_object( $post->post_date_gmt );
501
  }
502
  }
503
 
675
 
676
  public function release_claim( ActionScheduler_ActionClaim $claim ) {
677
  $action_ids = $this->find_actions_by_claim_id( $claim->get_id() );
678
+ if ( empty( $action_ids ) ) {
679
  return; // nothing to do
680
  }
681
+ $action_id_string = implode( ',', array_map( 'intval', $action_ids ) );
682
  /** @var wpdb $wpdb */
683
  global $wpdb;
684
  $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s";
685
  $sql = $wpdb->prepare( $sql, array( $claim->get_id() ) );
686
+ $result = $wpdb->query( $sql );
687
  if ( $result === false ) {
688
  /* translators: %s: claim ID */
689
+ throw new RuntimeException( sprintf( __( 'Unable to unlock claim %s. Database error.', 'action-scheduler' ), $claim->get_id() ) );
690
  }
691
  }
692
 
698
  global $wpdb;
699
  $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s";
700
  $sql = $wpdb->prepare( $sql, $action_id, self::POST_TYPE );
701
+ $result = $wpdb->query( $sql );
702
  if ( $result === false ) {
703
  /* translators: %s: action ID */
704
+ throw new RuntimeException( sprintf( __( 'Unable to unlock claim on action %s. Database error.', 'action-scheduler' ), $action_id ) );
705
  }
706
  }
707
 
710
  global $wpdb;
711
  $sql = "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s";
712
  $sql = $wpdb->prepare( $sql, self::STATUS_FAILED, $action_id, self::POST_TYPE );
713
+ $result = $wpdb->query( $sql );
714
  if ( $result === false ) {
715
  /* translators: %s: action ID */
716
+ throw new RuntimeException( sprintf( __( 'Unable to mark failure on action %s. Database error.', 'action-scheduler' ), $action_id ) );
717
  }
718
  }
719
 
768
  * @throws InvalidArgumentException|RuntimeException
769
  */
770
  public function mark_complete( $action_id ) {
771
+ $post = get_post( $action_id );
772
+ if ( empty( $post ) || ( $post->post_type != self::POST_TYPE ) ) {
773
+ throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
774
  }
775
  add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
776
  add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
780
  ), TRUE);
781
  remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
782
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
783
+ if ( is_wp_error( $result ) ) {
784
+ throw new RuntimeException( $result->get_error_message() );
785
  }
786
  }
787
 
809
 
810
  $dependencies_met = get_transient( self::DEPENDENCIES_MET );
811
  if ( empty( $dependencies_met ) ) {
812
+ $maximum_args_length = apply_filters( 'action_scheduler_maximum_args_length', 191 );
813
+ $found_action = $wpdb->get_var(
814
  $wpdb->prepare(
815
+ "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND CHAR_LENGTH(post_content) > %d LIMIT 1",
816
+ $maximum_args_length,
817
  self::POST_TYPE
818
  )
819
  );
includes/vendor/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_TaxonomyRegistrar.php CHANGED
@@ -11,7 +11,7 @@ class ActionScheduler_wpPostStore_TaxonomyRegistrar {
11
 
12
  protected function taxonomy_args() {
13
  $args = array(
14
- 'label' => __('Action Group', 'action-scheduler'),
15
  'public' => false,
16
  'hierarchical' => false,
17
  'show_admin_column' => true,
@@ -19,7 +19,7 @@ class ActionScheduler_wpPostStore_TaxonomyRegistrar {
19
  'rewrite' => false,
20
  );
21
 
22
- $args = apply_filters('action_scheduler_taxonomy_args', $args);
23
  return $args;
24
  }
25
  }
11
 
12
  protected function taxonomy_args() {
13
  $args = array(
14
+ 'label' => __( 'Action Group', 'action-scheduler' ),
15
  'public' => false,
16
  'hierarchical' => false,
17
  'show_admin_column' => true,
19
  'rewrite' => false,
20
  );
21
 
22
+ $args = apply_filters( 'action_scheduler_taxonomy_args', $args );
23
  return $args;
24
  }
25
  }
includes/vendor/action-scheduler/classes/schema/ActionScheduler_LoggerSchema.php CHANGED
@@ -25,7 +25,6 @@ class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema {
25
  global $wpdb;
26
  $table_name = $wpdb->$table;
27
  $charset_collate = $wpdb->get_charset_collate();
28
- $max_index_length = 191; // @see wp_get_db_schema()
29
  switch ( $table ) {
30
 
31
  case self::LOG_TABLE:
25
  global $wpdb;
26
  $table_name = $wpdb->$table;
27
  $charset_collate = $wpdb->get_charset_collate();
 
28
  switch ( $table ) {
29
 
30
  case self::LOG_TABLE:
includes/vendor/action-scheduler/classes/schema/ActionScheduler_StoreSchema.php CHANGED
@@ -15,7 +15,7 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
15
  /**
16
  * @var int Increment this value to trigger a schema update.
17
  */
18
- protected $schema_version = 2;
19
 
20
  public function __construct() {
21
  $this->tables = [
@@ -47,6 +47,7 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
47
  last_attempt_gmt datetime NOT NULL default '0000-00-00 00:00:00',
48
  last_attempt_local datetime NOT NULL default '0000-00-00 00:00:00',
49
  claim_id bigint(20) unsigned NOT NULL default '0',
 
50
  PRIMARY KEY (action_id),
51
  KEY hook (hook($max_index_length)),
52
  KEY status (status),
15
  /**
16
  * @var int Increment this value to trigger a schema update.
17
  */
18
+ protected $schema_version = 3;
19
 
20
  public function __construct() {
21
  $this->tables = [
47
  last_attempt_gmt datetime NOT NULL default '0000-00-00 00:00:00',
48
  last_attempt_local datetime NOT NULL default '0000-00-00 00:00:00',
49
  claim_id bigint(20) unsigned NOT NULL default '0',
50
+ extended_args varchar(8000) DEFAULT NULL,
51
  PRIMARY KEY (action_id),
52
  KEY hook (hook($max_index_length)),
53
  KEY status (status),
includes/vendor/action-scheduler/composer.json CHANGED
@@ -32,5 +32,12 @@
32
  "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer",
33
  "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier"
34
  }
 
 
 
 
 
 
 
35
  }
36
  }
32
  "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer",
33
  "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier"
34
  }
35
+ },
36
+ "autoload": {
37
+ "classmap": [
38
+ "classes/",
39
+ "deprecated/",
40
+ "lib/"
41
+ ]
42
  }
43
  }
includes/vendor/action-scheduler/docs/_layouts/default.html CHANGED
@@ -27,7 +27,7 @@
27
  </svg>
28
  </a>
29
  <div class="container">
30
- <p><a href="/usage/">Usage</a> | <a href="/admin/">Admin</a> | <a href="/wp-cli/">WP-CLI</a> | <a href="/perf/">Background Processing at Scale</a> | <a href="/api/">API</a> | <a href="/faq/">FAQ</a>
31
  <h1><a href="/">action-scheduler</a></h1>
32
  <h2>A scalable, traceable job queue for background processing large queues of tasks in WordPress. Designed for distribution in WordPress plugins - no server access required.</h2>
33
  </div>
27
  </svg>
28
  </a>
29
  <div class="container">
30
+ <p><a href="/usage/">Usage</a> | <a href="/admin/">Admin</a> | <a href="/wp-cli/">WP-CLI</a> | <a href="/perf/">Background Processing at Scale</a> | <a href="/api/">API</a> | <a href="/faq/">FAQ</a> | <a href="/version3-0/">Version 3.0</a>
31
  <h1><a href="/">action-scheduler</a></h1>
32
  <h2>A scalable, traceable job queue for background processing large queues of tasks in WordPress. Designed for distribution in WordPress plugins - no server access required.</h2>
33
  </div>
includes/vendor/action-scheduler/docs/api.md CHANGED
@@ -20,7 +20,7 @@ Functions return similar values and accept similar arguments to their WP-Cron co
20
 
21
  ## API Function Availability
22
 
23
- As mentioned in the [Usage - Load Order](/usage/#load-order) section, Action Scheduler will initialize itself on the `'init'` hook with priority `1`. While API functions are loaded prior to this and call be called, they should not be called until after `'init'` with priority `1`, because each component, like the data store, has not yet been initialized.
24
 
25
  Do not use Action Scheduler API functions prior to `'init'` hook with priority `1`. Doing so could lead to unexpected results, like data being stored in the incorrect location.
26
 
20
 
21
  ## API Function Availability
22
 
23
+ As mentioned in the [Usage - Load Order](/usage/#load-order) section, Action Scheduler will initialize itself on the `'init'` hook with priority `1`. While API functions are loaded prior to this and can be called, they should not be called until after `'init'` with priority `1`, because each component, like the data store, has not yet been initialized.
24
 
25
  Do not use Action Scheduler API functions prior to `'init'` hook with priority `1`. Doing so could lead to unexpected results, like data being stored in the incorrect location.
26
 
includes/vendor/action-scheduler/docs/usage.md CHANGED
@@ -6,7 +6,7 @@ description: Learn how to use the Action Scheduler background processing job que
6
  Using Action Scheduler requires:
7
 
8
  1. installing the library
9
- 1. scheduling and action
10
  1. attaching a callback to that action
11
 
12
  ## Scheduling an Action
6
  Using Action Scheduler requires:
7
 
8
  1. installing the library
9
+ 1. scheduling an action
10
  1. attaching a callback to that action
11
 
12
  ## Scheduling an Action
includes/vendor/action-scheduler/docs/version3-0.md ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Version 3.0 FAQ
2
+
3
+ ### Do we need to wait for this to be bundled with WooCommerce?
4
+
5
+ No. Action Scheduler can be run as a standalone plugin. Action Scheduler 3.0 is also part of WooCommerce Subscriptions 3.0, so when updating WooCommerce Subscriptions, Action Scheduler will also be updated.
6
+
7
+ ### Can we safely switch to action scheduler version 3.0 and ditch the custom tables plugin?
8
+
9
+ Yes! The Action Scheduler Custom Tables plugin code is now part of Action Scheduler itself (with a few improvements). We recommend disabling the Custom Tables plugin immediately after activating Action Scheduler 3.0, or a plugin containing Action Scheduler 3.0, like WooCommerce Subscriptions 3.0 and newer.
10
+
11
+ ### How do we migrate from our own custom data store?
12
+
13
+ By default, Action Scheduler will only initiate a migration from the internal `WPPostStore` data store. To enable migration from any custom datastore add the following filter `add_filter( 'action_scheduler_migrate_data_store', '__return_true' );`.
14
+
15
+ ### I'm currently on PHP <5.5. When I update PHP will the migration start automatically?
16
+
17
+ Yes! The migration is initiated as soon as all dependencies are met.
18
+
19
+ ### I would like to update a plugin for testing that includes Action Scheduler 3.0 but would like to postpone the migration until that testing is complete. Is that possible?
20
+
21
+ Yes, while we recommend migrating to custom tables as soon as possible for performance reasons, you can use `add_filter( 'action_scheduler_migration_dependencies_met', '__return_false' );` to prevent the migration from initiating.
22
+
23
+ ### Is there a strong likelihood of migration issues with any of the above?
24
+
25
+ There is always the possibilities of issues, but it is not a strong likelihood. We tested migrating from Action Scheduler 2.n with the custom data stores (including Action Scheduler Custom Tables plugin) active to Action Scheduler 3.0 on a number of test sites.
26
+
27
+ As with all major, and minor, upgrades, we still testing the update on a staging site before updating the live site. We also recommending taking a backup before updating the live site.
28
+
29
+ If you wish to undertake more comprehensive testing on a development or staging site before updating, or want to closely monitor the update on a live site, follow these steps:
30
+
31
+ #### Stage 1: Prepare your site:
32
+
33
+ 1. Take a backup of your database (AS 3.0 migrates data to custom tables, this can not be undone, you’ll need to restore a backup to downgrade).
34
+ 1. Go to Tools > Action Scheduler
35
+ 1. Take a screenshot of the action status counts at the top of the page. Example screenshot: https://cld.wthms.co/kwIqv7
36
+
37
+
38
+ #### Stage 2: Install & Activate Action Scheduler 3.0 as a plugin
39
+
40
+ 1. The migration will start almost immediately
41
+ 1. Keep an eye on your error log
42
+ 1. Report any notices, errors or other issues on GitHub
43
+
44
+ #### Stage 3: Verify Migration
45
+
46
+ 1. Go to Tools > Action Scheduler
47
+ 1. Take a screenshot of the action status counts at the top of the page.
48
+ 1. Verify the counts match the status counts taken in Stage 1 (the Completed counts could be higher because actions will have been completed to run the migration).
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.3.2
20
  * Author: Mailchimp
21
  * Author URI: https://mailchimp.com
22
  * License: GPL-2.0+
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.3.3
20
  * Author: Mailchimp
21
  * Author URI: https://mailchimp.com
22
  * License: GPL-2.0+