PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 7.3.0.1
Jetpack – WP Security, Backup, Speed, & Growth v7.3.0.1
15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / sync / class.jetpack-sync-sender.php
jetpack / sync Last commit date
class.jetpack-sync-actions.php 7 years ago class.jetpack-sync-defaults.php 7 years ago class.jetpack-sync-functions.php 7 years ago class.jetpack-sync-json-deflate-array-codec.php 7 years ago class.jetpack-sync-listener.php 7 years ago class.jetpack-sync-module-attachments.php 7 years ago class.jetpack-sync-module-callables.php 7 years ago class.jetpack-sync-module-comments.php 7 years ago class.jetpack-sync-module-constants.php 7 years ago class.jetpack-sync-module-full-sync.php 7 years ago class.jetpack-sync-module-import.php 7 years ago class.jetpack-sync-module-menus.php 7 years ago class.jetpack-sync-module-meta.php 7 years ago class.jetpack-sync-module-network-options.php 7 years ago class.jetpack-sync-module-options.php 7 years ago class.jetpack-sync-module-plugins.php 7 years ago class.jetpack-sync-module-posts.php 7 years ago class.jetpack-sync-module-protect.php 7 years ago class.jetpack-sync-module-stats.php 9 years ago class.jetpack-sync-module-terms.php 7 years ago class.jetpack-sync-module-themes.php 7 years ago class.jetpack-sync-module-updates.php 7 years ago class.jetpack-sync-module-users.php 7 years ago class.jetpack-sync-module-woocommerce.php 7 years ago class.jetpack-sync-module-wp-super-cache.php 7 years ago class.jetpack-sync-module.php 7 years ago class.jetpack-sync-modules.php 7 years ago class.jetpack-sync-queue.php 7 years ago class.jetpack-sync-sender.php 7 years ago class.jetpack-sync-server.php 7 years ago class.jetpack-sync-settings.php 7 years ago class.jetpack-sync-simple-codec.php 7 years ago class.jetpack-sync-users.php 7 years ago class.jetpack-sync-wp-replicastore.php 7 years ago interface.jetpack-sync-codec.php 9 years ago interface.jetpack-sync-replicastore.php 7 years ago
class.jetpack-sync-sender.php
417 lines
1 <?php
2
3 require_once dirname( __FILE__ ) . '/class.jetpack-sync-queue.php';
4 require_once dirname( __FILE__ ) . '/class.jetpack-sync-defaults.php';
5 require_once dirname( __FILE__ ) . '/class.jetpack-sync-json-deflate-array-codec.php';
6 require_once dirname( __FILE__ ) . '/class.jetpack-sync-simple-codec.php';
7 require_once dirname( __FILE__ ) . '/class.jetpack-sync-modules.php';
8 require_once dirname( __FILE__ ) . '/class.jetpack-sync-settings.php';
9
10 /**
11 * This class grabs pending actions from the queue and sends them
12 */
13 class Jetpack_Sync_Sender {
14
15 const NEXT_SYNC_TIME_OPTION_NAME = 'jetpack_next_sync_time';
16 const WPCOM_ERROR_SYNC_DELAY = 60;
17 const QUEUE_LOCKED_SYNC_DELAY = 10;
18
19 private $dequeue_max_bytes;
20 private $upload_max_bytes;
21 private $upload_max_rows;
22 private $max_dequeue_time;
23 private $sync_wait_time;
24 private $sync_wait_threshold;
25 private $enqueue_wait_time;
26 private $sync_queue;
27 private $full_sync_queue;
28 private $codec;
29 private $old_user;
30
31 // singleton functions
32 private static $instance;
33
34 public static function get_instance() {
35 if ( null === self::$instance ) {
36 self::$instance = new self();
37 }
38
39 return self::$instance;
40 }
41
42 // this is necessary because you can't use "new" when you declare instance properties >:(
43 protected function __construct() {
44 $this->set_defaults();
45 $this->init();
46 }
47
48 private function init() {
49 add_action( 'jetpack_sync_before_send_queue_sync', array( $this, 'maybe_set_user_from_token' ), 1 );
50 add_action( 'jetpack_sync_before_send_queue_sync', array( $this, 'maybe_clear_user_from_token' ), 20 );
51 foreach ( Jetpack_Sync_Modules::get_modules() as $module ) {
52 $module->init_before_send();
53 }
54 }
55
56 public function maybe_set_user_from_token() {
57 $jetpack = Jetpack::init();
58 $verified_user = $jetpack->verify_xml_rpc_signature();
59 if ( Jetpack_Constants::is_true( 'XMLRPC_REQUEST' ) &&
60 ! is_wp_error( $verified_user )
61 && $verified_user
62 ) {
63 $old_user = wp_get_current_user();
64 $this->old_user = isset( $old_user->ID ) ? $old_user->ID : 0;
65 wp_set_current_user( $verified_user['user_id'] );
66 }
67 }
68
69 public function maybe_clear_user_from_token() {
70 if ( isset( $this->old_user ) ) {
71 wp_set_current_user( $this->old_user );
72 }
73 }
74
75 public function get_next_sync_time( $queue_name ) {
76 return (float) get_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name, 0 );
77 }
78
79 public function set_next_sync_time( $time, $queue_name ) {
80 return update_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name, $time, true );
81 }
82
83 public function do_full_sync() {
84 if ( ! Jetpack_Sync_Modules::get_module( 'full-sync' ) ) {
85 return;
86 }
87 $this->continue_full_sync_enqueue();
88 return $this->do_sync_and_set_delays( $this->full_sync_queue );
89 }
90
91 private function continue_full_sync_enqueue() {
92 if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
93 return false;
94 }
95
96 if ( $this->get_next_sync_time( 'full-sync-enqueue' ) > microtime( true ) ) {
97 return false;
98 }
99
100 Jetpack_Sync_Modules::get_module( 'full-sync' )->continue_enqueuing();
101
102 $this->set_next_sync_time( time() + $this->get_enqueue_wait_time(), 'full-sync-enqueue' );
103 }
104
105 public function do_sync() {
106 return $this->do_sync_and_set_delays( $this->sync_queue );
107 }
108
109 public function do_sync_and_set_delays( $queue ) {
110 // don't sync if importing
111 if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
112 return new WP_Error( 'is_importing' );
113 }
114
115 // don't sync if we are throttled
116 if ( $this->get_next_sync_time( $queue->id ) > microtime( true ) ) {
117 return new WP_Error( 'sync_throttled' );
118 }
119
120 $start_time = microtime( true );
121
122 Jetpack_Sync_Settings::set_is_syncing( true );
123
124 $sync_result = $this->do_sync_for_queue( $queue );
125
126 Jetpack_Sync_Settings::set_is_syncing( false );
127
128 $exceeded_sync_wait_threshold = ( microtime( true ) - $start_time ) > (float) $this->get_sync_wait_threshold();
129
130 if ( is_wp_error( $sync_result ) ) {
131 if ( 'unclosed_buffer' === $sync_result->get_error_code() ) {
132 $this->set_next_sync_time( time() + self::QUEUE_LOCKED_SYNC_DELAY, $queue->id );
133 }
134 if ( 'wpcom_error' === $sync_result->get_error_code() ) {
135 $this->set_next_sync_time( time() + self::WPCOM_ERROR_SYNC_DELAY, $queue->id );
136 }
137 } elseif ( $exceeded_sync_wait_threshold ) {
138 // if we actually sent data and it took a while, wait before sending again
139 $this->set_next_sync_time( time() + $this->get_sync_wait_time(), $queue->id );
140 }
141
142 return $sync_result;
143 }
144
145 public function get_items_to_send( $buffer, $encode = true ) {
146 // track how long we've been processing so we can avoid request timeouts
147 $start_time = microtime( true );
148 $upload_size = 0;
149 $items_to_send = array();
150 $items = $buffer->get_items();
151 // set up current screen to avoid errors rendering content
152 require_once ABSPATH . 'wp-admin/includes/class-wp-screen.php';
153 require_once ABSPATH . 'wp-admin/includes/screen.php';
154 set_current_screen( 'sync' );
155 $skipped_items_ids = array();
156 // we estimate the total encoded size as we go by encoding each item individually
157 // this is expensive, but the only way to really know :/
158 foreach ( $items as $key => $item ) {
159 // Suspending cache addition help prevent overloading in memory cache of large sites.
160 wp_suspend_cache_addition( true );
161 /**
162 * Modify the data within an action before it is serialized and sent to the server
163 * For example, during full sync this expands Post ID's into full Post objects,
164 * so that we don't have to serialize the whole object into the queue.
165 *
166 * @since 4.2.0
167 *
168 * @param array The action parameters
169 * @param int The ID of the user who triggered the action
170 */
171 $item[1] = apply_filters( 'jetpack_sync_before_send_' . $item[0], $item[1], $item[2] );
172 wp_suspend_cache_addition( false );
173 if ( $item[1] === false ) {
174 $skipped_items_ids[] = $key;
175 continue;
176 }
177 $encoded_item = $encode ? $this->codec->encode( $item ) : $item;
178 $upload_size += strlen( $encoded_item );
179 if ( $upload_size > $this->upload_max_bytes && count( $items_to_send ) > 0 ) {
180 break;
181 }
182 $items_to_send[ $key ] = $encoded_item;
183 if ( microtime( true ) - $start_time > $this->max_dequeue_time ) {
184 break;
185 }
186 }
187
188 return array( $items_to_send, $skipped_items_ids, $items, microtime( true ) - $start_time );
189 }
190
191 private function fastcgi_finish_request() {
192 if ( function_exists( 'fastcgi_finish_request' ) && version_compare( phpversion(), '7.0.16', '>=' ) ) {
193 fastcgi_finish_request();
194 }
195 }
196
197 public function do_sync_for_queue( $queue ) {
198 do_action( 'jetpack_sync_before_send_queue_' . $queue->id );
199 if ( $queue->size() === 0 ) {
200 return new WP_Error( 'empty_queue_' . $queue->id );
201 }
202 // now that we're sure we are about to sync, try to
203 // ignore user abort so we can avoid getting into a
204 // bad state
205 if ( function_exists( 'ignore_user_abort' ) ) {
206 ignore_user_abort( true );
207 }
208
209 /* Don't make the request block till we finish, if possible. */
210 if ( Jetpack_Constants::is_true( 'REST_REQUEST' ) || Jetpack_Constants::is_true('XMLRPC_REQUEST' ) ) {
211 $this->fastcgi_finish_request();
212 }
213
214 $checkout_start_time = microtime( true );
215
216 $buffer = $queue->checkout_with_memory_limit( $this->dequeue_max_bytes, $this->upload_max_rows );
217
218 if ( ! $buffer ) {
219 // buffer has no items
220 return new WP_Error( 'empty_buffer' );
221 }
222
223 if ( is_wp_error( $buffer ) ) {
224 return $buffer;
225 }
226
227 $checkout_duration = microtime( true ) - $checkout_start_time;
228
229 list( $items_to_send, $skipped_items_ids, $items, $preprocess_duration ) = $this->get_items_to_send( $buffer, true );
230 if ( ! empty( $items_to_send ) ) {
231 /**
232 * Fires when data is ready to send to the server.
233 * Return false or WP_Error to abort the sync (e.g. if there's an error)
234 * The items will be automatically re-sent later
235 *
236 * @since 4.2.0
237 *
238 * @param array $data The action buffer
239 * @param string $codec The codec name used to encode the data
240 * @param double $time The current time
241 * @param string $queue The queue used to send ('sync' or 'full_sync')
242 */
243 Jetpack_Sync_Settings::set_is_sending( true );
244 $processed_item_ids = apply_filters( 'jetpack_sync_send_data', $items_to_send, $this->codec->name(), microtime( true ), $queue->id, $checkout_duration, $preprocess_duration );
245 Jetpack_Sync_Settings::set_is_sending( false );
246 } else {
247 $processed_item_ids = $skipped_items_ids;
248 $skipped_items_ids = array();
249 }
250
251 if ( ! $processed_item_ids || is_wp_error( $processed_item_ids ) ) {
252 $checked_in_item_ids = $queue->checkin( $buffer );
253 if ( is_wp_error( $checked_in_item_ids ) ) {
254 error_log( 'Error checking in buffer: ' . $checked_in_item_ids->get_error_message() );
255 $queue->force_checkin();
256 }
257 if ( is_wp_error( $processed_item_ids ) ) {
258 return new WP_Error( 'wpcom_error', $processed_item_ids->get_error_code() );
259 }
260 // returning a WP_Error('wpcom_error') is a sign to the caller that we should wait a while
261 // before syncing again
262 return new WP_Error( 'wpcom_error', 'jetpack_sync_send_data_false' );
263 } else {
264 // detect if the last item ID was an error
265 $had_wp_error = is_wp_error( end( $processed_item_ids ) );
266 if ( $had_wp_error ) {
267 $wp_error = array_pop( $processed_item_ids );
268 }
269 // also checkin any items that were skipped
270 if ( count( $skipped_items_ids ) > 0 ) {
271 $processed_item_ids = array_merge( $processed_item_ids, $skipped_items_ids );
272 }
273 $processed_items = array_intersect_key( $items, array_flip( $processed_item_ids ) );
274 /**
275 * Allows us to keep track of all the actions that have been sent.
276 * Allows us to calculate the progress of specific actions.
277 *
278 * @since 4.2.0
279 *
280 * @param array $processed_actions The actions that we send successfully.
281 */
282 do_action( 'jetpack_sync_processed_actions', $processed_items );
283 $queue->close( $buffer, $processed_item_ids );
284 // returning a WP_Error is a sign to the caller that we should wait a while
285 // before syncing again
286 if ( $had_wp_error ) {
287 return new WP_Error( 'wpcom_error', $wp_error->get_error_code() );
288 }
289 }
290 return true;
291 }
292
293 function get_sync_queue() {
294 return $this->sync_queue;
295 }
296
297 function get_full_sync_queue() {
298 return $this->full_sync_queue;
299 }
300
301 function get_codec() {
302 return $this->codec;
303 }
304 function set_codec() {
305 if ( function_exists( 'gzinflate' ) ) {
306 $this->codec = new Jetpack_Sync_JSON_Deflate_Array_Codec();
307 } else {
308 $this->codec = new Jetpack_Sync_Simple_Codec();
309 }
310 }
311
312 function send_checksum() {
313 require_once 'class.jetpack-sync-wp-replicastore.php';
314 $store = new Jetpack_Sync_WP_Replicastore();
315 do_action( 'jetpack_sync_checksum', $store->checksum_all() );
316 }
317
318 function reset_sync_queue() {
319 $this->sync_queue->reset();
320 }
321
322 function reset_full_sync_queue() {
323 $this->full_sync_queue->reset();
324 }
325
326 function set_dequeue_max_bytes( $size ) {
327 $this->dequeue_max_bytes = $size;
328 }
329
330 // in bytes
331 function set_upload_max_bytes( $max_bytes ) {
332 $this->upload_max_bytes = $max_bytes;
333 }
334
335 // in rows
336 function set_upload_max_rows( $max_rows ) {
337 $this->upload_max_rows = $max_rows;
338 }
339
340 // in seconds
341 function set_sync_wait_time( $seconds ) {
342 $this->sync_wait_time = $seconds;
343 }
344
345 function get_sync_wait_time() {
346 return $this->sync_wait_time;
347 }
348
349 function set_enqueue_wait_time( $seconds ) {
350 $this->enqueue_wait_time = $seconds;
351 }
352
353 function get_enqueue_wait_time() {
354 return $this->enqueue_wait_time;
355 }
356
357 // in seconds
358 function set_sync_wait_threshold( $seconds ) {
359 $this->sync_wait_threshold = $seconds;
360 }
361
362 function get_sync_wait_threshold() {
363 return $this->sync_wait_threshold;
364 }
365
366 // in seconds
367 function set_max_dequeue_time( $seconds ) {
368 $this->max_dequeue_time = $seconds;
369 }
370
371
372
373 function set_defaults() {
374 $this->sync_queue = new Jetpack_Sync_Queue( 'sync' );
375 $this->full_sync_queue = new Jetpack_Sync_Queue( 'full_sync' );
376 $this->set_codec();
377
378 // saved settings
379 Jetpack_Sync_Settings::set_importing( null );
380 $settings = Jetpack_Sync_Settings::get_settings();
381 $this->set_dequeue_max_bytes( $settings['dequeue_max_bytes'] );
382 $this->set_upload_max_bytes( $settings['upload_max_bytes'] );
383 $this->set_upload_max_rows( $settings['upload_max_rows'] );
384 $this->set_sync_wait_time( $settings['sync_wait_time'] );
385 $this->set_enqueue_wait_time( $settings['enqueue_wait_time'] );
386 $this->set_sync_wait_threshold( $settings['sync_wait_threshold'] );
387 $this->set_max_dequeue_time( Jetpack_Sync_Defaults::get_max_sync_execution_time() );
388 }
389
390 function reset_data() {
391 $this->reset_sync_queue();
392 $this->reset_full_sync_queue();
393
394 foreach ( Jetpack_Sync_Modules::get_modules() as $module ) {
395 $module->reset_data();
396 }
397
398 foreach ( array( 'sync', 'full_sync', 'full-sync-enqueue' ) as $queue_name ) {
399 delete_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name );
400 }
401
402 Jetpack_Sync_Settings::reset_data();
403 }
404
405 function uninstall() {
406 // Lets delete all the other fun stuff like transient and option and the sync queue
407 $this->reset_data();
408
409 // delete the full sync status
410 delete_option( 'jetpack_full_sync_status' );
411
412 // clear the sync cron.
413 wp_clear_scheduled_hook( 'jetpack_sync_cron' );
414 wp_clear_scheduled_hook( 'jetpack_sync_full_cron' );
415 }
416 }
417