Site Reviews - Version 6.0.6

Version Description

(2022-09-25) =

  • Fixed integration with Polylang's String Translations
  • Fixed the Reset Permissions tool
  • Fixed the Slack integration @andersk
  • Updated the Action Scheduler library to v3.5.2
Download this release

Release Info

Developer geminilabs
Plugin Icon 128x128 Site Reviews
Version 6.0.6
Comparing to
See all releases

Code changes from version 6.0.5 to 6.0.6

Files changed (32) hide show
  1. changelog.txt +7 -0
  2. languages/site-reviews-en_US.mo +0 -0
  3. languages/site-reviews-en_US.po +16 -12
  4. languages/site-reviews.pot +7 -7
  5. plugin/Contracts/QueueContract.php +66 -53
  6. plugin/Controllers/DeactivationController.php +6 -6
  7. plugin/Modules/Queue.php +8 -8
  8. plugin/Modules/Slack.php +1 -1
  9. readme.txt +8 -1
  10. site-reviews.php +1 -1
  11. vendors/woocommerce/action-scheduler/action-scheduler.php +7 -7
  12. vendors/woocommerce/action-scheduler/changelog.txt +23 -0
  13. vendors/woocommerce/action-scheduler/classes/ActionScheduler_ActionFactory.php +132 -49
  14. vendors/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php +91 -1
  15. vendors/woocommerce/action-scheduler/classes/ActionScheduler_Exception.php +1 -1
  16. vendors/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php +15 -1
  17. vendors/woocommerce/action-scheduler/classes/ActionScheduler_QueueRunner.php +25 -6
  18. vendors/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_Scheduler_command.php +30 -0
  19. vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler.php +2 -2
  20. vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php +1 -1
  21. vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php +58 -0
  22. vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php +1 -1
  23. vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php +30 -2
  24. vendors/woocommerce/action-scheduler/classes/actions/ActionScheduler_Action.php +22 -1
  25. vendors/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php +149 -11
  26. vendors/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php +10 -1
  27. vendors/woocommerce/action-scheduler/classes/schema/ActionScheduler_LoggerSchema.php +7 -7
  28. vendors/woocommerce/action-scheduler/functions.php +75 -55
  29. vendors/woocommerce/action-scheduler/lib/WP_Async_Request.php +24 -3
  30. vendors/woocommerce/action-scheduler/readme.txt +25 -2
  31. views/pages/tools/general/reset-permissions.php +1 -1
  32. wpml-config.xml +4 -4
changelog.txt CHANGED
@@ -1,5 +1,12 @@
1
  == Changelog ==
2
 
 
 
 
 
 
 
 
3
  = 6.0.5 (2022-09-16) =
4
 
5
  - Fixed CSS loading on pages which do not load the Gutenberg button and search CSS
1
  == Changelog ==
2
 
