434 lines
12 KiB
PHP
434 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* A status class for Jetpack.
|
|
*
|
|
* @package automattic/jetpack-status
|
|
*/
|
|
|
|
namespace Automattic\Jetpack;
|
|
|
|
use Automattic\Jetpack\Status\Cache;
|
|
use Automattic\Jetpack\Status\Host;
|
|
use WPCOM_Masterbar;
|
|
|
|
/**
|
|
* Class Automattic\Jetpack\Status
|
|
*
|
|
* Used to retrieve information about the current status of Jetpack and the site overall.
|
|
*/
|
|
class Status {
|
|
/**
|
|
* Is Jetpack in offline mode?
|
|
*
|
|
* This was formerly called "Development Mode", but sites "in development" aren't always offline/localhost.
|
|
*
|
|
* @since 1.3.0
|
|
*
|
|
* @return bool Whether Jetpack's offline mode is active.
|
|
*/
|
|
public function is_offline_mode() {
|
|
$cached = Cache::get( 'is_offline_mode' );
|
|
if ( null !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
$offline_mode = false;
|
|
|
|
if ( defined( '\\JETPACK_DEV_DEBUG' ) ) {
|
|
$offline_mode = constant( '\\JETPACK_DEV_DEBUG' );
|
|
} elseif ( defined( '\\WP_LOCAL_DEV' ) ) {
|
|
$offline_mode = constant( '\\WP_LOCAL_DEV' );
|
|
} elseif ( $this->is_local_site() ) {
|
|
$offline_mode = true;
|
|
}
|
|
|
|
/**
|
|
* Filters Jetpack's offline mode.
|
|
*
|
|
* @see https://jetpack.com/support/offline-mode/
|
|
*
|
|
* @since 1.3.0
|
|
*
|
|
* @param bool $offline_mode Is Jetpack's offline mode active.
|
|
*/
|
|
$offline_mode = (bool) apply_filters( 'jetpack_offline_mode', $offline_mode );
|
|
|
|
Cache::set( 'is_offline_mode', $offline_mode );
|
|
return $offline_mode;
|
|
}
|
|
|
|
/**
|
|
* Whether this is a system with a multiple networks.
|
|
* Implemented since there is no core is_multi_network function.
|
|
* Right now there is no way to tell which network is the dominant network on the system.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function is_multi_network() {
|
|
global $wpdb;
|
|
|
|
$cached = Cache::get( 'is_multi_network' );
|
|
if ( null !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
// If we don't have a multi site setup no need to do any more.
|
|
if ( ! is_multisite() ) {
|
|
Cache::set( 'is_multi_network', false );
|
|
return false;
|
|
}
|
|
|
|
$num_sites = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->site}" );
|
|
if ( $num_sites > 1 ) {
|
|
Cache::set( 'is_multi_network', true );
|
|
return true;
|
|
}
|
|
|
|
Cache::set( 'is_multi_network', false );
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Whether the current site is single user site.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_single_user_site() {
|
|
global $wpdb;
|
|
|
|
$ret = Cache::get( 'is_single_user_site' );
|
|
if ( null === $ret ) {
|
|
$some_users = get_transient( 'jetpack_is_single_user' );
|
|
if ( false === $some_users ) {
|
|
$some_users = $wpdb->get_var( "SELECT COUNT(*) FROM (SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '{$wpdb->prefix}capabilities' LIMIT 2) AS someusers" );
|
|
set_transient( 'jetpack_is_single_user', (int) $some_users, 12 * HOUR_IN_SECONDS );
|
|
}
|
|
$ret = 1 === (int) $some_users;
|
|
Cache::set( 'is_single_user_site', $ret );
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* If the site is a local site.
|
|
*
|
|
* @since 1.3.0
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_local_site() {
|
|
$cached = Cache::get( 'is_local_site' );
|
|
if ( null !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
$site_url = site_url();
|
|
|
|
// Check for localhost and sites using an IP only first.
|
|
// Note: str_contains() is not used here, as wp-includes/compat.php is not loaded in this file.
|
|
$is_local = $site_url && false === strpos( $site_url, '.' );
|
|
|
|
// Use Core's environment check, if available.
|
|
if ( 'local' === wp_get_environment_type() ) {
|
|
$is_local = true;
|
|
}
|
|
|
|
// Then check for usual usual domains used by local dev tools.
|
|
$known_local = array(
|
|
'#\.local$#i',
|
|
'#\.localhost$#i',
|
|
'#\.test$#i',
|
|
'#\.docksal$#i', // Docksal.
|
|
'#\.docksal\.site$#i', // Docksal.
|
|
'#\.dev\.cc$#i', // ServerPress.
|
|
'#\.lndo\.site$#i', // Lando.
|
|
'#^https?://127\.0\.0\.1$#',
|
|
);
|
|
|
|
if ( ! $is_local ) {
|
|
foreach ( $known_local as $url ) {
|
|
if ( preg_match( $url, $site_url ) ) {
|
|
$is_local = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filters is_local_site check.
|
|
*
|
|
* @since 1.3.0
|
|
*
|
|
* @param bool $is_local If the current site is a local site.
|
|
*/
|
|
$is_local = apply_filters( 'jetpack_is_local_site', $is_local );
|
|
|
|
Cache::set( 'is_local_site', $is_local );
|
|
return $is_local;
|
|
}
|
|
|
|
/**
|
|
* If is a staging site.
|
|
*
|
|
* @deprecated since 3.3.0
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_staging_site() {
|
|
_deprecated_function( __FUNCTION__, '3.3.0', 'in_safe_mode' );
|
|
$cached = Cache::get( 'is_staging_site' );
|
|
if ( null !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
/*
|
|
* Core's wp_get_environment_type allows for a few specific options.
|
|
* We should default to bowing out gracefully for anything other than production or local.
|
|
*/
|
|
$is_staging = ! in_array( wp_get_environment_type(), array( 'production', 'local' ), true );
|
|
|
|
$known_staging = array(
|
|
'urls' => array(
|
|
'#\.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
|
|
'#\.staging\.kinsta\.com$#i', // Kinsta.com.
|
|
'#\.kinsta\.cloud$#i', // Kinsta.com.
|
|
'#\.stage\.site$#i', // DreamPress.
|
|
'#\.newspackstaging\.com$#i', // Newspack.
|
|
'#^(?!live-)([a-zA-Z0-9-]+)\.pantheonsite\.io$#i', // Pantheon.
|
|
'#\.flywheelsites\.com$#i', // Flywheel.
|
|
'#\.flywheelstaging\.com$#i', // Flywheel.
|
|
'#\.cloudwaysapps\.com$#i', // Cloudways.
|
|
'#\.azurewebsites\.net$#i', // Azure.
|
|
'#\.wpserveur\.net$#i', // WPServeur.
|
|
'#\-liquidwebsites\.com$#i', // Liquidweb.
|
|
),
|
|
'constants' => array(
|
|
'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
|
|
'KINSTA_DEV_ENV', // Kinsta.com.
|
|
'WPSTAGECOACH_STAGING', // WP Stagecoach.
|
|
'JETPACK_STAGING_MODE', // Generic.
|
|
'WP_LOCAL_DEV', // Generic.
|
|
),
|
|
);
|
|
/**
|
|
* Filters the flags of known staging sites.
|
|
*
|
|
* @since 1.1.1
|
|
* @since-jetpack 3.9.0
|
|
*
|
|
* @param array $known_staging {
|
|
* An array of arrays that each are used to check if the current site is staging.
|
|
* @type array $urls URLs of staging sites in regex to check against site_url.
|
|
* @type array $constants PHP constants of known staging/developement environments.
|
|
* }
|
|
*/
|
|
$known_staging = apply_filters( 'jetpack_known_staging', $known_staging );
|
|
|
|
if ( isset( $known_staging['urls'] ) ) {
|
|
$site_url = site_url();
|
|
foreach ( $known_staging['urls'] as $url ) {
|
|
if ( preg_match( $url, wp_parse_url( $site_url, PHP_URL_HOST ) ) ) {
|
|
$is_staging = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $known_staging['constants'] ) ) {
|
|
foreach ( $known_staging['constants'] as $constant ) {
|
|
if ( defined( $constant ) && constant( $constant ) ) {
|
|
$is_staging = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Last, let's check if sync is erroring due to an IDC. If so, set the site to staging mode.
|
|
if ( ! $is_staging && method_exists( 'Automattic\\Jetpack\\Identity_Crisis', 'validate_sync_error_idc_option' ) && \Automattic\Jetpack\Identity_Crisis::validate_sync_error_idc_option() ) {
|
|
$is_staging = true;
|
|
}
|
|
|
|
/**
|
|
* Filters is_staging_site check.
|
|
*
|
|
* @since 1.1.1
|
|
* @since-jetpack 3.9.0
|
|
*
|
|
* @param bool $is_staging If the current site is a staging site.
|
|
*/
|
|
$is_staging = apply_filters( 'jetpack_is_staging_site', $is_staging );
|
|
|
|
Cache::set( 'is_staging_site', $is_staging );
|
|
return $is_staging;
|
|
}
|
|
|
|
/**
|
|
* If the site is in safe mode.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function in_safe_mode() {
|
|
$cached = Cache::get( 'in_safe_mode' );
|
|
if ( null !== $cached ) {
|
|
return $cached;
|
|
}
|
|
$in_safe_mode = false;
|
|
if ( method_exists( 'Automattic\\Jetpack\\Identity_Crisis', 'validate_sync_error_idc_option' ) && \Automattic\Jetpack\Identity_Crisis::validate_sync_error_idc_option() ) {
|
|
$in_safe_mode = true;
|
|
}
|
|
/**
|
|
* Filters in_safe_mode check.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @param bool $in_safe_mode If the current site is in safe mode.
|
|
*/
|
|
$in_safe_mode = apply_filters( 'jetpack_is_in_safe_mode', $in_safe_mode );
|
|
|
|
Cache::set( 'in_safe_mode', $in_safe_mode );
|
|
return $in_safe_mode;
|
|
}
|
|
|
|
/**
|
|
* If the site is a development/staging site.
|
|
* This is a new version of is_staging_site added to separate safe mode from the legacy staging mode.
|
|
* This method checks for core WP_ENVIRONMENT_TYPE setting
|
|
* Using the jetpack_is_development_site filter.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_development_site() {
|
|
$cached = Cache::get( 'is_development_site' );
|
|
if ( null !== $cached ) {
|
|
return $cached;
|
|
}
|
|
$is_dev_site = ! in_array( wp_get_environment_type(), array( 'production', 'local' ), true );
|
|
/**
|
|
* Filters is_development_site check.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @param bool $is_dev_site If the current site is a staging or dev site.
|
|
*/
|
|
$is_dev_site = apply_filters( 'jetpack_is_development_site', $is_dev_site );
|
|
|
|
Cache::set( 'is_development_site', $is_dev_site );
|
|
return $is_dev_site;
|
|
}
|
|
|
|
/**
|
|
* Whether the site is currently onboarding or not.
|
|
* A site is considered as being onboarded if it currently has an onboarding token.
|
|
*
|
|
* @since-jetpack 5.8
|
|
*
|
|
* @deprecated since 4.0.0
|
|
*
|
|
* @access public
|
|
* @static
|
|
*
|
|
* @return bool True if the site is currently onboarding, false otherwise
|
|
*/
|
|
public function is_onboarding() {
|
|
return \Jetpack_Options::get_option( 'onboarding' ) !== false;
|
|
}
|
|
|
|
/**
|
|
* Whether the site is currently private or not.
|
|
* On WordPress.com and WoA, sites can be marked as private
|
|
*
|
|
* @since 1.16.0
|
|
*
|
|
* @return bool True if the site is private.
|
|
*/
|
|
public function is_private_site() {
|
|
$ret = Cache::get( 'is_private_site' );
|
|
if ( null === $ret ) {
|
|
$is_private_site = '-1' === get_option( 'blog_public' );
|
|
|
|
/**
|
|
* Filters the is_private_site check.
|
|
*
|
|
* @since 1.16.1
|
|
*
|
|
* @param bool $is_private_site True if the site is private.
|
|
*/
|
|
$is_private_site = apply_filters( 'jetpack_is_private_site', $is_private_site );
|
|
|
|
Cache::set( 'is_private_site', $is_private_site );
|
|
return $is_private_site;
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Whether the site is currently unlaunched or not.
|
|
* On WordPress.com and WoA, sites can be marked as "coming soon", aka unlaunched
|
|
*
|
|
* @since 1.16.0
|
|
*
|
|
* @return bool True if the site is not launched.
|
|
*/
|
|
public function is_coming_soon() {
|
|
$ret = Cache::get( 'is_coming_soon' );
|
|
if ( null === $ret ) {
|
|
$is_coming_soon = (bool) ( function_exists( 'site_is_coming_soon' ) && \site_is_coming_soon() )
|
|
|| get_option( 'wpcom_public_coming_soon' );
|
|
|
|
/**
|
|
* Filters the is_coming_soon check.
|
|
*
|
|
* @since 1.16.1
|
|
*
|
|
* @param bool $is_coming_soon True if the site is coming soon (i.e. unlaunched).
|
|
*/
|
|
$is_coming_soon = apply_filters( 'jetpack_is_coming_soon', $is_coming_soon );
|
|
|
|
Cache::set( 'is_coming_soon', $is_coming_soon );
|
|
return $is_coming_soon;
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Returns the site slug suffix to be used as part of Calypso URLs.
|
|
*
|
|
* Strips http:// or https:// from a url, replaces forward slash with ::.
|
|
*
|
|
* @since 1.6.0
|
|
*
|
|
* @param string $url Optional. URL to build the site suffix from. Default: Home URL.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_site_suffix( $url = '' ) {
|
|
// On WordPress.com, site suffixes are a bit different.
|
|
if ( method_exists( 'WPCOM_Masterbar', 'get_calypso_site_slug' ) ) {
|
|
return WPCOM_Masterbar::get_calypso_site_slug( get_current_blog_id() );
|
|
}
|
|
|
|
// Grab the 'site_url' option for WoA sites to avoid plugins to interfere with the site
|
|
// identifier (e.g. i18n plugins may change the main url to '<DOMAIN>/<LOCALE>', but we
|
|
// want to exclude the locale since it's not part of the site suffix).
|
|
if ( ( new Host() )->is_woa_site() ) {
|
|
$url = \site_url();
|
|
}
|
|
|
|
if ( empty( $url ) ) {
|
|
// WordPress can be installed in subdirectories (e.g. make.wordpress.org/plugins)
|
|
// where the 'site_url' option points to the root domain (e.g. make.wordpress.org)
|
|
// which could collide with another site in the same domain but with WordPress
|
|
// installed in a different subdirectory (e.g. make.wordpress.org/core). To avoid
|
|
// such collision, we identify the site with the 'home_url' option.
|
|
$url = \home_url();
|
|
}
|
|
|
|
$url = preg_replace( '#^.*?://#', '', $url );
|
|
$url = str_replace( '/', '::', $url );
|
|
|
|
return rtrim( $url, ':' );
|
|
}
|
|
}
|