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-status/src/class-status.php +481 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,481 @@
1 +<?php
2 +/**
3 + * A status class for Jetpack.
4 + *
5 + * @package automattic/jetpack-status
6 + */
7 +
8 +namespace Automattic\Jetpack;
9 +
10 +use Automattic\Jetpack\Status\Cache;
11 +use Automattic\Jetpack\Status\Host;
12 +use WPCOM_Masterbar;
13 +
14 +/**
15 + * Class Automattic\Jetpack\Status
16 + *
17 + * Used to retrieve information about the current status of Jetpack and the site overall.
18 + */
19 +class Status {
20 + /**
21 + * Is Jetpack in offline mode?
22 + *
23 + * This was formerly called "Development Mode", but sites "in development" aren't always offline/localhost.
24 + *
25 + * @since 1.3.0
26 + *
27 + * @return bool Whether Jetpack's offline mode is active.
28 + */
29 + public function is_offline_mode() {
30 + $cached = Cache::get( 'is_offline_mode' );
31 + if ( null !== $cached ) {
32 + return $cached;
33 + }
34 +
35 + $offline_mode = false;
36 +
37 + if ( defined( '\\JETPACK_DEV_DEBUG' ) ) {
38 + $offline_mode = constant( '\\JETPACK_DEV_DEBUG' );
39 + } elseif ( defined( '\\WP_LOCAL_DEV' ) ) {
40 + $offline_mode = constant( '\\WP_LOCAL_DEV' );
41 + } elseif ( $this->is_local_site() ) {
42 + $offline_mode = true;
43 + }
44 +
45 + /**
46 + * Filters Jetpack's offline mode.
47 + *
48 + * @see https://jetpack.com/support/offline-mode/
49 + *
50 + * @since 1.3.0
51 + *
52 + * @param bool $offline_mode Is Jetpack's offline mode active.
53 + */
54 + $offline_mode = (bool) apply_filters( 'jetpack_offline_mode', $offline_mode );
55 +
56 + if ( ! $offline_mode ) {
57 + // Sentinel default so an absent option isn't confused with a stored null/false.
58 + $sentinel = new \stdClass();
59 + $option = get_option( 'jetpack_offline_mode', $sentinel );
60 +
61 + if ( $sentinel === $option ) {
62 + // Seed an autoloaded default to stop per-request reads, but only where it helps
63 + // (no persistent object cache) and writes are safe (keep front-end reads read-only).
64 + if ( ! wp_using_ext_object_cache() && ( is_admin() || wp_doing_cron() || ( defined( 'WP_CLI' ) && WP_CLI ) ) ) {
65 + add_option( 'jetpack_offline_mode', false, '', true );
66 + }
67 + } else {
68 + // A default_option filter could return a non-scalar; only a scalar is a real value.
69 + $offline_mode = is_scalar( $option ) ? (bool) $option : false;
70 + }
71 + }
72 +
73 + Cache::set( 'is_offline_mode', $offline_mode );
74 + return $offline_mode;
75 + }
76 +
77 + /**
78 + * Whether this is a system with a multiple networks.
79 + * Implemented since there is no core is_multi_network function.
80 + * Right now there is no way to tell which network is the dominant network on the system.
81 + *
82 + * @return boolean
83 + */
84 + public function is_multi_network() {
85 + global $wpdb;
86 +
87 + $cached = Cache::get( 'is_multi_network' );
88 + if ( null !== $cached ) {
89 + return $cached;
90 + }
91 +
92 + // If we don't have a multi site setup no need to do any more.
93 + if ( ! is_multisite() ) {
94 + Cache::set( 'is_multi_network', false );
95 + return false;
96 + }
97 +
98 + $num_sites = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->site}" );
99 + if ( $num_sites > 1 ) {
100 + Cache::set( 'is_multi_network', true );
101 + return true;
102 + }
103 +
104 + Cache::set( 'is_multi_network', false );
105 + return false;
106 + }
107 +
108 + /**
109 + * Whether the current site is single user site.
110 + *
111 + * @return bool
112 + */
113 + public function is_single_user_site() {
114 + global $wpdb;
115 +
116 + $ret = Cache::get( 'is_single_user_site' );
117 + if ( null === $ret ) {
118 + $some_users = get_transient( 'jetpack_is_single_user' );
119 + if ( false === $some_users ) {
120 + $some_users = $wpdb->get_var( "SELECT COUNT(*) FROM (SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '{$wpdb->prefix}capabilities' LIMIT 2) AS someusers" );
121 + set_transient( 'jetpack_is_single_user', (int) $some_users, 12 * HOUR_IN_SECONDS );
122 + }
123 + $ret = 1 === (int) $some_users;
124 + Cache::set( 'is_single_user_site', $ret );
125 + }
126 + return $ret;
127 + }
128 +
129 + /**
130 + * If the site is a local site.
131 + *
132 + * @since 1.3.0
133 + *
134 + * @return bool
135 + */
136 + public function is_local_site() {
137 + $cached = Cache::get( 'is_local_site' );
138 + if ( null !== $cached ) {
139 + return $cached;
140 + }
141 +
142 + $site_url = trim( (string) site_url() );
143 +
144 + /*
145 + * Every check below cares about the host, not the rest of the URL. Matching the host
146 + * alone means a port, a subdirectory install, or a trailing slash can't defeat them,
147 + * and a known local domain sitting in the path can't trigger them by accident.
148 + */
149 + $host = wp_parse_url( $site_url, PHP_URL_HOST );
150 + if ( ( ! is_string( $host ) || '' === $host ) && ! preg_match( '#^[a-z][a-z0-9+.\-]*:#i', $site_url ) ) {
151 + /*
152 + * No scheme, so site_url() isn't absolute. Read the value as a bare host.
153 + * A value that does carry a scheme but still won't parse is malformed, and
154 + * guessing at it would read "https:/example.com" as the host "https".
155 + */
156 + $host = wp_parse_url( '//' . ltrim( $site_url, '/' ), PHP_URL_HOST );
157 + }
158 + if ( ! is_string( $host ) ) {
159 + /*
160 + * Nothing host-shaped to test. Treat the site as remote rather than matching the
161 + * raw URL: a false "local" silently drops a live site into offline mode.
162 + */
163 + $host = '';
164 + }
165 +
166 + /*
167 + * Check for localhost and sites using an IP only first. No dot means it can't be a
168 + * public domain. Dotless IPv6 literals land here too, routable ones included:
169 + * WordPress.com won't register an IPv6 site URL, so offline mode is where they belong.
170 + * An IPv4-mapped literal like [::ffff:127.0.0.1] keeps its dots and reads as remote.
171 + */
172 + $is_local = '' !== $host && false === strpos( $host, '.' );
173 +
174 + // Use Core's environment check, if available.
175 + if ( 'local' === wp_get_environment_type() ) {
176 + $is_local = true;
177 + }
178 +
179 + // Then check for usual domains used by local dev tools.
180 + $known_local = array(
181 + '#\.local$#i',
182 + '#(^|\.)localhost$#i', // localhost and any subdomain of it.
183 + '#\.test$#i',
184 + '#\.docksal$#i', // Docksal.
185 + '#\.docksal\.site$#i', // Docksal.
186 + '#\.dev\.cc$#i', // ServerPress.
187 + '#\.lndo\.site$#i', // Lando.
188 + '#\.ddev\.site$#i', // DDEV.
189 + // The whole 127.0.0.0/8 range is loopback; each octet is capped at 255.
190 + '#^127\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){2}$#',
191 + '#^0\.0\.0\.0$#', // All-interfaces bind, common under Docker and `wp server`.
192 + '#^playground\.wordpress\.net$#i', // WordPress Playground, which runs entirely in the browser.
193 + );
194 +
195 + if ( ! $is_local && '' !== $host ) {
196 + foreach ( $known_local as $pattern ) {
197 + if ( preg_match( $pattern, $host ) ) {
198 + $is_local = true;
199 + break;
200 + }
201 + }
202 + }
203 +
204 + /**
205 + * Filters is_local_site check.
206 + *
207 + * @since 1.3.0
208 + *
209 + * @param bool $is_local If the current site is a local site.
210 + */
211 + $is_local = apply_filters( 'jetpack_is_local_site', $is_local );
212 +
213 + Cache::set( 'is_local_site', $is_local );
214 + return $is_local;
215 + }
216 +
217 + /**
218 + * If is a staging site.
219 + *
220 + * @deprecated since 3.3.0
221 + *
222 + * @return bool
223 + */
224 + public function is_staging_site() {
225 + _deprecated_function( __FUNCTION__, '3.3.0', 'in_safe_mode' );
226 + $cached = Cache::get( 'is_staging_site' );
227 + if ( null !== $cached ) {
228 + return $cached;
229 + }
230 +
231 + /*
232 + * Core's wp_get_environment_type allows for a few specific options.
233 + * We should default to bowing out gracefully for anything other than production or local.
234 + */
235 + $is_staging = ! in_array( wp_get_environment_type(), array( 'production', 'local' ), true );
236 +
237 + $known_staging = array(
238 + 'urls' => array(
239 + '#\.staging\.wpengine\.com$#i', // WP Engine. This is their legacy staging URL structure. Their new platform does not have a common URL. https://github.com/Automattic/jetpack/issues/21504
240 + '#\.staging\.kinsta\.com$#i', // Kinsta.com.
241 + '#\.kinsta\.cloud$#i', // Kinsta.com.
242 + '#\.stage\.site$#i', // DreamPress.
243 + '#\.newspackstaging\.com$#i', // Newspack.
244 + '#^(?!live-)([a-zA-Z0-9-]+)\.pantheonsite\.io$#i', // Pantheon.
245 + '#\.flywheelsites\.com$#i', // Flywheel.
246 + '#\.flywheelstaging\.com$#i', // Flywheel.
247 + '#\.cloudwaysapps\.com$#i', // Cloudways.
248 + '#\.azurewebsites\.net$#i', // Azure.
249 + '#\.wpserveur\.net$#i', // WPServeur.
250 + '#\-liquidwebsites\.com$#i', // Liquidweb.
251 + ),
252 + 'constants' => array(
253 + 'IS_WPE_SNAPSHOT', // WP Engine. This is used on their legacy staging environment. Their new platform does not have a constant. https://github.com/Automattic/jetpack/issues/21504
254 + 'KINSTA_DEV_ENV', // Kinsta.com.
255 + 'WPSTAGECOACH_STAGING', // WP Stagecoach.
256 + 'JETPACK_STAGING_MODE', // Generic.
257 + 'WP_LOCAL_DEV', // Generic.
258 + ),
259 + );
260 + /**
261 + * Filters the flags of known staging sites.
262 + *
263 + * @since 1.1.1
264 + * @since-jetpack 3.9.0
265 + *
266 + * @param array $known_staging {
267 + * An array of arrays that each are used to check if the current site is staging.
268 + * @type array $urls URLs of staging sites in regex to check against site_url.
269 + * @type array $constants PHP constants of known staging/developement environments.
270 + * }
271 + */
272 + $known_staging = apply_filters( 'jetpack_known_staging', $known_staging );
273 +
274 + if ( isset( $known_staging['urls'] ) ) {
275 + $site_url = site_url();
276 + foreach ( $known_staging['urls'] as $url ) {
277 + if ( preg_match( $url, wp_parse_url( $site_url, PHP_URL_HOST ) ) ) {
278 + $is_staging = true;
279 + break;
280 + }
281 + }
282 + }
283 +
284 + if ( isset( $known_staging['constants'] ) ) {
285 + foreach ( $known_staging['constants'] as $constant ) {
286 + if ( defined( $constant ) && constant( $constant ) ) {
287 + $is_staging = true;
288 + }
289 + }
290 + }
291 +
292 + // Last, let's check if sync is erroring due to an IDC. If so, set the site to staging mode.
293 + if ( ! $is_staging && method_exists( 'Automattic\\Jetpack\\Identity_Crisis', 'validate_sync_error_idc_option' ) && \Automattic\Jetpack\Identity_Crisis::validate_sync_error_idc_option() ) {
294 + $is_staging = true;
295 + }
296 +
297 + /**
298 + * Filters is_staging_site check.
299 + *
300 + * @since 1.1.1
301 + * @since-jetpack 3.9.0
302 + *
303 + * @param bool $is_staging If the current site is a staging site.
304 + */
305 + $is_staging = apply_filters( 'jetpack_is_staging_site', $is_staging );
306 +
307 + Cache::set( 'is_staging_site', $is_staging );
308 + return $is_staging;
309 + }
310 +
311 + /**
312 + * If the site is in safe mode.
313 + *
314 + * @since 3.3.0
315 + *
316 + * @return bool
317 + */
318 + public function in_safe_mode() {
319 + $cached = Cache::get( 'in_safe_mode' );
320 + if ( null !== $cached ) {
321 + return $cached;
322 + }
323 + $in_safe_mode = false;
324 + if ( method_exists( 'Automattic\\Jetpack\\Identity_Crisis', 'validate_sync_error_idc_option' ) && \Automattic\Jetpack\Identity_Crisis::validate_sync_error_idc_option() ) {
325 + $in_safe_mode = true;
326 + }
327 + /**
328 + * Filters in_safe_mode check.
329 + *
330 + * @since 3.3.0
331 + *
332 + * @param bool $in_safe_mode If the current site is in safe mode.
333 + */
334 + $in_safe_mode = apply_filters( 'jetpack_is_in_safe_mode', $in_safe_mode );
335 +
336 + Cache::set( 'in_safe_mode', $in_safe_mode );
337 + return $in_safe_mode;
338 + }
339 +
340 + /**
341 + * If the site is a development/staging site.
342 + * This is a new version of is_staging_site added to separate safe mode from the legacy staging mode.
343 + * This method checks for core WP_ENVIRONMENT_TYPE setting
344 + * Using the jetpack_is_development_site filter.
345 + *
346 + * @since 3.3.0
347 + *
348 + * @return bool
349 + */
350 + public static function is_development_site() {
351 + $cached = Cache::get( 'is_development_site' );
352 + if ( null !== $cached ) {
353 + return $cached;
354 + }
355 + $is_dev_site = ! in_array( wp_get_environment_type(), array( 'production', 'local' ), true );
356 + /**
357 + * Filters is_development_site check.
358 + *
359 + * @since 3.3.0
360 + *
361 + * @param bool $is_dev_site If the current site is a staging or dev site.
362 + */
363 + $is_dev_site = apply_filters( 'jetpack_is_development_site', $is_dev_site );
364 +
365 + Cache::set( 'is_development_site', $is_dev_site );
366 + return $is_dev_site;
367 + }
368 +
369 + /**
370 + * Whether the site is currently onboarding or not.
371 + * A site is considered as being onboarded if it currently has an onboarding token.
372 + *
373 + * @since-jetpack 5.8
374 + *
375 + * @deprecated since 4.0.0
376 + *
377 + * @access public
378 + * @static
379 + *
380 + * @return bool True if the site is currently onboarding, false otherwise
381 + */
382 + public function is_onboarding() {
383 + return \Jetpack_Options::get_option( 'onboarding' ) !== false;
384 + }
385 +
386 + /**
387 + * Whether the site is currently private or not.
388 + * On WordPress.com and WoA, sites can be marked as private
389 + *
390 + * @since 1.16.0
391 + *
392 + * @return bool True if the site is private.
393 + */
394 + public function is_private_site() {
395 + $ret = Cache::get( 'is_private_site' );
396 + if ( null === $ret ) {
397 + $is_private_site = '-1' === get_option( 'blog_public' );
398 +
399 + /**
400 + * Filters the is_private_site check.
401 + *
402 + * @since 1.16.1
403 + *
404 + * @param bool $is_private_site True if the site is private.
405 + */
406 + $is_private_site = apply_filters( 'jetpack_is_private_site', $is_private_site );
407 +
408 + Cache::set( 'is_private_site', $is_private_site );
409 + return $is_private_site;
410 + }
411 + return $ret;
412 + }
413 +
414 + /**
415 + * Whether the site is currently unlaunched or not.
416 + * On WordPress.com and WoA, sites can be marked as "coming soon", aka unlaunched
417 + *
418 + * @since 1.16.0
419 + *
420 + * @return bool True if the site is not launched.
421 + */
422 + public function is_coming_soon() {
423 + $ret = Cache::get( 'is_coming_soon' );
424 + if ( null === $ret ) {
425 + $is_coming_soon = ( function_exists( 'site_is_coming_soon' ) && \site_is_coming_soon() )
426 + || get_option( 'wpcom_public_coming_soon' );
427 +
428 + /**
429 + * Filters the is_coming_soon check.
430 + *
431 + * @since 1.16.1
432 + *
433 + * @param bool $is_coming_soon True if the site is coming soon (i.e. unlaunched).
434 + */
435 + $is_coming_soon = apply_filters( 'jetpack_is_coming_soon', $is_coming_soon );
436 +
437 + Cache::set( 'is_coming_soon', $is_coming_soon );
438 + return $is_coming_soon;
439 + }
440 + return $ret;
441 + }
442 +
443 + /**
444 + * Returns the site slug suffix to be used as part of Calypso URLs.
445 + *
446 + * Strips http:// or https:// from a url, replaces forward slash with ::.
447 + *
448 + * @since 1.6.0
449 + *
450 + * @param string $url Optional. URL to build the site suffix from. Default: Home URL.
451 + *
452 + * @return string
453 + */
454 + public function get_site_suffix( $url = '' ) {
455 + // On WordPress.com, site suffixes are a bit different.
456 + if ( method_exists( 'WPCOM_Masterbar', 'get_calypso_site_slug' ) ) {
457 + return WPCOM_Masterbar::get_calypso_site_slug( get_current_blog_id() );
458 + }
459 +
460 + // Grab the 'site_url' option for WoA sites to avoid plugins to interfere with the site
461 + // identifier (e.g. i18n plugins may change the main url to '<DOMAIN>/<LOCALE>', but we
462 + // want to exclude the locale since it's not part of the site suffix).
463 + if ( ( new Host() )->is_woa_site() ) {
464 + $url = \site_url();
465 + }
466 +
467 + if ( empty( $url ) ) {
468 + // WordPress can be installed in subdirectories (e.g. make.wordpress.org/plugins)
469 + // where the 'site_url' option points to the root domain (e.g. make.wordpress.org)
470 + // which could collide with another site in the same domain but with WordPress
471 + // installed in a different subdirectory (e.g. make.wordpress.org/core). To avoid
472 + // such collision, we identify the site with the 'home_url' option.
473 + $url = \home_url();
474 + }
475 +
476 + $url = preg_replace( '#^.*?://#', '', $url );
477 + $url = str_replace( '/', '::', $url );
478 +
479 + return rtrim( $url, ':' );
480 + }
481 +}