Plugins
This commit is contained in:
@@ -1,143 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper - React admin interface
|
||||
*
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Internal\Admin\Marketplace;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper Class
|
||||
*
|
||||
* The main entry-point for all things related to the Helper.
|
||||
* The Helper manages the connection between the store and
|
||||
* an account on WooCommerce.com.
|
||||
*/
|
||||
class WC_Helper_Admin {
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function load() {
|
||||
add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'add_marketplace_settings' ) );
|
||||
add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes settings onto the WooCommerce Admin global settings object (wcSettings).
|
||||
*
|
||||
* @param mixed $settings The settings object we're amending.
|
||||
*
|
||||
* @return mixed $settings
|
||||
*/
|
||||
public static function add_marketplace_settings( $settings ) {
|
||||
$auth_user_data = WC_Helper_Options::get( 'auth_user_data', array() );
|
||||
$auth_user_email = isset( $auth_user_data['email'] ) ? $auth_user_data['email'] : '';
|
||||
|
||||
// Get the all installed themes and plugins. Knowing this will help us decide to show Add to Store button on product cards.
|
||||
$installed_products = array_merge( WC_Helper::get_local_plugins(), WC_Helper::get_local_themes() );
|
||||
$installed_products = array_map(
|
||||
function ( $product ) {
|
||||
return $product['slug'];
|
||||
},
|
||||
$installed_products
|
||||
);
|
||||
|
||||
$woo_connect_notice_type = WC_Helper_Updater::get_woo_connect_notice_type();
|
||||
|
||||
$settings['wccomHelper'] = array(
|
||||
'isConnected' => WC_Helper::is_site_connected(),
|
||||
'connectURL' => self::get_connection_url(),
|
||||
'userEmail' => $auth_user_email,
|
||||
'userAvatar' => get_avatar_url( $auth_user_email, array( 'size' => '48' ) ),
|
||||
'storeCountry' => wc_get_base_location()['country'],
|
||||
'inAppPurchaseURLParams' => WC_Admin_Addons::get_in_app_purchase_url_params(),
|
||||
'installedProducts' => $installed_products,
|
||||
'wooUpdateManagerInstalled' => WC_Woo_Update_Manager_Plugin::is_plugin_installed(),
|
||||
'wooUpdateManagerActive' => WC_Woo_Update_Manager_Plugin::is_plugin_active(),
|
||||
'wooUpdateManagerInstallUrl' => WC_Woo_Update_Manager_Plugin::generate_install_url(),
|
||||
'wooUpdateManagerPluginSlug' => WC_Woo_Update_Manager_Plugin::WOO_UPDATE_MANAGER_SLUG,
|
||||
'wooUpdateCount' => WC_Helper_Updater::get_updates_count_based_on_site_status(),
|
||||
'woocomConnectNoticeType' => $woo_connect_notice_type,
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the URL for connecting or disconnecting the store to/from WooCommerce.com.
|
||||
* Approach taken from existing helper code that isn't exposed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_connection_url() {
|
||||
global $current_screen;
|
||||
|
||||
$connect_url_args = array(
|
||||
'page' => 'wc-addons',
|
||||
'section' => 'helper',
|
||||
);
|
||||
|
||||
// No active connection.
|
||||
if ( WC_Helper::is_site_connected() ) {
|
||||
$connect_url_args['wc-helper-disconnect'] = 1;
|
||||
$connect_url_args['wc-helper-nonce'] = wp_create_nonce( 'disconnect' );
|
||||
} else {
|
||||
$connect_url_args['wc-helper-connect'] = 1;
|
||||
$connect_url_args['wc-helper-nonce'] = wp_create_nonce( 'connect' );
|
||||
}
|
||||
|
||||
return add_query_arg(
|
||||
$connect_url_args,
|
||||
admin_url( 'admin.php' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the REST routes for the featured products endpoint.
|
||||
* This endpoint is used by the WooCommerce > Extensions > Discover
|
||||
* page.
|
||||
*/
|
||||
public static function register_rest_routes() {
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/featured',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( __CLASS__, 'get_featured' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Extensions page can only be accessed by users with the manage_woocommerce
|
||||
* capability. So the API mimics that behavior.
|
||||
*/
|
||||
public static function get_permission() {
|
||||
return current_user_can( 'manage_woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch featured products from WooCommerce.com and serve them
|
||||
* as JSON.
|
||||
*/
|
||||
public static function get_featured() {
|
||||
$featured = WC_Admin_Addons::fetch_featured();
|
||||
|
||||
if ( is_wp_error( $featured ) ) {
|
||||
wp_send_json_error( array( 'message' => $featured->get_error_message() ) );
|
||||
}
|
||||
|
||||
wp_send_json( $featured );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_Admin::load();
|
||||
@@ -1,223 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper API
|
||||
*
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_API Class
|
||||
*
|
||||
* Provides a communication interface with the WooCommerce.com Helper API.
|
||||
*/
|
||||
class WC_Helper_API {
|
||||
/**
|
||||
* Base path for API routes.
|
||||
*
|
||||
* @var $api_base
|
||||
*/
|
||||
public static $api_base;
|
||||
|
||||
/**
|
||||
* Load
|
||||
*
|
||||
* Allow devs to point the API base to a local API development or staging server.
|
||||
* Note that sslverify will be turned off for the woocommerce.dev + WP_DEBUG combination.
|
||||
* The URL can be changed on plugins_loaded before priority 10.
|
||||
*/
|
||||
public static function load() {
|
||||
self::$api_base = apply_filters( 'woocommerce_helper_api_base', 'https://woocommerce.com/wp-json/helper/1.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an HTTP request to the Helper API.
|
||||
*
|
||||
* @param string $endpoint The endpoint to request.
|
||||
* @param array $args Additional data for the request. Set authenticated to a truthy value to enable auth.
|
||||
*
|
||||
* @return array|WP_Error The response from wp_safe_remote_request()
|
||||
*/
|
||||
public static function request( $endpoint, $args = array() ) {
|
||||
if ( ! isset( $args['query_string'] ) ) {
|
||||
$args['query_string'] = '';
|
||||
}
|
||||
$url = self::url( $endpoint, $args['query_string'] );
|
||||
|
||||
if ( ! empty( $args['authenticated'] ) ) {
|
||||
if ( ! self::_authenticate( $url, $args ) ) {
|
||||
return new WP_Error( 'authentication', 'Authentication failed.' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $args['user-agent'] ) ) {
|
||||
$args['user-agent'] = 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow developers to filter the request args passed to wp_safe_remote_request().
|
||||
* Useful to remove sslverify when working on a local api dev environment.
|
||||
*/
|
||||
$args = apply_filters( 'woocommerce_helper_api_request_args', $args, $endpoint );
|
||||
|
||||
// TODO: Check response signatures on certain endpoints.
|
||||
return wp_safe_remote_request( $url, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create signature for a request.
|
||||
*
|
||||
* @param string $access_token_secret The access token secret.
|
||||
* @param string $url The URL to add the access token and signature to.
|
||||
* @param string $method The request method.
|
||||
* @param array $body The body of the request.
|
||||
* @return string The signature.
|
||||
*/
|
||||
private static function create_request_signature( string $access_token_secret, string $url, string $method, $body = null ): string {
|
||||
|
||||
$request_uri = wp_parse_url( $url, PHP_URL_PATH );
|
||||
$query_string = wp_parse_url( $url, PHP_URL_QUERY );
|
||||
|
||||
if ( is_string( $query_string ) ) {
|
||||
$request_uri .= '?' . $query_string;
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'host' => wp_parse_url( $url, PHP_URL_HOST ),
|
||||
'request_uri' => $request_uri,
|
||||
'method' => $method,
|
||||
);
|
||||
|
||||
if ( ! empty( $body ) ) {
|
||||
$data['body'] = $body;
|
||||
}
|
||||
|
||||
return hash_hmac( 'sha256', wp_json_encode( $data ), $access_token_secret );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the access token and signature to the provided URL.
|
||||
*
|
||||
* @param string $url The URL to add the access token and signature to.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_auth_parameters( string $url ): string {
|
||||
$auth = WC_Helper_Options::get( 'auth' );
|
||||
|
||||
if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$signature = self::create_request_signature( (string) $auth['access_token_secret'], $url, 'GET' );
|
||||
|
||||
return add_query_arg(
|
||||
array(
|
||||
'token' => $auth['access_token'],
|
||||
'signature' => $signature,
|
||||
),
|
||||
$url
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds authentication headers to an HTTP request.
|
||||
*
|
||||
* @param string $url The request URI.
|
||||
* @param array $args By-ref, the args that will be passed to wp_remote_request().
|
||||
* @return bool Were the headers added?
|
||||
*/
|
||||
private static function _authenticate( &$url, &$args ) {
|
||||
$auth = WC_Helper_Options::get( 'auth' );
|
||||
|
||||
if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$signature = self::create_request_signature(
|
||||
(string) $auth['access_token_secret'],
|
||||
$url,
|
||||
! empty( $args['method'] ) ? $args['method'] : 'GET',
|
||||
$args['body'] ?? null
|
||||
);
|
||||
|
||||
if ( empty( $args['headers'] ) ) {
|
||||
$args['headers'] = array();
|
||||
}
|
||||
|
||||
$headers = array(
|
||||
'Authorization' => 'Bearer ' . $auth['access_token'],
|
||||
'X-Woo-Signature' => $signature,
|
||||
);
|
||||
$args['headers'] = wp_parse_args( $headers, $args['headers'] );
|
||||
|
||||
$url = add_query_arg(
|
||||
array(
|
||||
'token' => $auth['access_token'],
|
||||
'signature' => $signature,
|
||||
),
|
||||
$url
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for self::request().
|
||||
*
|
||||
* @param string $endpoint The helper API endpoint to request.
|
||||
* @param array $args Arguments passed to wp_remote_request().
|
||||
*
|
||||
* @return array The response object from wp_safe_remote_request().
|
||||
*/
|
||||
public static function get( $endpoint, $args = array() ) {
|
||||
$args['method'] = 'GET';
|
||||
return self::request( $endpoint, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for self::request().
|
||||
*
|
||||
* @param string $endpoint The helper API endpoint to request.
|
||||
* @param array $args Arguments passed to wp_remote_request().
|
||||
*
|
||||
* @return array The response object from wp_safe_remote_request().
|
||||
*/
|
||||
public static function post( $endpoint, $args = array() ) {
|
||||
$args['method'] = 'POST';
|
||||
return self::request( $endpoint, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for self::request().
|
||||
*
|
||||
* @param string $endpoint The helper API endpoint to request.
|
||||
* @param array $args Arguments passed to wp_remote_request().
|
||||
*
|
||||
* @return array The response object from wp_safe_remote_request().
|
||||
*/
|
||||
public static function put( $endpoint, $args = array() ) {
|
||||
$args['method'] = 'PUT';
|
||||
return self::request( $endpoint, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the API base, form a request URL from a given endpoint.
|
||||
*
|
||||
* @param string $endpoint The endpoint to request.
|
||||
* @param string $query_string Optional query string to append to the URL.
|
||||
*
|
||||
* @return string The absolute endpoint URL.
|
||||
*/
|
||||
public static function url( $endpoint, $query_string = '' ) {
|
||||
$endpoint = ltrim( $endpoint, '/' );
|
||||
$endpoint = sprintf( '%s/%s/%s', self::$api_base, $endpoint, $query_string );
|
||||
$endpoint = esc_url_raw( $endpoint );
|
||||
$endpoint = rtrim( $endpoint, '/' );
|
||||
return $endpoint;
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_API::load();
|
||||
@@ -1,204 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper Compat
|
||||
*
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_Compat Class
|
||||
*
|
||||
* Some level of compatibility with the legacy WooCommerce Helper plugin.
|
||||
*/
|
||||
class WC_Helper_Compat {
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init.
|
||||
*/
|
||||
public static function load() {
|
||||
add_action( 'woocommerce_helper_loaded', array( __CLASS__, 'helper_loaded' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs during woocommerce_helper_loaded
|
||||
*/
|
||||
public static function helper_loaded() {
|
||||
// Stop the nagging about WooThemes Updater
|
||||
remove_action( 'admin_notices', 'woothemes_updater_notice' );
|
||||
|
||||
// A placeholder dashboard menu for legacy helper users.
|
||||
add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) );
|
||||
|
||||
if ( empty( $GLOBALS['woothemes_updater'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::remove_actions();
|
||||
self::migrate_connection();
|
||||
self::deactivate_plugin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove legacy helper actions (notices, menus, etc.)
|
||||
*/
|
||||
public static function remove_actions() {
|
||||
// Remove WooThemes Updater notices
|
||||
remove_action( 'network_admin_notices', array( $GLOBALS['woothemes_updater']->admin, 'maybe_display_activation_notice' ) );
|
||||
remove_action( 'admin_notices', array( $GLOBALS['woothemes_updater']->admin, 'maybe_display_activation_notice' ) );
|
||||
remove_action( 'network_admin_menu', array( $GLOBALS['woothemes_updater']->admin, 'register_settings_screen' ) );
|
||||
remove_action( 'admin_menu', array( $GLOBALS['woothemes_updater']->admin, 'register_settings_screen' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to migrate a legacy connection to a new one.
|
||||
*/
|
||||
public static function migrate_connection() {
|
||||
// Don't attempt to migrate if attempted before.
|
||||
if ( WC_Helper_Options::get( 'did-migrate' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$auth = WC_Helper_Options::get( 'auth' );
|
||||
if ( ! empty( $auth ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
WC_Helper::log( 'Attempting oauth/migrate' );
|
||||
WC_Helper_Options::update( 'did-migrate', true );
|
||||
|
||||
$master_key = get_option( 'woothemes_helper_master_key' );
|
||||
if ( empty( $master_key ) ) {
|
||||
WC_Helper::log( 'Master key not found, aborting' );
|
||||
return;
|
||||
}
|
||||
|
||||
$request = WC_Helper_API::post(
|
||||
'oauth/migrate',
|
||||
array(
|
||||
'body' => array(
|
||||
'home_url' => home_url(),
|
||||
'master_key' => $master_key,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) {
|
||||
WC_Helper::log( 'Call to oauth/migrate returned a non-200 response code' );
|
||||
return;
|
||||
}
|
||||
|
||||
$request_token = json_decode( wp_remote_retrieve_body( $request ) );
|
||||
if ( empty( $request_token ) ) {
|
||||
WC_Helper::log( 'Call to oauth/migrate returned an empty token' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Obtain an access token.
|
||||
$request = WC_Helper_API::post(
|
||||
'oauth/access_token',
|
||||
array(
|
||||
'body' => array(
|
||||
'request_token' => $request_token,
|
||||
'home_url' => home_url(),
|
||||
'migrate' => true,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) {
|
||||
WC_Helper::log( 'Call to oauth/access_token returned a non-200 response code' );
|
||||
return;
|
||||
}
|
||||
|
||||
$access_token = json_decode( wp_remote_retrieve_body( $request ), true );
|
||||
if ( empty( $access_token ) ) {
|
||||
WC_Helper::log( 'Call to oauth/access_token returned an invalid token' );
|
||||
return;
|
||||
}
|
||||
|
||||
WC_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' => null, // Set this later
|
||||
'updated' => time(),
|
||||
)
|
||||
);
|
||||
|
||||
// Obtain the connected user info.
|
||||
if ( ! WC_Helper::_flush_authentication_cache() ) {
|
||||
WC_Helper::log( 'Could not obtain connected user info in migrate_connection' );
|
||||
WC_Helper_Options::update( 'auth', array() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to deactivate the legacy helper plugin.
|
||||
*/
|
||||
public static function deactivate_plugin() {
|
||||
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
if ( ! function_exists( 'deactivate_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_plugin_active( 'woothemes-updater/woothemes-updater.php' ) ) {
|
||||
deactivate_plugins( 'woothemes-updater/woothemes-updater.php' );
|
||||
|
||||
// Notify the user when the plugin is deactivated.
|
||||
add_action( 'pre_current_active_plugins', array( __CLASS__, 'plugin_deactivation_notice' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display admin notice directing the user where to go.
|
||||
*/
|
||||
public static function plugin_deactivation_notice() {
|
||||
?>
|
||||
<div id="message" class="error is-dismissible">
|
||||
<p><?php printf( __( 'The WooCommerce Helper plugin is no longer needed. <a href="%s">Manage subscriptions</a> from the extensions tab instead.', 'woocommerce' ), esc_url( admin_url( 'admin.php?page=wc-addons§ion=helper' ) ) ); ?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Register menu item.
|
||||
*/
|
||||
public static function admin_menu() {
|
||||
// No additional menu items for users who did not have a connected helper before.
|
||||
$master_key = get_option( 'woothemes_helper_master_key' );
|
||||
if ( empty( $master_key ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not show the menu item if user has already seen the new screen.
|
||||
$auth = WC_Helper_Options::get( 'auth' );
|
||||
if ( ! empty( $auth['user_id'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_dashboard_page( __( 'WooCommerce Helper', 'woocommerce' ), __( 'WooCommerce Helper', 'woocommerce' ), 'manage_options', 'woothemes-helper', array( __CLASS__, 'render_compat_menu' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the legacy helper compat view.
|
||||
*/
|
||||
public static function render_compat_menu() {
|
||||
$helper_url = add_query_arg(
|
||||
array(
|
||||
'page' => 'wc-addons',
|
||||
'section' => 'helper',
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
);
|
||||
include WC_Helper::get_view_filename( 'html-helper-compat.php' );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_Compat::load();
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper Options
|
||||
*
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_Options Class
|
||||
*
|
||||
* An interface to the woocommerce_helper_data entry in the wp_options table.
|
||||
*/
|
||||
class WC_Helper_Options {
|
||||
/**
|
||||
* The option name used to store the helper data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $option_name = 'woocommerce_helper_data';
|
||||
|
||||
/**
|
||||
* Update an option by key
|
||||
*
|
||||
* All helper options are grouped in a single options entry. This method
|
||||
* is not thread-safe, use with caution.
|
||||
*
|
||||
* @param string $key The key to update.
|
||||
* @param mixed $value The new option value.
|
||||
*
|
||||
* @return bool True if the option has been updated.
|
||||
*/
|
||||
public static function update( $key, $value ) {
|
||||
$options = get_option( self::$option_name, array() );
|
||||
$options[ $key ] = $value;
|
||||
return update_option( self::$option_name, $options, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an option by key
|
||||
*
|
||||
* @see self::update
|
||||
*
|
||||
* @param string $key The key to fetch.
|
||||
* @param mixed $default The default option to return if the key does not exist.
|
||||
*
|
||||
* @return mixed An option or the default.
|
||||
*/
|
||||
public static function get( $key, $default = false ) {
|
||||
$options = get_option( self::$option_name, array() );
|
||||
if ( is_array( $options ) && array_key_exists( $key, $options ) ) {
|
||||
return $options[ $key ];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper - React admin interface
|
||||
*
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_Orders_API
|
||||
*
|
||||
* Pings WooCommerce.com to create an order and pull in the necessary data to start the installation process.
|
||||
*/
|
||||
class WC_Helper_Orders_API {
|
||||
/**
|
||||
* Loads the class, runs on init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function load() {
|
||||
add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the REST routes for the Marketplace Orders API.
|
||||
* These endpoints are used by the Marketplace Subscriptions React UI.
|
||||
*/
|
||||
public static function register_rest_routes() {
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/create-order',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( __CLASS__, 'create_order' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
'args' => array(
|
||||
'product_id' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function( $argument ) {
|
||||
return is_int( $argument );
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Extensions page can only be accessed by users with the manage_woocommerce
|
||||
* capability. So the API mimics that behavior.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function get_permission() {
|
||||
return WC_Helper_Subscriptions_API::get_permission();
|
||||
}
|
||||
|
||||
/**
|
||||
* Core function to create an order on WooCommerce.com. Pings the API and catches the exceptions if any.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function create_order( $request ) {
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return new \WP_REST_Response(
|
||||
array(
|
||||
'message' => __( 'You do not have permission to install plugins.', 'woocommerce' ),
|
||||
),
|
||||
403
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$response = WC_Helper_API::post(
|
||||
'create-order',
|
||||
array(
|
||||
'authenticated' => true,
|
||||
'body' => http_build_query(
|
||||
array(
|
||||
'product_id' => $request['product_id'],
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
return new \WP_REST_Response(
|
||||
json_decode( wp_remote_retrieve_body( $response ), true ),
|
||||
wp_remote_retrieve_response_code( $response )
|
||||
);
|
||||
} catch ( Exception $e ) {
|
||||
return new \WP_REST_Response(
|
||||
array(
|
||||
'message' => __( 'Could not start the installation process. Reason: ', 'woocommerce' ) . $e->getMessage(),
|
||||
'code' => 'could-not-install',
|
||||
),
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_Orders_API::load();
|
||||
@@ -1,325 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper - React admin interface
|
||||
*
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_Subscriptions_API
|
||||
*
|
||||
* The main entry-point for all things related to the Marketplace Subscriptions API.
|
||||
* The Subscriptions API manages WooCommerce.com Subscriptions.
|
||||
*/
|
||||
class WC_Helper_Subscriptions_API {
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function load() {
|
||||
add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the REST routes for the Marketplace Subscriptions API.
|
||||
* These endpoints are used by the Marketplace Subscriptions React UI.
|
||||
*/
|
||||
public static function register_rest_routes() {
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/refresh',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( __CLASS__, 'refresh' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/subscriptions',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( __CLASS__, 'get_subscriptions' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/subscriptions/connect',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( __CLASS__, 'connect' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
'args' => array(
|
||||
'product_key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/subscriptions/disconnect',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( __CLASS__, 'disconnect' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
'args' => array(
|
||||
'product_key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/subscriptions/activate',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( __CLASS__, 'activate' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
'args' => array(
|
||||
'product_key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
'wc/v3',
|
||||
'/marketplace/subscriptions/install-url',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( __CLASS__, 'install_url' ),
|
||||
'permission_callback' => array( __CLASS__, 'get_permission' ),
|
||||
'args' => array(
|
||||
'product_key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Extensions page can only be accessed by users with the manage_woocommerce
|
||||
* capability. So the API mimics that behavior.
|
||||
*/
|
||||
public static function get_permission() {
|
||||
return current_user_can( 'manage_woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch subscriptions from WooCommerce.com and serve them
|
||||
* as JSON.
|
||||
*/
|
||||
public static function get_subscriptions() {
|
||||
$subscriptions = WC_Helper::get_subscription_list_data();
|
||||
wp_send_json(
|
||||
array_values(
|
||||
$subscriptions
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh account and subscriptions from WooCommerce.com and serve subscriptions
|
||||
* as JSON.
|
||||
*/
|
||||
public static function refresh() {
|
||||
WC_Helper::refresh_helper_subscriptions();
|
||||
self::get_subscriptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect a WooCommerce.com subscription.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
public static function connect( $request ) {
|
||||
$product_key = $request->get_param( 'product_key' );
|
||||
try {
|
||||
$success = WC_Helper::activate_helper_subscription( $product_key );
|
||||
} catch ( Exception $e ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => $e->getMessage(),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
if ( $success ) {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'message' => __( 'Your subscription has been connected.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'There was an error connecting your subscription. Please try again.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect a WooCommerce.com subscription.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
public static function disconnect( $request ) {
|
||||
$product_key = $request->get_param( 'product_key' );
|
||||
try {
|
||||
$success = WC_Helper::deactivate_helper_subscription( $product_key );
|
||||
} catch ( Exception $e ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => $e->getMessage(),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
if ( $success ) {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'message' => __( 'Your subscription has been disconnected.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'There was an error disconnecting your subscription. Please try again.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate a WooCommerce.com product.
|
||||
* This activates the plugin/theme on the site.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
public static function activate( $request ) {
|
||||
$product_key = $request->get_param( 'product_key' );
|
||||
$subscription = WC_Helper::get_subscription( $product_key );
|
||||
|
||||
if ( ! $subscription ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'We couldn\'t find a subscription for this product.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
if ( true !== $subscription['local']['installed'] || ! isset( $subscription['local']['active'] ) ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'This product is not installed.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
if ( true === $subscription['local']['active'] ) {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'message' => __( 'This product is already active.', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'plugin' === $subscription['product_type'] ) {
|
||||
$success = activate_plugin( $subscription['local']['path'] );
|
||||
if ( is_wp_error( $success ) ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'There was an error activating this plugin.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
} elseif ( 'theme' === $subscription['product_type'] ) {
|
||||
switch_theme( $subscription['local']['slug'] );
|
||||
$theme = wp_get_theme();
|
||||
if ( $subscription['local']['slug'] !== $theme->get_stylesheet() ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'There was an error activating this theme.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'message' => __( 'This product has been activated.', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the install URL for a WooCommerce.com product.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
public static function install_url( $request ) {
|
||||
$product_key = $request->get_param( 'product_key' );
|
||||
$subscription = WC_Helper::get_subscription( $product_key );
|
||||
|
||||
if ( ! $subscription ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'We couldn\'t find a subscription for this product.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
if ( true === $subscription['local']['installed'] ) {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'message' => __( 'This product is already installed.', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$install_url = WC_Helper::get_subscription_install_url(
|
||||
$subscription['product_key'],
|
||||
$subscription['product_slug']
|
||||
);
|
||||
|
||||
if ( ! $install_url ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'There was an error getting the install URL for this product.', 'woocommerce' ),
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'url' => $install_url,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_Subscriptions_API::load();
|
||||
@@ -1,664 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* The update helper for WooCommerce.com plugins.
|
||||
*
|
||||
* @class WC_Helper_Updater
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_Updater Class
|
||||
*
|
||||
* Contains the logic to fetch available updates and hook into Core's update
|
||||
* routines to serve WooCommerce.com-provided packages.
|
||||
*/
|
||||
class WC_Helper_Updater {
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init.
|
||||
*/
|
||||
public static function load() {
|
||||
add_action( 'pre_set_site_transient_update_plugins', array( __CLASS__, 'transient_update_plugins' ), 21, 1 );
|
||||
add_action( 'pre_set_site_transient_update_themes', array( __CLASS__, 'transient_update_themes' ), 21, 1 );
|
||||
add_action( 'upgrader_process_complete', array( __CLASS__, 'upgrader_process_complete' ) );
|
||||
add_action( 'upgrader_pre_download', array( __CLASS__, 'block_expired_updates' ), 10, 2 );
|
||||
add_action( 'plugins_loaded', array( __CLASS__, 'add_hook_for_modifying_update_notices' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the hook for modifying default WPCore update notices on the plugins management page.
|
||||
*/
|
||||
public static function add_hook_for_modifying_update_notices() {
|
||||
if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_active() || ! WC_Helper::is_site_connected() ) {
|
||||
add_action( 'load-plugins.php', array( __CLASS__, 'setup_update_plugins_messages' ), 11 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs in a cron thread, or in a visitor thread if triggered
|
||||
* by _maybe_update_plugins(), or in an auto-update thread.
|
||||
*
|
||||
* @param object $transient The update_plugins transient object.
|
||||
*
|
||||
* @return object The same or a modified version of the transient.
|
||||
*/
|
||||
public static function transient_update_plugins( $transient ) {
|
||||
$update_data = self::get_update_data();
|
||||
|
||||
foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
|
||||
if ( empty( $update_data[ $plugin['_product_id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $update_data[ $plugin['_product_id'] ];
|
||||
$filename = $plugin['_filename'];
|
||||
|
||||
$item = array(
|
||||
'id' => 'woocommerce-com-' . $plugin['_product_id'],
|
||||
'slug' => 'woocommerce-com-' . $data['slug'],
|
||||
'plugin' => $filename,
|
||||
'new_version' => $data['version'],
|
||||
'url' => $data['url'],
|
||||
'package' => '',
|
||||
'upgrade_notice' => $data['upgrade_notice'],
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the Woo plugin data before saving it in transient used for updates.
|
||||
*
|
||||
* @since 8.7.0
|
||||
*
|
||||
* @param array $item Plugin item to modify.
|
||||
* @param array $data Subscription data fetched from Helper API for the plugin.
|
||||
* @param int $product_id Woo product id assigned to the plugin.
|
||||
*/
|
||||
$item = apply_filters( 'update_woo_com_subscription_details', $item, $data, $plugin['_product_id'] );
|
||||
|
||||
if ( isset( $data['requires_php'] ) ) {
|
||||
$item['requires_php'] = $data['requires_php'];
|
||||
}
|
||||
|
||||
if ( $transient instanceof stdClass ) {
|
||||
if ( version_compare( $plugin['Version'], $data['version'], '<' ) ) {
|
||||
$transient->response[ $filename ] = (object) $item;
|
||||
unset( $transient->no_update[ $filename ] );
|
||||
} else {
|
||||
$transient->no_update[ $filename ] = (object) $item;
|
||||
unset( $transient->response[ $filename ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $transient instanceof stdClass ) {
|
||||
$translations = self::get_translations_update_data();
|
||||
$transient->translations = array_merge( isset( $transient->translations ) ? $transient->translations : array(), $translations );
|
||||
}
|
||||
|
||||
return $transient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on pre_set_site_transient_update_themes, provides custom
|
||||
* packages for WooCommerce.com-hosted extensions.
|
||||
*
|
||||
* @param object $transient The update_themes transient object.
|
||||
*
|
||||
* @return object The same or a modified version of the transient.
|
||||
*/
|
||||
public static function transient_update_themes( $transient ) {
|
||||
$update_data = self::get_update_data();
|
||||
|
||||
foreach ( WC_Helper::get_local_woo_themes() as $theme ) {
|
||||
if ( empty( $update_data[ $theme['_product_id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $update_data[ $theme['_product_id'] ];
|
||||
$slug = $theme['_stylesheet'];
|
||||
|
||||
$item = array(
|
||||
'theme' => $slug,
|
||||
'new_version' => $data['version'],
|
||||
'url' => $data['url'],
|
||||
'package' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the Woo plugin data before saving it in transient used for updates.
|
||||
*
|
||||
* @since 8.7.0
|
||||
*
|
||||
* @param array $item Plugin item to modify.
|
||||
* @param array $data Subscription data fetched from Helper API for the plugin.
|
||||
* @param int $product_id Woo product id assigned to the plugin.
|
||||
*/
|
||||
$item = apply_filters( 'update_woo_com_subscription_details', $item, $data, $theme['_product_id'] );
|
||||
|
||||
if ( version_compare( $theme['Version'], $data['version'], '<' ) ) {
|
||||
$transient->response[ $slug ] = $item;
|
||||
} else {
|
||||
unset( $transient->response[ $slug ] );
|
||||
$transient->checked[ $slug ] = $data['version'];
|
||||
}
|
||||
}
|
||||
|
||||
return $transient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on load-plugins.php, adds a hook to show a custom plugin update message for WooCommerce.com hosted plugins.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
public static function setup_update_plugins_messages() {
|
||||
$is_site_connected = WC_Helper::is_site_connected();
|
||||
foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
|
||||
$filename = $plugin['_filename'];
|
||||
if ( $is_site_connected ) {
|
||||
add_action( 'in_plugin_update_message-' . $filename, array( __CLASS__, 'add_install_marketplace_plugin_message' ), 10, 2 );
|
||||
} else {
|
||||
add_action( 'in_plugin_update_message-' . $filename, array( __CLASS__, 'add_connect_woocom_plugin_message' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on in_plugin_update_message-{file-name}, show a message to connect to woocommerce.com for unconnected stores
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
public static function add_connect_woocom_plugin_message() {
|
||||
$connect_page_url = add_query_arg(
|
||||
array(
|
||||
'page' => 'wc-admin',
|
||||
'tab' => 'my-subscriptions',
|
||||
'path' => rawurlencode( '/extensions' ),
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
);
|
||||
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: 1: Woo Update Manager plugin install URL */
|
||||
__( ' <a href="%1$s" class="woocommerce-connect-your-store">Connect your store</a> to woocommerce.com to update.', 'woocommerce' ),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
'class' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
esc_url( $connect_page_url ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on in_plugin_update_message-{file-name}, show a message to install the Woo Marketplace plugin, on plugin update notification,
|
||||
* if the Woo Marketplace plugin isn't already installed.
|
||||
*
|
||||
* @param object $plugin_data TAn array of plugin metadata.
|
||||
* @param object $response An object of metadata about the available plugin update.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
public static function add_install_marketplace_plugin_message( $plugin_data, $response ) {
|
||||
if ( ! empty( $response->package ) || WC_Woo_Update_Manager_Plugin::is_plugin_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_installed() ) {
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: 1: Woo Update Manager plugin install URL */
|
||||
__( ' <a href="%1$s">Install WooCommerce.com Update Manager</a> to update.', 'woocommerce' ),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
esc_url( WC_Woo_Update_Manager_Plugin::generate_install_url() ),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_active() ) {
|
||||
echo esc_html_e( ' Activate WooCommerce.com Update Manager to update.', 'woocommerce' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get update data for all plugins.
|
||||
*
|
||||
* @return array Update data {product_id => data}
|
||||
* @see get_update_data
|
||||
*/
|
||||
public static function get_available_extensions_downloads_data() {
|
||||
$payload = array();
|
||||
|
||||
// Scan subscriptions.
|
||||
foreach ( WC_Helper::get_subscriptions() as $subscription ) {
|
||||
$payload[ $subscription['product_id'] ] = array(
|
||||
'product_id' => $subscription['product_id'],
|
||||
'file_id' => '',
|
||||
);
|
||||
}
|
||||
|
||||
// Scan local plugins which may or may not have a subscription.
|
||||
foreach ( WC_Helper::get_local_woo_plugins() as $data ) {
|
||||
if ( ! isset( $payload[ $data['_product_id'] ] ) ) {
|
||||
$payload[ $data['_product_id'] ] = array(
|
||||
'product_id' => $data['_product_id'],
|
||||
);
|
||||
}
|
||||
|
||||
$payload[ $data['_product_id'] ]['file_id'] = $data['_file_id'];
|
||||
}
|
||||
|
||||
return self::_update_check( $payload );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get update data for all extensions.
|
||||
*
|
||||
* Scans through all subscriptions for the connected user, as well
|
||||
* as all Woo extensions without a subscription, and obtains update
|
||||
* data for each product.
|
||||
*
|
||||
* @return array Update data {product_id => data}
|
||||
*/
|
||||
public static function get_update_data() {
|
||||
$payload = array();
|
||||
|
||||
// Scan subscriptions.
|
||||
foreach ( WC_Helper::get_subscriptions() as $subscription ) {
|
||||
$payload[ $subscription['product_id'] ] = array(
|
||||
'product_id' => $subscription['product_id'],
|
||||
'file_id' => '',
|
||||
);
|
||||
}
|
||||
|
||||
// Scan local plugins which may or may not have a subscription.
|
||||
foreach ( WC_Helper::get_local_woo_plugins() as $data ) {
|
||||
if ( ! isset( $payload[ $data['_product_id'] ] ) ) {
|
||||
$payload[ $data['_product_id'] ] = array(
|
||||
'product_id' => $data['_product_id'],
|
||||
);
|
||||
}
|
||||
|
||||
$payload[ $data['_product_id'] ]['file_id'] = $data['_file_id'];
|
||||
}
|
||||
|
||||
// Scan local themes.
|
||||
foreach ( WC_Helper::get_local_woo_themes() as $data ) {
|
||||
if ( ! isset( $payload[ $data['_product_id'] ] ) ) {
|
||||
$payload[ $data['_product_id'] ] = array(
|
||||
'product_id' => $data['_product_id'],
|
||||
);
|
||||
}
|
||||
|
||||
$payload[ $data['_product_id'] ]['file_id'] = $data['_file_id'];
|
||||
}
|
||||
|
||||
return self::_update_check( $payload );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translations updates information.
|
||||
*
|
||||
* Scans through all subscriptions for the connected user, as well
|
||||
* as all Woo extensions without a subscription, and obtains update
|
||||
* data for each product.
|
||||
*
|
||||
* @return array Update data {product_id => data}
|
||||
*/
|
||||
public static function get_translations_update_data() {
|
||||
$payload = array();
|
||||
|
||||
$installed_translations = wp_get_installed_translations( 'plugins' );
|
||||
|
||||
$locales = array_values( get_available_languages() );
|
||||
/**
|
||||
* Filters the locales requested for plugin translations.
|
||||
*
|
||||
* @since 3.7.0
|
||||
* @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
|
||||
*
|
||||
* @param array $locales Plugin locales. Default is all available locales of the site.
|
||||
*/
|
||||
$locales = apply_filters( 'plugins_update_check_locales', $locales );
|
||||
$locales = array_unique( $locales );
|
||||
|
||||
// No locales, the response will be empty, we can return now.
|
||||
if ( empty( $locales ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Scan local plugins which may or may not have a subscription.
|
||||
$plugins = WC_Helper::get_local_woo_plugins();
|
||||
$active_woo_plugins = array_intersect( array_keys( $plugins ), get_option( 'active_plugins', array() ) );
|
||||
|
||||
/*
|
||||
* Use only plugins that are subscribed to the automatic translations updates.
|
||||
*/
|
||||
$active_for_translations = array_filter(
|
||||
$active_woo_plugins,
|
||||
function ( $plugin ) use ( $plugins ) {
|
||||
/**
|
||||
* Filters the plugins that are subscribed to the automatic translations updates.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
return apply_filters( 'woocommerce_translations_updates_for_' . $plugins[ $plugin ]['slug'], false );
|
||||
}
|
||||
);
|
||||
|
||||
// Nothing to check for, exit.
|
||||
if ( empty( $active_for_translations ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( wp_doing_cron() ) {
|
||||
$timeout = 30;
|
||||
} else {
|
||||
// Three seconds, plus one extra second for every 10 plugins.
|
||||
$timeout = 3 + (int) ( count( $active_for_translations ) / 10 );
|
||||
}
|
||||
|
||||
$request_body = array(
|
||||
'locales' => $locales,
|
||||
'plugins' => array(),
|
||||
);
|
||||
|
||||
foreach ( $active_for_translations as $active_plugin ) {
|
||||
$plugin = $plugins[ $active_plugin ];
|
||||
$request_body['plugins'][ $plugin['slug'] ] = array( 'version' => $plugin['Version'] );
|
||||
}
|
||||
|
||||
$raw_response = wp_remote_post(
|
||||
'https://translate.wordpress.com/api/translations-updates/woocommerce',
|
||||
array(
|
||||
'body' => wp_json_encode( $request_body ),
|
||||
'headers' => array( 'Content-Type: application/json' ),
|
||||
'timeout' => $timeout,
|
||||
)
|
||||
);
|
||||
|
||||
// Something wrong happened on the translate server side.
|
||||
$response_code = wp_remote_retrieve_response_code( $raw_response );
|
||||
if ( 200 !== $response_code ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
|
||||
|
||||
// API error, api returned but something was wrong.
|
||||
if ( array_key_exists( 'success', $response ) && false === $response['success'] ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$translations = array();
|
||||
|
||||
foreach ( $response['data'] as $plugin_name => $language_packs ) {
|
||||
foreach ( $language_packs as $language_pack ) {
|
||||
// Maybe we have this language pack already installed so lets check revision date.
|
||||
if ( array_key_exists( $plugin_name, $installed_translations ) && array_key_exists( $language_pack['wp_locale'], $installed_translations[ $plugin_name ] ) ) {
|
||||
$installed_translation_revision_time = new DateTime( $installed_translations[ $plugin_name ][ $language_pack['wp_locale'] ]['PO-Revision-Date'] );
|
||||
$new_translation_revision_time = new DateTime( $language_pack['last_modified'] );
|
||||
// Skip if translation language pack is not newer than what is installed already.
|
||||
if ( $new_translation_revision_time <= $installed_translation_revision_time ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$translations[] = array(
|
||||
'type' => 'plugin',
|
||||
'slug' => $plugin_name,
|
||||
'language' => $language_pack['wp_locale'],
|
||||
'version' => $language_pack['version'],
|
||||
'updated' => $language_pack['last_modified'],
|
||||
'package' => $language_pack['package'],
|
||||
'autoupdate' => true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an update check API call.
|
||||
*
|
||||
* The call is cached based on the payload (product ids, file ids). If
|
||||
* the payload changes, the cache is going to miss.
|
||||
*
|
||||
* @param array $payload Information about the plugin to update.
|
||||
* @return array Update data for each requested product.
|
||||
*/
|
||||
private static function _update_check( $payload ) {
|
||||
if ( empty( $payload ) ) {
|
||||
return array();
|
||||
}
|
||||
ksort( $payload );
|
||||
$hash = md5( wp_json_encode( $payload ) );
|
||||
|
||||
$cache_key = '_woocommerce_helper_updates';
|
||||
$data = get_transient( $cache_key );
|
||||
if ( false !== $data ) {
|
||||
if ( hash_equals( $hash, $data['hash'] ) ) {
|
||||
return $data['products'];
|
||||
}
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'hash' => $hash,
|
||||
'updated' => time(),
|
||||
'products' => array(),
|
||||
'errors' => array(),
|
||||
);
|
||||
|
||||
if ( WC_Helper::is_site_connected() ) {
|
||||
$request = WC_Helper_API::post(
|
||||
'update-check',
|
||||
array(
|
||||
'body' => wp_json_encode( array( 'products' => $payload ) ),
|
||||
'authenticated' => true,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$request = WC_Helper_API::post(
|
||||
'update-check-public',
|
||||
array(
|
||||
'body' => wp_json_encode( array( 'products' => $payload ) ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( wp_remote_retrieve_response_code( $request ) !== 200 ) {
|
||||
$data['errors'][] = 'http-error';
|
||||
} else {
|
||||
$data['products'] = json_decode( wp_remote_retrieve_body( $request ), true );
|
||||
}
|
||||
|
||||
set_transient( $cache_key, $data, 12 * HOUR_IN_SECONDS );
|
||||
return $data['products'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of products that have updates.
|
||||
*
|
||||
* @return int The number of products with updates.
|
||||
*/
|
||||
public static function get_updates_count() {
|
||||
$cache_key = '_woocommerce_helper_updates_count';
|
||||
$count = get_transient( $cache_key );
|
||||
if ( false !== $count ) {
|
||||
return $count;
|
||||
}
|
||||
|
||||
// Don't fetch any new data since this function in high-frequency.
|
||||
if ( ! get_transient( '_woocommerce_helper_subscriptions' ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ! get_transient( '_woocommerce_helper_updates' ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$update_data = self::get_update_data();
|
||||
|
||||
if ( empty( $update_data ) ) {
|
||||
set_transient( $cache_key, $count, 12 * HOUR_IN_SECONDS );
|
||||
return $count;
|
||||
}
|
||||
|
||||
// Scan local plugins.
|
||||
foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
|
||||
if ( empty( $update_data[ $plugin['_product_id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( version_compare( $plugin['Version'], $update_data[ $plugin['_product_id'] ]['version'], '<' ) ) {
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan local themes.
|
||||
foreach ( WC_Helper::get_local_woo_themes() as $theme ) {
|
||||
if ( empty( $update_data[ $theme['_product_id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( version_compare( $theme['Version'], $update_data[ $theme['_product_id'] ]['version'], '<' ) ) {
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
|
||||
set_transient( $cache_key, $count, 12 * HOUR_IN_SECONDS );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the update count to based on the status of the site.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_updates_count_based_on_site_status() {
|
||||
if ( ! WC_Helper::is_site_connected() ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$count = self::get_updates_count() ?? 0;
|
||||
if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_installed() || ! WC_Woo_Update_Manager_Plugin::is_plugin_active() ) {
|
||||
++$count;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of woo connect notice to be shown in the WC Settings and Marketplace pages.
|
||||
* - If a store is connected to woocommerce.com or has no installed woo plugins, return 'none'.
|
||||
* - If a store has installed woo plugins but no updates, return 'short'.
|
||||
* - If a store has an installed woo plugin with update, return 'long'.
|
||||
*
|
||||
* @return string The notice type, 'none', 'short', or 'long'.
|
||||
*/
|
||||
public static function get_woo_connect_notice_type() {
|
||||
if ( WC_Helper::is_site_connected() ) {
|
||||
return 'none';
|
||||
}
|
||||
|
||||
$woo_plugins = WC_Helper::get_local_woo_plugins();
|
||||
|
||||
if ( empty( $woo_plugins ) ) {
|
||||
return 'none';
|
||||
}
|
||||
|
||||
$update_data = self::get_update_data();
|
||||
|
||||
if ( empty( $update_data ) ) {
|
||||
return 'short';
|
||||
}
|
||||
|
||||
// Scan local plugins.
|
||||
foreach ( $woo_plugins as $plugin ) {
|
||||
if ( empty( $update_data[ $plugin['_product_id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( version_compare( $plugin['Version'], $update_data[ $plugin['_product_id'] ]['version'], '<' ) ) {
|
||||
return 'long';
|
||||
}
|
||||
}
|
||||
|
||||
return 'short';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the updates count markup.
|
||||
*
|
||||
* @return string Updates count markup, empty string if no updates avairable.
|
||||
*/
|
||||
public static function get_updates_count_html() {
|
||||
$count = self::get_updates_count_based_on_site_status();
|
||||
$count_html = sprintf( '<span class="update-plugins count-%d"><span class="update-count">%d</span></span>', $count, number_format_i18n( $count ) );
|
||||
|
||||
return $count_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes cached update data.
|
||||
*/
|
||||
public static function flush_updates_cache() {
|
||||
delete_transient( '_woocommerce_helper_updates' );
|
||||
delete_transient( '_woocommerce_helper_updates_count' );
|
||||
delete_site_transient( 'update_plugins' );
|
||||
delete_site_transient( 'update_themes' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires when a user successfully updated a theme or a plugin.
|
||||
*/
|
||||
public static function upgrader_process_complete() {
|
||||
delete_transient( '_woocommerce_helper_updates_count' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooked into the upgrader_pre_download filter in order to better handle error messaging around expired
|
||||
* plugin updates. Initially we were using an empty string, but the error message that no_package
|
||||
* results in does not fit the cause.
|
||||
*
|
||||
* @since 4.1.0
|
||||
* @param bool $reply Holds the current filtered response.
|
||||
* @param string $package The path to the package file for the update.
|
||||
* @return false|WP_Error False to proceed with the update as normal, anything else to be returned instead of updating.
|
||||
*/
|
||||
public static function block_expired_updates( $reply, $package ) {
|
||||
// Don't override a reply that was set already.
|
||||
if ( false !== $reply ) {
|
||||
return $reply;
|
||||
}
|
||||
|
||||
// Only for packages with expired subscriptions.
|
||||
if ( 0 !== strpos( $package, 'woocommerce-com-expired-' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new WP_Error(
|
||||
'woocommerce_subscription_expired',
|
||||
sprintf(
|
||||
// translators: %s: URL of WooCommerce.com subscriptions tab.
|
||||
__( 'Please visit the <a href="%s" target="_blank">subscriptions page</a> and renew to continue receiving updates.', 'woocommerce' ),
|
||||
esc_url( admin_url( 'admin.php?page=wc-addons§ion=helper' ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_Updater::load();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,106 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Updates the Product API response from WP.org.
|
||||
*
|
||||
* @class WC_Plugin_Api_Updater
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Class WC_Plugin_Api_Updater
|
||||
*/
|
||||
class WC_Plugin_Api_Updater {
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init.
|
||||
*/
|
||||
public static function load() {
|
||||
add_filter( 'plugins_api', array( __CLASS__, 'plugins_api' ), 20, 3 );
|
||||
add_filter( 'themes_api', array( __CLASS__, 'themes_api' ), 20, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin information callback for Woo extensions.
|
||||
*
|
||||
* @param object $response The response core needs to display the modal.
|
||||
* @param string $action The requested plugins_api() action.
|
||||
* @param object $args Arguments passed to plugins_api().
|
||||
*
|
||||
* @return object An updated $response.
|
||||
*/
|
||||
public static function plugins_api( $response, $action, $args ) {
|
||||
if ( 'plugin_information' !== $action ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return self::override_products_api_response( $response, $action, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme information callback for Woo themes.
|
||||
*
|
||||
* @param object $response The response core needs to display the modal.
|
||||
* @param string $action The requested themes_api() action.
|
||||
* @param object $args Arguments passed to themes_api().
|
||||
*/
|
||||
public static function themes_api( $response, $action, $args ) {
|
||||
if ( 'theme_information' !== $action ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return self::override_products_api_response( $response, $action, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the products API to fetch data from the Helper API if it's a Woo product.
|
||||
*
|
||||
* @param object $response The response core needs to display the modal.
|
||||
* @param string $action The requested action.
|
||||
* @param object $args Arguments passed to the API.
|
||||
*/
|
||||
public static function override_products_api_response( $response, $action, $args ) {
|
||||
if ( empty( $args->slug ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Only for slugs that start with woocommerce-com-.
|
||||
if ( 0 !== strpos( $args->slug, 'woocommerce-com-' ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$clean_slug = str_replace( 'woocommerce-com-', '', $args->slug );
|
||||
|
||||
// Look through update data by slug.
|
||||
$update_data = WC_Helper_Updater::get_update_data();
|
||||
$products = wp_list_filter( $update_data, array( 'slug' => $clean_slug ) );
|
||||
|
||||
if ( empty( $products ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$product_id = array_keys( $products );
|
||||
$product_id = array_shift( $product_id );
|
||||
|
||||
// Fetch the product information from the Helper API.
|
||||
$request = WC_Helper_API::get(
|
||||
add_query_arg(
|
||||
array(
|
||||
'product_id' => absint( $product_id ),
|
||||
),
|
||||
'info'
|
||||
),
|
||||
array( 'authenticated' => true )
|
||||
);
|
||||
|
||||
$results = json_decode( wp_remote_retrieve_body( $request ), true );
|
||||
if ( ! empty( $results ) ) {
|
||||
$response = (object) $results;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
WC_Plugin_Api_Updater::load();
|
||||
@@ -1,130 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* A utility class for Woo Update Manager plugin.
|
||||
*
|
||||
* @class WC_Woo_Update_Manager_Plugin
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\PageController;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Helper_Plugin Class
|
||||
*
|
||||
* Contains the logic to manage the Woo Update Manager plugin.
|
||||
*/
|
||||
class WC_Woo_Update_Manager_Plugin {
|
||||
const WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE = 'woo-update-manager/woo-update-manager.php';
|
||||
const WOO_UPDATE_MANAGER_DOWNLOAD_URL = 'https://woocommerce.com/product-download/woo-update-manager';
|
||||
const WOO_UPDATE_MANAGER_SLUG = 'woo-update-manager';
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function load(): void {
|
||||
add_action( 'admin_notices', array( __CLASS__, 'show_woo_update_manager_install_notice' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Woo Update Manager plugin is active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_plugin_active(): bool {
|
||||
return is_plugin_active_for_network( self::WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE ) || is_plugin_active( self::WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Woo Update Manager plugin is installed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_plugin_installed(): bool {
|
||||
return file_exists( WP_PLUGIN_DIR . '/' . self::WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the URL to install the Woo Update Manager plugin.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generate_install_url(): string {
|
||||
$install_url = WC_Helper::get_install_base_url() . self::WOO_UPDATE_MANAGER_SLUG . '/';
|
||||
|
||||
return WC_Helper_API::add_auth_parameters( $install_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the Woo Update Manager plugin.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_plugin_slug(): string {
|
||||
return self::WOO_UPDATE_MANAGER_SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a notice on the WC admin pages to install or activate the Woo Update Manager plugin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function show_woo_update_manager_install_notice(): void {
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! WC_Helper::is_site_connected() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! PageController::is_admin_or_embed_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self::is_plugin_installed() && self::is_plugin_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! self::is_plugin_installed() ) {
|
||||
|
||||
if ( self::install_admin_notice_dismissed() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
include __DIR__ . '/views/html-notice-woo-updater-not-installed.php';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self::activate_admin_notice_dismissed() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
include __DIR__ . '/views/html-notice-woo-updater-not-activated.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the installation notice has been dismissed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function install_admin_notice_dismissed(): bool {
|
||||
return get_user_meta( get_current_user_id(), 'dismissed_woo_updater_not_installed_notice', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the activation notice has been dismissed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function activate_admin_notice_dismissed(): bool {
|
||||
return get_user_meta( get_current_user_id(), 'dismissed_woo_updater_not_activated_notice', true );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Woo_Update_Manager_Plugin::load();
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php defined( 'ABSPATH' ) or exit(); ?>
|
||||
|
||||
<div class="wrap">
|
||||
<h1><?php _e( 'Looking for the WooCommerce Helper?', 'woocommerce' ); ?></h1>
|
||||
<p><?php printf( __( 'We\'ve made things simpler and easier to manage moving forward. From now on you can manage all your WooCommerce purchases directly from the Extensions menu within the WooCommerce plugin itself. <a href="%s">View and manage</a> your extensions now.', 'woocommerce' ), esc_url( $helper_url ) ); ?></p>
|
||||
</div>
|
||||
@@ -1,260 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper main view
|
||||
*
|
||||
* @package WooCommerce\Helper
|
||||
*/
|
||||
|
||||
?>
|
||||
<?php defined( 'ABSPATH' ) || exit(); ?>
|
||||
|
||||
<div class="wrap woocommerce wc-subscriptions-wrap wc-helper">
|
||||
<?php require WC_Helper::get_view_filename( 'html-section-nav.php' ); ?>
|
||||
<h1 class="screen-reader-text"><?php esc_html_e( 'WooCommerce Extensions', 'woocommerce' ); ?></h1>
|
||||
|
||||
<?php require WC_Helper::get_view_filename( 'html-section-notices.php' ); ?>
|
||||
|
||||
<div class="subscriptions-header">
|
||||
<h2><?php esc_html_e( 'Subscriptions', 'woocommerce' ); ?></h2>
|
||||
<?php require WC_Helper::get_view_filename( 'html-section-account.php' ); ?>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: Introduction to list of WooCommerce.com extensions the merchant has subscriptions for. */
|
||||
__(
|
||||
'Below is a list of extensions available on your WooCommerce.com account. To receive extension updates please make sure the extension is installed, and its subscription activated and connected to your WooCommerce.com account. Extensions can be activated from the <a href="%s">Plugins</a> screen.',
|
||||
'woocommerce'
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
esc_url(
|
||||
admin_url( 'plugins.php' )
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ul class="subscription-filter">
|
||||
<label><?php esc_html_e( 'Sort by:', 'woocommerce' ); ?> <span class="chevron dashicons dashicons-arrow-up-alt2"></span></label>
|
||||
<?php
|
||||
$filters = array_keys( WC_Helper::get_filters() );
|
||||
$last_filter = array_pop( $filters );
|
||||
$current_filter = WC_Helper::get_current_filter();
|
||||
$counts = WC_Helper::get_filters_counts();
|
||||
?>
|
||||
|
||||
<?php
|
||||
foreach ( WC_Helper::get_filters() as $key => $label ) :
|
||||
// Don't show empty filters.
|
||||
if ( empty( $counts[ $key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = admin_url( 'admin.php?page=wc-addons§ion=helper&filter=' . $key );
|
||||
$class_html = $current_filter === $key ? 'class="current"' : '';
|
||||
?>
|
||||
<li>
|
||||
<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<a <?php echo $class_html; ?> href="<?php echo esc_url( $url ); ?>">
|
||||
<?php echo esc_html( $label ); ?>
|
||||
<span class="count">(<?php echo absint( $counts[ $key ] ); ?>)</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<?php if ( ! empty( $subscriptions ) ) : ?>
|
||||
<?php foreach ( $subscriptions as $subscription ) : ?>
|
||||
<tbody>
|
||||
<tr class="wp-list-table__row is-ext-header">
|
||||
<td class="wp-list-table__ext-details">
|
||||
<div class="wp-list-table__ext-title">
|
||||
<a href="<?php echo esc_url( WC_Helper::add_utm_params_to_url_for_subscription_link( $subscription['product_url'], 'product-name' ) ); ?>" target="_blank">
|
||||
<?php echo esc_html( $subscription['product_name'] ); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="wp-list-table__ext-description">
|
||||
<?php if ( $subscription['lifetime'] ) : ?>
|
||||
<span class="renews">
|
||||
<?php esc_html_e( 'Lifetime Subscription', 'woocommerce' ); ?>
|
||||
</span>
|
||||
<?php elseif ( $subscription['expired'] ) : ?>
|
||||
<span class="renews">
|
||||
<strong><?php esc_html_e( 'Expired :(', 'woocommerce' ); ?></strong>
|
||||
<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
|
||||
</span>
|
||||
<?php elseif ( $subscription['autorenew'] ) : ?>
|
||||
<span class="renews">
|
||||
<?php esc_html_e( 'Auto renews on:', 'woocommerce' ); ?>
|
||||
<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
|
||||
</span>
|
||||
<?php elseif ( $subscription['expiring'] ) : ?>
|
||||
<span class="renews">
|
||||
<strong><?php esc_html_e( 'Expiring soon!', 'woocommerce' ); ?></strong>
|
||||
<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
|
||||
</span>
|
||||
<?php else : ?>
|
||||
<span class="renews">
|
||||
<?php esc_html_e( 'Expires on:', 'woocommerce' ); ?>
|
||||
<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<br/>
|
||||
<span class="subscription">
|
||||
<?php
|
||||
if ( ! $subscription['active'] && $subscription['maxed'] ) {
|
||||
/* translators: %1$d: sites active, %2$d max sites active */
|
||||
printf( esc_html__( 'Subscription: Not available - %1$d of %2$d already in use', 'woocommerce' ), absint( $subscription['sites_active'] ), absint( $subscription['sites_max'] ) );
|
||||
} elseif ( $subscription['sites_max'] > 0 ) {
|
||||
/* translators: %1$d: sites active, %2$d max sites active */
|
||||
printf( esc_html__( 'Subscription: Using %1$d of %2$d sites available', 'woocommerce' ), absint( $subscription['sites_active'] ), absint( $subscription['sites_max'] ) );
|
||||
} else {
|
||||
esc_html_e( 'Subscription: Unlimited', 'woocommerce' );
|
||||
}
|
||||
|
||||
// Check shared.
|
||||
if ( ! empty( $subscription['is_shared'] ) && ! empty( $subscription['owner_email'] ) ) {
|
||||
/* translators: Email address of person who shared the subscription. */
|
||||
printf( '</br>' . esc_html__( 'Shared by %s', 'woocommerce' ), esc_html( $subscription['owner_email'] ) );
|
||||
} elseif ( isset( $subscription['master_user_email'] ) ) {
|
||||
/* translators: Email address of person who shared the subscription. */
|
||||
printf( '</br>' . esc_html__( 'Shared by %s', 'woocommerce' ), esc_html( $subscription['master_user_email'] ) );
|
||||
}
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="wp-list-table__ext-actions">
|
||||
<?php if ( ! $subscription['active'] && $subscription['maxed'] ) : ?>
|
||||
<a class="button" href="https://woocommerce.com/my-account/my-subscriptions/" target="_blank"><?php esc_html_e( 'Upgrade', 'woocommerce' ); ?></a>
|
||||
<?php elseif ( ! $subscription['local']['installed'] && ! $subscription['expired'] ) : ?>
|
||||
<a class="button <?php echo empty( $subscription['download_primary'] ) ? 'button-secondary' : ''; ?>" href="<?php echo esc_url( $subscription['download_url'] ); ?>" target="_blank"><?php esc_html_e( 'Download', 'woocommerce' ); ?></a>
|
||||
<?php elseif ( $subscription['active'] ) : ?>
|
||||
<span class="form-toggle__wrapper">
|
||||
<a href="<?php echo esc_url( $subscription['deactivate_url'] ); ?>" class="form-toggle active is-compact" role="link" aria-checked="true"><?php esc_html_e( 'Active', 'woocommerce' ); ?></a>
|
||||
<label class="form-toggle__label" for="activate-extension">
|
||||
<span class="form-toggle__label-content">
|
||||
<label for="activate-extension"><?php esc_html_e( 'Active', 'woocommerce' ); ?></label>
|
||||
</span>
|
||||
<span class="form-toggle__switch"></span>
|
||||
</label>
|
||||
</span>
|
||||
<?php elseif ( ! $subscription['expired'] ) : ?>
|
||||
<span class="form-toggle__wrapper">
|
||||
<a href="<?php echo esc_url( $subscription['activate_url'] ); ?>" class="form-toggle is-compact" role="link" aria-checked="false"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></a>
|
||||
<label class="form-toggle__label" for="activate-extension">
|
||||
<span class="form-toggle__label-content">
|
||||
<label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label>
|
||||
</span>
|
||||
<span class="form-toggle__switch"></span>
|
||||
</label>
|
||||
</span>
|
||||
<?php else : ?>
|
||||
<span class="form-toggle__wrapper">
|
||||
<span class="form-toggle disabled is-compact"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></span>
|
||||
<label class="form-toggle__label" for="activate-extension">
|
||||
<span class="form-toggle__label-content">
|
||||
<label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label>
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php foreach ( $subscription['actions'] as $subscription_action ) : ?>
|
||||
<tr class="wp-list-table__row wp-list-table__ext-updates">
|
||||
<td class="wp-list-table__ext-status <?php echo sanitize_html_class( $subscription_action['status'] ); ?>">
|
||||
<p><span class="dashicons <?php echo sanitize_html_class( $subscription_action['icon'] ); ?>"></span>
|
||||
<?php echo wp_kses_post( $subscription_action['message'] ); ?>
|
||||
</p>
|
||||
</td>
|
||||
<td class="wp-list-table__ext-actions">
|
||||
<?php if ( ! empty( $subscription_action['button_label'] ) && ! empty( $subscription_action['button_url'] ) ) : ?>
|
||||
<a class="button <?php echo empty( $subscription_action['primary'] ) ? 'button-secondary' : ''; ?>" href="<?php echo esc_url( $subscription_action['button_url'] ); ?>"><?php echo esc_html( $subscription_action['button_label'] ); ?></a>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</tbody>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr>
|
||||
<td colspan="3"><em><?php esc_html_e( 'Could not find any subscriptions on your WooCommerce.com account', 'woocommerce' ); ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php if ( ! empty( $no_subscriptions ) ) : ?>
|
||||
<h2><?php esc_html_e( 'Installed Extensions without a Subscription', 'woocommerce' ); ?></h2>
|
||||
<p>Below is a list of WooCommerce.com products available on your site - but are either out-dated or do not have a valid subscription.</p>
|
||||
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<?php /* Extensions without a subscription. */ ?>
|
||||
<?php foreach ( $no_subscriptions as $filename => $data ) : ?>
|
||||
<tbody>
|
||||
<tr class="wp-list-table__row is-ext-header">
|
||||
<td class="wp-list-table__ext-details color-bar autorenews">
|
||||
<div class="wp-list-table__ext-title">
|
||||
<a href="<?php echo esc_url( WC_Helper::add_utm_params_to_url_for_subscription_link( $data['_product_url'], 'product-name' ) ); ?>" target="_blank">
|
||||
<?php echo esc_html( $data['Name'] ); ?>
|
||||
</a>
|
||||
</div>
|
||||
<div class="wp-list-table__ext-description">
|
||||
</div>
|
||||
</td>
|
||||
<td class="wp-list-table__ext-actions">
|
||||
<span class="form-toggle__wrapper">
|
||||
<span class="form-toggle disabled is-compact" ><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></span>
|
||||
<label class="form-toggle__label" for="activate-extension">
|
||||
<span class="form-toggle__label-content">
|
||||
<label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label>
|
||||
</span>
|
||||
</label>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php foreach ( $data['_actions'] as $subscription_action ) : ?>
|
||||
<tr class="wp-list-table__row wp-list-table__ext-updates">
|
||||
<td class="wp-list-table__ext-status <?php echo sanitize_html_class( $subscription_action['status'] ); ?>">
|
||||
<p><span class="dashicons <?php echo sanitize_html_class( $subscription_action['icon'] ); ?>"></span>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
$subscription_action['message'],
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
'title' => array(),
|
||||
),
|
||||
'br' => array(),
|
||||
'em' => array(),
|
||||
'strong' => array(),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</td>
|
||||
<td class="wp-list-table__ext-actions">
|
||||
<a class="button" href="<?php echo esc_url( $subscription_action['button_url'] ); ?>" target="_blank"><?php echo esc_html( $subscription_action['button_label'] ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</tbody>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper Admin Notice - Woo Updater Plugin is not activated.
|
||||
*
|
||||
* @package WooCommerce\Views
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
?>
|
||||
<div id="message" class="error woocommerce-message">
|
||||
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'woo_updater_not_activated' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
sprintf(
|
||||
/* translators: 1: WP plugin management URL */
|
||||
__(
|
||||
'Please <a href="%1$s">activate the WooCommerce.com Update Manager</a> to continue receiving the updates and streamlined support included in your WooCommerce.com subscriptions.',
|
||||
'woocommerce'
|
||||
),
|
||||
esc_url( admin_url( 'plugins.php' ) ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper Admin Notice - Woo Updater Plugin is not Installed.
|
||||
*
|
||||
* @package WooCommerce\Views
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
?>
|
||||
<div id="message" class="error woocommerce-message">
|
||||
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'woo_updater_not_installed' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
sprintf(
|
||||
/* translators: 1: Woo Update Manager plugin install URL 2: Woo Update Manager plugin download URL */
|
||||
__(
|
||||
'Please <a href="%1$s">Install the WooCommerce.com Update Manager</a> to continue receiving the updates and streamlined support included in your WooCommerce.com subscriptions. Alternatively, you can <a href="%2$s">download</a> and install it manually.',
|
||||
'woocommerce'
|
||||
),
|
||||
esc_url( WC_Woo_Update_Manager_Plugin::generate_install_url() ),
|
||||
esc_url( WC_Woo_Update_Manager_Plugin::WOO_UPDATE_MANAGER_DOWNLOAD_URL )
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin -> WooCommerce -> Extensions -> WooCommerce.com Subscriptions main page.
|
||||
*
|
||||
* @package WooCommerce\Views
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit();
|
||||
|
||||
?>
|
||||
|
||||
<div class="wrap woocommerce wc-addons-wrap wc-helper">
|
||||
<?php require WC_Helper::get_view_filename( 'html-section-nav.php' ); ?>
|
||||
<h1 class="screen-reader-text"><?php esc_html_e( 'WooCommerce Extensions', 'woocommerce' ); ?></h1>
|
||||
<?php require WC_Helper::get_view_filename( 'html-section-notices.php' ); ?>
|
||||
|
||||
<div class="start-container">
|
||||
<div class="text">
|
||||
<img src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/woocommerce_logo.png' ); ?>" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" style="width:180px;">
|
||||
|
||||
<?php if ( ! empty( $_GET['wc-helper-status'] ) && 'helper-disconnected' === $_GET['wc-helper-status'] ) : ?>
|
||||
<p><strong><?php esc_html_e( 'Sorry to see you go.', 'woocommerce' ); ?></strong> <?php esc_html_e( 'Feel free to reconnect again using the button below.', 'woocommerce' ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h2><?php esc_html_e( 'Manage your subscriptions, get important product notifications, and updates, all from the convenience of your WooCommerce dashboard', 'woocommerce' ); ?></h2>
|
||||
<p><?php esc_html_e( 'Once connected, your WooCommerce.com purchases will be listed here.', 'woocommerce' ); ?></p>
|
||||
<p><a class="button button-primary button-helper-connect" href="<?php echo esc_url( $connect_url ); ?>"><?php esc_html_e( 'Connect', 'woocommerce' ); ?></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php defined( 'ABSPATH' ) or exit(); ?>
|
||||
|
||||
<a class="button button-update" href="<?php echo esc_url( $refresh_url ); ?>"><span class="dashicons dashicons-image-rotate"></span> <?php esc_html_e( 'Update', 'woocommerce' ); ?></a>
|
||||
<div class="user-info">
|
||||
<header>
|
||||
<p><?php esc_html_e( 'Connected to WooCommerce.com', 'woocommerce' ); ?> <span class="chevron dashicons dashicons-arrow-down-alt2"></span></p>
|
||||
</header>
|
||||
<section>
|
||||
<p><?php echo get_avatar( $auth_user_data['email'], 48 ); ?> <?php echo esc_html( $auth_user_data['email'] ); ?></p>
|
||||
<div class="actions">
|
||||
<a class="" href="https://woocommerce.com/my-account/my-subscriptions/" target="_blank"><span class="dashicons dashicons-admin-generic"></span> <?php esc_html_e( 'My Subscriptions', 'woocommerce' ); ?></a>
|
||||
<a class="" href="<?php echo esc_url( $disconnect_url ); ?>"><span class="dashicons dashicons-no"></span> <?php esc_html_e( 'Disconnect', 'woocommerce' ); ?></a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper admin navigation.
|
||||
*
|
||||
* @package WooCommerce\Helper
|
||||
*
|
||||
* @deprecated 5.7.0
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Utilities\FeaturesUtil;
|
||||
|
||||
$addons_url = admin_url( 'admin.php?page=wc-addons' );
|
||||
if ( FeaturesUtil::feature_is_enabled( 'marketplace' ) ) {
|
||||
$addons_url = admin_url( 'admin.php?page=wc-admin&path=/extensions&tab=extensions' );
|
||||
}
|
||||
|
||||
defined( 'ABSPATH' ) || exit(); ?>
|
||||
|
||||
<nav class="nav-tab-wrapper woo-nav-tab-wrapper">
|
||||
<a href="<?php echo esc_url( $addons_url ); ?>" class="nav-tab"><?php esc_html_e( 'Browse Extensions', 'woocommerce' ); ?></a>
|
||||
|
||||
<?php
|
||||
$count_html = WC_Helper_Updater::get_updates_count_html();
|
||||
/* translators: %s: WooCommerce.com Subscriptions tab count HTML. */
|
||||
$menu_title = sprintf( __( 'My Subscriptions %s', 'woocommerce' ), $count_html );
|
||||
?>
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-addons§ion=helper' ) ); ?>" class="nav-tab nav-tab-active"><?php echo wp_kses_post( $menu_title ); ?></a>
|
||||
</nav>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php defined( 'ABSPATH' ) or exit(); ?>
|
||||
|
||||
<?php foreach ( $notices as $notice ) : ?>
|
||||
<div class="notice <?php echo sanitize_html_class( $notice['type'] ); ?>">
|
||||
<?php echo wpautop( $notice['message'] ); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
Reference in New Issue
Block a user