oont-contents/plugins/jetpack-boost/app/lib/class-connection.php
2025-02-08 15:10:23 +01:00

296 lines
7.4 KiB
PHP

<?php
/**
* Jetpack connection client.
*
* @link https://automattic.com
* @since 1.0.0
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Lib;
use Automattic\Jetpack\Config as Jetpack_Config;
use Automattic\Jetpack\Connection\Manager;
use Automattic\Jetpack\Terms_Of_Service;
/**
* Class Connection
*
* Manages the Jetpack connection on behalf of Jetpack Boost.
*/
class Connection {
/**
* Jetpack Connection Manager.
*
* @var Manager $manager The connection manager.
*/
private $manager;
public function __construct() {
$this->manager = new Manager( 'jetpack-boost' );
}
public function init() {
add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
$this->initialize_deactivate_disconnect();
}
/**
* Initialize the plugin deactivation hook.
*/
public function initialize_deactivate_disconnect() {
require_once ABSPATH . '/wp-admin/includes/plugin.php';
if ( is_plugin_active_for_network( JETPACK_BOOST_PATH ) ) {
register_deactivation_hook( JETPACK_BOOST_PATH, array( $this, 'deactivate_disconnect_network' ) );
} else {
register_deactivation_hook( JETPACK_BOOST_PATH, array( $this, 'deactivate_disconnect' ) );
}
}
/**
* Deactivate the connection on plugin disconnect.
*/
public function deactivate_disconnect() {
$this->manager->remove_connection();
}
/**
* Deactivate the connection on plugin disconnect for network-activated plugins.
*/
public function deactivate_disconnect_network() {
if ( ! is_network_admin() ) {
return;
}
foreach ( get_sites() as $s ) {
switch_to_blog( $s->blog_id );
$active_plugins = get_option( 'active_plugins' );
/*
* If this plugin was activated in the subsite individually
* we do not want to call disconnect. Plugins activated
* individually (before network activation) stay activated
* when the network deactivation occurs
*/
if ( ! in_array( JETPACK_BOOST_PATH, $active_plugins, true ) ) {
$this->deactivate_disconnect();
}
restore_current_blog();
}
}
/**
* Connection Lifecycle methods.
*/
/**
* Get the WordPress.com blog ID of this site, if it's connected
*/
public static function wpcom_blog_id() {
return defined( 'IS_WPCOM' ) && IS_WPCOM ? get_current_blog_id() : (int) \Jetpack_Options::get_option( 'id' );
}
/**
* True if the site is connected to WP.com.
*
* @return boolean
*/
public function is_connected() {
/**
* Filter that fakes the connection to WordPress.com. Useful for testing.
*
* @param bool $connection Return true to fake the connection.
*
* @since 1.0.0
*/
if ( true === apply_filters( 'jetpack_boost_connection_bypass', false ) ) {
return true;
}
return $this->manager->is_connected();
}
/**
* Register site using connection manager.
*
* @return true|\WP_Error The error object.
*/
public function register() {
if ( $this->is_connected() ) {
Analytics::record_user_event( 'using_existing_connection' );
return true;
}
$result = $this->manager->register();
if ( ! is_wp_error( $result ) ) {
Analytics::record_user_event( 'established_connection' );
Premium_Features::clear_cache();
}
return $result;
}
/**
* Disconnect from Jetpack account.
*
* @return bool
*/
public function disconnect() {
// @todo implement check for Jetpack::validate_sync_error_idc_option() so we don't disconnect production site from staging etc.
Analytics::record_user_event( 'disconnect_site' );
$this->manager->remove_connection();
return true;
}
/**
* REST endpoint methods.
*/
public function register_rest_routes() {
register_rest_route(
JETPACK_BOOST_REST_NAMESPACE,
JETPACK_BOOST_REST_PREFIX . '/connection',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_connection_endpoint' ),
'permission_callback' => array( $this, 'can_manage_connection' ),
)
);
register_rest_route(
JETPACK_BOOST_REST_NAMESPACE,
JETPACK_BOOST_REST_PREFIX . '/connection',
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'create_connection_endpoint' ),
'permission_callback' => array( $this, 'can_manage_connection' ),
)
);
}
/**
* Register site using connection manager.
*
* @param \WP_REST_Request $request The request object.
*
* @return \WP_REST_Response|\WP_Error
*/
public function create_connection_endpoint( \WP_REST_Request $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
( new Terms_Of_Service() )->agree();
$response = $this->register();
// Clear premium features cache to force a refresh.
Premium_Features::clear_cache();
if ( is_wp_error( $response ) ) {
return $response;
}
do_action( 'jetpack_boost_connection_established' );
return rest_ensure_response( $this->get_connection_api_response() );
}
/**
* Fetch connection info.
*
* @param \WP_REST_Request $request The request object.
*
* @return \WP_REST_Response|\WP_Error
*/
public function get_connection_endpoint( \WP_REST_Request $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return rest_ensure_response( $this->get_connection_api_response() );
}
/**
* Connection state sent to client on initialization and after updates.
*
* @return array
*/
public function get_connection_api_response() {
/**
* Filter that fakes the connection to WordPress.com. Useful for testing.
*
* @param bool $connection Return true to fake the connection.
*
* @since 1.0.0
*/
$force_connected = apply_filters( 'jetpack_boost_connection_bypass', false );
$response = array(
'connected' => $force_connected || $this->is_connected(),
'wpcomBlogId' => ( $force_connected || $this->is_connected() ) ? self::wpcom_blog_id() : null,
'userConnected' => $this->manager->is_user_connected(),
);
return $response;
}
/**
* Can user manage the connection?
*
* @return boolean | \WP_Error
*/
public function can_manage_connection() {
if ( current_user_can( 'manage_options' ) ) {
return true;
}
$user_permissions_error_msg = __(
'You do not have the correct user permissions to perform this action.
Please contact your site admin if you think this is a mistake.',
'jetpack-boost'
);
return new \WP_Error(
'invalid_user_permission_jetpack_connect',
$user_permissions_error_msg,
array( 'status' => self::rest_authorization_required_code() )
);
}
/**
* Contextual HTTP error code for authorization failure.
*
* Taken from rest_authorization_required_code() in WP-API plugin until is added to core.
*
* @see https://github.com/WP-API/WP-API/commit/7ba0ae6fe4f605d5ffe4ee85b1cd5f9fb46900a6
*
* @since 4.3.0
*
* @return int
*/
public static function rest_authorization_required_code() {
return is_user_logged_in() ? 403 : 401;
}
public function ensure_connection() {
/**
* Filter that fakes the connection to WordPress.com. Useful for testing.
*
* @param bool $connection Return true to fake the connection.
*
* @since 1.0.0
*/
if ( ! apply_filters( 'jetpack_boost_connection_bypass', false ) ) {
$jetpack_config = new Jetpack_Config();
$jetpack_config->ensure(
'connection',
array(
'slug' => 'jetpack-boost',
'name' => 'Jetpack Boost',
'url_info' => '', // Optional, URL of the plugin.
)
);
}
}
}