3
+ = 6.0.6 (2022-09-25) =
4
+
5
+ - Fixed integration with Polylang's String Translations
6
+ - Fixed the Reset Permissions tool
7
+ - Fixed the Slack integration [@andersk](https://github.com/andersk)
8
+ - Updated the [Action Scheduler](https://github.com/woocommerce/action-scheduler/) library to v3.5.2
9
+
10
  = 6.0.5 (2022-09-16) =
11
 
12
  - Fixed CSS loading on pages which do not load the Gutenberg button and search CSS
languages/site-reviews-en_US.mo CHANGED
Binary file
languages/site-reviews-en_US.po CHANGED
@@ -1835,7 +1835,7 @@ msgctxt "admin-text"
1835
  msgid "Choose the action that should be taken when a review is blacklisted."
1836
  msgstr "Choose the action that should be taken when a review is blacklisted."
1837
 
1838
- #: plugin/Application.php:182, plugin/Controllers/SettingsController.php:175
1839
  msgctxt "admin-text"
1840
  msgid "License Keys"
1841
  msgstr "License Keys"
@@ -2189,13 +2189,17 @@ msgstr "Processing..."
2189
 
2190
  #: plugin/Controllers/DeactivationController.php:108
2191
  msgctxt "admin-text"
2192
- msgid "Would you like me to assist you?"
2193
- msgstr "Would you like me to assist you?"
 
 
 
 
2194
 
2195
  #: plugin/Controllers/DeactivationController.php:109
2196
  msgctxt "admin-text"
2197
- msgid "Couldn't understand"
2198
- msgstr "Couldn't understand"
2199
 
2200
  #: plugin/Controllers/DeactivationController.php:114
2201
  msgctxt "admin-text"
@@ -2209,8 +2213,8 @@ msgstr "I found a better plugin"
2209
 
2210
  #: plugin/Controllers/DeactivationController.php:120
2211
  msgctxt "admin-text"
2212
- msgid "Could you tell me more about what's not working?"
2213
- msgstr "Could you tell me more about what's not working?"
2214
 
2215
  #: plugin/Controllers/DeactivationController.php:121
2216
  msgctxt "admin-text"
@@ -2219,8 +2223,8 @@ msgstr "It's not working for me"
2219
 
2220
  #: plugin/Controllers/DeactivationController.php:126
2221
  msgctxt "admin-text"
2222
- msgid "Could you tell me more about the missing feature?"
2223
- msgstr "Could you tell me more about the missing feature?"
2224
 
2225
  #: plugin/Controllers/DeactivationController.php:127
2226
  msgctxt "admin-text"
@@ -2229,8 +2233,8 @@ msgstr "Missing a specific feature"
2229
 
2230
  #: plugin/Controllers/DeactivationController.php:132
2231
  msgctxt "admin-text"
2232
- msgid "Could you tell me what you were looking for?"
2233
- msgstr "Could you tell me what you were looking for?"
2234
 
2235
  #: plugin/Controllers/DeactivationController.php:133
2236
  msgctxt "admin-text"
@@ -5222,7 +5226,7 @@ msgctxt "limit time (admin-text)"
5222
  msgid "days"
5223
  msgstr "days"
5224
 
5225
- #: plugin/Application.php:181
5226
  msgctxt "License Keys (admin-text)"
5227
  msgid ""
5228
  "Enter the license key here. Your license can be found on the %s page of "
1835
  msgid "Choose the action that should be taken when a review is blacklisted."
1836
  msgstr "Choose the action that should be taken when a review is blacklisted."
1837
 
1838
+ #: plugin/Application.php:183, plugin/Controllers/SettingsController.php:175
1839
  msgctxt "admin-text"
1840
  msgid "License Keys"
1841
  msgstr "License Keys"
2189
 
2190
  #: plugin/Controllers/DeactivationController.php:108
2191
  msgctxt "admin-text"
2192
+ msgid ""
2193
+ "Would like me to help you? If you enter your email I'll be happy to assist "
2194
+ "you."
2195
+ msgstr ""
2196
+ "Would like me to help you? If you enter your email I'll be happy to assist "
2197
+ "you."
2198
 
2199
  #: plugin/Controllers/DeactivationController.php:109
2200
  msgctxt "admin-text"
2201
+ msgid "It's too complicated"
2202
+ msgstr "It's too complicated"
2203
 
2204
  #: plugin/Controllers/DeactivationController.php:114
2205
  msgctxt "admin-text"
2213
 
2214
  #: plugin/Controllers/DeactivationController.php:120
2215
  msgctxt "admin-text"
2216
+ msgid "What isn't working? Please let me know so I can fix it."
2217
+ msgstr "What isn't working? Please let me know so I can fix it."
2218
 
2219
  #: plugin/Controllers/DeactivationController.php:121
2220
  msgctxt "admin-text"
2223
 
2224
  #: plugin/Controllers/DeactivationController.php:126
2225
  msgctxt "admin-text"
2226
+ msgid "Which feature are you looking for?"
2227
+ msgstr "Which feature are you looking for?"
2228
 
2229
  #: plugin/Controllers/DeactivationController.php:127
2230
  msgctxt "admin-text"
2233
 
2234
  #: plugin/Controllers/DeactivationController.php:132
2235
  msgctxt "admin-text"
2236
+ msgid "What are you looking for? Maybe I can help."
2237
+ msgstr "What are you looking for? Maybe I can help."
2238
 
2239
  #: plugin/Controllers/DeactivationController.php:133
2240
  msgctxt "admin-text"
5226
  msgid "days"
5227
  msgstr "days"
5228
 
5229
+ #: plugin/Application.php:182
5230
  msgctxt "License Keys (admin-text)"
5231
  msgid ""
5232
  "Enter the license key here. Your license can be found on the %s page of "
languages/site-reviews.pot CHANGED
@@ -1309,12 +1309,12 @@ msgctxt "admin-text"
1309
  msgid "Choose the action that should be taken when a review is blacklisted."
1310
  msgstr ""
1311
 
1312
- #: plugin/Application.php:181
1313
  msgctxt "License Keys (admin-text)"
1314
  msgid "Enter the license key here. Your license can be found on the %s page of your Nifty Plugins account."
1315
  msgstr ""
1316
 
1317
- #: plugin/Application.php:182, plugin/Controllers/SettingsController.php:175
1318
  msgctxt "admin-text"
1319
  msgid "License Keys"
1320
  msgstr ""
@@ -1734,12 +1734,12 @@ msgstr ""
1734
 
1735
  #: plugin/Controllers/DeactivationController.php:108
1736
  msgctxt "admin-text"
1737
- msgid "Would you like me to assist you?"
1738
  msgstr ""
1739
 
1740
  #: plugin/Controllers/DeactivationController.php:109
1741
  msgctxt "admin-text"
1742
- msgid "Couldn't understand"
1743
  msgstr ""
1744
 
1745
  #: plugin/Controllers/DeactivationController.php:114
@@ -1754,7 +1754,7 @@ msgstr ""
1754
 
1755
  #: plugin/Controllers/DeactivationController.php:120
1756
  msgctxt "admin-text"
1757
- msgid "Could you tell me more about what's not working?"
1758
  msgstr ""
1759
 
1760
  #: plugin/Controllers/DeactivationController.php:121
@@ -1764,7 +1764,7 @@ msgstr ""
1764
 
1765
  #: plugin/Controllers/DeactivationController.php:126
1766
  msgctxt "admin-text"
1767
- msgid "Could you tell me more about the missing feature?"
1768
  msgstr ""
1769
 
1770
  #: plugin/Controllers/DeactivationController.php:127
@@ -1774,7 +1774,7 @@ msgstr ""
1774
 
1775
  #: plugin/Controllers/DeactivationController.php:132
1776
  msgctxt "admin-text"
1777
- msgid "Could you tell me what you were looking for?"
1778
  msgstr ""
1779
 
1780
  #: plugin/Controllers/DeactivationController.php:133
1309
  msgid "Choose the action that should be taken when a review is blacklisted."
1310
  msgstr ""
1311
 
1312
+ #: plugin/Application.php:182
1313
  msgctxt "License Keys (admin-text)"
1314
  msgid "Enter the license key here. Your license can be found on the %s page of your Nifty Plugins account."
1315
  msgstr ""
1316
 
1317
+ #: plugin/Application.php:183, plugin/Controllers/SettingsController.php:175
1318
  msgctxt "admin-text"
1319
  msgid "License Keys"
1320
  msgstr ""
1734
 
1735
  #: plugin/Controllers/DeactivationController.php:108
1736
  msgctxt "admin-text"
1737
+ msgid "Would like me to help you? If you enter your email I'll be happy to assist you."
1738
  msgstr ""
1739
 
1740
  #: plugin/Controllers/DeactivationController.php:109
1741
  msgctxt "admin-text"
1742
+ msgid "It's too complicated"
1743
  msgstr ""
1744
 
1745
  #: plugin/Controllers/DeactivationController.php:114
1754
 
1755
  #: plugin/Controllers/DeactivationController.php:120
1756
  msgctxt "admin-text"
1757
+ msgid "What isn't working? Please let me know so I can fix it."
1758
  msgstr ""
1759
 
1760
  #: plugin/Controllers/DeactivationController.php:121
1764
 
1765
  #: plugin/Controllers/DeactivationController.php:126
1766
  msgctxt "admin-text"
1767
+ msgid "Which feature are you looking for?"
1768
  msgstr ""
1769
 
1770
  #: plugin/Controllers/DeactivationController.php:127
1774
 
1775
  #: plugin/Controllers/DeactivationController.php:132
1776
  msgctxt "admin-text"
1777
+ msgid "What are you looking for? Maybe I can help."
1778
  msgstr ""
1779
 
1780
  #: plugin/Controllers/DeactivationController.php:133
plugin/Contracts/QueueContract.php CHANGED
@@ -5,13 +5,15 @@ namespace GeminiLabs\SiteReviews\Contracts;
5
  interface QueueContract
6
  {
7
  /**
8
- * Enqueue an action to run one time, as soon as possible.
9
  *
10
- * @param string $hook the hook to trigger
11
- * @param array $args arguments to pass when the hook triggers
12
- * @return int the action ID
 
 
13
  */
14
- public function async($hook, $args = []);
15
 
16
  /**
17
  * Cancel the next occurrence of a scheduled action.
@@ -23,9 +25,10 @@ interface QueueContract
23
  * then the following instance will never be scheduled (or exist), which is effectively the same as being unscheduled
24
  * by this method also.
25
  *
26
- * @param string $hook the hook that the job will trigger
27
- * @param array $args args that would have been passed to the job
28
- * @return string|null the scheduled action ID if a scheduled action was found, or null if no matching action found
 
29
  */
30
  public function cancel($hook, $args = []);
31
 
@@ -40,10 +43,10 @@ interface QueueContract
40
  /**
41
  * Schedule an action that recurs on a cron-like schedule.
42
  *
43
- * @param int $timestamp The first instance of the action will be scheduled
44
- * to run at a time calculated after this timestamp matching the cron
45
- * expression. This can be used to delay the first instance of the action.
46
- * @param string $schedule A cron-link schedule string
47
  * @see http://en.wikipedia.org/wiki/Cron
48
  * * * * * * *
49
  * ┬ ┬ ┬ ┬ ┬ ┬
@@ -54,20 +57,24 @@ interface QueueContract
54
  * | | +--------------- day of month (1 - 31)
55
  * | +-------------------- hour (0 - 23)
56
  * +------------------------- min (0 - 59)
57
- * @param string $hook the hook to trigger
58
- * @param array $args arguments to pass when the hook triggers
59
- * @return int the action ID
 
 
60
  */
61
- public function cron($timestamp, $schedule, $hook, $args = []);
62
 
63
  /**
64
  * Check if there is a scheduled action in the queue but more efficiently than as_next_scheduled_action().
65
  *
66
- * It's recommended to use this function when you need to know whether a specific action is currently scheduled (pending or in-progress).
 
67
  *
68
- * @param string $hook the hook of the action
69
  * @param array $args Args that have been passed to the action. Null will matches any args.
70
- * @return bool true if a matching action is pending or in-progress, false otherwise
 
71
  */
72
  public function isPending($hook, $args = []);
73
 
@@ -80,52 +87,58 @@ interface QueueContract
80
  * returned. Or there may be no async, in-progress or pending action for this hook, in which case,
81
  * boolean false will be the return value.
82
  *
83
- * @param string $hook
84
- * @param array $args
85
- * @return \DateTime|bool the timestamp for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action
 
86
  */
87
  public function next($hook, $args = null);
88
 
89
  /**
90
- * Schedule an action to run one time.
 
 
 
 
 
91
  *
92
- * @param int $timestamp when the job will run
93
- * @param string $hook the hook to trigger
94
- * @param array $args arguments to pass when the hook triggers
95
- * @return int the action ID
96
  */
97
- public function once($timestamp, $hook, $args = []);
98
 
99
  /**
100
- * Schedule a recurring action.
 
 
 
 
 
 
101
  *
102
- * @param int $timestamp when the first instance of the job will run
103
- * @param int $intervalInSeconds how long to wait between runs
104
- * @param string $hook the hook to trigger
105
- * @param array $args arguments to pass when the hook triggers
106
- * @return int the action ID
107
  */
108
- public function recurring($timestamp, $intervalInSeconds, $hook, $args = []);
109
 
110
  /**
111
- * Find scheduled actions.
112
- *
113
- * @param array $args Possible arguments, with their default values:
114
- * 'hook' => '' - the name of the action that will be triggered
115
- * 'args' => NULL - the args array that will be passed with the action
116
- * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
117
- * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='
118
- * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
119
- * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='
120
- * 'group' => '' - the group the action belongs to
121
- * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING
122
- * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID
123
- * 'per_page' => 5 - Number of results to return
124
- * 'offset' => 0
125
- * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', 'date' or 'none'
126
- * 'order' => 'ASC'
127
- *
128
- * @param string $returnFormat OBJECT, ARRAY_A, or ids
 
129
  * @return array
130
  */
131
  public function search($args = [], $returnFormat = OBJECT);
5
  interface QueueContract
6
  {
7
  /**
8
+ * Enqueue an action to run one time, as soon as possible
9
  *
10
+ * @param string $hook The hook to trigger.
11
+ * @param array $args Arguments to pass when the hook triggers.
12
+ * @param bool $unique Whether the action should be unique.
13
+ *
14
+ * @return int The action ID.
15
  */
16
+ public function async($hook, $args = [], $unique = false);
17
 
18
  /**
19
  * Cancel the next occurrence of a scheduled action.
25
  * then the following instance will never be scheduled (or exist), which is effectively the same as being unscheduled
26
  * by this method also.
27
  *
28
+ * @param string $hook The hook that the job will trigger.
29
+ * @param array $args Args that would have been passed to the job.
30
+ *
31
+ * @return int|null The scheduled action ID if a scheduled action was found, or null if no matching action found.
32
  */
33
  public function cancel($hook, $args = []);
34
 
43
  /**
44
  * Schedule an action that recurs on a cron-like schedule.
45
  *
46
+ * @param int $timestamp The first instance of the action will be scheduled
47
+ * to run at a time calculated after this timestamp matching the cron
48
+ * expression. This can be used to delay the first instance of the action.
49
+ * @param string $schedule A cron-link schedule string.
50
  * @see http://en.wikipedia.org/wiki/Cron
51
  * * * * * * *
52
  * ┬ ┬ ┬ ┬ ┬ ┬
57
  * | | +--------------- day of month (1 - 31)
58
  * | +-------------------- hour (0 - 23)
59
  * +------------------------- min (0 - 59)
60
+ * @param string $hook The hook to trigger.
61
+ * @param array $args Arguments to pass when the hook triggers.
62
+ * @param bool $unique Whether the action should be unique.
63
+ *
64
+ * @return int The action ID.
65
  */
66
+ public function cron($timestamp, $schedule, $hook, $args = [], $unique = false);
67
 
68
  /**
69
  * Check if there is a scheduled action in the queue but more efficiently than as_next_scheduled_action().
70
  *
71
+ * It's recommended to use this function when you need to know whether a specific action is currently scheduled
72
+ * (pending or in-progress).
73
  *
74
+ * @param string $hook The hook of the action.
75
  * @param array $args Args that have been passed to the action. Null will matches any args.
76
+ *
77
+ * @return bool True if a matching action is pending or in-progress, false otherwise.
78
  */
79
  public function isPending($hook, $args = []);
80
 
87
  * returned. Or there may be no async, in-progress or pending action for this hook, in which case,
88
  * boolean false will be the return value.
89
  *
90
+ * @param string $hook Name of the hook to search for.
91
+ * @param array $args Arguments of the action to be searched.
92
+ *
93
+ * @return \DateTime|bool The DateTime for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action.
94
  */
95
  public function next($hook, $args = null);
96
 
97
  /**
98
+ * Schedule an action to run one time
99
+ *
100
+ * @param int $timestamp When the job will run.
101
+ * @param string $hook The hook to trigger.
102
+ * @param array $args Arguments to pass when the hook triggers.
103
+ * @param bool $unique Whether the action should be unique.
104
  *
105
+ * @return int The action ID.
 
 
 
106
  */
107
+ public function once($timestamp, $hook, $args = [], $unique = false);
108
 
109
  /**
110
+ * Schedule a recurring action
111
+ *
112
+ * @param int $timestamp When the first instance of the job will run.
113
+ * @param int $intervalInSeconds How long to wait between runs.
114
+ * @param string $hook The hook to trigger.
115
+ * @param array $args Arguments to pass when the hook triggers.
116
+ * @param bool $unique Whether the action should be unique.
117
  *
118
+ * @return int The action ID.
 
 
 
 
119
  */
120
+ public function recurring($timestamp, $intervalInSeconds, $hook, $args = [], $unique = false);
121
 
122
  /**
123
+ * Find scheduled actions
124
+ *
125
+ * @param array $args Possible arguments, with their default values.
126
+ * 'hook' => '' - the name of the action that will be triggered.
127
+ * 'args' => NULL - the args array that will be passed with the action.
128
+ * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
129
+ * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='.
130
+ * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
131
+ * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='.
132
+ * 'group' => '' - the group the action belongs to.
133
+ * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING.
134
+ * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID.
135
+ * 'per_page' => 5 - Number of results to return.
136
+ * 'offset' => 0.
137
+ * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', 'date' or 'none'.
138
+ * 'order' => 'ASC'.
139
+ *
140
+ * @param string $returnFormat OBJECT, ARRAY_A, or ids.
141
+ *
142
  * @return array
143
  */
144
  public function search($args = [], $returnFormat = OBJECT);
plugin/Controllers/DeactivationController.php CHANGED
@@ -105,8 +105,8 @@ class DeactivationController extends Controller
105
  [
106
  'icon' => file_get_contents(glsr()->path('assets/images/icons/confused.svg')),
107
  'id' => 'confused',
108
- 'placeholder' => _x('Would you like me to assist you?', 'admin-text', 'site-reviews'),
109
- 'text' => _x('Couldn\'t understand', 'admin-text', 'site-reviews'),
110
  ],
111
  [
112
  'icon' => file_get_contents(glsr()->path('assets/images/icons/found-better.svg')),
@@ -117,19 +117,19 @@ class DeactivationController extends Controller
117
  [
118
  'icon' => file_get_contents(glsr()->path('assets/images/icons/not-working.svg')),
119
  'id' => 'not-working',
120
- 'placeholder' => _x('Could you tell me more about what\'s not working?', 'admin-text', 'site-reviews'),
121
- 'text' => _x('It\'s not working for me', 'admin-text', 'site-reviews'),
122
  ],
123
  [
124
  'icon' => file_get_contents(glsr()->path('assets/images/icons/feature-missing.svg')),
125
  'id' => 'feature-missing',
126
- 'placeholder' => _x('Could you tell me more about the missing feature?', 'admin-text', 'site-reviews'),
127
  'text' => _x('Missing a specific feature', 'admin-text', 'site-reviews'),
128
  ],
129
  [
130
  'icon' => file_get_contents(glsr()->path('assets/images/icons/looking-for-different.svg')),
131
  'id' => 'looking-for-different',
132
- 'placeholder' => _x('Could you tell me what you were looking for?', 'admin-text', 'site-reviews'),
133
  'text' => _x('Not what I was looking for', 'admin-text', 'site-reviews'),
134
  ],
135
  [
105
  [
106
  'icon' => file_get_contents(glsr()->path('assets/images/icons/confused.svg')),
107
  'id' => 'confused',
108
+ 'placeholder' => _x("Would like me to help you? If you enter your email I'll be happy to assist you.", 'admin-text', 'site-reviews'),
109
+ 'text' => _x("It's too complicated", 'admin-text', 'site-reviews'),
110
  ],
111
  [
112
  'icon' => file_get_contents(glsr()->path('assets/images/icons/found-better.svg')),
117
  [
118
  'icon' => file_get_contents(glsr()->path('assets/images/icons/not-working.svg')),
119
  'id' => 'not-working',
120
+ 'placeholder' => _x("What isn't working? Please let me know so I can fix it.", 'admin-text', 'site-reviews'),
121
+ 'text' => _x("It's not working for me", 'admin-text', 'site-reviews'),
122
  ],
123
  [
124
  'icon' => file_get_contents(glsr()->path('assets/images/icons/feature-missing.svg')),
125
  'id' => 'feature-missing',
126
+ 'placeholder' => _x('Which feature are you looking for?', 'admin-text', 'site-reviews'),
127
  'text' => _x('Missing a specific feature', 'admin-text', 'site-reviews'),
128
  ],
129
  [
130
  'icon' => file_get_contents(glsr()->path('assets/images/icons/looking-for-different.svg')),
131
  'id' => 'looking-for-different',
132
+ 'placeholder' => _x('What are you looking for? Maybe I can help.', 'admin-text', 'site-reviews'),
133
  'text' => _x('Not what I was looking for', 'admin-text', 'site-reviews'),
134
  ],
135
  [
plugin/Modules/Queue.php CHANGED
@@ -36,12 +36,12 @@ class Queue implements QueueContract
36
  /**
37
  * {@inheritdoc}
38
  */
39
- public function async($hook, $args = [])
40
  {
41
  if (!function_exists('as_enqueue_async_action') || $this->isTesting) {
42
  return 0;
43
  }
44
- return as_enqueue_async_action($this->hook($hook), $args, glsr()->id);
45
  }
46
 
47
  /**
@@ -73,12 +73,12 @@ class Queue implements QueueContract
73
  /**
74
  * {@inheritdoc}
75
  */
76
- public function cron($timestamp, $cron, $hook, $args = [])
77
  {
78
  if (!function_exists('as_schedule_cron_action') || $this->isTesting) {
79
  return 0;
80
  }
81
- return as_schedule_cron_action($timestamp, $cron, $this->hook($hook), $args, glsr()->id);
82
  }
83
 
84
  /**
@@ -118,23 +118,23 @@ class Queue implements QueueContract
118
  /**
119
  * {@inheritdoc}
120
  */
121
- public function once($timestamp, $hook, $args = [])
122
  {
123
  if (!function_exists('as_schedule_single_action') || $this->isTesting) {
124
  return 0;
125
  }
126
- return as_schedule_single_action($timestamp, $this->hook($hook), $args, glsr()->id);
127
  }
128
 
129
  /**
130
  * {@inheritdoc}
131
  */
132
- public function recurring($timestamp, $intervalInSeconds, $hook, $args = [])
133
  {
134
  if (!function_exists('as_schedule_recurring_action') || $this->isTesting) {
135
  return 0;
136
  }
137
- return as_schedule_recurring_action($timestamp, $intervalInSeconds, $this->hook($hook), $args, glsr()->id);
138
  }
139
 
140
  /**
36
  /**
37
  * {@inheritdoc}
38
  */
39
+ public function async($hook, $args = [], $unique = false)
40
  {
41
  if (!function_exists('as_enqueue_async_action') || $this->isTesting) {
42
  return 0;
43
  }
44
+ return as_enqueue_async_action($this->hook($hook), $args, glsr()->id, $unique);
45
  }
46
 
47
  /**
73
  /**
74
  * {@inheritdoc}
75
  */
76
+ public function cron($timestamp, $cron, $hook, $args = [], $unique = false)
77
  {
78
  if (!function_exists('as_schedule_cron_action') || $this->isTesting) {
79
  return 0;
80
  }
81
+ return as_schedule_cron_action($timestamp, $cron, $this->hook($hook), $args, glsr()->id, $unique);
82
  }
83
 
84
  /**
118
  /**
119
  * {@inheritdoc}
120
  */
121
+ public function once($timestamp, $hook, $args = [], $unique = false)
122
  {
123
  if (!function_exists('as_schedule_single_action') || $this->isTesting) {
124
  return 0;
125
  }
126
+ return as_schedule_single_action($timestamp, $this->hook($hook), $args, glsr()->id, $unique);
127
  }
128
 
129
  /**
130
  * {@inheritdoc}
131
  */
132
+ public function recurring($timestamp, $intervalInSeconds, $hook, $args = [], $unique = false)
133
  {
134
  if (!function_exists('as_schedule_recurring_action') || $this->isTesting) {
135
  return 0;
136
  }
137
+ return as_schedule_recurring_action($timestamp, $intervalInSeconds, $this->hook($hook), $args, glsr()->id, $unique);
138
  }
139
 
140
  /**
plugin/Modules/Slack.php CHANGED
@@ -118,7 +118,7 @@ class Slack
118
  $this->buildContentField(),
119
  $this->buildAuthorField(),
120
  ];
121
- return array_filter($fields);
122
  }
123
 
124
  /**
118
  $this->buildContentField(),
119
  $this->buildAuthorField(),
120
  ];
121
+ return array_values(array_filter($fields));
122
  }
123
 
124
  /**
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://ko-fi.com/pryley
4
  Tags: reviews, ratings, testimonials, woocommerce, product reviews, business reviews, stars, star ratings, elementor
5
  Tested up to: 6.0
6
  Requires at least: 5.8
7
- Stable tag: 6.0.5
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -156,6 +156,13 @@ This update requires a minimum of PHP 7.2 and WordPress 5.8. There are also a fe
156
 
157
  == Changelog ==
158
 
 
 
 
 
 
 
 
159
  = 6.0.5 (2022-09-16) =
160
 
161
  - Fixed CSS loading on pages which do not load the Gutenberg button and search CSS
4
  Tags: reviews, ratings, testimonials, woocommerce, product reviews, business reviews, stars, star ratings, elementor
5
  Tested up to: 6.0
6
  Requires at least: 5.8
7
+ Stable tag: 6.0.6
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
156
 
157
  == Changelog ==
158
 
159
+ = 6.0.6 (2022-09-25) =
160
+
161
+ - Fixed integration with Polylang's String Translations
162
+ - Fixed the Reset Permissions tool
163
+ - Fixed the Slack integration [@andersk](https://github.com/andersk)
164
+ - Updated the [Action Scheduler](https://github.com/woocommerce/action-scheduler/) library to v3.5.2
165
+
166
  = 6.0.5 (2022-09-16) =
167
 
168
  - Fixed CSS loading on pages which do not load the Gutenberg button and search CSS
site-reviews.php CHANGED
@@ -7,7 +7,7 @@
7
  * Plugin Name: Site Reviews
8
  * Plugin URI: https://wordpress.org/plugins/site-reviews
9
  * Description: Receive and display reviews on your website
10
- * Version: 6.0.5
11
  * Author: Paul Ryley
12
  * Author URI: https://geminilabs.io
13
  * License: GPL2
7
  * Plugin Name: Site Reviews
8
  * Plugin URI: https://wordpress.org/plugins/site-reviews
9
  * Description: Receive and display reviews on your website
10
+ * Version: 6.0.6
11
  * Author: Paul Ryley
12
  * Author URI: https://geminilabs.io
13
  * License: GPL2
vendors/woocommerce/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.4.0
9
  * License: GPLv3
10
  *
11
  * Copyright 2019 Automattic, Inc. (https://automattic.com/contact/)
@@ -26,27 +26,27 @@
26
  * @package ActionScheduler
27
  */
28
 
29
- if ( ! function_exists( 'action_scheduler_register_3_dot_4_dot_0' ) && function_exists( 'add_action' ) ) {
30
 
31
  if ( ! class_exists( 'ActionScheduler_Versions', false ) ) {
32
  require_once __DIR__ . '/classes/ActionScheduler_Versions.php';
33
  add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
34
  }
35
 
36
- add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_4_dot_0', 0, 0 );
37
 
38
  /**
39
  * Registers this version of Action Scheduler.
40
  */
41
- function action_scheduler_register_3_dot_4_dot_0() {
42
  $versions = ActionScheduler_Versions::instance();
43
- $versions->register( '3.4.0', 'action_scheduler_initialize_3_dot_4_dot_0' );
44
  }
45
 
46
  /**
47
  * Initializes this version of Action Scheduler.
48
  */
49
- function action_scheduler_initialize_3_dot_4_dot_0() {
50
  // A final safety check is required even here, because historic versions of Action Scheduler
51
  // followed a different pattern (in some unusual cases, we could reach this point and the
52
  // ActionScheduler class is already defined—so we need to guard against that).
@@ -58,7 +58,7 @@ if ( ! function_exists( 'action_scheduler_register_3_dot_4_dot_0' ) && function_
58
 
59
  // Support usage in themes - load this version if no plugin has loaded a version yet.
60
  if ( did_action( 'plugins_loaded' ) && ! doing_action( 'plugins_loaded' ) && ! class_exists( 'ActionScheduler', false ) ) {
61
- action_scheduler_initialize_3_dot_4_dot_0();
62
  do_action( 'action_scheduler_pre_theme_init' );
63
  ActionScheduler_Versions::initialize_latest_version();
64
  }
5
  * Description: A robust scheduling library for use in WordPress plugins.
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/
8
+ * Version: 3.5.2
9
  * License: GPLv3
10
  *
11
  * Copyright 2019 Automattic, Inc. (https://automattic.com/contact/)
26
  * @package ActionScheduler
27
  */
28
 
29
+ if ( ! function_exists( 'action_scheduler_register_3_dot_5_dot_2' ) && function_exists( 'add_action' ) ) {
30
 
31
  if ( ! class_exists( 'ActionScheduler_Versions', false ) ) {
32
  require_once __DIR__ . '/classes/ActionScheduler_Versions.php';
33
  add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
34
  }
35
 
36
+ add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_5_dot_2', 0, 0 );
37
 
38
  /**
39
  * Registers this version of Action Scheduler.
40
  */
41
+ function action_scheduler_register_3_dot_5_dot_2() {
42
  $versions = ActionScheduler_Versions::instance();
43
+ $versions->register( '3.5.2', 'action_scheduler_initialize_3_dot_5_dot_2' );
44
  }
45
 
46
  /**
47
  * Initializes this version of Action Scheduler.
48
  */
49
+ function action_scheduler_initialize_3_dot_5_dot_2() {
50
  // A final safety check is required even here, because historic versions of Action Scheduler
51
  // followed a different pattern (in some unusual cases, we could reach this point and the
52
  // ActionScheduler class is already defined—so we need to guard against that).
58
 
59
  // Support usage in themes - load this version if no plugin has loaded a version yet.
60
  if ( did_action( 'plugins_loaded' ) && ! doing_action( 'plugins_loaded' ) && ! class_exists( 'ActionScheduler', false ) ) {
61
+ action_scheduler_initialize_3_dot_5_dot_2();
62
  do_action( 'action_scheduler_pre_theme_init' );
63
  ActionScheduler_Versions::initialize_latest_version();
64
  }
vendors/woocommerce/action-scheduler/changelog.txt CHANGED
@@ -1,5 +1,28 @@
1
  *** Changelog ***
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  = 3.4.0 - 2021-10-29 =
4
  * Enhancement - Number of items per page can now be set for the Scheduled Actions view (props @ovidiul). #771
5
  * Fix - Do not lower the max_execution_time if it is already set to 0 (unlimited) (props @barryhughes). #755
1
  *** Changelog ***
2
 
3
+ = 3.5.2 - 2022-09-16 =
4
+ * Fix - erroneous 3.5.1 release.
5
+
6
+ = 3.5.1 - 2022-09-13 =
7
+ * Maintenance on A/S docs.
8
+ * fix: PHP 8.2 deprecated notice.
9
+
10
+ = 3.5.0 - 2022-08-25 =
11
+ * Add - The active view link within the "Tools > Scheduled Actions" screen is now clickable.
12
+ * Add - A warning when there are past-due actions.
13
+ * Enhancement - Added the ability to schedule unique actions via an atomic operation.
14
+ * Enhancement - Improvements to cache invalidation when processing batches (when running on WordPress 6.0+).
15
+ * Enhancement - If a recurring action is found to be consistently failing, it will stop being rescheduled.
16
+ * Enhancement - Adds a new "Past Due" view to the scheduled actions list table.
17
+
18
+ = 3.4.2 - 2022-06-08 =
19
+ * Fix - Change the include for better linting.
20
+ * Fix - update: Added Action scheduler completed action hook.
21
+
22
+ = 3.4.1 - 2022-05-24 =
23
+ * Fix - Change the include for better linting.
24
+ * Fix - Fix the documented return type.
25
+
26
  = 3.4.0 - 2021-10-29 =
27
  * Enhancement - Number of items per page can now be set for the Scheduled Actions view (props @ovidiul). #771
28
  * Fix - Do not lower the max_execution_time if it is already set to 0 (unlimited) (props @barryhughes). #755
vendors/woocommerce/action-scheduler/classes/ActionScheduler_ActionFactory.php CHANGED
@@ -6,27 +6,29 @@
6
  class ActionScheduler_ActionFactory {
7
 
8
  /**
9
- * @param string $status The action's status in the data store
10
- * @param string $hook The hook to trigger when this action runs
11
- * @param array $args Args to pass to callbacks when the hook is triggered
12
- * @param ActionScheduler_Schedule $schedule The action's schedule
13
- * @param string $group A group to put the action in
14
  *
15
- * @return ActionScheduler_Action An instance of the stored action
 
 
 
 
 
 
16
  */
17
  public function get_stored_action( $status, $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
18
 
19
  switch ( $status ) {
20
- case ActionScheduler_Store::STATUS_PENDING :
21
  $action_class = 'ActionScheduler_Action';
22
  break;
23
- case ActionScheduler_Store::STATUS_CANCELED :
24
  $action_class = 'ActionScheduler_CanceledAction';
25
  if ( ! is_null( $schedule ) && ! is_a( $schedule, 'ActionScheduler_CanceledSchedule' ) && ! is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
26
  $schedule = new ActionScheduler_CanceledSchedule( $schedule->get_date() );
27
  }
28
  break;
29
- default :
30
  $action_class = 'ActionScheduler_FinishedAction';
31
  break;
32
  }
@@ -57,76 +59,142 @@ class ActionScheduler_ActionFactory {
57
  * given priority in queue processing. This has the added advantage of making sure async actions can be
58
  * claimed by both the existing WP Cron and WP CLI runners, as well as a new async request runner.
59
  *
60
- * @param string $hook The hook to trigger when this action runs
61
- * @param array $args Args to pass when the hook is triggered
62
- * @param string $group A group to put the action in
63
  *
64
- * @return int The ID of the stored action
65
  */
66
  public function async( $hook, $args = array(), $group = '' ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  $schedule = new ActionScheduler_NullSchedule();
68
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
69
- return $this->store( $action );
70
  }
71
 
72
  /**
73
- * @param string $hook The hook to trigger when this action runs
74
- * @param array $args Args to pass when the hook is triggered
75
- * @param int $when Unix timestamp when the action will run
76
- * @param string $group A group to put the action in
77
  *
78
- * @return int The ID of the stored action
 
 
 
 
 
79
  */
80
  public function single( $hook, $args = array(), $when = null, $group = '' ) {
81
- $date = as_get_datetime_object( $when );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  $schedule = new ActionScheduler_SimpleSchedule( $date );
83
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
84
- return $this->store( $action );
85
  }
86
 
87
  /**
88
  * Create the first instance of an action recurring on a given interval.
89
  *
90
- * @param string $hook The hook to trigger when this action runs
91
- * @param array $args Args to pass when the hook is triggered
92
- * @param int $first Unix timestamp for the first run
93
- * @param int $interval Seconds between runs
94
- * @param string $group A group to put the action in
95
  *
96
- * @return int The ID of the stored action
97
  */
98
  public function recurring( $hook, $args = array(), $first = null, $interval = null, $group = '' ) {
99
- if ( empty($interval) ) {
100
- return $this->single( $hook, $args, $first, $group );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  }
102
- $date = as_get_datetime_object( $first );
103
  $schedule = new ActionScheduler_IntervalSchedule( $date, $interval );
104
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
105
- return $this->store( $action );
106
  }
107
 
108
  /**
109
  * Create the first instance of an action recurring on a Cron schedule.
110
  *
111
- * @param string $hook The hook to trigger when this action runs
112
- * @param array $args Args to pass when the hook is triggered
113
- * @param int $base_timestamp The first instance of the action will be scheduled
114
  * to run at a time calculated after this timestamp matching the cron
115
  * expression. This can be used to delay the first instance of the action.
116
- * @param int $schedule A cron definition string
117
- * @param string $group A group to put the action in
118
  *
119
- * @return int The ID of the stored action
120
  */
121
  public function cron( $hook, $args = array(), $base_timestamp = null, $schedule = null, $group = '' ) {
122
- if ( empty($schedule) ) {
123
- return $this->single( $hook, $args, $base_timestamp, $group );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
- $date = as_get_datetime_object( $base_timestamp );
126
- $cron = CronExpression::factory( $schedule );
127
  $schedule = new ActionScheduler_CronSchedule( $date, $cron );
128
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
129
- return $this->store( $action );
130
  }
131
 
132
  /**
@@ -162,13 +230,15 @@ class ActionScheduler_ActionFactory {
162
  }
163
 
164
  $schedule_class = get_class( $schedule );
165
- $new_schedule = new $schedule( $next, $schedule->get_recurrence(), $schedule->get_first_date() );
166
- $new_action = new ActionScheduler_Action( $action->get_hook(), $action->get_args(), $new_schedule, $action->get_group() );
167
  return $this->store( $new_action );
168
  }
169
 
170
  /**
171
- * @param ActionScheduler_Action $action
 
 
172
  *
173
  * @return int The ID of the stored action
174
  */
@@ -176,4 +246,17 @@ class ActionScheduler_ActionFactory {
176
  $store = ActionScheduler_Store::instance();
177
  return $store->save_action( $action );
178
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }
6
  class ActionScheduler_ActionFactory {
7
 
8
  /**
9
+ * Return stored actions for given params.
 
 
 
 
10
  *
11
+ * @param string $status The action's status in the data store.
12
+ * @param string $hook The hook to trigger when this action runs.
13
+ * @param array $args Args to pass to callbacks when the hook is triggered.
14
+ * @param ActionScheduler_Schedule $schedule The action's schedule.
15
+ * @param string $group A group to put the action in.
16
+ *
17
+ * @return ActionScheduler_Action An instance of the stored action.
18
  */
19
  public function get_stored_action( $status, $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
20
 
21
  switch ( $status ) {
22
+ case ActionScheduler_Store::STATUS_PENDING:
23
  $action_class = 'ActionScheduler_Action';
24
  break;
25
+ case ActionScheduler_Store::STATUS_CANCELED:
26
  $action_class = 'ActionScheduler_CanceledAction';
27
  if ( ! is_null( $schedule ) && ! is_a( $schedule, 'ActionScheduler_CanceledSchedule' ) && ! is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
28
  $schedule = new ActionScheduler_CanceledSchedule( $schedule->get_date() );
29
  }
30
  break;
31
+ default:
32
  $action_class = 'ActionScheduler_FinishedAction';
33
  break;
34
  }
59
  * given priority in queue processing. This has the added advantage of making sure async actions can be
60
  * claimed by both the existing WP Cron and WP CLI runners, as well as a new async request runner.
61
  *
62
+ * @param string $hook The hook to trigger when this action runs.
63
+ * @param array $args Args to pass when the hook is triggered.
64
+ * @param string $group A group to put the action in.
65
  *
66
+ * @return int The ID of the stored action.
67
  */
68
  public function async( $hook, $args = array(), $group = '' ) {
69
+ return $this->async_unique( $hook, $args, $group, false );
70
+ }
71
+
72
+ /**
73
+ * Same as async, but also supports $unique param.
74
+ *
75
+ * @param string $hook The hook to trigger when this action runs.
76
+ * @param array $args Args to pass when the hook is triggered.
77
+ * @param string $group A group to put the action in.
78
+ * @param bool $unique Whether to ensure the action is unique.
79
+ *
80
+ * @return int The ID of the stored action.
81
+ */
82
+ public function async_unique( $hook, $args = array(), $group = '', $unique = true ) {
83
  $schedule = new ActionScheduler_NullSchedule();
84
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
85
+ return $unique ? $this->store_unique_action( $action, $unique ) : $this->store( $action );
86
  }
87
 
88
  /**
89
+ * Create single action.
 
 
 
90
  *
91
+ * @param string $hook The hook to trigger when this action runs.
92
+ * @param array $args Args to pass when the hook is triggered.
93
+ * @param int $when Unix timestamp when the action will run.
94
+ * @param string $group A group to put the action in.
95
+ *
96
+ * @return int The ID of the stored action.
97
  */
98
  public function single( $hook, $args = array(), $when = null, $group = '' ) {
99
+ return $this->single_unique( $hook, $args, $when, $group, false );
100
+ }
101
+
102
+ /**
103
+ * Create single action only if there is no pending or running action with same name and params.
104
+ *
105
+ * @param string $hook The hook to trigger when this action runs.
106
+ * @param array $args Args to pass when the hook is triggered.
107
+ * @param int $when Unix timestamp when the action will run.
108
+ * @param string $group A group to put the action in.
109
+ * @param bool $unique Whether action scheduled should be unique.
110
+ *
111
+ * @return int The ID of the stored action.
112
+ */
113
+ public function single_unique( $hook, $args = array(), $when = null, $group = '', $unique = true ) {
114
+ $date = as_get_datetime_object( $when );
115
  $schedule = new ActionScheduler_SimpleSchedule( $date );
116
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
117
+ return $unique ? $this->store_unique_action( $action ) : $this->store( $action );
118
  }
119
 
120
  /**
121
  * Create the first instance of an action recurring on a given interval.
122
  *
123
+ * @param string $hook The hook to trigger when this action runs.
124
+ * @param array $args Args to pass when the hook is triggered.
125
+ * @param int $first Unix timestamp for the first run.
126
+ * @param int $interval Seconds between runs.
127
+ * @param string $group A group to put the action in.
128
  *
129
+ * @return int The ID of the stored action.
130
  */
131
  public function recurring( $hook, $args = array(), $first = null, $interval = null, $group = '' ) {
132
+ return $this->recurring_unique( $hook, $args, $first, $interval, $group, false );
133
+ }
134
+
135
+ /**
136
+ * Create the first instance of an action recurring on a given interval only if there is no pending or running action with same name and params.
137
+ *
138
+ * @param string $hook The hook to trigger when this action runs.
139
+ * @param array $args Args to pass when the hook is triggered.
140
+ * @param int $first Unix timestamp for the first run.
141
+ * @param int $interval Seconds between runs.
142
+ * @param string $group A group to put the action in.
143
+ * @param bool $unique Whether action scheduled should be unique.
144
+ *
145
+ * @return int The ID of the stored action.
146
+ */
147
+ public function recurring_unique( $hook, $args = array(), $first = null, $interval = null, $group = '', $unique = true ) {
148
+ if ( empty( $interval ) ) {
149
+ return $this->single_unique( $hook, $unique, $args, $first, $group );
150
  }
151
+ $date = as_get_datetime_object( $first );
152
  $schedule = new ActionScheduler_IntervalSchedule( $date, $interval );
153
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
154
+ return $unique ? $this->store_unique_action( $action ) : $this->store( $action );
155
  }
156
 
157
  /**
158
  * Create the first instance of an action recurring on a Cron schedule.
159
  *
160
+ * @param string $hook The hook to trigger when this action runs.
161
+ * @param array $args Args to pass when the hook is triggered.
162
+ * @param int $base_timestamp The first instance of the action will be scheduled
163
  * to run at a time calculated after this timestamp matching the cron
164
  * expression. This can be used to delay the first instance of the action.
165
+ * @param int $schedule A cron definition string.
166
+ * @param string $group A group to put the action in.
167
  *
168
+ * @return int The ID of the stored action.
169
  */
170
  public function cron( $hook, $args = array(), $base_timestamp = null, $schedule = null, $group = '' ) {
171
+ return $this->cron_unique( $hook, $args, $base_timestamp, $schedule, $group, false );
172
+ }
173
+
174
+
175
+ /**
176
+ * Create the first instance of an action recurring on a Cron schedule only if there is no pending or running action with same name and params.
177
+ *
178
+ * @param string $hook The hook to trigger when this action runs.
179
+ * @param array $args Args to pass when the hook is triggered.
180
+ * @param int $base_timestamp The first instance of the action will be scheduled
181
+ * to run at a time calculated after this timestamp matching the cron
182
+ * expression. This can be used to delay the first instance of the action.
183
+ * @param int $schedule A cron definition string.
184
+ * @param string $group A group to put the action in.
185
+ * @param bool $unique Whether action scheduled should be unique.
186
+ *
187
+ * @return int The ID of the stored action.
188
+ **/
189
+ public function cron_unique( $hook, $args = array(), $base_timestamp = null, $schedule = null, $group = '', $unique = true ) {
190
+ if ( empty( $schedule ) ) {
191
+ return $this->single_unique( $hook, $unique, $args, $base_timestamp, $group );
192
  }
193
+ $date = as_get_datetime_object( $base_timestamp );
194
+ $cron = CronExpression::factory( $schedule );
195
  $schedule = new ActionScheduler_CronSchedule( $date, $cron );
196
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
197
+ return $unique ? $this->store_unique_action( $action ) : $this->store( $action );
198
  }
199
 
200
  /**
230
  }
231
 
232
  $schedule_class = get_class( $schedule );
233
+ $new_schedule = new $schedule( $next, $schedule->get_recurrence(), $schedule->get_first_date() );
234
+ $new_action = new ActionScheduler_Action( $action->get_hook(), $action->get_args(), $new_schedule, $action->get_group() );
235
  return $this->store( $new_action );
236
  }
237
 
238
  /**
239
+ * Save action to database.
240
+ *
241
+ * @param ActionScheduler_Action $action Action object to save.
242
  *
243
  * @return int The ID of the stored action
244
  */
246
  $store = ActionScheduler_Store::instance();
247
  return $store->save_action( $action );
248
  }
249
+
250
+ /**
251
+ * Store action if it's unique.
252
+ *
253
+ * @param ActionScheduler_Action $action Action object to store.
254
+ *
255
+ * @return int ID of the created action. Will be 0 if action was not created.
256
+ */
257
+ protected function store_unique_action( ActionScheduler_Action $action ) {
258
+ $store = ActionScheduler_Store::instance();
259
+ return method_exists( $store, 'save_unique_action' ) ?
260
+ $store->save_unique_action( $action ) : $store->save_action( $action );
261
+ }
262
  }
vendors/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php CHANGED
@@ -40,7 +40,7 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
40
  }
41
 
42
  add_action( 'admin_menu', array( $this, 'register_menu' ) );
43
-
44
  add_action( 'current_screen', array( $this, 'add_help_tabs' ) );
45
  }
46
  }
@@ -110,6 +110,96 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
110
  return $this->list_table;
111
  }
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  /**
114
  * Provide more information about the screen and its data in the help tab.
115
  */
40
  }
41
 
42
  add_action( 'admin_menu', array( $this, 'register_menu' ) );
43
+ add_action( 'admin_notices', array( $this, 'maybe_check_pastdue_actions' ) );
44
  add_action( 'current_screen', array( $this, 'add_help_tabs' ) );
45
  }
46
  }
110
  return $this->list_table;
111
  }
112
 
113
+ /**
114
+ * Action: admin_notices
115
+ *
116
+ * Maybe check past-due actions, and print notice.
117
+ *
118
+ * @uses $this->check_pastdue_actions()
119
+ */
120
+ public function maybe_check_pastdue_actions() {
121
+
122
+ # Filter to prevent checking actions (ex: inappropriate user).
123
+ if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
124
+ return;
125
+ }
126
+
127
+ # Get last check transient.
128
+ $last_check = get_transient( 'action_scheduler_last_pastdue_actions_check' );
129
+
130
+ # If transient exists, we're within interval, so bail.
131
+ if ( ! empty( $last_check ) ) {
132
+ return;
133
+ }
134
+
135
+ # Perform the check.
136
+ $this->check_pastdue_actions();
137
+ }
138
+
139
+ /**
140
+ * Check past-due actions, and print notice.
141
+ *
142
+ * @todo update $link_url to "Past-due" filter when released (see issue #510, PR #511)
143
+ */
144
+ protected function check_pastdue_actions() {
145
+
146
+ # Set thresholds.
147
+ $threshold_seconds = ( int ) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
148
+ $threshhold_min = ( int ) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
149
+
150
+ # Allow third-parties to preempt the default check logic.
151
+ $check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
152
+
153
+ # Scheduled actions query arguments.
154
+ $query_args = array(
155
+ 'date' => as_get_datetime_object( time() - $threshold_seconds ),
156
+ 'status' => ActionScheduler_Store::STATUS_PENDING,
157
+ 'per_page' => $threshhold_min,
158
+ );
159
+
160
+ # If no third-party preempted, run default check.
161
+ if ( is_null( $check ) ) {
162
+ $store = ActionScheduler_Store::instance();
163
+ $num_pastdue_actions = ( int ) $store->query_actions( $query_args, 'count' );
164
+
165
+ # Check if past-due actions count is greater than or equal to threshold.
166
+ $check = ( $num_pastdue_actions >= $threshhold_min );
167
+ $check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshhold_min );
168
+ }
169
+
170
+ # If check failed, set transient and abort.
171
+ if ( ! boolval( $check ) ) {
172
+ $interval = apply_filters( 'action_scheduler_pastdue_actions_check_interval', round( $threshold_seconds / 4 ), $threshold_seconds );
173
+ set_transient( 'action_scheduler_last_pastdue_actions_check', time(), $interval );
174
+
175
+ return;
176
+ }
177
+
178
+ $actions_url = add_query_arg( array(
179
+ 'page' => 'action-scheduler',
180
+ 'status' => 'past-due',
181
+ 'order' => 'asc',
182
+ ), admin_url( 'tools.php' ) );
183
+
184
+ # Print notice.
185
+ echo '<div class="notice notice-warning"><p>';
186
+ printf(
187
+ _n(
188
+ // translators: 1) is the number of affected actions, 2) is a link to an admin screen.
189
+ '<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due action</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation &raquo;</a>',
190
+ '<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due actions</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation &raquo;</a>',
191
+ $num_pastdue_actions,
192
+ 'action-scheduler'
193
+ ),
194
+ $num_pastdue_actions,
195
+ esc_attr( esc_url( $actions_url ) )
196
+ );
197
+ echo '</p></div>';
198
+
199
+ # Facilitate third-parties to evaluate and print notices.
200
+ do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
201
+ }
202
+
203
  /**
204
  * Provide more information about the screen and its data in the help tab.
205
  */
vendors/woocommerce/action-scheduler/classes/ActionScheduler_Exception.php CHANGED
@@ -6,6 +6,6 @@
6
  * Facilitates catching Exceptions unique to Action Scheduler.
7
  *
8
  * @package ActionScheduler
9
- * @since %VERSION%
10
  */
11
  interface ActionScheduler_Exception {}
6
  * Facilitates catching Exceptions unique to Action Scheduler.
7
  *
8
  * @package ActionScheduler
9
+ * @since 2.1.0
10
  */
11
  interface ActionScheduler_Exception {}
vendors/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php CHANGED
@@ -467,6 +467,10 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
467
 
468
  $schedule_display_string = '';
469
 
 
 
 
 
470
  if ( ! $schedule->get_date() ) {
471
  return '0000-00-00 00:00:00';
472
  }
@@ -583,6 +587,16 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
583
  'search' => $this->get_request_search_query(),
584
  );
585
 
 
 
 
 
 
 
 
 
 
 
586
  $this->items = array();
587
 
588
  $total_items = $this->store->query_actions( $query, 'count' );
@@ -623,7 +637,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
623
  * Prints the available statuses so the user can click to filter.
624
  */
625
  protected function display_filter_by_status() {
626
- $this->status_counts = $this->store->action_counts();
627
  parent::display_filter_by_status();
628
  }
629
 
467
 
468
  $schedule_display_string = '';
469
 
470
+ if ( is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
471
+ return __( 'async', 'action-scheduler' );
472
+ }
473
+
474
  if ( ! $schedule->get_date() ) {
475
  return '0000-00-00 00:00:00';
476
  }
587
  'search' => $this->get_request_search_query(),
588
  );
589
 
590
+ /**
591
+ * Change query arguments to query for past-due actions.
592
+ * Past-due actions have the 'pending' status and are in the past.
593
+ * This is needed because registering 'past-due' as a status is overkill.
594
+ */
595
+ if ( 'past-due' === $this->get_request_status() ) {
596
+ $query['status'] = ActionScheduler_Store::STATUS_PENDING;
597
+ $query['date'] = as_get_datetime_object();
598
+ }
599
+
600
  $this->items = array();
601
 
602
  $total_items = $this->store->query_actions( $query, 'count' );
637
  * Prints the available statuses so the user can click to filter.
638
  */
639
  protected function display_filter_by_status() {
640
+ $this->status_counts = $this->store->action_counts() + $this->store->extra_action_counts();
641
  parent::display_filter_by_status();
642
  }
643
 
vendors/woocommerce/action-scheduler/classes/ActionScheduler_QueueRunner.php CHANGED
@@ -173,15 +173,34 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
173
  }
174
 
175
  /**
176
- * Running large batches can eat up memory, as WP adds data to its object cache.
177
  *
178
- * If using a persistent object store, this has the side effect of flushing that
179
- * as well, so this is disabled by default. To enable:
180
- *
181
- * add_filter( 'action_scheduler_queue_runner_flush_cache', '__return_true' );
182
  */
183
  protected function clear_caches() {
184
- if ( ! wp_using_ext_object_cache() || apply_filters( 'action_scheduler_queue_runner_flush_cache', false ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  wp_cache_flush();
186
  }
187
  }
173
  }
174
 
175
  /**
176
+ * Flush the cache if possible (intended for use after a batch of actions has been processed).
177
  *
178
+ * This is useful because running large batches can eat up memory and because invalid data can accrue in the
179
+ * runtime cache, which may lead to unexpected results.
 
 
180
  */
181
  protected function clear_caches() {
182
+ /*
183
+ * Calling wp_cache_flush_runtime() lets us clear the runtime cache without invalidating the external object
184
+ * cache, so we will always prefer this when it is available (but it was only introduced in WordPress 6.0).
185
+ */
186
+ if ( function_exists( 'wp_cache_flush_runtime' ) ) {
187
+ wp_cache_flush_runtime();
188
+ } elseif (
189
+ ! wp_using_ext_object_cache()
190
+ /**
191
+ * When an external object cache is in use, and when wp_cache_flush_runtime() is not available, then
192
+ * normally the cache will not be flushed after processing a batch of actions (to avoid a performance
193
+ * penalty for other processes).
194
+ *
195
+ * This filter makes it possible to override this behavior and always flush the cache, even if an external
196
+ * object cache is in use.
197
+ *
198
+ * @since 1.0
199
+ *
200
+ * @param bool $flush_cache If the cache should be flushed.
201
+ */
202
+ || apply_filters( 'action_scheduler_queue_runner_flush_cache', false )
203
+ ) {
204
  wp_cache_flush();
205
  }
206
  }
vendors/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_Scheduler_command.php CHANGED
@@ -5,6 +5,36 @@
5
  */
6
  class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  /**
9
  * Run the Action Scheduler
10
  *
5
  */
6
  class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
7
 
8
+ /**
9
+ * Force tables schema creation for Action Scheduler
10
+ *
11
+ * ## OPTIONS
12
+ *
13
+ * @param array $args Positional arguments.
14
+ * @param array $assoc_args Keyed arguments.
15
+ *
16
+ * @subcommand fix-schema
17
+ */
18
+ public function fix_schema( $args, $assoc_args ) {
19
+ $schema_classes = array( ActionScheduler_LoggerSchema::class, ActionScheduler_StoreSchema::class );
20
+
21
+ foreach ( $schema_classes as $classname ) {
22
+ if ( is_subclass_of( $classname, ActionScheduler_Abstract_Schema::class ) ) {
23
+ $obj = new $classname();
24
+ $obj->init();
25
+ $obj->register_tables( true );
26
+
27
+ WP_CLI::success(
28
+ sprintf(
29
+ /* translators: %s refers to the schema name*/
30
+ __( 'Registered schema for %s', 'action-scheduler' ),
31
+ $classname
32
+ )
33
+ );
34
+ }
35
+ }
36
+ }
37
+
38
  /**
39
  * Run the Action Scheduler
40
  *
vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler.php CHANGED
@@ -118,8 +118,8 @@ abstract class ActionScheduler {
118
  return;
119
  }
120
 
121
- if ( file_exists( "{$dir}{$class}.php" ) ) {
122
- include( "{$dir}{$class}.php" );
123
  return;
124
  }
125
  }
118
  return;
119
  }
120
 
121
+ if ( file_exists( $dir . "{$class}.php" ) ) {
122
+ include( $dir . "{$class}.php" );
123
  return;
124
  }
125
  }
vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php CHANGED
@@ -683,7 +683,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
683
  }
684
 
685
  if ( $status_name === $request_status || ( empty( $request_status ) && 'all' === $status_name ) ) {
686
- $status_list_item = '<li class="%1$s"><strong>%3$s</strong> (%4$d)</li>';
687
  } else {
688
  $status_list_item = '<li class="%1$s"><a href="%2$s">%3$s</a> (%4$d)</li>';
689
  }
683
  }
684
 
685
  if ( $status_name === $request_status || ( empty( $request_status ) && 'all' === $status_name ) ) {
686
+ $status_list_item = '<li class="%1$s"><a href="%2$s" class="current">%3$s</a> (%4$d)</li>';
687
  } else {
688
  $status_list_item = '<li class="%1$s"><a href="%2$s">%3$s</a> (%4$d)</li>';
689
  }
vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php CHANGED
@@ -86,6 +86,19 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
86
  * @param int $action_id
87
  */
88
  protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  try {
90
  ActionScheduler::factory()->repeat( $action );
91
  } catch ( Exception $e ) {
@@ -93,6 +106,51 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
93
  }
94
  }
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  /**
97
  * Run the queue cleaner.
98
  *
86
  * @param int $action_id
87
  */
88
  protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
89
+ // If a recurring action has been consistently failing, we may wish to stop rescheduling it.
90
+ if (
91
+ ActionScheduler_Store::STATUS_FAILED === $this->store->get_status( $action_id )
92
+ && $this->recurring_action_is_consistently_failing( $action, $action_id )
93
+ ) {
94
+ ActionScheduler_Logger::instance()->log(
95
+ $action_id,
96
+ __( 'This action appears to be consistently failing. A new instance will not be scheduled.', 'action-scheduler' )
97
+ );
98
+
99
+ return;
100
+ }
101
+
102
  try {
103
  ActionScheduler::factory()->repeat( $action );
104
  } catch ( Exception $e ) {
106
  }
107
  }
108
 
109
+ /**
110
+ * Determine if the specified recurring action has been consistently failing.
111
+ *
112
+ * @param ActionScheduler_Action $action The recurring action to be rescheduled.
113
+ * @param int $action_id The ID of the recurring action.
114
+ *
115
+ * @return bool
116
+ */
117
+ private function recurring_action_is_consistently_failing( ActionScheduler_Action $action, $action_id ) {
118
+ /**
119
+ * Controls the failure threshold for recurring actions.
120
+ *
121
+ * Before rescheduling a recurring action, we look at its status. If it failed, we then check if all of the most
122
+ * recent actions (upto the threshold set by this filter) sharing the same hook have also failed: if they have,
123
+ * that is considered consistent failure and a new instance of the action will not be scheduled.
124
+ *
125
+ * @param int $failure_threshold Number of actions of the same hook to examine for failure. Defaults to 5.
126
+ */
127
+ $consistent_failure_threshold = (int) apply_filters( 'action_scheduler_recurring_action_failure_threshold', 5 );
128
+
129
+ // This query should find the earliest *failing* action (for the hook we are interested in) within our threshold.
130
+ $query_args = array(
131
+ 'hook' => $action->get_hook(),
132
+ 'status' => ActionScheduler_Store::STATUS_FAILED,
133
+ 'date' => date_create( 'now', timezone_open( 'UTC' ) )->format( 'Y-m-d H:i:s' ),
134
+ 'date_compare' => '<',
135
+ 'per_page' => 1,
136
+ 'offset' => $consistent_failure_threshold - 1
137
+ );
138
+
139
+ $first_failing_action_id = $this->store->query_actions( $query_args );
140
+
141
+ // If we didn't retrieve an action ID, then there haven't been enough failures for us to worry about.
142
+ if ( empty( $first_failing_action_id ) ) {
143
+ return false;
144
+ }
145
+
146
+ // Now let's fetch the first action (having the same hook) of *any status*ithin the same window.
147
+ unset( $query_args['status'] );
148
+ $first_action_id_with_the_same_hook = $this->store->query_actions( $query_args );
149
+
150
+ // If the IDs match, then actions for this hook must be consistently failing.
151
+ return $first_action_id_with_the_same_hook === $first_failing_action_id;
152
+ }
153
+
154
  /**
155
  * Run the queue cleaner.
156
  *
vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php CHANGED
@@ -109,7 +109,7 @@ abstract class ActionScheduler_Logger {
109
 
110
  public function log_timed_out_action( $action_id, $timeout ) {
111
  /* translators: %s: amount of time */
112
- $this->log( $action_id, sprintf( __( 'action marked as failed after %s seconds', 'action-scheduler' ), $timeout ) );
113
  }
114
 
115
  public function log_unexpected_shutdown( $action_id, $error ) {
109
 
110
  public function log_timed_out_action( $action_id, $timeout ) {
111
  /* translators: %s: amount of time */
112
+ $this->log( $action_id, sprintf( __( 'action marked as failed after %s seconds. Unknown error occurred. Check server, PHP and database error logs to diagnose cause.', 'action-scheduler' ), $timeout ) );
113
  }
114
 
115
  public function log_unexpected_shutdown( $action_id, $error ) {
vendors/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php CHANGED
@@ -76,7 +76,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
76
  /**
77
  * Query for action count or list of action IDs.
78
  *
79
- * @since x.x.x $query['status'] accepts array of statuses instead of a single status.
80
  *
81
  * @param array $query {
82
  * Query filtering options.
@@ -104,7 +104,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
104
  /**
105
  * Run query to get a single action ID.
106
  *
107
- * @since x.x.x
108
  *
109
  * @see ActionScheduler_Store::query_actions for $query arg usage but 'per_page' and 'offset' can't be used.
110
  *
@@ -131,6 +131,34 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
131
  */
132
  abstract public function action_counts();
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  /**
135
  * @param string $action_id
136
  */
76
  /**
77
  * Query for action count or list of action IDs.
78
  *
79
+ * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
80
  *
81
  * @param array $query {
82
  * Query filtering options.
104
  /**
105
  * Run query to get a single action ID.
106
  *
107
+ * @since 3.3.0
108
  *
109
  * @see ActionScheduler_Store::query_actions for $query arg usage but 'per_page' and 'offset' can't be used.
110
  *
131
  */
132
  abstract public function action_counts();
133
 
134
+ /**
135
+ * Get additional action counts.
136
+ *
137
+ * - add past-due actions
138
+ *
139
+ * @return array
140
+ */
141
+ public function extra_action_counts() {
142
+ $extra_actions = array();
143
+
144
+ $pastdue_action_counts = ( int ) $this->query_actions( array(
145
+ 'status' => self::STATUS_PENDING,
146
+ 'date' => as_get_datetime_object(),
147
+ ), 'count' );
148
+
149
+ if ( $pastdue_action_counts ) {
150
+ $extra_actions['past-due'] = $pastdue_action_counts;
151
+ }
152
+
153
+ /**
154
+ * Allows 3rd party code to add extra action counts (used in filters in the list table).
155
+ *
156
+ * @since 3.5.0
157
+ * @param $extra_actions array Array with format action_count_identifier => action count.
158
+ */
159
+ return apply_filters( 'action_scheduler_extra_action_counts', $extra_actions );
160
+ }
161
+
162
  /**
163
  * @param string $action_id
164
  */
vendors/woocommerce/action-scheduler/classes/actions/ActionScheduler_Action.php CHANGED
@@ -18,8 +18,29 @@ class ActionScheduler_Action {
18
  $this->set_group($group);
19
  }
20
 
 
 
 
 
 
 
 
 
 
21
  public function execute() {
22
- return do_action_ref_array( $this->get_hook(), array_values( $this->get_args() ) );
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
 
25
  /**
18
  $this->set_group($group);
19
  }
20
 
21
+ /**
22
+ * Executes the action.
23
+ *
24
+ * If no callbacks are registered, an exception will be thrown and the action will not be
25
+ * fired. This is useful to help detect cases where the code responsible for setting up
26
+ * a scheduled action no longer exists.
27
+ *
28
+ * @throws Exception If no callbacks are registered for this action.
29
+ */
30
  public function execute() {
31
+ $hook = $this->get_hook();
32
+
33
+ if ( ! has_action( $hook ) ) {
34
+ throw new Exception(
35
+ sprintf(
36
+ /* translators: 1: action hook. */
37
+ __( 'Scheduled action for %1$s will not be executed as no callbacks are registered.', 'action-scheduler' ),
38
+ $hook
39
+ )
40
+ );
41
+ }
42
+
43
+ do_action_ref_array( $hook, array_values( $this->get_args() ) );
44
  }
45
 
46
  /**
vendors/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php CHANGED
@@ -36,22 +36,48 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
36
  $table_maker->register_tables();
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  /**
40
  * Save an action.
41
  *
42
  * @param ActionScheduler_Action $action Action object.
43
- * @param DateTime $date Optional schedule date. Default null.
 
44
  *
45
  * @return int Action ID.
46
  * @throws RuntimeException Throws exception when saving the action fails.
47
  */
48
- public function save_action( ActionScheduler_Action $action, \DateTime $date = null ) {
49
- try {
50
 
 
51
  $this->validate_action( $action );
52
 
53
- /** @var \wpdb $wpdb */
54
- global $wpdb;
55
  $data = array(
56
  'hook' => $action->get_hook(),
57
  'status' => ( $action->is_finished() ? self::STATUS_COMPLETE : self::STATUS_PENDING ),
@@ -60,6 +86,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
60
  'schedule' => serialize( $action->get_schedule() ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
61
  'group_id' => $this->get_group_id( $action->get_group() ),
62
  );
 
63
  $args = wp_json_encode( $action->get_args() );
64
  if ( strlen( $args ) <= static::$max_index_length ) {
65
  $data['args'] = $args;
@@ -68,13 +95,18 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
68
  $data['extended_args'] = $args;
69
  }
70
 
71
- $table_name = ! empty( $wpdb->actionscheduler_actions ) ? $wpdb->actionscheduler_actions : $wpdb->prefix . 'actionscheduler_actions';
72
- $wpdb->insert( $table_name, $data );
 
 
73
  $action_id = $wpdb->insert_id;
74
 
75
  if ( is_wp_error( $action_id ) ) {
76
  throw new \RuntimeException( $action_id->get_error_message() );
77
  } elseif ( empty( $action_id ) ) {
 
 
 
78
  throw new \RuntimeException( $wpdb->last_error ? $wpdb->last_error : __( 'Database error.', 'action-scheduler' ) );
79
  }
80
 
@@ -87,6 +119,103 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
87
  }
88
  }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  /**
91
  * Generate a hash from json_encoded $args using MD5 as this isn't for security.
92
  *
@@ -232,7 +361,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
232
  /**
233
  * Returns the SQL statement to query (or count) actions.
234
  *
235
- * @since x.x.x $query['status'] accepts array of statuses instead of a single status.
236
  *
237
  * @param array $query Filtering options.
238
  * @param string $select_or_count Whether the SQL should select and return the IDs or just the row count.
@@ -384,7 +513,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
384
  /**
385
  * Query for action count or list of action IDs.
386
  *
387
- * @since x.x.x $query['status'] accepts array of statuses instead of a single status.
388
  *
389
  * @see ActionScheduler_Store::query_actions for $query arg usage.
390
  *
@@ -446,7 +575,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
446
  array( '%s' ),
447
  array( '%d' )
448
  );
449
- if ( empty( $updated ) ) {
450
  /* translators: %s: action ID */
451
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
452
  }
@@ -670,7 +799,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
670
  /**
671
  * Sets the order-by clause used in the action claim query.
672
  *
673
- * @since x.x.x
674
  *
675
  * @param string $order_by_sql
676
  */
@@ -839,6 +968,15 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
839
  if ( empty( $updated ) ) {
840
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) ); //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
841
  }
 
 
 
 
 
 
 
 
 
842
  }
843
 
844
  /**
36
  $table_maker->register_tables();
37
  }
38
 
39
+ /**
40
+ * Save an action, checks if this is a unique action before actually saving.
41
+ *
42
+ * @param ActionScheduler_Action $action Action object.
43
+ * @param \DateTime $scheduled_date Optional schedule date. Default null.
44
+ *
45
+ * @return int Action ID.
46
+ * @throws RuntimeException Throws exception when saving the action fails.
47
+ */
48
+ public function save_unique_action( ActionScheduler_Action $action, \DateTime $scheduled_date = null ) {
49
+ return $this->save_action_to_db( $action, $scheduled_date, true );
50
+ }
51
+
52
+ /**
53
+ * Save an action. Can save duplicate action as well, prefer using `save_unique_action` instead.
54
+ *
55
+ * @param ActionScheduler_Action $action Action object.
56
+ * @param \DateTime $scheduled_date Optional schedule date. Default null.
57
+ *
58
+ * @return int Action ID.
59
+ * @throws RuntimeException Throws exception when saving the action fails.
60
+ */
61
+ public function save_action( ActionScheduler_Action $action, \DateTime $scheduled_date = null ) {
62
+ return $this->save_action_to_db( $action, $scheduled_date, false );
63
+ }
64
+
65
  /**
66
  * Save an action.
67
  *
68
  * @param ActionScheduler_Action $action Action object.
69
+ * @param ?DateTime $date Optional schedule date. Default null.
70
+ * @param bool $unique Whether the action should be unique.
71
  *
72
  * @return int Action ID.
73
  * @throws RuntimeException Throws exception when saving the action fails.
74
  */
75
+ private function save_action_to_db( ActionScheduler_Action $action, DateTime $date = null, $unique = false ) {
76
+ global $wpdb;
77
 
78
+ try {
79
  $this->validate_action( $action );
80
 
 
 
81
  $data = array(
82
  'hook' => $action->get_hook(),
83
  'status' => ( $action->is_finished() ? self::STATUS_COMPLETE : self::STATUS_PENDING ),
86
  'schedule' => serialize( $action->get_schedule() ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
87
  'group_id' => $this->get_group_id( $action->get_group() ),
88
  );
89
+
90
  $args = wp_json_encode( $action->get_args() );
91
  if ( strlen( $args ) <= static::$max_index_length ) {
92
  $data['args'] = $args;
95
  $data['extended_args'] = $args;
96
  }
97
 
98
+ $insert_sql = $this->build_insert_sql( $data, $unique );
99
+
100
+ // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $insert_sql should be already prepared.
101
+ $wpdb->query( $insert_sql );
102
  $action_id = $wpdb->insert_id;
103
 
104
  if ( is_wp_error( $action_id ) ) {
105
  throw new \RuntimeException( $action_id->get_error_message() );
106
  } elseif ( empty( $action_id ) ) {
107
+ if ( $unique ) {
108
+ return 0;
109
+ }
110
  throw new \RuntimeException( $wpdb->last_error ? $wpdb->last_error : __( 'Database error.', 'action-scheduler' ) );
111
  }
112
 
119
  }
120
  }
121
 
122
+ /**
123
+ * Helper function to build insert query.
124
+ *
125
+ * @param array $data Row data for action.
126
+ * @param bool $unique Whether the action should be unique.
127
+ *
128
+ * @return string Insert query.
129
+ */
130
+ private function build_insert_sql( array $data, $unique ) {
131
+ global $wpdb;
132
+ $columns = array_keys( $data );
133
+ $values = array_values( $data );
134
+ $placeholders = array_map( array( $this, 'get_placeholder_for_column' ), $columns );
135
+
136
+ $table_name = ! empty( $wpdb->actionscheduler_actions ) ? $wpdb->actionscheduler_actions : $wpdb->prefix . 'actionscheduler_actions';
137
+
138
+ $column_sql = '`' . implode( '`, `', $columns ) . '`';
139
+ $placeholder_sql = implode( ', ', $placeholders );
140
+ $where_clause = $this->build_where_clause_for_insert( $data, $table_name, $unique );
141
+ // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $column_sql and $where_clause are already prepared. $placeholder_sql is hardcoded.
142
+ $insert_query = $wpdb->prepare(
143
+ "
144
+ INSERT INTO $table_name ( $column_sql )
145
+ SELECT $placeholder_sql FROM DUAL
146
+ WHERE ( $where_clause ) IS NULL",
147
+ $values
148
+ );
149
+ // phpcs:enable
150
+
151
+ return $insert_query;
152
+ }
153
+
154
+ /**
155
+ * Helper method to build where clause for action insert statement.
156
+ *
157
+ * @param array $data Row data for action.
158
+ * @param string $table_name Action table name.
159
+ * @param bool $unique Where action should be unique.
160
+ *
161
+ * @return string Where clause to be used with insert.
162
+ */
163
+ private function build_where_clause_for_insert( $data, $table_name, $unique ) {
164
+ global $wpdb;
165
+
166
+ if ( ! $unique ) {
167
+ return 'SELECT NULL FROM DUAL';
168
+ }
169
+
170
+ $pending_statuses = array(
171
+ ActionScheduler_Store::STATUS_PENDING,
172
+ ActionScheduler_Store::STATUS_RUNNING,
173
+ );
174
+ $pending_status_placeholders = implode( ', ', array_fill( 0, count( $pending_statuses ), '%s' ) );
175
+ // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $pending_status_placeholders is hardcoded.
176
+ $where_clause = $wpdb->prepare(
177
+ "
178
+ SELECT action_id FROM $table_name
179
+ WHERE status IN ( $pending_status_placeholders )
180
+ AND hook = %s
181
+ AND `group_id` = %d
182
+ ",
183
+ array_merge(
184
+ $pending_statuses,
185
+ array(
186
+ $data['hook'],
187
+ $data['group_id'],
188
+ )
189
+ )
190
+ );
191
+ // phpcs:enable
192
+
193
+ return "$where_clause" . ' LIMIT 1';
194
+ }
195
+
196
+ /**
197
+ * Helper method to get $wpdb->prepare placeholder for a given column name.
198
+ *
199
+ * @param string $column_name Name of column in actions table.
200
+ *
201
+ * @return string Placeholder to use for given column.
202
+ */
203
+ private function get_placeholder_for_column( $column_name ) {
204
+ $string_columns = array(
205
+ 'hook',
206
+ 'status',
207
+ 'scheduled_date_gmt',
208
+ 'scheduled_date_local',
209
+ 'args',
210
+ 'schedule',
211
+ 'last_attempt_gmt',
212
+ 'last_attempt_local',
213
+ 'extended_args',
214
+ );
215
+
216
+ return in_array( $column_name, $string_columns ) ? '%s' : '%d';
217
+ }
218
+
219
  /**
220
  * Generate a hash from json_encoded $args using MD5 as this isn't for security.
221
  *
361
  /**
362
  * Returns the SQL statement to query (or count) actions.
363
  *
364
+ * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
365
  *
366
  * @param array $query Filtering options.
367
  * @param string $select_or_count Whether the SQL should select and return the IDs or just the row count.
513
  /**
514
  * Query for action count or list of action IDs.
515
  *
516
+ * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
517
  *
518
  * @see ActionScheduler_Store::query_actions for $query arg usage.
519
  *
575
  array( '%s' ),
576
  array( '%d' )
577
  );
578
+ if ( false === $updated ) {
579
  /* translators: %s: action ID */
580
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
581
  }
799
  /**
800
  * Sets the order-by clause used in the action claim query.
801
  *
802
+ * @since 3.4.0
803
  *
804
  * @param string $order_by_sql
805
  */
968
  if ( empty( $updated ) ) {
969
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) ); //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
970
  }
