관리-도구
편집 파일: Plugins.php
<?php /** * REST API Plugins Controller * * Handles requests to install and activate depedent plugins. */ namespace Automattic\Kkart\Admin\API; use Automattic\Kkart\Admin\Features\Onboarding; use Automattic\Kkart\Admin\PluginsHelper; use \Automattic\Kkart\Admin\Notes\InstallJPAndKKARTSPlugins; defined( 'ABSPATH' ) || exit; /** * Plugins Controller. * * @extends KKART_REST_Data_Controller */ class Plugins extends \KKART_REST_Data_Controller { /** * Endpoint namespace. * * @var string */ protected $namespace = 'kkart-admin'; /** * Route base. * * @var string */ protected $rest_base = 'plugins'; /** * Register routes. */ public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base . '/install', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'install_plugins' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/active', array( array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array( $this, 'active_plugins' ), 'permission_callback' => array( $this, 'get_item_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/installed', array( array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array( $this, 'installed_plugins' ), 'permission_callback' => array( $this, 'get_item_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/activate', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'activate_plugins' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/connect-jetpack', array( array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array( $this, 'connect_jetpack' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_connect_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/request-wccom-connect', array( array( 'methods' => 'POST', 'callback' => array( $this, 'request_wccom_connect' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_connect_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/finish-wccom-connect', array( array( 'methods' => 'POST', 'callback' => array( $this, 'finish_wccom_connect' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_connect_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/connect-paypal', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'connect_paypal' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_connect_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/connect-wcpay', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'connect_wcpay' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_connect_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/connect-square', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'connect_square' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ), ), 'schema' => array( $this, 'get_connect_schema' ), ) ); } /** * Check if a given request has access to manage plugins. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|boolean */ public function update_item_permissions_check( $request ) { if ( ! current_user_can( 'install_plugins' ) ) { return new \WP_Error( 'kkart_rest_cannot_update', __( 'Sorry, you cannot manage plugins.', 'kkart' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Create an alert notification in response to an error installing a plugin. * * @todo This should be moved to a filter to make this API more generic and less plugin-specific. * * @param string $slug The slug of the plugin being installed. */ private function create_install_plugin_error_inbox_notification_for_jetpack_installs( $slug ) { // Exit early if we're not installing the Jetpack or the Kkart Shipping & Tax plugins. if ( 'jetpack' !== $slug && 'kkart-services' !== $slug ) { return; } InstallJPAndKKARTSPlugins::possibly_add_note(); } /** * Install the requested plugin. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|array Plugin Status */ public function install_plugin( $request ) { kkart_deprecated_function( 'install_plugin', '4.3', '\Automattic\Kkart\Admin\API\Plugins()->install_plugins' ); // This method expects a `plugin` argument to be sent, install plugins requires plugins. $request['plugins'] = $request['plugin']; return self::install_plugins( $request ); } /** * Installs the requested plugins. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|array Plugin Status */ public function install_plugins( $request ) { $allowed_plugins = self::get_allowed_plugins(); $plugins = explode( ',', $request['plugins'] ); if ( empty( $request['plugins'] ) || ! is_array( $plugins ) ) { return new \WP_Error( 'kkart_rest_invalid_plugins', __( 'Plugins must be a non-empty array.', 'kkart' ), 404 ); } require_once KKART_ADMIN_DIR . 'includes/plugin.php'; include_once KKART_ADMIN_DIR . 'includes/admin.php'; include_once KKART_ADMIN_DIR . 'includes/plugin-install.php'; include_once KKART_ADMIN_DIR . 'includes/plugin.php'; include_once KKART_ADMIN_DIR . 'includes/class-wp-upgrader.php'; include_once KKART_ADMIN_DIR . 'includes/class-plugin-upgrader.php'; $existing_plugins = get_plugins(); $installed_plugins = array(); $results = array(); $errors = new \WP_Error(); foreach ( $plugins as $plugin ) { $slug = sanitize_key( $plugin ); $path = isset( $allowed_plugins[ $slug ] ) ? $allowed_plugins[ $slug ] : false; if ( ! $path ) { $errors->add( $plugin, /* translators: %s: plugin slug (example: kkart-services) */ sprintf( __( 'The requested plugin `%s` is not in the list of allowed plugins.', 'kkart' ), $slug ) ); continue; } if ( in_array( $path, array_keys( $existing_plugins ), true ) ) { $installed_plugins[] = $plugin; continue; } $api = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false, ), ) ); if ( is_wp_error( $api ) ) { $properties = array( /* translators: %s: plugin slug (example: kkart-services) */ 'error_message' => __( 'The requested plugin `%s` could not be installed. Plugin API call failed.', 'kkart' ), 'api' => $api, 'slug' => $slug, ); kkart_admin_record_tracks_event( 'install_plugin_error', $properties ); $this->create_install_plugin_error_inbox_notification_for_jetpack_installs( $slug ); $errors->add( $plugin, sprintf( /* translators: %s: plugin slug (example: kkart-services) */ __( 'The requested plugin `%s` could not be installed. Plugin API call failed.', 'kkart' ), $slug ) ); continue; } $upgrader = new \Plugin_Upgrader( new \Automatic_Upgrader_Skin() ); $result = $upgrader->install( $api->download_link ); $results[ $plugin ] = $result; if ( is_wp_error( $result ) || is_null( $result ) ) { $properties = array( /* translators: %s: plugin slug (example: kkart-services) */ 'error_message' => __( 'The requested plugin `%s` could not be installed.', 'kkart' ), 'slug' => $slug, 'api' => $api, 'upgrader' => $upgrader, 'result' => $result, ); kkart_admin_record_tracks_event( 'install_plugin_error', $properties ); $this->create_install_plugin_error_inbox_notification_for_jetpack_installs( $slug ); $errors->add( $plugin, sprintf( /* translators: %s: plugin slug (example: kkart-services) */ __( 'The requested plugin `%s` could not be installed. Upgrader install failed.', 'kkart' ), $slug ) ); continue; } $installed_plugins[] = $plugin; } return array( 'data' => array( 'installed' => $installed_plugins, 'results' => $results, ), 'errors' => $errors, 'success' => count( $errors->errors ) === 0, 'message' => count( $errors->errors ) === 0 ? __( 'Plugins were successfully installed.', 'kkart' ) : __( 'There was a problem installing some of the requested plugins.', 'kkart' ), ); } /** * Gets an array of plugins that can be installed & activated. * * @return array */ public static function get_allowed_plugins() { return apply_filters( 'kkart_admin_plugins_whitelist', array() ); } /** * Returns a list of active plugins in API format. * * @return array Active plugins */ public static function active_plugins() { $allowed = self::get_allowed_plugins(); $plugins = array_values( array_intersect( PluginsHelper::get_active_plugin_slugs(), array_keys( $allowed ) ) ); return( array( 'plugins' => array_values( $plugins ), ) ); } /** * Returns a list of active plugins. * * @return array Active plugins */ public static function get_active_plugins() { $data = self::active_plugins(); return $data['plugins']; } /** * Returns a list of installed plugins. * * @return array Installed plugins */ public function installed_plugins() { return( array( 'plugins' => PluginsHelper::get_installed_plugin_slugs(), ) ); } /** * Activate the requested plugin. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|array Plugin Status */ public function activate_plugins( $request ) { $allowed_plugins = self::get_allowed_plugins(); $plugins = explode( ',', $request['plugins'] ); $errors = new \WP_Error(); $activated_plugins = array(); if ( empty( $request['plugins'] ) || ! is_array( $plugins ) ) { return new \WP_Error( 'kkart_rest_invalid_plugins', __( 'Plugins must be a non-empty array.', 'kkart' ), 404 ); } require_once KKART_ADMIN_DIR . 'includes/plugin.php'; foreach ( $plugins as $plugin ) { $slug = $plugin; $path = isset( $allowed_plugins[ $slug ] ) ? $allowed_plugins[ $slug ] : false; if ( ! $path ) { $errors->add( $plugin, /* translators: %s: plugin slug (example: kkart-services) */ sprintf( __( 'The requested plugin `%s`. is not in the list of allowed plugins.', 'kkart' ), $slug ) ); continue; } if ( ! PluginsHelper::is_plugin_installed( $path ) ) { $errors->add( $plugin, /* translators: %s: plugin slug (example: kkart-services) */ sprintf( __( 'The requested plugin `%s`. is not yet installed.', 'kkart' ), $slug ) ); continue; } $result = activate_plugin( $path ); if ( ! is_null( $result ) ) { $this->create_install_plugin_error_inbox_notification_for_jetpack_installs( $slug ); $errors->add( $plugin, /* translators: %s: plugin slug (example: kkart-services) */ sprintf( __( 'The requested plugin `%s` could not be activated.', 'kkart' ), $slug ) ); continue; } $activated_plugins[] = $plugin; } return( array( 'data' => array( 'activated' => $activated_plugins, 'active' => self::get_active_plugins(), ), 'errors' => $errors, 'success' => count( $errors->errors ) === 0, 'message' => count( $errors->errors ) === 0 ? __( 'Plugins were successfully activated.', 'kkart' ) : __( 'There was a problem activating some of the requested plugins.', 'kkart' ), ) ); } /** * Generates a Jetpack Connect URL. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|array Connection URL for Jetpack */ public function connect_jetpack( $request ) { if ( ! class_exists( '\Jetpack' ) ) { return new \WP_Error( 'kkart_rest_jetpack_not_active', __( 'Jetpack is not installed or active.', 'kkart' ), 404 ); } $redirect_url = apply_filters( 'kkart_admin_onboarding_jetpack_connect_redirect_url', esc_url_raw( $request['redirect_url'] ) ); $connect_url = \Jetpack::init()->build_connect_url( true, $redirect_url, 'kkart-onboarding' ); $calypso_env = defined( 'KKART_CALYPSO_ENVIRONMENT' ) && in_array( KKART_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ), true ) ? KKART_CALYPSO_ENVIRONMENT : 'production'; $connect_url = add_query_arg( array( 'calypso_env' => $calypso_env ), $connect_url ); return( array( 'slug' => 'jetpack', 'name' => __( 'Jetpack', 'kkart' ), 'connectAction' => $connect_url, ) ); } /** * Kicks off the KKARTCOM Connect process. * * @return WP_Error|array Connection URL for Kkart.com */ public function request_wccom_connect() { include_once KKART_ABSPATH . 'includes/admin/helper/class-kkart-helper-api.php'; if ( ! class_exists( 'KKART_Helper_API' ) ) { return new \WP_Error( 'kkart_rest_helper_not_active', __( 'There was an error loading the Kkart.com Helper API.', 'kkart' ), 404 ); } $redirect_uri = kkart_admin_url( '&task=connect&wccom-connected=1' ); $request = \KKART_Helper_API::post( 'oauth/request_token', array( 'body' => array( 'home_url' => home_url(), 'redirect_uri' => $redirect_uri, ), ) ); $code = wp_remote_retrieve_response_code( $request ); if ( 200 !== $code ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to Kkart.com. Please try again.', 'kkart' ), 500 ); } $secret = json_decode( wp_remote_retrieve_body( $request ) ); if ( empty( $secret ) ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to Kkart.com. Please try again.', 'kkart' ), 500 ); } do_action( 'kkart_helper_connect_start' ); $connect_url = add_query_arg( array( 'home_url' => rawurlencode( home_url() ), 'redirect_uri' => rawurlencode( $redirect_uri ), 'secret' => rawurlencode( $secret ), 'wccom-from' => 'onboarding', ), \KKART_Helper_API::url( 'oauth/authorize' ) ); if ( defined( 'KKART_CALYPSO_ENVIRONMENT' ) && in_array( KKART_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ), true ) ) { $connect_url = add_query_arg( array( 'calypso_env' => KKART_CALYPSO_ENVIRONMENT, ), $connect_url ); } return( array( 'connectAction' => $connect_url, ) ); } /** * Finishes connecting to Kkart.com. * * @param object $rest_request Request details. * @return WP_Error|array Contains success status. */ public function finish_wccom_connect( $rest_request ) { include_once KKART_ABSPATH . 'includes/admin/helper/class-kkart-helper.php'; include_once KKART_ABSPATH . 'includes/admin/helper/class-kkart-helper-api.php'; include_once KKART_ABSPATH . 'includes/admin/helper/class-kkart-helper-updater.php'; include_once KKART_ABSPATH . 'includes/admin/helper/class-kkart-helper-options.php'; if ( ! class_exists( 'KKART_Helper_API' ) ) { return new \WP_Error( 'kkart_rest_helper_not_active', __( 'There was an error loading the Kkart.com Helper API.', 'kkart' ), 404 ); } // Obtain an access token. $request = \KKART_Helper_API::post( 'oauth/access_token', array( 'body' => array( 'request_token' => wp_unslash( $rest_request['request_token'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 'home_url' => home_url(), ), ) ); $code = wp_remote_retrieve_response_code( $request ); if ( 200 !== $code ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to Kkart.com. Please try again.', 'kkart' ), 500 ); } $access_token = json_decode( wp_remote_retrieve_body( $request ), true ); if ( ! $access_token ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to Kkart.com. Please try again.', 'kkart' ), 500 ); } \KKART_Helper_Options::update( 'auth', array( 'access_token' => $access_token['access_token'], 'access_token_secret' => $access_token['access_token_secret'], 'site_id' => $access_token['site_id'], 'user_id' => get_current_user_id(), 'updated' => time(), ) ); if ( ! \KKART_Helper::_flush_authentication_cache() ) { \KKART_Helper_Options::update( 'auth', array() ); return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to Kkart.com. Please try again.', 'kkart' ), 500 ); } delete_transient( '_kkart_helper_subscriptions' ); \KKART_Helper_Updater::flush_updates_cache(); do_action( 'kkart_helper_connected' ); return array( 'success' => true, ); } /** * Returns a URL that can be used to connect to PayPal. * * @return WP_Error|array Connect URL. */ public function connect_paypal() { if ( ! function_exists( 'kkart_gateway_ppec' ) ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to PayPal.', 'kkart' ), 500 ); } $redirect_url = add_query_arg( array( 'env' => 'live', 'kkart_ppec_ips_admin_nonce' => wp_create_nonce( 'kkart_ppec_ips' ), ), kkart_admin_url( '&task=payments&method=paypal&paypal-connect-finish=1' ) ); // https://github.com/kkart/kkart-gateway-paypal-express-checkout/blob/b6df13ba035038aac5024d501e8099a37e13d6cf/includes/class-kkart-gateway-ppec-ips-handler.php#L79-L93. $query_args = array( 'redirect' => rawurlencode( $redirect_url ), 'countryCode' => KKART()->countries->get_base_country(), 'merchantId' => md5( site_url( '/' ) . time() ), ); $connect_url = add_query_arg( $query_args, kkart_gateway_ppec()->ips->get_middleware_login_url( 'live' ) ); return( array( 'connectUrl' => $connect_url, ) ); } /** * Returns a URL that can be used to connect to Square. * * @return WP_Error|array Connect URL. */ public function connect_square() { if ( ! class_exists( '\Kkart\Square\Handlers\Connection' ) ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error connecting to Square.', 'kkart' ), 500 ); } if ( 'US' === KKART()->countries->get_base_country() ) { $profile = get_option( Onboarding::PROFILE_DATA_OPTION, array() ); if ( ! empty( $profile['industry'] ) ) { $has_cbd_industry = in_array( 'cbd-other-hemp-derived-products', array_column( $profile['industry'], 'slug' ), true ); } } if ( $has_cbd_industry ) { $url = 'https://squareup.com/t/f_partnerships/d_referrals/p_kkart/c_general/o_none/l_us/dt_alldevice/pr_payments/?route=/solutions/cbd'; } else { $url = \Kkart\Square\Handlers\Connection::CONNECT_URL_PRODUCTION; } $redirect_url = wp_nonce_url( kkart_admin_url( '&task=payments&method=square&square-connect-finish=1' ), 'kkart_square_connected' ); $args = array( 'redirect' => rawurlencode( rawurlencode( $redirect_url ) ), 'scopes' => implode( ',', array( 'MERCHANT_PROFILE_READ', 'PAYMENTS_READ', 'PAYMENTS_WRITE', 'ORDERS_READ', 'ORDERS_WRITE', 'CUSTOMERS_READ', 'CUSTOMERS_WRITE', 'SETTLEMENTS_READ', 'ITEMS_READ', 'ITEMS_WRITE', 'INVENTORY_READ', 'INVENTORY_WRITE', ) ), ); $connect_url = add_query_arg( $args, $url ); return( array( 'connectUrl' => $connect_url, ) ); } /** * Returns a URL that can be used to by KKARTPay to verify business details with Stripe. * * @return WP_Error|array Connect URL. */ public function connect_wcpay() { if ( ! class_exists( 'KKART_Payments_Account' ) ) { return new \WP_Error( 'kkart_rest_helper_connect', __( 'There was an error communicating with the Kkart Payments plugin.', 'kkart' ), 500 ); } $connect_url = add_query_arg( array( 'wcpay-connect' => 'KKARTADMIN_PAYMENT_TASK', '_wpnonce' => wp_create_nonce( 'wcpay-connect' ), ), admin_url() ); return( array( 'connectUrl' => $connect_url, ) ); } /** * Get the schema, conforming to JSON Schema. * * @return array */ public function get_item_schema() { $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'plugins', 'type' => 'object', 'properties' => array( 'slug' => array( 'description' => __( 'Plugin slug.', 'kkart' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'name' => array( 'description' => __( 'Plugin name.', 'kkart' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'status' => array( 'description' => __( 'Plugin status.', 'kkart' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ), ); return $this->add_additional_fields_schema( $schema ); } /** * Get the schema, conforming to JSON Schema. * * @return array */ public function get_connect_schema() { $schema = $this->get_item_schema(); unset( $schema['properties']['status'] ); $schema['properties']['connectAction'] = array( 'description' => __( 'Action that should be completed to connect Jetpack.', 'kkart' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ); return $schema; } }