plugin install
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* WCCOM Site Installer Error Codes Class
|
||||
*
|
||||
* @package WooCommerce\WCCom\API
|
||||
* @since 7.7.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WCCOM Site Installer Error Codes Class
|
||||
*
|
||||
* Stores data for errors, returned by installer API.
|
||||
*/
|
||||
class WC_REST_WCCOM_Site_Installer_Error_Codes {
|
||||
|
||||
const NOT_AUTHENTICATED = 'not_authenticated';
|
||||
const NO_ACCESS_TOKEN = 'no_access_token';
|
||||
const NO_SIGNATURE = 'no_signature';
|
||||
const SITE_NOT_CONNECTED = 'site_not_connnected';
|
||||
const INVALID_TOKEN = 'invalid_token';
|
||||
const REQUEST_VERIFICATION_FAILED = 'request_verification_failed';
|
||||
const USER_NOT_FOUND = 'user_not_found';
|
||||
const NO_PERMISSION = 'forbidden';
|
||||
const IDEMPOTENCY_KEY_MISMATCH = 'idempotency_key_mismatch';
|
||||
const NO_INITIATED_INSTALLATION_FOUND = 'no_initiated_installation_found';
|
||||
const ALL_INSTALLATION_STEPS_RUN = 'all_installation_steps_run';
|
||||
const REQUESTED_STEP_ALREADY_RUN = 'requested_step_already_run';
|
||||
const PLUGIN_ALREADY_INSTALLED = 'plugin_already_installed';
|
||||
const INSTALLATION_ALREADY_RUNNING = 'installation_already_running';
|
||||
const INSTALLATION_FAILED = 'installation_failed';
|
||||
const FILESYSTEM_REQUIREMENTS_NOT_MET = 'filesystem_requirements_not_met';
|
||||
const FAILED_GETTING_PRODUCT_INFO = 'product_info_failed';
|
||||
const INVALID_PRODUCT_INFO_RESPONSE = 'invalid_product_info_response';
|
||||
const WCCOM_PRODUCT_MISSING_SUBSCRIPTION = 'wccom_product_missing_subscription';
|
||||
const WCCOM_PRODUCT_MISSING_PACKAGE = 'wccom_product_missing_package';
|
||||
const WPORG_PRODUCT_MISSING_DOWNLOAD_LINK = 'wporg_product_missing_download_link';
|
||||
const MISSING_DOWNLOAD_PATH = 'missing_download_path';
|
||||
const MISSING_UNPACKED_PATH = 'missing_unpacked_path';
|
||||
const UNKNOWN_FILENAME = 'unknown_filename';
|
||||
const PLUGIN_ACTIVATION_ERROR = 'plugin_activation_error';
|
||||
const UNEXPECTED_ERROR = 'unexpected_error';
|
||||
const FAILED_TO_RESET_INSTALLATION_STATE = 'failed_to_reset_installation_state';
|
||||
|
||||
const ERROR_MESSAGES = array(
|
||||
self::NOT_AUTHENTICATED => 'Authentication required',
|
||||
self::NO_ACCESS_TOKEN => 'No access token provided',
|
||||
self::NO_SIGNATURE => 'No signature provided',
|
||||
self::SITE_NOT_CONNECTED => 'Site not connected to WooCommerce.com',
|
||||
self::INVALID_TOKEN => 'Invalid access token provided',
|
||||
self::REQUEST_VERIFICATION_FAILED => 'Request verification by signature failed',
|
||||
self::USER_NOT_FOUND => 'Token owning user not found',
|
||||
self::NO_PERMISSION => 'You do not have permission to install plugin or theme',
|
||||
self::IDEMPOTENCY_KEY_MISMATCH => 'Idempotency key mismatch',
|
||||
self::NO_INITIATED_INSTALLATION_FOUND => 'No initiated installation for the product found',
|
||||
self::ALL_INSTALLATION_STEPS_RUN => 'All installation steps have been run',
|
||||
self::REQUESTED_STEP_ALREADY_RUN => 'Requested step has already been run',
|
||||
self::PLUGIN_ALREADY_INSTALLED => 'The plugin has already been installed',
|
||||
self::INSTALLATION_ALREADY_RUNNING => 'The installation of the plugin is already running',
|
||||
self::INSTALLATION_FAILED => 'The installation of the plugin failed',
|
||||
self::FILESYSTEM_REQUIREMENTS_NOT_MET => 'The filesystem requirements are not met',
|
||||
self::FAILED_GETTING_PRODUCT_INFO => 'Failed to retrieve product info from WooCommerce.com',
|
||||
self::INVALID_PRODUCT_INFO_RESPONSE => 'Invalid product info response from WooCommerce.com',
|
||||
self::WCCOM_PRODUCT_MISSING_SUBSCRIPTION => 'Product subscription is missing',
|
||||
self::WCCOM_PRODUCT_MISSING_PACKAGE => 'Could not find product package',
|
||||
self::MISSING_DOWNLOAD_PATH => 'Download path is missing',
|
||||
self::MISSING_UNPACKED_PATH => 'Unpacked path is missing',
|
||||
self::UNKNOWN_FILENAME => 'Unknown product filename',
|
||||
self::PLUGIN_ACTIVATION_ERROR => 'Plugin activation error',
|
||||
self::UNEXPECTED_ERROR => 'Unexpected error',
|
||||
self::FAILED_TO_RESET_INSTALLATION_STATE => 'Failed to reset installation state',
|
||||
);
|
||||
|
||||
const HTTP_CODES = array(
|
||||
self::NOT_AUTHENTICATED => 401,
|
||||
self::NO_ACCESS_TOKEN => 400,
|
||||
self::NO_SIGNATURE => 400,
|
||||
self::SITE_NOT_CONNECTED => 401,
|
||||
self::INVALID_TOKEN => 401,
|
||||
self::REQUEST_VERIFICATION_FAILED => 400,
|
||||
self::USER_NOT_FOUND => 401,
|
||||
self::NO_PERMISSION => 403,
|
||||
self::IDEMPOTENCY_KEY_MISMATCH => 400,
|
||||
self::NO_INITIATED_INSTALLATION_FOUND => 400,
|
||||
self::ALL_INSTALLATION_STEPS_RUN => 400,
|
||||
self::REQUESTED_STEP_ALREADY_RUN => 400,
|
||||
self::UNEXPECTED_ERROR => 500,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* WCCOM Site Installer Error Class
|
||||
*
|
||||
* @package WooCommerce\WCCom\API
|
||||
* @since 7.7.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WCCOM Site Installer Error Class
|
||||
*/
|
||||
class WC_REST_WCCOM_Site_Installer_Error extends Exception {
|
||||
|
||||
/**
|
||||
* Constructor for the Installer Error class.
|
||||
*
|
||||
* @param string $error_code Error code.
|
||||
* @param string $error_message Error message.
|
||||
* @param int $http_code HTTP status code.
|
||||
*/
|
||||
public function __construct( $error_code, $error_message = null, $http_code = null ) {
|
||||
$this->error_code = $error_code;
|
||||
$this->error_message = $error_message ?? WC_REST_WCCOM_Site_Installer_Error_Codes::ERROR_MESSAGES[ $error_code ] ?? '';
|
||||
$this->http_code = $http_code ?? WC_REST_WCCOM_Site_Installer_Error_Codes::HTTP_CODES[ $error_code ] ?? 400;
|
||||
|
||||
parent::__construct( $error_code );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error code.
|
||||
*/
|
||||
public function get_error_code() {
|
||||
return $this->error_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error message.
|
||||
*/
|
||||
public function get_error_message() {
|
||||
return $this->error_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP status code.
|
||||
*/
|
||||
public function get_http_code() {
|
||||
return $this->http_code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* WCCOM Site Base REST API Controller
|
||||
*
|
||||
* Handles requests to /ssr.
|
||||
*
|
||||
* @package WooCommerce\WCCom\API
|
||||
* @since 8.6.0
|
||||
*/
|
||||
|
||||
use WC_REST_WCCOM_Site_Installer_Error_Codes as Installer_Error_Codes;
|
||||
use WC_REST_WCCOM_Site_Installer_Error as Installer_Error;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API WCCOM Site Base REST API Controller Astract Class.
|
||||
*
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
abstract class WC_REST_WCCOM_Site_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wccom-site/v3';
|
||||
|
||||
/**
|
||||
* Check whether user has permission to access controller's endpoints.
|
||||
*
|
||||
* @since 8.6.0
|
||||
* @param WP_USER $user User object.
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function user_has_permission( $user ) : bool;
|
||||
|
||||
/**
|
||||
* Check permissions.
|
||||
*
|
||||
* Please note that access to this endpoint is also governed by the WC_WCCOM_Site::authenticate_wccom() method.
|
||||
*
|
||||
* @since 7.8.0
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
public function check_permission() {
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
if ( empty( $current_user ) || ( $current_user instanceof WP_User && ! $current_user->exists() ) ) {
|
||||
/**
|
||||
* This filter allows to provide a custom error message when the user is not authenticated.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
$error = apply_filters(
|
||||
WC_WCCOM_Site::AUTH_ERROR_FILTER_NAME,
|
||||
new Installer_Error( Installer_Error_Codes::NOT_AUTHENTICATED )
|
||||
);
|
||||
return new WP_Error(
|
||||
$error->get_error_code(),
|
||||
$error->get_error_message(),
|
||||
array( 'status' => $error->get_http_code() )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $this->user_has_permission( $current_user ) ) {
|
||||
$error = new Installer_Error( Installer_Error_Codes::NO_PERMISSION );
|
||||
return new WP_Error(
|
||||
$error->get_error_code(),
|
||||
$error->get_error_message(),
|
||||
array( 'status' => $error->get_http_code() )
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* WCCOM Site Installer REST API Controller Version
|
||||
*
|
||||
* Handles requests to /installer.
|
||||
*
|
||||
* @package WooCommerce\WCCom\API
|
||||
* @since 7.7.0
|
||||
*/
|
||||
|
||||
use WC_REST_WCCOM_Site_Installer_Error as Installer_Error;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API WCCOM Site Installer Controller Class.
|
||||
*
|
||||
* @extends WC_REST_WCCOM_Site_Controller
|
||||
*/
|
||||
class WC_REST_WCCOM_Site_Installer_Controller extends WC_REST_WCCOM_Site_Controller {
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'installer';
|
||||
|
||||
/**
|
||||
* Register the routes for plugin auto-installer.
|
||||
*
|
||||
* @since 7.7.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'install' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
'args' => array(
|
||||
'product-id' => array(
|
||||
'required' => true,
|
||||
'type' => 'integer',
|
||||
),
|
||||
'run-until-step' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'enum' => WC_WCCOM_Site_Installation_Manager::STEPS,
|
||||
),
|
||||
'idempotency-key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/reset',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'reset_install' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
'args' => array(
|
||||
'product-id' => array(
|
||||
'required' => true,
|
||||
'type' => 'integer',
|
||||
),
|
||||
'idempotency-key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether user has permission to access controller's endpoints.
|
||||
*
|
||||
* @since 8.6.0
|
||||
* @param WP_USER $user User object.
|
||||
* @return bool
|
||||
*/
|
||||
public function user_has_permission( $user ) : bool {
|
||||
return user_can( $user, 'install_plugins' ) && user_can( $user, 'install_themes' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Install WooCommerce.com products.
|
||||
*
|
||||
* @since 7.7.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function install( $request ) {
|
||||
try {
|
||||
$product_id = $request['product-id'];
|
||||
$run_until_step = $request['run-until-step'];
|
||||
$idempotency_key = $request['idempotency-key'];
|
||||
|
||||
$installation_manager = new WC_WCCOM_Site_Installation_Manager( $product_id, $idempotency_key );
|
||||
$installation_manager->run_installation( $run_until_step );
|
||||
|
||||
$response = $this->success_response( $product_id );
|
||||
|
||||
} catch ( Installer_Error $exception ) {
|
||||
$response = $this->failure_response( $product_id, $exception );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset installation state.
|
||||
*
|
||||
* @since 7.7.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function reset_install( $request ) {
|
||||
try {
|
||||
$product_id = $request['product-id'];
|
||||
$idempotency_key = $request['idempotency-key'];
|
||||
|
||||
$installation_manager = new WC_WCCOM_Site_Installation_Manager( $product_id, $idempotency_key );
|
||||
$installation_manager->reset_installation();
|
||||
|
||||
$response = $this->success_response( $product_id );
|
||||
|
||||
} catch ( Installer_Error $exception ) {
|
||||
$response = $this->failure_response( $product_id, $exception );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a standardized response for a successful request.
|
||||
*
|
||||
* @param int $product_id Product ID.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
protected function success_response( $product_id ) {
|
||||
$state = WC_WCCOM_Site_Installation_State_Storage::get_state( $product_id );
|
||||
$response = rest_ensure_response(
|
||||
array(
|
||||
'success' => true,
|
||||
'state' => $state ? $this->map_state_to_response( $state ) : null,
|
||||
)
|
||||
);
|
||||
$response->set_status( 200 );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a standardized response for a failed request.
|
||||
*
|
||||
* @param int $product_id Product ID.
|
||||
* @param Installer_Error $exception The exception.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
protected function failure_response( $product_id, $exception ) {
|
||||
$state = WC_WCCOM_Site_Installation_State_Storage::get_state( $product_id );
|
||||
$response = rest_ensure_response(
|
||||
array(
|
||||
'success' => false,
|
||||
'error_code' => $exception->get_error_code(),
|
||||
'error_message' => $exception->get_error_message(),
|
||||
'state' => $state ? $this->map_state_to_response( $state ) : null,
|
||||
)
|
||||
);
|
||||
$response->set_status( $exception->get_http_code() );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the installation state to a response.
|
||||
*
|
||||
* @param WC_WCCOM_Site_Installation_State $state The installation state.
|
||||
* @return array
|
||||
*/
|
||||
protected function map_state_to_response( $state ) {
|
||||
return array(
|
||||
'product_id' => $state->get_product_id(),
|
||||
'idempotency_key' => $state->get_idempotency_key(),
|
||||
'last_step_name' => $state->get_last_step_name(),
|
||||
'last_step_status' => $state->get_last_step_status(),
|
||||
'last_step_error' => $state->get_last_step_error(),
|
||||
'product_type' => $state->get_product_type(),
|
||||
'product_name' => $state->get_product_name(),
|
||||
'already_installed_plugin_info' => $state->get_already_installed_plugin_info(),
|
||||
'started_seconds_ago' => time() - $state->get_started_date(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* WCCOM Site System Status Report REST API Controller
|
||||
*
|
||||
* Handles requests to /ssr.
|
||||
*
|
||||
* @package WooCommerce\WCCom\API
|
||||
* @since 7.8.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API WCCOM System Status Report Controller Class.
|
||||
*
|
||||
* @extends WC_REST_WCCOM_Site_Controller
|
||||
*/
|
||||
class WC_REST_WCCOM_Site_SSR_Controller extends WC_REST_WCCOM_Site_Controller {
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'ssr';
|
||||
|
||||
/**
|
||||
* Register the routes for SSR Controller.
|
||||
*
|
||||
* @since 7.8.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'handle_ssr_request' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether user has permission to access controller's endpoints.
|
||||
*
|
||||
* @since 8.6.0
|
||||
* @param WP_USER $user User object.
|
||||
* @return bool
|
||||
*/
|
||||
public function user_has_permission( $user ) : bool {
|
||||
return user_can( $user, 'manage_woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SSR data and submit it to WooCommmerce.com.
|
||||
*
|
||||
* @since 7.8.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function handle_ssr_request( $request ) {
|
||||
$ssr_controller = new WC_REST_System_Status_Controller();
|
||||
$data = $ssr_controller->get_items( $request );
|
||||
$data = $data->get_data();
|
||||
|
||||
// Submit SSR data to WooCommerce.com.
|
||||
$request = WC_Helper_API::post(
|
||||
'ssr',
|
||||
array(
|
||||
'body' => wp_json_encode( array( 'data' => $data ) ),
|
||||
'authenticated' => true,
|
||||
)
|
||||
);
|
||||
|
||||
$response_code = wp_remote_retrieve_response_code( $request );
|
||||
|
||||
if ( 201 === $response_code ) {
|
||||
$response = rest_ensure_response(
|
||||
array(
|
||||
'success' => true,
|
||||
'message' => 'SSR data submitted successfully',
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$response = rest_ensure_response(
|
||||
array(
|
||||
'success' => false,
|
||||
'error_code' => 'failed_submitting_ssr',
|
||||
'error_message' => "Submitting SSR data failed with response code: $response_code",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* WCCOM Site Status REST API Controller
|
||||
*
|
||||
* Handle requests to /status.
|
||||
*
|
||||
* @package WooCommerce\WCCom\API
|
||||
* @since 8.7.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API WCCOM Site Status Controller Class.
|
||||
*
|
||||
* @extends WC_REST_WCCOM_Site_Status_Controller
|
||||
*/
|
||||
class WC_REST_WCCOM_Site_Status_Controller extends WC_REST_WCCOM_Site_Controller {
|
||||
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'status';
|
||||
|
||||
/**
|
||||
* Register the routes for Site Status Controller.
|
||||
*
|
||||
* @since 8.7.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'handle_status_request' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether user has permission to access controller's endpoints.
|
||||
*
|
||||
* @since 8.7.0
|
||||
* @param WP_USER $user User object.
|
||||
* @return bool
|
||||
*/
|
||||
public function user_has_permission( $user ): bool {
|
||||
return user_can( $user, 'install_plugins' ) && user_can( $user, 'activate_plugins' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status details of the site.
|
||||
*
|
||||
* @since 8.7.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function handle_status_request( $request ) {
|
||||
|
||||
return rest_ensure_response(
|
||||
array(
|
||||
'success' => true,
|
||||
'data' => array(
|
||||
'wc_version' => WC()->version,
|
||||
'woo_update_manager_installed' => WC_Woo_Update_Manager_Plugin::is_plugin_installed(),
|
||||
'woo_update_manager_active' => WC_Woo_Update_Manager_Plugin::is_plugin_active(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user