971
+
972
+ /**
973
+ * Fires after a scheduled action has been completed.
974
+ *
975
+ * @since 3.4.2
976
+ *
977
+ * @param int $action_id Action ID.
978
+ */
979
+ do_action( 'action_scheduler_completed_action', $action_id );
980
  }
981
 
982
  /**
vendors/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php CHANGED
@@ -452,7 +452,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
452
  /**
453
  * Query for action count or list of action IDs.
454
  *
455
- * @since x.x.x $query['status'] accepts array of statuses instead of a single status.
456
  *
457
  * @see ActionScheduler_Store::query_actions for $query arg usage.
458
  *
@@ -987,6 +987,15 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
987
  if ( is_wp_error( $result ) ) {
988
  throw new RuntimeException( $result->get_error_message() );
989
  }
 
 
 
 
 
 
 
 
 
990
  }
991
 
992
  /**
452
  /**
453
  * Query for action count or list of action IDs.
454
  *
455
+ * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
456
  *
457
  * @see ActionScheduler_Store::query_actions for $query arg usage.
458
  *
987
  if ( is_wp_error( $result ) ) {
988
  throw new RuntimeException( $result->get_error_message() );
989
  }
990
+
991
+ /**
992
+ * Fires after a scheduled action has been completed.
993
+ *
994
+ * @since 3.4.2
995
+ *
996
+ * @param int $action_id Action ID.
997
+ */
998
+ do_action( 'action_scheduler_completed_action', $action_id );
999
  }
