PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 13.8.2
Jetpack – WP Security, Backup, Speed, & Growth v13.8.2
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 / class.jetpack-autoupdate.php
jetpack Last commit date
3rd-party 2 years ago _inc 1 year ago css 1 year ago extensions 1 year ago images 1 year ago jetpack_vendor 1 year ago json-endpoints 1 year ago modules 1 year ago sal 1 year ago src 1 year ago vendor 1 year ago views 2 years ago CHANGELOG.md 1 year ago LICENSE.txt 5 years ago SECURITY.md 2 years ago class-jetpack-connection-status.php 2 years ago class-jetpack-gallery-settings.php 3 years ago class-jetpack-pre-connection-jitms.php 2 years ago class-jetpack-stats-dashboard-widget.php 2 years ago class-jetpack-xmlrpc-methods.php 1 year ago class.frame-nonce-preview.php 4 years ago class.jetpack-admin.php 1 year ago class.jetpack-affiliate.php 2 years ago class.jetpack-autoupdate.php 2 years ago class.jetpack-bbpress-json-api.compat.php 2 years ago class.jetpack-cli.php 1 year ago class.jetpack-client-server.php 2 years ago class.jetpack-gutenberg.php 1 year ago class.jetpack-heartbeat.php 2 years ago class.jetpack-modules-list-table.php 2 years ago class.jetpack-network-sites-list-table.php 2 years ago class.jetpack-network.php 2 years ago class.jetpack-plan.php 2 years ago class.jetpack-post-images.php 1 year ago class.jetpack-twitter-cards.php 2 years ago class.jetpack-user-agent.php 2 years ago class.jetpack.php 1 year ago class.json-api-endpoints.php 2 years ago class.json-api.php 2 years ago class.photon.php 3 years ago composer.json 1 year ago enhanced-open-graph.php 3 years ago functions.compat.php 2 years ago functions.cookies.php 2 years ago functions.global.php 1 year ago functions.is-mobile.php 2 years ago functions.opengraph.php 1 year ago functions.photon.php 2 years ago global.d.ts 1 year ago jetpack.php 1 year ago json-api-config.php 3 years ago json-endpoints.php 2 years ago load-jetpack.php 2 years ago locales.php 4 years ago readme.txt 1 year ago uninstall.php 2 years ago wpml-config.xml 3 years ago
class.jetpack-autoupdate.php
369 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Handles items that have been selected for automatic updates.
4 * Hooks into WP_Automatic_Updater
5 *
6 * @package automattic/jetpack
7 */
8
9 /**
10 * Handles items that have been selected for automatic updates.
11 * Hooks into WP_Automatic_Updater
12 */
13 class Jetpack_Autoupdate {
14
15 /**
16 * Results.
17 *
18 * @var array
19 */
20 private $results = array();
21
22 /**
23 * Expected updates.
24 *
25 * @var array
26 */
27 private $expected = array();
28
29 /**
30 * Successful updates.
31 *
32 * @var array
33 */
34 private $success = array(
35 'plugin' => array(),
36 'theme' => array(),
37 );
38
39 /**
40 * Failed updates.
41 *
42 * @var array
43 */
44 private $failed = array(
45 'plugin' => array(),
46 'theme' => array(),
47 );
48
49 /**
50 * Static instance.
51 *
52 * @var self
53 */
54 private static $instance = null;
55
56 /**
57 * Initialize and fetch the static instance.
58 *
59 * @return self
60 */
61 public static function init() {
62 if ( self::$instance === null ) {
63 self::$instance = new Jetpack_Autoupdate();
64 }
65
66 return self::$instance;
67 }
68
69 /** Constructor. */
70 private function __construct() {
71 if (
72 /** This filter is documented in class.jetpack-json-api-endpoint.php */
73 apply_filters( 'jetpack_json_manage_api_enabled', true )
74 ) {
75 add_filter( 'auto_update_theme', array( $this, 'autoupdate_theme' ), 10, 2 );
76 add_filter( 'auto_update_core', array( $this, 'autoupdate_core' ), 10, 2 );
77 add_filter( 'auto_update_translation', array( $this, 'autoupdate_translation' ), 10, 2 );
78 add_action( 'automatic_updates_complete', array( $this, 'automatic_updates_complete' ), 999, 1 );
79 }
80 }
81
82 /**
83 * Filter function for `auto_update_translation`.
84 *
85 * @param bool|null $update Whether to update.
86 * @param object $item The update offer.
87 * @return bool|null Whether to update.
88 */
89 public function autoupdate_translation( $update, $item ) {
90 // Autoupdate all translations.
91 if ( Jetpack_Options::get_option( 'autoupdate_translations', false ) ) {
92 return true;
93 }
94
95 // Themes.
96 $autoupdate_themes_translations = Jetpack_Options::get_option( 'autoupdate_themes_translations', array() );
97 $autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() );
98
99 if ( ( in_array( $item->slug, $autoupdate_themes_translations, true ) || in_array( $item->slug, $autoupdate_theme_list, true ) )
100 && 'theme' === $item->type
101 ) {
102 $this->expect( $item->type . ':' . $item->slug, 'translation' );
103
104 return true;
105 }
106
107 // Plugins.
108 $autoupdate_plugin_translations = Jetpack_Options::get_option( 'autoupdate_plugins_translations', array() );
109 $autoupdate_plugin_list = (array) get_site_option( 'auto_update_plugins', array() );
110 $plugin_files = array_unique( array_merge( $autoupdate_plugin_list, $autoupdate_plugin_translations ) );
111 $plugin_slugs = array_map( array( __CLASS__, 'get_plugin_slug' ), $plugin_files );
112
113 if ( in_array( $item->slug, $plugin_slugs, true )
114 && 'plugin' === $item->type
115 ) {
116 $this->expect( $item->type . ':' . $item->slug, 'translation' );
117 return true;
118 }
119
120 return $update;
121 }
122
123 /**
124 * Filter function for `auto_update_theme`.
125 *
126 * @param bool|null $update Whether to update.
127 * @param object $item The update offer.
128 * @return bool|null Whether to update.
129 */
130 public function autoupdate_theme( $update, $item ) {
131 $autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() );
132 if ( in_array( $item->theme, $autoupdate_theme_list, true ) ) {
133 $this->expect( $item->theme, 'theme' );
134 return true;
135 }
136
137 return $update;
138 }
139
140 /**
141 * Filter function for `auto_update_core`.
142 *
143 * @param bool|null $update Whether to update.
144 * @return bool|null Whether to update.
145 */
146 public function autoupdate_core( $update ) {
147 $autoupdate_core = Jetpack_Options::get_option( 'autoupdate_core', false );
148 if ( $autoupdate_core ) {
149 return $autoupdate_core;
150 }
151
152 return $update;
153 }
154
155 /**
156 * Stores the an item identifier to the expected array.
157 *
158 * @param string $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme'.
159 * @param string $type 'plugin' or 'theme'.
160 */
161 private function expect( $item, $type ) {
162 if ( ! isset( $this->expected[ $type ] ) ) {
163 $this->expected[ $type ] = array();
164 }
165 $this->expected[ $type ][] = $item;
166 }
167
168 /**
169 * On completion of an automatic update, let's store the results.
170 *
171 * @param mixed $results - Sent by WP_Automatic_Updater after it completes an autoupdate action. Results may be empty.
172 */
173 public function automatic_updates_complete( $results ) {
174 if ( empty( $this->expected ) ) {
175 return;
176 }
177 $this->results = empty( $results ) ? self::get_possible_failures() : $results;
178
179 add_action( 'shutdown', array( $this, 'bump_stats' ) );
180
181 Jetpack::init();
182
183 $items_to_log = array( 'plugin', 'theme', 'translation' );
184 foreach ( $items_to_log as $items ) {
185 $this->log_items( $items );
186 }
187
188 Jetpack::log( 'autoupdates', $this->get_log() );
189 }
190
191 /**
192 * Get log data.
193 *
194 * @return array Data.
195 */
196 public function get_log() {
197 return array(
198 'results' => $this->results,
199 'failed' => $this->failed,
200 'success' => $this->success,
201 );
202 }
203
204 /**
205 * Iterates through expected items ( plugins or themes ) and compares them to actual results.
206 *
207 * @param string $items 'plugin' or 'theme'.
208 */
209 private function log_items( $items ) {
210 if ( ! isset( $this->expected[ $items ] ) ) {
211 return;
212 }
213
214 $item_results = $this->get_successful_updates( $items );
215
216 if ( is_array( $this->expected[ $items ] ) ) {
217 foreach ( $this->expected[ $items ] as $item ) {
218 if ( in_array( $item, $item_results, true ) ) {
219 $this->success[ $items ][] = $item;
220 } else {
221 $this->failed[ $items ][] = $item;
222 }
223 }
224 }
225 }
226
227 /**
228 * Bump stats.
229 */
230 public function bump_stats() {
231 $instance = Jetpack::init();
232 $log = array();
233 // Bump numbers.
234
235 if ( ! empty( $this->success['theme'] ) ) {
236 $instance->stat( 'autoupdates/theme-success', is_countable( $this->success['theme'] ) ? count( $this->success['theme'] ) : 0 );
237 $log['themes_success'] = $this->success['theme'];
238 }
239
240 if ( ! empty( $this->failed['theme'] ) ) {
241 $instance->stat( 'autoupdates/theme-fail', is_countable( $this->failed['theme'] ) ? count( $this->failed['theme'] ) : 0 );
242 $log['themes_failed'] = $this->failed['theme'];
243 }
244
245 $instance->do_stats( 'server_side' );
246
247 // Send a more detailed log to logstash.
248 if ( ! empty( $log ) ) {
249 $xml = new Jetpack_IXR_Client(
250 array(
251 'user_id' => get_current_user_id(),
252 )
253 );
254 $log['blog_id'] = Jetpack_Options::get_option( 'id' );
255 $xml->query( 'jetpack.debug_autoupdate', $log );
256 }
257 }
258
259 /**
260 * Parses the autoupdate results generated by WP_Automatic_Updater and returns a simple array of successful items.
261 *
262 * @param string $type 'plugin' or 'theme'.
263 * @return array
264 */
265 private function get_successful_updates( $type ) {
266 $successful_updates = array();
267
268 if ( ! isset( $this->results[ $type ] ) ) {
269 return $successful_updates;
270 }
271
272 foreach ( $this->results[ $type ] as $result ) {
273 if ( $result->result ) {
274 switch ( $type ) {
275 case 'theme':
276 $successful_updates[] = $result->item->theme;
277 break;
278 case 'translation':
279 $successful_updates[] = $result->item->type . ':' . $result->item->slug;
280 break;
281 }
282 }
283 }
284
285 return $successful_updates;
286 }
287
288 /**
289 * Get possible failure codes.
290 *
291 * @return string[] Failure codes.
292 */
293 public static function get_possible_failures() {
294 $result = array();
295 // Lets check some reasons why it might not be working as expected.
296 include_once ABSPATH . '/wp-admin/includes/admin.php';
297 include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php';
298 $upgrader = new WP_Automatic_Updater();
299
300 if ( $upgrader->is_disabled() ) {
301 $result[] = 'autoupdates-disabled';
302 }
303 if ( ! is_main_site() ) {
304 $result[] = 'is-not-main-site';
305 }
306 if ( ! is_main_network() ) {
307 $result[] = 'is-not-main-network';
308 }
309 if ( $upgrader->is_vcs_checkout( ABSPATH ) ) {
310 $result[] = 'site-on-vcs';
311 }
312 if ( $upgrader->is_vcs_checkout( WP_PLUGIN_DIR ) ) {
313 $result[] = 'plugin-directory-on-vcs';
314 }
315 if ( $upgrader->is_vcs_checkout( WP_CONTENT_DIR ) ) {
316 $result[] = 'content-directory-on-vcs';
317 }
318 $lock = get_option( 'auto_updater.lock' );
319 if ( $lock > ( time() - HOUR_IN_SECONDS ) ) {
320 $result[] = 'lock-is-set';
321 }
322 $skin = new Automatic_Upgrader_Skin();
323 include_once ABSPATH . 'wp-admin/includes/file.php';
324 include_once ABSPATH . 'wp-admin/includes/template.php';
325 if ( ! $skin->request_filesystem_credentials( false, ABSPATH, false ) ) {
326 $result[] = 'no-system-write-access';
327 }
328 if ( ! $skin->request_filesystem_credentials( false, WP_PLUGIN_DIR, false ) ) {
329 $result[] = 'no-plugin-directory-write-access';
330 }
331 if ( ! $skin->request_filesystem_credentials( false, WP_CONTENT_DIR, false ) ) {
332 $result[] = 'no-wp-content-directory-write-access';
333 }
334
335 return $result;
336 }
337
338 /**
339 * Get the plugin slug.
340 *
341 * @param string $plugin_file Plugin file.
342 * @return string Slug.
343 */
344 public static function get_plugin_slug( $plugin_file ) {
345 $update_plugins = get_site_transient( 'update_plugins' );
346 if ( isset( $update_plugins->no_update ) ) {
347 if ( isset( $update_plugins->no_update[ $plugin_file ]->slug ) ) {
348 $slug = $update_plugins->no_update[ $plugin_file ]->slug;
349 }
350 }
351 if ( empty( $slug ) && isset( $update_plugins->response ) ) {
352 if ( isset( $update_plugins->response[ $plugin_file ]->slug ) ) {
353 $slug = $update_plugins->response[ $plugin_file ]->slug;
354 }
355 }
356
357 // Try to infer from the plugin file if not cached.
358 if ( empty( $slug ) ) {
359 $slug = dirname( $plugin_file );
360 if ( '.' === $slug ) {
361 $slug = preg_replace( '/(.+)\.php$/', '$1', $plugin_file );
362 }
363 }
364 return $slug;
365 }
366 }
367
368 Jetpack_Autoupdate::init();
369