plugin updates

This commit is contained in:
Tony Volpe
2024-06-17 14:48:11 -04:00
parent ecc5fbf831
commit 3751a5a1a6
1318 changed files with 91130 additions and 52250 deletions

View File

@@ -51,7 +51,6 @@ class Init {
add_filter( 'woocommerce_rest_prepare_shop_order_object', array( __CLASS__, 'add_currency_symbol_to_order_response' ) );
include_once WC_ABSPATH . 'includes/admin/class-wc-admin-upload-downloadable-product.php';
}
/**
@@ -105,6 +104,10 @@ class Init {
$product_form_controllers[] = 'Automattic\WooCommerce\Admin\API\ProductForm';
}
if ( Features::is_enabled( 'launch-your-store' ) ) {
$controllers[] = 'Automattic\WooCommerce\Admin\API\LaunchYourStore';
}
if ( Features::is_enabled( 'analytics' ) ) {
$analytics_controllers = array(
'Automattic\WooCommerce\Admin\API\Customers',
@@ -134,8 +137,7 @@ class Init {
// The performance indicators controller must be registered last, after other /stats endpoints have been registered.
$analytics_controllers[] = 'Automattic\WooCommerce\Admin\API\Reports\PerformanceIndicators\Controller';
$controllers = array_merge( $controllers, $analytics_controllers, $product_form_controllers );
$controllers = array_merge( $controllers, $analytics_controllers, $product_form_controllers );
}
/**

View File

@@ -0,0 +1,98 @@
<?php
/**
* REST API Launch Your Store Controller
*
* Handles requests to /launch-your-store/*
*/
namespace Automattic\WooCommerce\Admin\API;
use Automattic\WooCommerce\Admin\WCAdminHelper;
defined( 'ABSPATH' ) || exit;
/**
* Launch Your Store controller.
*
* @internal
*/
class LaunchYourStore {
/**
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'wc-admin';
/**
* Route base.
*
* @var string
*/
protected $rest_base = 'launch-your-store';
/**
* Register routes.
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/initialize-coming-soon',
array(
array(
'methods' => 'POST',
'callback' => array( $this, 'initialize_coming_soon' ),
'permission_callback' => array( $this, 'must_be_shop_manager_or_admin' ),
),
)
);
}
/**
* User must be either shop_manager or administrator.
*
* @return bool
*/
public function must_be_shop_manager_or_admin() {
// phpcs:ignore
if ( ! current_user_can( 'manage_woocommerce' ) && ! current_user_can( 'administrator' ) ) {
return false;
}
return true;
}
/**
* Initializes options for coming soon. Does not override if options exist.
*
* @return bool|void
*/
public function initialize_coming_soon() {
$current_user_id = get_current_user_id();
// Abort if we don't have a user id for some reason.
if ( ! $current_user_id ) {
return;
}
$coming_soon = 'yes';
$store_pages_only = WCAdminHelper::is_site_fresh() ? 'no' : 'yes';
$private_link = 'no';
$share_key = wp_generate_password( 32, false );
add_option( 'woocommerce_coming_soon', $coming_soon );
add_option( 'woocommerce_store_pages_only', $store_pages_only );
add_option( 'woocommerce_private_link', $private_link );
add_option( 'woocommerce_share_key', $share_key );
wc_admin_record_tracks_event(
'launch_your_store_initialize_coming_soon',
array(
'coming_soon' => $coming_soon,
'store_pages_only' => $store_pages_only,
'private_link' => $private_link,
)
);
return true;
}
}

View File

