PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 2.7.0
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v2.7.0
2.7.0 2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 All 43 releases
← All changes | includes/core/update/db-updater.php +118 -0 1.2.92.7.0 View file →
@@ -15,8 +15,18 @@
15 15 */
16 16 class Db_Updater extends \WP_Background_Process {
17 17
18 18 /**
19 + * Whether this site already has migration batches queued or in progress.
20 + *
21 + * @since 2.4.1
22 + * @return bool
23 + */
24 + public function has_pending_migrations() {
25 + return ! $this->is_queue_empty();
26 + }
27 +
28 + /**
19 29 * SellKit db version.
20 30 *
21 31 * @since 1.1.0
22 32 * @var $db_version
@@ -31,8 +41,24 @@
31 41 */
32 42 protected $action = 'sellkit-database-updater';
33 43
34 44 /**
45 + * When set before the first save()->dispatch() from Install, multisite uses a short network-wide
46 + * cooldown so not every subsite fires a loopback HTTP request at the same time after an update.
47 + * Chained dispatch() calls from the background handler leave this false and are not gated.
48 + *
49 + * @var bool
50 + */
51 + public $gate_multisite_initial_loopback = false;
52 +
53 + /**
54 + * Network-wide cooldown in seconds for the initial multisite loopback spawn.
55 + *
56 + * @var int
57 + */
58 + protected $initial_loopback_gate_ttl = MINUTE_IN_SECONDS;
59 +
60 + /**
35 61 * Override this method to perform any actions required on each
36 62 * queue item. Return the modified item for further processing
37 63 * in the next pass through. Or, return false to remove the
38 64 * item from the queue.
@@ -53,8 +79,65 @@
53 79 return false;
54 80 }
55 81
56 82 /**
83 + * Spawn loopback to process the queue; on multisite optionally throttle initial storm across subsites.
84 + *
85 + * @since 2.4.1
86 + * @return array|false|WP_Error
87 + */
88 + public function dispatch() {
89 + if ( $this->gate_multisite_initial_loopback && is_multisite() ) {
90 + $this->gate_multisite_initial_loopback = false;
91 +
92 + // Allow one initial loopback at a time network-wide; other sites rely on cron until the cooldown expires.
93 + if ( ! $this->acquire_multisite_initial_loopback_gate() ) {
94 + $this->schedule_event();
95 + return false;
96 + }
97 + }
98 +
99 + return parent::dispatch();
100 + }
101 +
102 + /**
103 + * Acquire the multisite loopback gate using the main site's options table.
104 + *
105 + * `add_option()` is backed by a unique index in `wp_options`, which makes it much safer than a
106 + * get/set transient pair during concurrent requests across many subsites.
107 + *
108 + * @return bool
109 + */
110 + protected function acquire_multisite_initial_loopback_gate() {
111 + $network_key = 'sellkit_ms_init_loopback_gate';
112 + $expires_at = time() + $this->initial_loopback_gate_ttl;
113 + $main_site_id = (int) get_main_site_id();
114 + $switched = false;
115 +
116 + if ( $main_site_id > 0 && get_current_blog_id() !== $main_site_id ) {
117 + switch_to_blog( $main_site_id );
118 + $switched = true;
119 + }
120 +
121 + $acquired = add_option( $network_key, $expires_at, '', false );
122 +
123 + if ( ! $acquired ) {
124 + $existing_expiry = (int) get_option( $network_key );
125 +
126 + if ( $existing_expiry <= time() ) {
127 + delete_option( $network_key );
128 + $acquired = add_option( $network_key, $expires_at, '', false );
129 + }
130 + }
131 +
132 + if ( $switched ) {
133 + restore_current_blog();
134 + }
135 +
136 + return $acquired;
137 + }
138 +
139 + /**
57 140 * Complete
58 141 *
59 142 * Override if applicable, but ensure that the below actions are
60 143 * performed, or, call parent::complete().
@@ -64,6 +147,41 @@
64 147 protected function complete() {
65 148 parent::complete();
66 149
67 150 sellkit_update_option( 'current_db_version', $this->db_version );
151 + }
152 +
153 + /**
154 + * Maybe process queue
155 + *
156 + * Checks whether data exists within the queue and that
157 + * the process is not already running.
158 + *
159 + * @since 2.3.3
160 + */
161 + public function maybe_handle() {
162 + // Don't lock up other requests while processing.
163 + session_write_close();
164 +
165 + if ( ! current_user_can( 'manage_options' ) ) {
166 + wp_send_json_error( 'Unauthorized', 403 );
167 +
168 + exit;
169 + }
170 +
171 + if ( $this->is_process_running() ) {
172 + // Background process already running.
173 + wp_die();
174 + }
175 +
176 + if ( $this->is_queue_empty() ) {
177 + // No data to process.
178 + wp_die();
179 + }
180 +
181 + check_ajax_referer( $this->identifier, 'nonce' );
182 +
183 + $this->handle();
184 +
185 + wp_die();
68 186 }
69 187 }