296 lines
7.4 KiB
PHP
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.
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|