PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / trunk
WCPOS – Point of Sale (POS) plugin for WooCommerce vtrunk
1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 1.9.13 1.9.12 1.9.11 1.9.10 1.9.9 All 158 releases
woocommerce-pos / includes / Sync / Order_Query.php

Order_Query.php in WCPOS – Point of Sale (POS) plugin for WooCommerce trunk, at includes/Sync/Order_Query.php

113 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WCPOS sync read surface.
4 *
5 * @package WCPOS\WooCommercePOS\Sync
6 */
7
8 namespace WCPOS\WooCommercePOS\Sync;
9
10 use Automattic\WooCommerce\Utilities\OrderUtil;
11
12 // phpcs:disable Squiz.Commenting, Generic.Commenting -- Ported lab documentation is preserved verbatim.
13
14 /**
15 * Order change candidates after a checkpoint. Prefers the authoritative
16 * append-only journal (rows_after_sequence); falls back to a verified
17 * WooCommerce modified-date scan (sequence 0 rows) when the journal has no rows
18 * for the cursor yet (fresh install / mid-backfill).
19 */
20 final class Order_Query {
21 /** @var object|null Injected journal (tests); defaults to a real Sync_Journal. */
22 private $journal;
23
24 public function __construct( ?object $journal = null ) {
25 $this->journal = $journal;
26 }
27
28 public function changes_after_checkpoint( string $updated_at_gmt, int $order_id, int $sequence, int $limit ): array {
29 $journal = $this->journal ?? new Sync_Journal();
30 if ( method_exists( $journal, 'rows_after_sequence' ) ) {
31 // A SEQUENCE-ZERO pull is the client's baseline claim, and the journal
32 // can only honor it once it covers every historical order — i.e. after
33 // the backfill reports complete (fresh no-order stores mark it complete
34 // at install). Before that, a journal holding only post-install writes
35 // would silently suppress the modified-date baseline scan: one order
36 // write after the upgrade's legacy-table drop and a first-pull client
37 // would never see its history. Non-zero cursors are always
38 // journal-authoritative (the client is past its baseline).
39 $journal_owns_baseline = ! method_exists( $journal, 'backfill_status' )
40 || 'complete' === (string) ( $journal->backfill_status()['status'] ?? '' );
41 if ( 0 < $sequence || $journal_owns_baseline ) {
42 $journal_rows = $journal->rows_after_sequence( $sequence, $limit );
43 if ( ! empty( $journal_rows ) ) {
44 return $journal_rows;
45 }
46 if ( 0 < $sequence ) {
47 return array();
48 }
49 }
50 }
51
52 return array_map(
53 static function ( int $id ): array {
54 return array(
55 'sequence' => 0,
56 'order_id' => $id,
57 'modified_gmt' => '',
58 'revision' => '',
59 'deleted' => 0,
60 'origin' => 'fallback:modified',
61 );
62 },
63 $this->ids_after_modified_checkpoint( $updated_at_gmt, $order_id, $limit )
64 );
65 }
66
67 private function ids_after_modified_checkpoint( string $updated_at_gmt, int $order_id, int $limit ): array {
68 global $wpdb;
69
70 $checkpoint_modified = gmdate( 'Y-m-d H:i:s', $this->timestamp_from_checkpoint( $updated_at_gmt ) );
71 $limit = max( 1, min( 251, $limit ) );
72
73 if ( class_exists( OrderUtil::class ) && OrderUtil::custom_orders_table_usage_is_enabled() ) {
74 $sql = $wpdb->prepare(
75 "SELECT id FROM {$wpdb->prefix}wc_orders"
76 . " WHERE type = 'shop_order' AND status NOT IN ('trash', 'auto-draft')"
77 . ' AND (date_updated_gmt > %s OR (date_updated_gmt = %s AND id > %d))'
78 . ' ORDER BY date_updated_gmt ASC, id ASC LIMIT %d',
79 $checkpoint_modified,
80 $checkpoint_modified,
81 $order_id,
82 $limit
83 );
84 } else {
85 $sql = $wpdb->prepare(
86 "SELECT ID FROM {$wpdb->posts}"
87 . " WHERE post_type = 'shop_order' AND post_status NOT IN ('trash', 'auto-draft')"
88 . ' AND (post_modified_gmt > %s OR (post_modified_gmt = %s AND ID > %d))'
89 . ' ORDER BY post_modified_gmt ASC, ID ASC LIMIT %d',
90 $checkpoint_modified,
91 $checkpoint_modified,
92 $order_id,
93 $limit
94 );
95 }
96
97 /** @var array<int, int|string> $ids Exact compound-key page from the active order store. */
98 $ids = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Prepared above with bounded values and known table names.
99
100 return array_map(
101 static function ( $id ): int {
102 return (int) $id;
103 },
104 $ids
105 );
106 }
107
108 private function timestamp_from_checkpoint( string $updated_at_gmt ): int {
109 $timestamp = strtotime( $updated_at_gmt );
110 return false === $timestamp ? 0 : (int) $timestamp;
111 }
112 }
113