PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 2.1.1
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v2.1.1
4.9.0 0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / vendor / woocommerce / action-scheduler / classes / data-stores / ActionScheduler_HybridStore.php
wp-mail-smtp / vendor / woocommerce / action-scheduler / classes / data-stores Last commit date
ActionScheduler_DBLogger.php 6 years ago ActionScheduler_DBStore.php 6 years ago ActionScheduler_HybridStore.php 6 years ago ActionScheduler_wpCommentLogger.php 6 years ago ActionScheduler_wpPostStore.php 6 years ago ActionScheduler_wpPostStore_PostStatusRegistrar.php 6 years ago ActionScheduler_wpPostStore_PostTypeRegistrar.php 6 years ago ActionScheduler_wpPostStore_TaxonomyRegistrar.php 6 years ago
ActionScheduler_HybridStore.php
427 lines
1 <?php
2
3 use ActionScheduler_Store as Store;
4 use Action_Scheduler\Migration\Runner;
5 use Action_Scheduler\Migration\Config;
6 use Action_Scheduler\Migration\Controller;
7
8 /**
9 * Class ActionScheduler_HybridStore
10 *
11 * A wrapper around multiple stores that fetches data from both.
12 *
13 * @since 3.0.0
14 */
15 class ActionScheduler_HybridStore extends Store {
16 const DEMARKATION_OPTION = 'action_scheduler_hybrid_store_demarkation';
17
18 private $primary_store;
19 private $secondary_store;
20 private $migration_runner;
21
22 /**
23 * @var int The dividing line between IDs of actions created
24 * by the primary and secondary stores.
25 *
26 * Methods that accept an action ID will compare the ID against
27 * this to determine which store will contain that ID. In almost
28 * all cases, the ID should come from the primary store, but if
29 * client code is bypassing the API functions and fetching IDs
30 * from elsewhere, then there is a chance that an unmigrated ID
31 * might be requested.
32 */
33 private $demarkation_id = 0;
34
35 /**
36 * ActionScheduler_HybridStore constructor.
37 *
38 * @param Config $config Migration config object.
39 */
40 public function __construct( Config $config = null ) {
41 $this->demarkation_id = (int) get_option( self::DEMARKATION_OPTION, 0 );
42 if ( empty( $config ) ) {
43 $config = Controller::instance()->get_migration_config_object();
44 }
45 $this->primary_store = $config->get_destination_store();
46 $this->secondary_store = $config->get_source_store();
47 $this->migration_runner = new Runner( $config );
48 }
49
50 /**
51 * Initialize the table data store tables.
52 *
53 * @codeCoverageIgnore
54 */
55 public function init() {
56 add_action( 'action_scheduler/created_table', [ $this, 'set_autoincrement' ], 10, 2 );
57 $this->primary_store->init();
58 $this->secondary_store->init();
59 remove_action( 'action_scheduler/created_table', [ $this, 'set_autoincrement' ], 10 );
60 }
61
62 /**
63 * When the actions table is created, set its autoincrement
64 * value to be one higher than the posts table to ensure that
65 * there are no ID collisions.
66 *
67 * @param string $table_name
68 * @param string $table_suffix
69 *
70 * @return void
71 * @codeCoverageIgnore
72 */
73 public function set_autoincrement( $table_name, $table_suffix ) {
74 if ( ActionScheduler_StoreSchema::ACTIONS_TABLE === $table_suffix ) {
75 if ( empty( $this->demarkation_id ) ) {
76 $this->demarkation_id = $this->set_demarkation_id();
77 }
78 /** @var \wpdb $wpdb */
79 global $wpdb;
80 /**
81 * A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
82 * sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
83 */
84 $default_date = new DateTime( 'tomorrow' );
85 $null_action = new ActionScheduler_NullAction();
86 $date_gmt = $this->get_scheduled_date_string( $null_action, $default_date );
87 $date_local = $this->get_scheduled_date_string_local( $null_action, $default_date );
88
89 $row_count = $wpdb->insert(
90 $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
91 [
92 'action_id' => $this->demarkation_id,
93 'hook' => '',
94 'status' => '',
95 'scheduled_date_gmt' => $date_gmt,
96 'scheduled_date_local' => $date_local,
97 'last_attempt_gmt' => $date_gmt,
98 'last_attempt_local' => $date_local,
99 ]
100 );
101 if ( $row_count > 0 ) {
102 $wpdb->delete(
103 $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
104 [ 'action_id' => $this->demarkation_id ]
105 );
106 }
107 }
108 }
109
110 /**
111 * Store the demarkation id in WP options.
112 *
113 * @param int $id The ID to set as the demarkation point between the two stores
114 * Leave null to use the next ID from the WP posts table.
115 *
116 * @return int The new ID.
117 *
118 * @codeCoverageIgnore
119 */
120 private function set_demarkation_id( $id = null ) {
121 if ( empty( $id ) ) {
122 /** @var \wpdb $wpdb */
123 global $wpdb;
124 $id = (int) $wpdb->get_var( "SELECT MAX(ID) FROM $wpdb->posts" );
125 $id ++;
126 }
127 update_option( self::DEMARKATION_OPTION, $id );
128
129 return $id;
130 }
131
132 /**
133 * Find the first matching action from the secondary store.
134 * If it exists, migrate it to the primary store immediately.
135 * After it migrates, the secondary store will logically contain
136 * the next matching action, so return the result thence.
137 *
138 * @param string $hook
139 * @param array $params
140 *
141 * @return string
142 */
143 public function find_action( $hook, $params = [] ) {
144 $found_unmigrated_action = $this->secondary_store->find_action( $hook, $params );
145 if ( ! empty( $found_unmigrated_action ) ) {
146 $this->migrate( [ $found_unmigrated_action ] );
147 }
148
149 return $this->primary_store->find_action( $hook, $params );
150 }
151
152 /**
153 * Find actions matching the query in the secondary source first.
154 * If any are found, migrate them immediately. Then the secondary
155 * store will contain the canonical results.
156 *
157 * @param array $query
158 * @param string $query_type Whether to select or count the results. Default, select.
159 *
160 * @return int[]
161 */
162 public function query_actions( $query = [], $query_type = 'select' ) {
163 $found_unmigrated_actions = $this->secondary_store->query_actions( $query, 'select' );
164 if ( ! empty( $found_unmigrated_actions ) ) {
165 $this->migrate( $found_unmigrated_actions );
166 }
167
168 return $this->primary_store->query_actions( $query, $query_type );
169 }
170
171 /**
172 * Get a count of all actions in the store, grouped by status
173 *
174 * @return array Set of 'status' => int $count pairs for statuses with 1 or more actions of that status.
175 */
176 public function action_counts() {
177 $unmigrated_actions_count = $this->secondary_store->action_counts();
178 $migrated_actions_count = $this->primary_store->action_counts();
179 $actions_count_by_status = array();
180
181 foreach ( $this->get_status_labels() as $status_key => $status_label ) {
182
183 $count = 0;
184
185 if ( isset( $unmigrated_actions_count[ $status_key ] ) ) {
186 $count += $unmigrated_actions_count[ $status_key ];
187 }
188
189 if ( isset( $migrated_actions_count[ $status_key ] ) ) {
190 $count += $migrated_actions_count[ $status_key ];
191 }
192
193 $actions_count_by_status[ $status_key ] = $count;
194 }
195
196 $actions_count_by_status = array_filter( $actions_count_by_status );
197
198 return $actions_count_by_status;
199 }
200
201 /**
202 * If any actions would have been claimed by the secondary store,
203 * migrate them immediately, then ask the primary store for the
204 * canonical claim.
205 *
206 * @param int $max_actions
207 * @param DateTime|null $before_date
208 *
209 * @return ActionScheduler_ActionClaim
210 */
211 public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
212 $claim = $this->secondary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
213
214 $claimed_actions = $claim->get_actions();
215 if ( ! empty( $claimed_actions ) ) {
216 $this->migrate( $claimed_actions );
217 }
218
219 $this->secondary_store->release_claim( $claim );
220
221 return $this->primary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
222 }
223
224 /**
225 * Migrate a list of actions to the table data store.
226 *
227 * @param array $action_ids List of action IDs.
228 */
229 private function migrate( $action_ids ) {
230 $this->migration_runner->migrate_actions( $action_ids );
231 }
232
233 /**
234 * Save an action to the primary store.
235 *
236 * @param ActionScheduler_Action $action Action object to be saved.
237 * @param DateTime $date Optional. Schedule date. Default null.
238 *
239 * @return int The action ID
240 */
241 public function save_action( ActionScheduler_Action $action, DateTime $date = null ) {
242 return $this->primary_store->save_action( $action, $date );
243 }
244
245 /**
246 * Retrieve an existing action whether migrated or not.
247 *
248 * @param int $action_id Action ID.
249 */
250 public function fetch_action( $action_id ) {
251 $store = $this->get_store_from_action_id( $action_id, true );
252 if ( $store ) {
253 return $store->fetch_action( $action_id );
254 } else {
255 return new ActionScheduler_NullAction();
256 }
257 }
258
259 /**
260 * Cancel an existing action whether migrated or not.
261 *
262 * @param int $action_id Action ID.
263 */
264 public function cancel_action( $action_id ) {
265 $store = $this->get_store_from_action_id( $action_id );
266 if ( $store ) {
267 $store->cancel_action( $action_id );
268 }
269 }
270
271 /**
272 * Delete an existing action whether migrated or not.
273 *
274 * @param int $action_id Action ID.
275 */
276 public function delete_action( $action_id ) {
277 $store = $this->get_store_from_action_id( $action_id );
278 if ( $store ) {
279 $store->delete_action( $action_id );
280 }
281 }
282
283 /**
284 * Get the schedule date an existing action whether migrated or not.
285 *
286 * @param int $action_id Action ID.
287 */
288 public function get_date( $action_id ) {
289 $store = $this->get_store_from_action_id( $action_id );
290 if ( $store ) {
291 return $store->get_date( $action_id );
292 } else {
293 return null;
294 }
295 }
296
297 /**
298 * Mark an existing action as failed whether migrated or not.
299 *
300 * @param int $action_id Action ID.
301 */
302 public function mark_failure( $action_id ) {
303 $store = $this->get_store_from_action_id( $action_id );
304 if ( $store ) {
305 $store->mark_failure( $action_id );
306 }
307 }
308
309 /**
310 * Log the execution of an existing action whether migrated or not.
311 *
312 * @param int $action_id Action ID.
313 */
314 public function log_execution( $action_id ) {
315 $store = $this->get_store_from_action_id( $action_id );
316 if ( $store ) {
317 $store->log_execution( $action_id );
318 }
319 }
320
321 /**
322 * Mark an existing action complete whether migrated or not.
323 *
324 * @param int $action_id Action ID.
325 */
326 public function mark_complete( $action_id ) {
327 $store = $this->get_store_from_action_id( $action_id );
328 if ( $store ) {
329 $store->mark_complete( $action_id );
330 }
331 }
332
333 /**
334 * Get an existing action status whether migrated or not.
335 *
336 * @param int $action_id Action ID.
337 */
338 public function get_status( $action_id ) {
339 $store = $this->get_store_from_action_id( $action_id );
340 if ( $store ) {
341 return $store->get_status( $action_id );
342 }
343 return null;
344 }
345
346 /**
347 * Return which store an action is stored in.
348 *
349 * @param int $action_id ID of the action.
350 * @param bool $primary_first Optional flag indicating search the primary store first.
351 * @return ActionScheduler_Store
352 */
353 protected function get_store_from_action_id( $action_id, $primary_first = false ) {
354 if ( $primary_first ) {
355 $stores = [
356 $this->primary_store,
357 $this->secondary_store,
358 ];
359 } elseif ( $action_id < $this->demarkation_id ) {
360 $stores = [
361 $this->secondary_store,
362 $this->primary_store,
363 ];
364 } else {
365 $stores = [
366 $this->primary_store,
367 ];
368 }
369
370 foreach ( $stores as $store ) {
371 $action = $store->fetch_action( $action_id );
372 if ( ! is_a( $action, 'ActionScheduler_NullAction' ) ) {
373 return $store;
374 }
375 }
376 return null;
377 }
378
379 /* * * * * * * * * * * * * * * * * * * * * * * * * * *
380 * All claim-related functions should operate solely
381 * on the primary store.
382 * * * * * * * * * * * * * * * * * * * * * * * * * * */
383
384 /**
385 * Get the claim count from the table data store.
386 */
387 public function get_claim_count() {
388 return $this->primary_store->get_claim_count();
389 }
390
391 /**
392 * Retrieve the claim ID for an action from the table data store.
393 *
394 * @param int $action_id Action ID.
395 */
396 public function get_claim_id( $action_id ) {
397 return $this->primary_store->get_claim_id( $action_id );
398 }
399
400 /**
401 * Release a claim in the table data store.
402 *
403 * @param ActionScheduler_ActionClaim $claim Claim object.
404 */
405 public function release_claim( ActionScheduler_ActionClaim $claim ) {
406 $this->primary_store->release_claim( $claim );
407 }
408
409 /**
410 * Release claims on an action in the table data store.
411 *
412 * @param int $action_id Action ID.
413 */
414 public function unclaim_action( $action_id ) {
415 $this->primary_store->unclaim_action( $action_id );
416 }
417
418 /**
419 * Retrieve a list of action IDs by claim.
420 *
421 * @param int $claim_id Claim ID.
422 */
423 public function find_actions_by_claim_id( $claim_id ) {
424 return $this->primary_store->find_actions_by_claim_id( $claim_id );
425 }
426 }
427