plugin updates
This commit is contained in:
@@ -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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -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'],
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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, <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' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ class TaskLists {
|
||||
),
|
||||
),
|
||||
'tasks' => array(
|
||||
'StoreConnect',
|
||||
'AdditionalPayments',
|
||||
'GetMobileApp',
|
||||
),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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' );
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user