1000
 
1001
  /**
vendors/woocommerce/action-scheduler/classes/schema/ActionScheduler_LoggerSchema.php CHANGED
@@ -37,12 +37,12 @@ class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema {
37
  case self::LOG_TABLE:
38
 
39
  $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE;
40
- return "CREATE TABLE {$table_name} (
41
  log_id bigint(20) unsigned NOT NULL auto_increment,
42
  action_id bigint(20) unsigned NOT NULL,
43
  message text NOT NULL,
44
- log_date_gmt datetime NULL default '${default_date}',
45
- log_date_local datetime NULL default '${default_date}',
46
  PRIMARY KEY (log_id),
47
  KEY action_id (action_id),
48
  KEY log_date_gmt (log_date_gmt)
@@ -74,14 +74,14 @@ class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema {
74
 
75
  // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
76
  $table_name = $wpdb->prefix . 'actionscheduler_logs';
77
- $table_list = $wpdb->get_col( "SHOW TABLES LIKE '${table_name}'" );
78
  $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE;
79
 
80
  if ( ! empty( $table_list ) ) {
81
  $query = "
82
- ALTER TABLE ${table_name}
83
- MODIFY COLUMN log_date_gmt datetime NULL default '${default_date}',
84
- MODIFY COLUMN log_date_local datetime NULL default '${default_date}'
85
  ";
86
  $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
87
  }
37
  case self::LOG_TABLE:
38
 
39
  $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE;
40
+ return "CREATE TABLE $table_name (
41
  log_id bigint(20) unsigned NOT NULL auto_increment,
42
  action_id bigint(20) unsigned NOT NULL,
43
  message text NOT NULL,
44
+ log_date_gmt datetime NULL default '{$default_date}',
45
+ log_date_local datetime NULL default '{$default_date}',
46
  PRIMARY KEY (log_id),
47
  KEY action_id (action_id),
48
  KEY log_date_gmt (log_date_gmt)
74
 
75
  // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
76
  $table_name = $wpdb->prefix . 'actionscheduler_logs';
77
+ $table_list = $wpdb->get_col( "SHOW TABLES LIKE '{$table_name}'" );
78
  $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE;
79
 
80
  if ( ! empty( $table_list ) ) {
81
  $query = "
82
+ ALTER TABLE {$table_name}
83
+ MODIFY COLUMN log_date_gmt datetime NULL default '{$default_date}',
84
+ MODIFY COLUMN log_date_local datetime NULL default '{$default_date}'
85
  ";
86
  $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
87
  }
vendors/woocommerce/action-scheduler/functions.php CHANGED
@@ -1,7 +1,8 @@
1
  <?php
2
-
3
  /**
4
  * General API functions for scheduling actions
 
 
5
  */
