PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / trunk
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell vtrunk
3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 2.8.17 2.8.18 All 259 releases
wpfunnels / admin / Migrations / StatStatusSyncMigration.php

StatStatusSyncMigration.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell trunk, at admin/Migrations/StatStatusSyncMigration.php

159 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPFunnels\Admin\Migrations;
4
5 /**
6 * Class StatStatusSyncMigration
7 *
8 * Syncs the status of existing wpfnl_stats rows that are stuck on "pending"
9 * with the actual WooCommerce order status.
10 *
11 * Uses an ID-based cursor to move through all pending rows systematically,
12 * ensuring no rows are skipped even if some orders are genuinely still pending.
13 *
14 * @package WPFunnels\Admin\Migrations
15 * @since 3.5.1
16 */
17 class StatStatusSyncMigration extends AbstractMigrations
18 {
19
20 /**
21 * Migration key
22 *
23 * @var string
24 * @since 3.5.1
25 */
26 public $key = 'stat_status_sync';
27
28
29 /**
30 * Batch size – number of rows to process per batch.
31 *
32 * @var int
33 */
34 private $batch_size = 50;
35
36
37 /**
38 * Option key for storing the last processed row ID (cursor).
39 *
40 * @var string
41 */
42 private $cursor_option = 'wpfunnels_stat_status_sync_last_id';
43
44
45 /**
46 * Get the next batch to process.
47 *
48 * @return int|false
49 * @since 3.5.1
50 */
51 public function get_next_batch_to_process()
52 {
53 if (!$this->is_on_queue()) {
54 return get_option("wpfunnels_{$this->key}_batch", '1');
55 }
56 return false;
57 }
58
59
60 /**
61 * Run the migration directly.
62 *
63 * Processes one batch per admin page load. Uses an ID-based cursor
64 * to track progress, so it moves through ALL pending rows even if
65 * some WooCommerce orders are genuinely still pending.
66 *
67 * @since 3.5.1
68 */
69 public function run()
70 {
71 // Already completed — do nothing.
72 if ('completed' === $this->is_migration_completed()) {
73 return;
74 }
75
76 $this->set_migration_status('running');
77 $this->process_batch();
78 }
79
80
81 /**
82 * Process a single batch.
83 *
84 * Queries rows in wpfnl_stats with status = 'pending' AND id > cursor,
85 * looks up the real WooCommerce order status, and updates the stats table.
86 *
87 * @since 3.5.1
88 */
89 public function process_batch()
90 {
91 global $wpdb;
92
93 $table = $wpdb->prefix . 'wpfnl_stats';
94 $last_id = (int) get_option($this->cursor_option, 0);
95
96 $rows = $wpdb->get_results(
97 $wpdb->prepare(
98 "SELECT id, order_id FROM {$table} WHERE status = 'pending' AND id > %d ORDER BY id ASC LIMIT %d",
99 $last_id,
100 $this->batch_size
101 )
102 );
103
104 // No more rows beyond the cursor → migration is done.
105 if (empty($rows)) {
106 $this->set_migration_status('completed');
107 delete_option($this->cursor_option);
108 return;
109 }
110
111 $max_id = $last_id;
112
113 foreach ($rows as $row) {
114 // Always advance the cursor, even if we skip this row.
115 if ((int) $row->id > $max_id) {
116 $max_id = (int) $row->id;
117 }
118
119 $order = wc_get_order($row->order_id);
120
121 if (!$order) {
122 // Order no longer exists — mark as 'cancelled' to avoid re-processing.
123 $wpdb->update(
124 $table,
125 array('status' => 'cancelled'),
126 array('id' => $row->id)
127 );
128 continue;
129 }
130
131 $new_status = $order->get_status();
132
133 // If still truly pending in WooCommerce, skip but cursor still advances.
134 if ('pending' === $new_status) {
135 continue;
136 }
137
138 $update_data = array('status' => $new_status);
139
140 // Record the paid date for completed/processing orders.
141 if ('completed' === $new_status || 'processing' === $new_status) {
142 $paid_date = $order->get_date_paid();
143 if ($paid_date) {
144 $update_data['paid_date'] = $paid_date->date('Y-m-d H:i:s');
145 }
146 }
147
148 $wpdb->update(
149 $table,
150 $update_data,
151 array('id' => $row->id)
152 );
153 }
154
155 // Save the cursor so the next batch starts after this point.
156 update_option($this->cursor_option, $max_id, false);
157 }
158 }
159