PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-sync/src/class-server.php +196 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,196 @@
1 +<?php
2 +/**
3 + * Sync server.
4 + *
5 + * @package automattic/jetpack-sync
6 + */
7 +
8 +namespace Automattic\Jetpack\Sync;
9 +
10 +use WP_Error;
11 +
12 +/**
13 + * Simple version of a Jetpack Sync Server - just receives arrays of events and
14 + * issues them locally with the 'jetpack_sync_remote_action' action.
15 + */
16 +class Server {
17 + /**
18 + * Codec used to decode sync events.
19 + *
20 + * @access private
21 + *
22 + * @var \Automattic\Jetpack\Sync\Codec_Interface
23 + */
24 + private $codec;
25 +
26 + /**
27 + * Maximum time for processing sync actions.
28 + *
29 + * @access public
30 + *
31 + * @var int
32 + */
33 + const MAX_TIME_PER_REQUEST_IN_SECONDS = 15;
34 +
35 + /**
36 + * Prefix of the blog lock transient.
37 + *
38 + * @access public
39 + *
40 + * @var string
41 + */
42 + const BLOG_LOCK_TRANSIENT_PREFIX = 'jp_sync_req_lock_';
43 +
44 + /**
45 + * Lifetime of the blog lock transient.
46 + *
47 + * @access public
48 + *
49 + * @var int
50 + */
51 + const BLOG_LOCK_TRANSIENT_EXPIRY = 60; // Seconds.
52 +
53 + /**
54 + * Constructor.
55 + *
56 + * This is necessary because you can't use "new" when you declare instance properties >:(
57 + *
58 + * @access public
59 + */
60 + public function __construct() {
61 + $this->codec = new JSON_Deflate_Array_Codec();
62 + }
63 +
64 + /**
65 + * Set the codec instance.
66 + *
67 + * @access public
68 + *
69 + * @param Automattic\Jetpack\Sync\Codec_Interface $codec Codec instance.
70 + */
71 + public function set_codec( Codec_Interface $codec ) {
72 + $this->codec = $codec;
73 + }
74 +
75 + /**
76 + * Attempt to lock the request when the server receives concurrent requests from the same blog.
77 + *
78 + * @access public
79 + *
80 + * @param int $blog_id ID of the blog.
81 + * @param int $expiry Blog lock transient lifetime.
82 + * @return boolean True if succeeded, false otherwise.
83 + */
84 + public function attempt_request_lock( $blog_id, $expiry = self::BLOG_LOCK_TRANSIENT_EXPIRY ) {
85 + $transient_name = $this->get_concurrent_request_transient_name( $blog_id );
86 + $locked_time = get_site_transient( $transient_name );
87 + if ( $locked_time ) {
88 + return false;
89 + }
90 + set_site_transient( $transient_name, microtime( true ), $expiry );
91 +
92 + return true;
93 + }
94 +
95 + /**
96 + * Retrieve the blog lock transient name for a particular blog.
97 + *
98 + * @access public
99 + *
100 + * @param int $blog_id ID of the blog.
101 + * @return string Name of the blog lock transient.
102 + */
103 + private function get_concurrent_request_transient_name( $blog_id ) {
104 + return self::BLOG_LOCK_TRANSIENT_PREFIX . $blog_id;
105 + }
106 +
107 + /**
108 + * Remove the request lock from a particular blog ID.
109 + *
110 + * @access public
111 + *
112 + * @param int $blog_id ID of the blog.
113 + */
114 + public function remove_request_lock( $blog_id ) {
115 + delete_site_transient( $this->get_concurrent_request_transient_name( $blog_id ) );
116 + }
117 +
118 + /**
119 + * Receive and process sync events.
120 + *
121 + * @access public
122 + *
123 + * @param array $data Sync events.
124 + * @param object $token The auth token used to invoke the API.
125 + * @param int $sent_timestamp Timestamp (in seconds) when the actions were transmitted.
126 + * @param string $queue_id ID of the queue from which the event was sent (`sync` or `full_sync`).
127 + * @return array Processed sync events.
128 + */
129 + public function receive( $data, $token = null, $sent_timestamp = null, $queue_id = null ) {
130 + $start_time = microtime( true );
131 + if ( ! is_array( $data ) ) {
132 + return new WP_Error( 'action_decoder_error', 'Events must be an array' );
133 + }
134 +
135 + if ( $token && ! $this->attempt_request_lock( $token->blog_id ) ) {
136 + /**
137 + * Fires when the server receives two concurrent requests from the same blog
138 + *
139 + * @since 1.6.3
140 + * @since-jetpack 4.2.0
141 + *
142 + * @param object|null $token The token object of the misbehaving site
143 + */
144 + do_action( 'jetpack_sync_multi_request_fail', $token );
145 +
146 + return new WP_Error( 'concurrent_request_error', 'There is another request running for the same blog ID' );
147 + }
148 +
149 + $events = wp_unslash( array_map( array( $this->codec, 'decode' ), $data ) );
150 + $events_processed = array();
151 +
152 + /**
153 + * Fires when an array of actions are received from a remote Jetpack site
154 + *
155 + * @since 1.6.3
156 + * @since-jetpack 4.2.0
157 + *
158 + * @param array $events Array of actions received from the remote site
159 + * @param object|null $token The auth token used to invoke the API
160 + */
161 + do_action( 'jetpack_sync_remote_actions', $events, $token );
162 +
163 + foreach ( $events as $key => $event ) {
164 + list( $action_name, $args, $user_id, $timestamp, $silent ) = $event;
165 +
166 + /**
167 + * Fires when an action is received from a remote Jetpack site
168 + *
169 + * @since 1.6.3
170 + * @since-jetpack 4.2.0
171 + *
172 + * @param string $action_name The name of the action executed on the remote site
173 + * @param array $args The arguments passed to the action
174 + * @param int $user_id The external_user_id who did the action
175 + * @param bool $silent Whether the item was created via import
176 + * @param double $timestamp Timestamp (in seconds) when the action occurred
177 + * @param double $sent_timestamp Timestamp (in seconds) when the action was transmitted
178 + * @param string $queue_id ID of the queue from which the event was sent (sync or full_sync)
179 + * @param object|null $token The auth token used to invoke the API
180 + */
181 + do_action( 'jetpack_sync_remote_action', $action_name, $args, $user_id, $silent, $timestamp, $sent_timestamp, $queue_id, $token );
182 +
183 + $events_processed[] = $key;
184 +
185 + if ( microtime( true ) - $start_time > self::MAX_TIME_PER_REQUEST_IN_SECONDS ) {
186 + break;
187 + }
188 + }
189 +
190 + if ( $token ) {
191 + $this->remove_request_lock( $token->blog_id );
192 + }
193 +
194 + return $events_processed;
195 + }
196 +}