6
 
7
  /**
@@ -10,57 +11,61 @@
10
  * @param string $hook The hook to trigger.
11
  * @param array $args Arguments to pass when the hook triggers.
12
  * @param string $group The group to assign this job to.
 
 
13
  * @return int The action ID.
14
  */
15
- function as_enqueue_async_action( $hook, $args = array(), $group = '' ) {
16
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
17
  return 0;
18
  }
19
- return ActionScheduler::factory()->async( $hook, $args, $group );
20
  }
21
 
22
  /**
23
  * Schedule an action to run one time
24
  *
25
- * @param int $timestamp When the job will run.
26
  * @param string $hook The hook to trigger.
27
- * @param array $args Arguments to pass when the hook triggers.
28
  * @param string $group The group to assign this job to.
 
29
  *
30
  * @return int The action ID.
31
  */
32
- function as_schedule_single_action( $timestamp, $hook, $args = array(), $group = '' ) {
33
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
34
  return 0;
35
  }
36
- return ActionScheduler::factory()->single( $hook, $args, $timestamp, $group );
37
  }
38
 
39
  /**
40
  * Schedule a recurring action
41
  *
42
- * @param int $timestamp When the first instance of the job will run.
43
- * @param int $interval_in_seconds How long to wait between runs.
44
  * @param string $hook The hook to trigger.
45
- * @param array $args Arguments to pass when the hook triggers.
46
  * @param string $group The group to assign this job to.
 
47
  *
48
  * @return int The action ID.
49
  */