@@ -220,11 +220,12 @@ class Options extends \WC_REST_Data_Controller {
'woocommerce_admin_customize_store_completed',
'woocommerce_admin_customize_store_completed_theme_id',
'woocommerce_admin_customize_store_survey_completed',
'woocommerce_admin_launch_your_store_survey_completed',
'woocommerce_coming_soon',
'woocommerce_store_pages_only',
'woocommerce_private_link',
'woocommerce_share_key',
'launch-status',
'woocommerce_show_lys_tour',
// WC Test helper options.
'wc-admin-test-helper-rest-api-filters',
'wc_admin_helper_feature_values',

View File

@@ -211,24 +211,30 @@ class Controller extends ReportsController implements ExportableInterface {
'readonly' => true,
),
'extended_info' => array(
'products' => array(
'products' => array(
'type' => 'array',
'readonly' => true,
'context' => array( 'view', 'edit' ),
'description' => __( 'List of order product IDs, names, quantities.', 'woocommerce' ),
),
'coupons' => array(
'coupons' => array(
'type' => 'array',
'readonly' => true,
'context' => array( 'view', 'edit' ),
'description' => __( 'List of order coupons.', 'woocommerce' ),
),
'customer' => array(
'customer' => array(
'type' => 'object',
'readonly' => true,
'context' => array( 'view', 'edit' ),
'description' => __( 'Order customer information.', 'woocommerce' ),
),
'attribution' => array(
'type' => 'object',
'readonly' => true,
'context' => array( 'view', 'edit' ),
'description' => __( 'Order attribution information.', 'woocommerce' ),
),
),
),
);
@@ -526,6 +532,7 @@ class Controller extends ReportsController implements ExportableInterface {
'num_items_sold' => __( 'Items sold', 'woocommerce' ),
'coupons' => __( 'Coupon(s)', 'woocommerce' ),
'net_total' => __( 'N. Revenue', 'woocommerce' ),
'attribution' => __( 'Attribution', 'woocommerce' ),
);
/**
@@ -558,6 +565,7 @@ class Controller extends ReportsController implements ExportableInterface {
'num_items_sold' => $item['num_items_sold'],
'coupons' => isset( $item['extended_info']['coupons'] ) ? $this->get_coupons( $item['extended_info']['coupons'] ) : null,
'net_total' => $item['net_total'],
'attribution' => $item['extended_info']['attribution']['origin'],
);
/**

View File

@@ -7,6 +7,9 @@ namespace Automattic\WooCommerce\Admin\API\Reports\Orders;
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Internal\Traits\OrderAttributionMeta;
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Utilities\OrderUtil;
use Automattic\WooCommerce\Admin\API\Reports\DataStore as ReportsDataStore;
use Automattic\WooCommerce\Admin\API\Reports\DataStoreInterface;
use Automattic\WooCommerce\Admin\API\Reports\SqlQuery;
@@ -18,6 +21,7 @@ use Automattic\WooCommerce\Admin\API\Reports\TimeInterval;
* API\Reports\Orders\DataStore.
*/
class DataStore extends ReportsDataStore implements DataStoreInterface {
use OrderAttributionMeta;
/**
* Dynamically sets the date column name based on configuration
@@ -338,13 +342,14 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
* @param array $query_args Query parameters.
*/
protected function include_extended_info( &$orders_data, $query_args ) {
$mapped_orders = $this->map_array_by_key( $orders_data, 'order_id' );
$related_orders = $this->get_orders_with_parent_id( $mapped_orders );
$order_ids = array_merge( array_keys( $mapped_orders ), array_keys( $related_orders ) );
$products = $this->get_products_by_order_ids( $order_ids );
$coupons = $this->get_coupons_by_order_ids( array_keys( $mapped_orders ) );
$customers = $this->get_customers_by_orders( $orders_data );
$mapped_customers = $this->map_array_by_key( $customers, 'customer_id' );
$mapped_orders = $this->map_array_by_key( $orders_data, 'order_id' );
$related_orders = $this->get_orders_with_parent_id( $mapped_orders );
$order_ids = array_merge( array_keys( $mapped_orders ), array_keys( $related_orders ) );
$products = $this->get_products_by_order_ids( $order_ids );
$coupons = $this->get_coupons_by_order_ids( array_keys( $mapped_orders ) );
$order_attributions = $this->get_order_attributions_by_order_ids( array_keys( $mapped_orders ) );
$customers = $this->get_customers_by_orders( $orders_data );
$mapped_customers = $this->map_array_by_key( $customers, 'customer_id' );
$mapped_data = array();
foreach ( $products as $product ) {
@@ -384,7 +389,7 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
foreach ( $coupons as $coupon ) {
if ( ! isset( $mapped_data[ $coupon['order_id'] ] ) ) {
$mapped_data[ $product['order_id'] ]['coupons'] = array();
$mapped_data[ $coupon['order_id'] ]['coupons'] = array();
}
$mapped_data[ $coupon['order_id'] ]['coupons'][] = array(
@@ -394,15 +399,22 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
}
foreach ( $orders_data as $key => $order_data ) {
$defaults = array(
'products' => array(),
'coupons' => array(),
'customer' => array(),
$defaults = array(
'products' => array(),
'coupons' => array(),
'customer' => array(),
'attribution' => array(),
);
$orders_data[ $key ]['extended_info'] = isset( $mapped_data[ $order_data['order_id'] ] ) ? array_merge( $defaults, $mapped_data[ $order_data['order_id'] ] ) : $defaults;
$order_id = $order_data['order_id'];
$orders_data[ $key ]['extended_info'] = isset( $mapped_data[ $order_id ] ) ? array_merge( $defaults, $mapped_data[ $order_id ] ) : $defaults;
if ( $order_data['customer_id'] && isset( $mapped_customers[ $order_data['customer_id'] ] ) ) {
$orders_data[ $key ]['extended_info']['customer'] = $mapped_customers[ $order_data['customer_id'] ];
}
$source_type = $order_attributions[ $order_id ]['_wc_order_attribution_source_type'] ?? '';
$utm_source = $order_attributions[ $order_id ]['_wc_order_attribution_utm_source'] ?? '';
$orders_data[ $key ]['extended_info']['attribution']['origin'] = $this->get_origin_label( $source_type, $utm_source );
}
}
@@ -534,6 +546,52 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
return $coupons;
}
/**
* Get order attributions data from order IDs.
*
* @param array $order_ids Array of order IDs.
* @return array
*/
protected function get_order_attributions_by_order_ids( $order_ids ) {
global $wpdb;
$order_meta_table = OrdersTableDataStore::get_meta_table_name();
$included_order_ids = implode( ',', array_map( 'absint', $order_ids ) );
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
/* phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared */
$order_attributions_meta = $wpdb->get_results(
"SELECT order_id, meta_key, meta_value
FROM $order_meta_table
WHERE order_id IN ({$included_order_ids})
AND meta_key IN ( '_wc_order_attribution_source_type', '_wc_order_attribution_utm_source' )
",
ARRAY_A
);
/* phpcs:enable */
} else {
/* phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared */
$order_attributions_meta = $wpdb->get_results(
"SELECT post_id as order_id, meta_key, meta_value
FROM $wpdb->postmeta
WHERE post_id IN ({$included_order_ids})
AND meta_key IN ( '_wc_order_attribution_source_type', '_wc_order_attribution_utm_source' )
",
ARRAY_A
);
/* phpcs:enable */
}
$order_attributions = array();
foreach ( $order_attributions_meta as $meta ) {
if ( ! isset( $order_attributions[ $meta['order_id'] ] ) ) {
$order_attributions[ $meta['order_id'] ] = array();
}
$order_attributions[ $meta['order_id'] ][ $meta['meta_key'] ] = $meta['meta_value'];
}
return $order_attributions;
}
/**
* Get all statuses that have been synced.
*

View File

@@ -2,15 +2,24 @@
namespace Automattic\WooCommerce\Admin\Features;
use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
use Automattic\WooCommerce\Admin\WCAdminHelper;
/**
* Takes care of Launch Your Store related actions.
*/
class LaunchYourStore {
const BANNER_DISMISS_USER_META_KEY = 'woocommerce_coming_soon_banner_dismissed';
/**
* Constructor.
*/
public function __construct() {
add_action( 'woocommerce_update_options_general', array( $this, 'save_site_visibility_options' ) );
add_action( 'woocommerce_update_options_site-visibility', array( $this, 'save_site_visibility_options' ) );
add_filter( 'woocommerce_admin_shared_settings', array( $this, 'preload_settings' ) );
add_action( 'wp_footer', array( $this, 'maybe_add_coming_soon_banner_on_frontend' ) );
add_action( 'init', array( $this, 'register_launch_your_store_user_meta_fields' ) );
add_action( 'wp_login', array( $this, 'reset_woocommerce_coming_soon_banner_dismissed' ), 10, 2 );
}
/**
@@ -30,12 +39,163 @@ class LaunchYourStore {
'woocommerce_private_link' => array( 'yes', 'no' ),
);
$at_least_one_saved = false;
foreach ( $options as $name => $option ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $_POST[ $name ] ) && in_array( $_POST[ $name ], $option, true ) ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
update_option( $name, wp_unslash( $_POST[ $name ] ) );
$at_least_one_saved = true;
}
}
if ( $at_least_one_saved ) {
wc_admin_record_tracks_event( 'site_visibility_saved' );
}
}
/**
* Preload settings for Site Visibility.
*
* @param array $settings settings array.
*
* @return mixed
*/
public function preload_settings( $settings ) {
if ( ! is_admin() ) {
return $settings;
}
$current_screen = get_current_screen();
$is_setting_page = $current_screen && 'woocommerce_page_wc-settings' === $current_screen->id;
if ( $is_setting_page ) {
// Regnerate the share key if it's not set.
add_option( 'woocommerce_share_key', wp_generate_password( 32, false ) );
$settings['siteVisibilitySettings'] = array(
'shop_permalink' => get_permalink( wc_get_page_id( 'shop' ) ),
'woocommerce_coming_soon' => get_option( 'woocommerce_coming_soon' ),
'woocommerce_store_pages_only' => get_option( 'woocommerce_store_pages_only' ),
'woocommerce_private_link' => get_option( 'woocommerce_private_link' ),
'woocommerce_share_key' => get_option( 'woocommerce_share_key' ),
);
}
return $settings;
}
/**
* User must be an admin or editor.
*
* @return bool
*/
private function is_manager_or_admin() {
// phpcs:ignore
if ( ! current_user_can( 'shop_manager' ) && ! current_user_can( 'administrator' ) ) {
return false;
}
return true;
}
/**
* Add 'coming soon' banner on the frontend when the following conditions met.
*
* - User must be either an admin or store editor (must be logged in).
* - 'woocommerce_coming_soon' option value must be 'yes'
* - The page must not be the Coming soon page itself.
*/
public function maybe_add_coming_soon_banner_on_frontend() {
// Do not show the banner if the site is being previewed.
if ( isset( $_GET['site-preview'] ) ) { // @phpcs:ignore
return false;
}
$current_user_id = get_current_user_id();
if ( ! $current_user_id ) {
return false;
}
if ( get_user_meta( $current_user_id, self::BANNER_DISMISS_USER_META_KEY, true ) === 'yes' ) {
return false;
}
if ( ! $this->is_manager_or_admin() ) {
return false;
}
// 'woocommerce_coming_soon' must be 'yes'
if ( get_option( 'woocommerce_coming_soon', 'no' ) !== 'yes' ) {
return false;
}
$store_pages_only = get_option( 'woocommerce_store_pages_only' ) === 'yes';
if ( $store_pages_only && ! WCAdminHelper::is_store_page() ) {
return false;
}
$link = admin_url( 'admin.php?page=wc-settings&tab=site-visibility' );
$rest_url = rest_url( 'wp/v2/users/' . $current_user_id );
$rest_nonce = wp_create_nonce( 'wp_rest' );
$text = sprintf(
// translators: no need to translate it. It's a link.
__(
"
This page is in \"Coming soon\" mode and is only visible to you and those who have permission. To make it public to everyone,&nbsp;<a href='%s'>change visibility settings</a>
",
'woocommerce'
),
$link
);
// phpcs:ignore
echo "<div id='coming-soon-footer-banner'>$text<a class='coming-soon-footer-banner-dismiss' data-rest-url='$rest_url' data-rest-nonce='$rest_nonce'></a></div>";
}
/**
* Register user meta fields for Launch Your Store.
*/
public function register_launch_your_store_user_meta_fields() {
if ( ! $this->is_manager_or_admin() ) {
return;
}
register_meta(
'user',
'woocommerce_launch_your_store_tour_hidden',
array(
'type' => 'string',
'description' => 'Indicate whether the user has dismissed the site visibility tour on the home screen.',
'single' => true,
'show_in_rest' => true,
)
);
register_meta(
'user',
self::BANNER_DISMISS_USER_META_KEY,
array(
'type' => 'string',
'description' => 'Indicate whether the user has dismissed the coming soon notice or not.',
'single' => true,
'show_in_rest' => true,
)
);
}
/**
* Reset 'woocommerce_coming_soon_banner_dismissed' user meta to 'no'.
*
* Runs when a user logs-in successfully.
*
* @param string $user_login user login.
* @param object $user user object.
*/
public function reset_woocommerce_coming_soon_banner_dismissed( $user_login, $user ) {
$existing_meta = get_user_meta( $user->ID, self::BANNER_DISMISS_USER_META_KEY, true );
if ( 'yes' === $existing_meta ) {
update_user_meta( $user->ID, self::BANNER_DISMISS_USER_META_KEY, 'no' );
}
}
}

View File

@@ -165,6 +165,7 @@ class TaskLists {
),
),
'tasks' => array(
'StoreConnect',
'AdditionalPayments',
'GetMobileApp',
),

View File

@@ -9,13 +9,24 @@ use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
* Launch Your Store Task
*/
class LaunchYourStore extends Task {
/**
* Constructor
*
* @param TaskList $task_list Parent task list.
*/
public function __construct( $task_list ) {
parent::__construct( $task_list );
add_action( 'show_admin_bar', array( $this, 'possibly_hide_wp_admin_bar' ) );
}
/**
* ID.
*
* @return string
*/
public function get_id() {
return 'launch_your_store';
return 'launch-your-store';
}
/**
@@ -48,21 +59,22 @@ class LaunchYourStore extends Task {
return '';
}
/**
* Action URL.
*
* @return string
*/
public function get_action_url() {
return admin_url( 'wp-admin/admin.php?page=wc-admin&path=%2Flaunch-your-store' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
$launch_status = get_option( 'launch-status' );
// The site is launched when the launch status is 'launched' or missing.
$launched_values = array(
'launched',
'',
false,
);
return in_array( $launch_status, $launched_values, true );
return 'yes' !== get_option( 'woocommerce_coming_soon' );
}
/**
@@ -73,4 +85,40 @@ class LaunchYourStore extends Task {
public function can_view() {
return Features::is_enabled( 'launch-your-store' );
}
/**
* Hide the WP admin bar when the user is previewing the site.
*
* @param bool $show Whether to show the admin bar.
*/
public function possibly_hide_wp_admin_bar( $show ) {
if ( isset( $_GET['site-preview'] ) ) { // @phpcs:ignore
return false;
}
global $wp;
$http_referer = wp_get_referer() ?? '';
$parsed_url = wp_parse_url( $http_referer, PHP_URL_QUERY );
$query_string = is_string( $parsed_url ) ? $parsed_url : '';
// Check if the user is coming from the site preview link.
if ( strpos( $query_string, 'site-preview' ) !== false ) {
if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
return $show;
}
// Redirect to the current URL with the site-preview query string.
$current_url =
add_query_arg(
array(
'site-preview' => 1,
),
esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
);
wp_safe_redirect( $current_url );
exit;
}
return $show;
}
}

View File

@@ -45,7 +45,7 @@ class Shipping extends Task {
* @return string
*/
public function get_title() {
return __( 'Get your products shipped', 'woocommerce' );
return __( 'Select your shipping options', 'woocommerce' );
}
/**

View File

@@ -0,0 +1,73 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
* Connect store to WooCommerce.com Task
*/
class StoreConnect extends Task {
/**
* ID.
*
* @return string
*/
public function get_id() {
return 'connect-store';
}
/**
* Title.
*
* @return string
*/
public function get_title() {
return __( 'Manage your WooCommerce.com Marketplace subscriptions', 'woocommerce' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return '';
}
/**
* Time.
*
* @return string
*/
public function get_time() {
return '';
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return \WC_Helper::is_site_connected();
}
/**
* Always dismissable.
*
* @return bool
*/
public function is_dismissable() {
return true;
}
/**
* Action URL.
*
* @return string
*/
public function get_action_url() {
return admin_url( 'admin.php?page=wc-admin&tab=my-subscriptions&path=/extensions' );
}
}

View File

@@ -78,6 +78,8 @@ class Init {
add_action( 'rest_api_init', array( $this, 'register_layout_templates' ) );
add_action( 'rest_api_init', array( $this, 'register_user_metas' ) );
add_filter( 'register_block_type_args', array( $this, 'register_metadata_attribute' ) );
// Make sure the block registry is initialized so that core blocks are registered.
BlockRegistry::get_instance();
@@ -113,6 +115,9 @@ class Init {
);
wp_tinymce_inline_scripts();
wp_enqueue_media();
wp_register_style( 'wc-global-presets', false ); // phpcs:ignore
wp_add_inline_style( 'wc-global-presets', wp_get_global_stylesheet( array( 'presets' ) ) );
wp_enqueue_style( 'wc-global-presets' );
}
/**
@@ -417,4 +422,31 @@ class Init {
)
);
}
/**
* Registers the metadata block attribute for all block types.
* This is a fallback/temporary solution until
* the Gutenberg core version registers the metadata attribute.
*
* @see https://github.com/WordPress/gutenberg/blob/6aaa3686ae67adc1a6a6b08096d3312859733e1b/lib/compat/wordpress-6.5/blocks.php#L27-L47
* To do: Remove this method once the Gutenberg core version registers the metadata attribute.
*
* @param array $args Array of arguments for registering a block type.
* @return array $args
*/
public function register_metadata_attribute( $args ) {
// Setup attributes if needed.
if ( ! isset( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) {
$args['attributes'] = array();
}
// Add metadata attribute if it doesn't exist.
if ( ! array_key_exists( 'metadata', $args['attributes'] ) ) {
$args['attributes']['metadata'] = array(
'type' => 'object',
);
}
return $args;
}
}

View File

@@ -61,6 +61,13 @@ class ProductTemplate {
*/
private $icon = null;
/**
* If the template is directly selectable through the UI.
*
* @var boolean
*/
private $is_selectable_by_user = true;
/**
* ProductTemplate constructor
*
@@ -86,6 +93,10 @@ class ProductTemplate {
if ( isset( $data['icon'] ) ) {
$this->icon = $data['icon'];
}
if ( isset( $data['is_selectable_by_user'] ) ) {
$this->is_selectable_by_user = $data['is_selectable_by_user'];
}
}
/**
@@ -180,6 +191,15 @@ class ProductTemplate {
return $this->order;
}
/**
* Get the selectable attribute.
*
* @return boolean Selectable.
*/
public function get_is_selectable_by_user() {
return $this->is_selectable_by_user;
}
/**
* Set the template order.
*
@@ -196,13 +216,14 @@ class ProductTemplate {
*/
public function to_json() {
return array(
'id' => $this->get_id(),
'title' => $this->get_title(),
'description' => $this->get_description(),
'icon' => $this->get_icon(),
'order' => $this->get_order(),
'layoutTemplateId' => $this->get_layout_template_id(),
'productData' => $this->get_product_data(),
'id' => $this->get_id(),
'title' => $this->get_title(),
'description' => $this->get_description(),
'icon' => $this->get_icon(),
'order' => $this->get_order(),
'layoutTemplateId' => $this->get_layout_template_id(),
'productData' => $this->get_product_data(),
'isSelectableByUser' => $this->get_is_selectable_by_user(),
);
}
}

View File

@@ -13,7 +13,10 @@ use ActionScheduler_QueueRunner;
use Automatic_Upgrader_Skin;
use Automattic\WooCommerce\Admin\PluginsInstallLoggers\AsyncPluginsInstallLogger;
use Automattic\WooCommerce\Admin\PluginsInstallLoggers\PluginsInstallLogger;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Plugin_Upgrader;
use WC_Helper;
use WC_Helper_Updater;
use WP_Error;
use WP_Upgrader;
@@ -35,6 +38,9 @@ class PluginsHelper {
add_action( 'woocommerce_plugins_install_callback', array( __CLASS__, 'install_plugins' ), 10, 2 );
add_action( 'woocommerce_plugins_install_and_activate_async_callback', array( __CLASS__, 'install_and_activate_plugins_async_callback' ), 10, 2 );
add_action( 'woocommerce_plugins_activate_callback', array( __CLASS__, 'activate_plugins' ), 10, 2 );
add_action( 'admin_notices', array( __CLASS__, 'maybe_show_connect_notice_in_plugin_list' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'maybe_enqueue_scripts_for_connect_notice' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'maybe_enqueue_scripts_for_connect_notice_in_plugins' ) );
}
/**
@@ -532,4 +538,80 @@ class PluginsHelper {
return self::get_action_data( $actions );
}
/**
* Show notices to connect to woocommerce.com for unconnected store in the plugin list.
*
* @return void
*/
public static function maybe_show_connect_notice_in_plugin_list() {
if ( 'woocommerce_page_wc-settings' !== get_current_screen()->id ) {
return;
}
$notice_type = WC_Helper_Updater::get_woo_connect_notice_type();
if ( 'none' === $notice_type ) {
return;
}
$notice_string = '';
if ( 'long' === $notice_type ) {
$notice_string .= __( 'Your store might be at risk as you are running old versions of WooCommerce plugins.', 'woocommerce' );
$notice_string .= ' ';
}
$connect_page_url = add_query_arg(
array(
'page' => 'wc-admin',
'tab' => 'my-subscriptions',
'path' => rawurlencode( '/extensions' ),
),
admin_url( 'admin.php' )
);
$notice_string .= sprintf(
/* translators: %s: Connect page URL */
__( '<a id="woo-connect-notice-url" href="%s">Connect your store</a> to WooCommerce.com to get updates and streamlined support for your subscriptions.', 'woocommerce' ),
esc_url( $connect_page_url )
);
echo '<div class="woo-connect-notice notice notice-error is-dismissible">
<p class="widefat">' . wp_kses_post( $notice_string ) . '</p>
</div>';
}
/**
* Enqueue scripts for connect notice in WooCommerce settings page.
*
* @return void
*/
public static function maybe_enqueue_scripts_for_connect_notice() {
if ( 'woocommerce_page_wc-settings' !== get_current_screen()->id ) {
return;
}
$notice_type = WC_Helper_Updater::get_woo_connect_notice_type();
if ( 'none' === $notice_type ) {
return;
}
WCAdminAssets::register_script( 'wp-admin-scripts', 'woo-connect-notice' );
wp_enqueue_script( 'woo-connect-notice' );
}
/**
* Enqueue scripts for connect notice in plugin list page.
*
* @return void
*/
public static function maybe_enqueue_scripts_for_connect_notice_in_plugins() {
if ( 'plugins' !== get_current_screen()->id ) {
return;
}
WCAdminAssets::register_script( 'wp-admin-scripts', 'woo-plugin-update-connect-notice' );
wp_enqueue_script( 'woo-plugin-update-connect-notice' );
}
}

View File

@@ -128,7 +128,6 @@ class WCAdminHelper {
*
* Store pages are defined as:
*
* - My Account
* - Shop
* - Cart
* - Checkout
@@ -153,12 +152,12 @@ class WCAdminHelper {
// WC store pages.
$store_pages = array(
'myaccount' => wc_get_page_id( 'myaccount' ),
'shop' => wc_get_page_id( 'shop' ),
'cart' => wc_get_page_id( 'cart' ),
'checkout' => wc_get_page_id( 'checkout' ),
'privacy' => wc_privacy_policy_page_id(),
'terms' => wc_terms_and_conditions_page_id(),
'shop' => wc_get_page_id( 'shop' ),
'cart' => wc_get_page_id( 'cart' ),
'checkout' => wc_get_page_id( 'checkout' ),
'privacy' => wc_privacy_policy_page_id(),
'terms' => wc_terms_and_conditions_page_id(),
'coming_soon' => wc_get_page_id( 'coming_soon' ),
);
/**
@@ -237,7 +236,7 @@ class WCAdminHelper {
private static function get_normalized_url_path( $url ) {
$query = wp_parse_url( $url, PHP_URL_QUERY );
$path = wp_parse_url( $url, PHP_URL_PATH ) . ( $query ? '?' . $query : '' );
$home_path = wp_parse_url( site_url(), PHP_URL_PATH );
$home_path = wp_parse_url( site_url(), PHP_URL_PATH ) ?? '';
$normalized_path = trim( substr( $path, strlen( $home_path ) ), '/' );
return $normalized_path;
}