50
- function as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) {
51
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
52
  return 0;
53
  }
54
- return ActionScheduler::factory()->recurring( $hook, $args, $timestamp, $interval_in_seconds, $group );
55
  }
56
 
57
  /**
58
  * Schedule an action that recurs on a cron-like schedule.
59
  *
60
- * @param int $base_timestamp The first instance of the action will be scheduled
61
- * to run at a time calculated after this timestamp matching the cron
62
- * expression. This can be used to delay the first instance of the action.
63
- * @param string $schedule A cron-link schedule string
64
  * @see http://en.wikipedia.org/wiki/Cron
65
  * * * * * * *
66
  * ┬ ┬ ┬ ┬ ┬ ┬
@@ -72,16 +77,17 @@ function as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook,
72
  * | +-------------------- hour (0 - 23)
73
  * +------------------------- min (0 - 59)
74
  * @param string $hook The hook to trigger.
75
- * @param array $args Arguments to pass when the hook triggers.
76
  * @param string $group The group to assign this job to.
 
77
  *
78
  * @return int The action ID.
79
  */
80
- function as_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(), $group = '' ) {
81
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
82
  return 0;
83
  }
84
- return ActionScheduler::factory()->cron( $hook, $args, $timestamp, $schedule, $group );
85
  }
86
 
87
  /**
@@ -95,10 +101,10 @@ function as_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(),
95
  * by this method also.
96
  *
97
  * @param string $hook The hook that the job will trigger.
98
- * @param array $args Args that would have been passed to the job.
99
  * @param string $group The group the job is assigned to.
100
  *
101
- * @return string|null The scheduled action ID if a scheduled action was found, or null if no matching action found.
102
  */
103
  function as_unschedule_action( $hook, $args = array(), $group = '' ) {
104
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
@@ -116,8 +122,22 @@ function as_unschedule_action( $hook, $args = array(), $group = '' ) {
116
  }
117
 
118
  $action_id = ActionScheduler::store()->query_action( $params );
 
119
  if ( $action_id ) {
120
- ActionScheduler::store()->cancel_action( $action_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
  return $action_id;
@@ -127,7 +147,7 @@ function as_unschedule_action( $hook, $args = array(), $group = '' ) {
127
  * Cancel all occurrences of a scheduled action.
128
  *
129
  * @param string $hook The hook that the job will trigger.
130
- * @param array $args Args that would have been passed to the job.
131
  * @param string $group The group the job is assigned to.
132
  */
133
  function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
@@ -158,9 +178,9 @@ function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
158
  * returned. Or there may be no async, in-progress or pending action for this hook, in which case,
159
  * boolean false will be the return value.
160
  *
161
- * @param string $hook
162
- * @param array $args
163
- * @param string $group
164
  *
165
  * @return int|bool The timestamp for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action.
166
  */
@@ -196,7 +216,7 @@ function as_next_scheduled_action( $hook, $args = null, $group = '' ) {
196
  $scheduled_date = $action->get_schedule()->get_date();
197
  if ( $scheduled_date ) {
198
  return (int) $scheduled_date->format( 'U' );
199
- } elseif ( null === $scheduled_date ) { // pending async action with NullSchedule
200
  return true;
201
  }
202
 
@@ -209,7 +229,7 @@ function as_next_scheduled_action( $hook, $args = null, $group = '' ) {
209
  * It's recommended to use this function when you need to know whether a specific action is currently scheduled
210
  * (pending or in-progress).
211
  *
212
- * @since x.x.x
213
  *
214
  * @param string $hook The hook of the action.
215
  * @param array $args Args that have been passed to the action. Null will matches any args.
@@ -223,10 +243,10 @@ function as_has_scheduled_action( $hook, $args = null, $group = '' ) {
223
  }
224
 
225
  $query_args = array(
226
- 'hook' => $hook,
227
- 'status' => array( ActionScheduler_Store::STATUS_RUNNING, ActionScheduler_Store::STATUS_PENDING ),
228
- 'group' => $group,
229
- 'orderby' => 'none',
230
  );
231
 
232
  if ( null !== $args ) {
@@ -235,26 +255,26 @@ function as_has_scheduled_action( $hook, $args = null, $group = '' ) {
235
 
236
  $action_id = ActionScheduler::store()->query_action( $query_args );
237
 
238
- return $action_id !== null;
239
  }
240
 
241
  /**
242
  * Find scheduled actions
243
  *
244
- * @param array $args Possible arguments, with their default values:
245
- * 'hook' => '' - the name of the action that will be triggered
246
- * 'args' => NULL - the args array that will be passed with the action
247
- * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
248
- * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='
249
- * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
250
- * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='
251
- * 'group' => '' - the group the action belongs to
252
- * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING
253
- * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID
254
- * 'per_page' => 5 - Number of results to return
255
- * 'offset' => 0
256
- * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', 'date' or 'none'
257
- * 'order' => 'ASC'
258
  *
259
  * @param string $return_format OBJECT, ARRAY_A, or ids.
260
  *
@@ -265,25 +285,25 @@ function as_get_scheduled_actions( $args = array(), $return_format = OBJECT ) {
265
  return array();
266
  }
267
  $store = ActionScheduler::store();
268
- foreach ( array('date', 'modified') as $key ) {
269
- if ( isset($args[$key]) ) {
270
- $args[$key] = as_get_datetime_object($args[$key]);
271
  }
272
  }
273
  $ids = $store->query_actions( $args );
274
 
275
- if ( $return_format == 'ids' || $return_format == 'int' ) {
276
  return $ids;
277
  }
278
 
279
  $actions = array();
280
  foreach ( $ids as $action_id ) {
281
- $actions[$action_id] = $store->fetch_action( $action_id );
282
  }
283
 
284
- if ( $return_format == ARRAY_A ) {
285
  foreach ( $actions as $action_id => $action_object ) {
286
- $actions[$action_id] = get_object_vars($action_object);
287
  }
288
  }
289
 
@@ -302,7 +322,7 @@ function as_get_scheduled_actions( $args = array(), $return_format = OBJECT ) {
302
  * timezone when instantiating datetimes rather than leaving it up to
303
  * the PHP default.
304
  *
305
- * @param mixed $date_string A date/time string. Valid formats are explained in http://php.net/manual/en/datetime.formats.php.
306
  * @param string $timezone A timezone identifier, like UTC or Europe/Lisbon. The list of valid identifiers is available http://php.net/manual/en/timezones.php.
307
  *
308
  * @return ActionScheduler_DateTime
1
  <?php
 
2
  /**
3
  * General API functions for scheduling actions
4
+ *
5
+ * @package ActionScheduler.
6
  */
7
 
8
  /**
11
  * @param string $hook The hook to trigger.
12
  * @param array $args Arguments to pass when the hook triggers.
13
  * @param string $group The group to assign this job to.
14
+ * @param bool $unique Whether the action should be unique.
15
+ *
16
  * @return int The action ID.
17
  */
18
+ function as_enqueue_async_action( $hook, $args = array(), $group = '', $unique = false ) {
19
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
20
  return 0;
21
  }
22
+ return ActionScheduler::factory()->async_unique( $hook, $args, $group, $unique );
23
  }
24
 
25
  /**
26
  * Schedule an action to run one time
27
  *
28
+ * @param int $timestamp When the job will run.
29
  * @param string $hook The hook to trigger.
30
+ * @param array $args Arguments to pass when the hook triggers.
31
  * @param string $group The group to assign this job to.
32
+ * @param bool $unique Whether the action should be unique.
33
  *
34
  * @return int The action ID.
35
  */
36
+ function as_schedule_single_action( $timestamp, $hook, $args = array(), $group = '', $unique = false ) {
37
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
38
  return 0;
39
  }
40
+ return ActionScheduler::factory()->single_unique( $hook, $args, $timestamp, $group, $unique );
41
  }
42
 
43
  /**
44
  * Schedule a recurring action
45
  *
46
+ * @param int $timestamp When the first instance of the job will run.
47
+ * @param int $interval_in_seconds How long to wait between runs.
48
  * @param string $hook The hook to trigger.
49
+ * @param array $args Arguments to pass when the hook triggers.
50
  * @param string $group The group to assign this job to.
51
+ * @param bool $unique Whether the action should be unique.
52
  *
53
  * @return int The action ID.
54
  */
55
+ function as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '', $unique = false ) {
56
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
57
  return 0;
58
  }
59
+ return ActionScheduler::factory()->recurring_unique( $hook, $args, $timestamp, $interval_in_seconds, $group, $unique );
60
  }
61
 
62
  /**
63
  * Schedule an action that recurs on a cron-like schedule.
64
  *
65
+ * @param int $timestamp The first instance of the action will be scheduled
66
+ * to run at a time calculated after this timestamp matching the cron
67
+ * expression. This can be used to delay the first instance of the action.
68
+ * @param string $schedule A cron-link schedule string.
69
  * @see http://en.wikipedia.org/wiki/Cron
70
  * * * * * * *
71
  * ┬ ┬ ┬ ┬ ┬ ┬
77
  * | +-------------------- hour (0 - 23)
78
  * +------------------------- min (0 - 59)
79
  * @param string $hook The hook to trigger.
80
+ * @param array $args Arguments to pass when the hook triggers.
81
  * @param string $group The group to assign this job to.
82
+ * @param bool $unique Whether the action should be unique.
83
  *
84
  * @return int The action ID.
85
  */
86
+ function as_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(), $group = '', $unique = false ) {
87
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
88
  return 0;
89
  }
90
+ return ActionScheduler::factory()->cron_unique( $hook, $args, $timestamp, $schedule, $group, $unique );
91
  }
92
 
93
  /**
101
  * by this method also.
102
  *
103
  * @param string $hook The hook that the job will trigger.
104
+ * @param array $args Args that would have been passed to the job.
105
  * @param string $group The group the job is assigned to.
106
  *
107
+ * @return int|null The scheduled action ID if a scheduled action was found, or null if no matching action found.
108
  */
109
  function as_unschedule_action( $hook, $args = array(), $group = '' ) {
110
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
122
  }
123
 
124
  $action_id = ActionScheduler::store()->query_action( $params );
125
+
126
  if ( $action_id ) {
127
+ try {
128
+ ActionScheduler::store()->cancel_action( $action_id );
129
+ } catch ( Exception $exception ) {
130
+ ActionScheduler::logger()->log(
131
+ $action_id,
132
+ sprintf(
133
+ /* translators: %s is the name of the hook to be cancelled. */
134
+ __( 'Caught exception while cancelling action: %s', 'action-scheduler' ),
135
+ esc_attr( $hook )
136
+ )
137
+ );
138
+
139
+ $action_id = null;
140
+ }
141
  }
142
 
143
  return $action_id;
147
  * Cancel all occurrences of a scheduled action.
148
  *
149
  * @param string $hook The hook that the job will trigger.
150
+ * @param array $args Args that would have been passed to the job.
151
  * @param string $group The group the job is assigned to.
152
  */
153
  function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
178
  * returned. Or there may be no async, in-progress or pending action for this hook, in which case,
179
  * boolean false will be the return value.
180
  *
181
+ * @param string $hook Name of the hook to search for.
182
+ * @param array $args Arguments of the action to be searched.
183
+ * @param string $group Group of the action to be searched.
184
  *
185
  * @return int|bool The timestamp for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action.
186
  */
216
  $scheduled_date = $action->get_schedule()->get_date();
217
  if ( $scheduled_date ) {
218
  return (int) $scheduled_date->format( 'U' );
219
+ } elseif ( null === $scheduled_date ) { // pending async action with NullSchedule.
220
  return true;
221
  }
222
 
229
  * It's recommended to use this function when you need to know whether a specific action is currently scheduled
230
  * (pending or in-progress).
231
  *
232
+ * @since 3.3.0
233
  *
234
  * @param string $hook The hook of the action.
235
  * @param array $args Args that have been passed to the action. Null will matches any args.
243
  }
244
 
245
  $query_args = array(
246
+ 'hook' => $hook,
247
+ 'status' => array( ActionScheduler_Store::STATUS_RUNNING, ActionScheduler_Store::STATUS_PENDING ),
248
+ 'group' => $group,
249
+ 'orderby' => 'none',
250
  );
251
 
252
  if ( null !== $args ) {
255
 
256
  $action_id = ActionScheduler::store()->query_action( $query_args );
257
 
258
+ return null !== $action_id;
259
  }
260
 
261
  /**
262
  * Find scheduled actions
263
  *
264
+ * @param array $args Possible arguments, with their default values.
265
+ * 'hook' => '' - the name of the action that will be triggered.
266
+ * 'args' => NULL - the args array that will be passed with the action.
267
+ * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
268
+ * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='.
269
+ * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
270
+ * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='.
271
+ * 'group' => '' - the group the action belongs to.
272
+ * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING.
273
+ * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID.
274
+ * 'per_page' => 5 - Number of results to return.
275
+ * 'offset' => 0.
276
+ * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', 'date' or 'none'.
277
+ * 'order' => 'ASC'.
278
  *
279
  * @param string $return_format OBJECT, ARRAY_A, or ids.
280
  *
285
  return array();
286
  }
287
  $store = ActionScheduler::store();
288
+ foreach ( array( 'date', 'modified' ) as $key ) {
289
+ if ( isset( $args[ $key ] ) ) {
290
+ $args[ $key ] = as_get_datetime_object( $args[ $key ] );
291
  }
292
  }
293
  $ids = $store->query_actions( $args );
294
 
295
+ if ( 'ids' === $return_format || 'int' === $return_format ) {
296
  return $ids;
297
  }
298
 
299
  $actions = array();
300
  foreach ( $ids as $action_id ) {
301
+ $actions[ $action_id ] = $store->fetch_action( $action_id );
302
  }
303
 
304
+ if ( ARRAY_A == $return_format ) {
305
  foreach ( $actions as $action_id => $action_object ) {
306
+ $actions[ $action_id ] = get_object_vars( $action_object );
307
  }
308
  }
309
 
322
  * timezone when instantiating datetimes rather than leaving it up to
323
  * the PHP default.
324
  *
325
+ * @param mixed $date_string A date/time string. Valid formats are explained in http://php.net/manual/en/datetime.formats.php.
326
  * @param string $timezone A timezone identifier, like UTC or Europe/Lisbon. The list of valid identifiers is available http://php.net/manual/en/timezones.php.
327
  *
328
  * @return ActionScheduler_DateTime
vendors/woocommerce/action-scheduler/lib/WP_Async_Request.php CHANGED
@@ -104,10 +104,17 @@ if ( ! class_exists( 'WP_Async_Request' ) ) {
104
  return $this->query_args;
105
  }
106
 
107
- return array(
108
  'action' => $this->identifier,
109
  'nonce' => wp_create_nonce( $this->identifier ),
110
  );
 
 
 
 
 
 
 
111
  }
112
 
113
  /**
@@ -120,7 +127,14 @@ if ( ! class_exists( 'WP_Async_Request' ) ) {
120
  return $this->query_url;
121
  }
122
 
123
- return admin_url( 'admin-ajax.php' );
 
 
 
 
 
 
 
124
  }
125
 
126
  /**
@@ -133,13 +147,20 @@ if ( ! class_exists( 'WP_Async_Request' ) ) {
133
  return $this->post_args;
134
  }
135
 
136
- return array(
137
  'timeout' => 0.01,
138
  'blocking' => false,
139
  'body' => $this->data,
140
  'cookies' => $_COOKIE,
141
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
142
  );
 
 
 
 
 
 
 
143
  }
144
 
145
  /**
104
  return $this->query_args;
105
  }
106
 
107
+ $args = array(
108
  'action' => $this->identifier,
109
  'nonce' => wp_create_nonce( $this->identifier ),
110
  );
111
+
112
+ /**
113
+ * Filters the post arguments used during an async request.
114
+ *
115
+ * @param array $url
116
+ */
117
+ return apply_filters( $this->identifier . '_query_args', $args );
118
  }
119
 
120
  /**
127
  return $this->query_url;
128
  }
129
 
130
+ $url = admin_url( 'admin-ajax.php' );
131
+
132
+ /**
133
+ * Filters the post arguments used during an async request.
134
+ *
135
+ * @param string $url
136
+ */
137
+ return apply_filters( $this->identifier . '_query_url', $url );
138
  }
139
 
140
  /**
147
  return $this->post_args;
148
  }
149
 
150
+ $args = array(
151
  'timeout' => 0.01,
152
  'blocking' => false,
153
  'body' => $this->data,
154
  'cookies' => $_COOKIE,
155
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
156
  );
157
+
158
+ /**
159
+ * Filters the post arguments used during an async request.
160
+ *
161
+ * @param array $args
162
+ */
163
+ return apply_filters( $this->identifier . '_post_args', $args );
164
  }
165
 
166
  /**
vendors/woocommerce/action-scheduler/readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: Automattic, wpmuguru, claudiosanches, peterfabian1000, vedjain, jamosova, obliviousharmony, konamiman, sadowski, royho, barryhughes-1
3
  Tags: scheduler, cron
4
  Requires at least: 5.2
5
- Tested up to: 5.7
6
- Stable tag: 3.4.0
7
  License: GPLv3
8
  Requires PHP: 5.6
9
 
@@ -47,6 +47,29 @@ Collaboration is cool. We'd love to work with you to improve Action Scheduler. [
47
 
48
  == Changelog ==
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  = 3.4.0 - 2021-10-29 =
51
  * Enhancement - Number of items per page can now be set for the Scheduled Actions view (props @ovidiul). #771
52
  * Fix - Do not lower the max_execution_time if it is already set to 0 (unlimited) (props @barryhughes). #755
2
  Contributors: Automattic, wpmuguru, claudiosanches, peterfabian1000, vedjain, jamosova, obliviousharmony, konamiman, sadowski, royho, barryhughes-1
3
  Tags: scheduler, cron
4
  Requires at least: 5.2
5
+ Tested up to: 6.0
6
+ Stable tag: 3.5.2
7
  License: GPLv3
8
  Requires PHP: 5.6
9
 
47
 
48
  == Changelog ==
49
 
50
+ = 3.5.2 - 2022-09-16 =
51
+ * Fix - erroneous 3.5.1 release.
52
+
53
+ = 3.5.1 - 2022-09-13 =
54
+ * Maintenance on A/S docs.
55
+ * fix: PHP 8.2 deprecated notice.
56
+
57
+ = 3.5.0 - 2022-08-25 =
58
+ * Add - The active view link within the "Tools > Scheduled Actions" screen is now clickable.
59
+ * Add - A warning when there are past-due actions.
60
+ * Enhancement - Added the ability to schedule unique actions via an atomic operation.
61
+ * Enhancement - Improvements to cache invalidation when processing batches (when running on WordPress 6.0+).
62
+ * Enhancement - If a recurring action is found to be consistently failing, it will stop being rescheduled.
63
+ * Enhancement - Adds a new "Past Due" view to the scheduled actions list table.
64
+
65
+ = 3.4.2 - 2022-06-08 =
66
+ * Fix - Change the include for better linting.
67
+ * Fix - update: Added Action scheduler completed action hook.
68
+
69
+ = 3.4.1 - 2022-05-24 =
70
+ * Fix - Change the include for better linting.
71
+ * Fix - Fix the documented return type.
72
+
73
  = 3.4.0 - 2021-10-29 =
74
  * Enhancement - Number of items per page can now be set for the Scheduled Actions view (props @ovidiul). #771
75
  * Fix - Do not lower the max_execution_time if it is already set to 0 (unlimited) (props @barryhughes). #755
views/pages/tools/general/reset-permissions.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php defined('ABSPATH') || exit; ?>
2
 
3
- <?php if (glsr()->can('edit_roles')): ?>
4
  <div class="glsr-card postbox">
5
  <h3 class="glsr-card-heading">
6
  <button type="button" class="glsr-accordion-trigger" aria-expanded="false" aria-controls="tools-reset-permissions">
1
  <?php defined('ABSPATH') || exit; ?>
2
 
3
+ <?php if (glsr()->can('edit_users')): ?>
4
  <div class="glsr-card postbox">
5
  <h3 class="glsr-card-heading">
6
  <button type="button" class="glsr-accordion-trigger" aria-expanded="false" aria-controls="tools-reset-permissions">
wpml-config.xml CHANGED
@@ -1,6 +1,6 @@
1
  <wpml-config>
2
  <admin-texts>
3
- <key name="site_reviews_v5">
4
  <key name="settings">
5
  <key name="general">
6
  <key name="notification_message"/>
@@ -27,7 +27,7 @@
27
  </key>
28
  </key>
29
  </admin-texts>
30
- <custom-types>
31
- <custom-type translate="0">site-review</custom-type>
32
- </custom-types>
33
  </wpml-config>
1
  <wpml-config>
2
  <admin-texts>
3
+ <key name="site_reviews_v6">
4
  <key name="settings">
5
  <key name="general">
6
  <key name="notification_message"/>
27
  </key>
28
  </key>
29
  </admin-texts>
30
+ <custom-types>
31
+ <custom-type translate="0">site-review</custom-type>
32
+ </custom-types>
33
  </wpml-config>