auto-patch 638-dev-dev01-2024-05-14T20_44_36
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
use Automattic\Jetpack\Constants;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications as PromotionRuleEngine;
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\RuleEvaluator;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
@@ -315,16 +316,16 @@ class WC_Admin_Addons {
|
||||
|
||||
if ( 'storefront' === $template ) {
|
||||
if ( 'storefront' === $stylesheet ) {
|
||||
$url = 'https://woo.com/product-category/themes/storefront-child-theme-themes/';
|
||||
$url = 'https://woocommerce.com/product-category/themes/storefront-child-theme-themes/';
|
||||
$text = __( 'Need a fresh look? Try Storefront child themes', 'woocommerce' );
|
||||
$utm_content = 'nostorefrontchildtheme';
|
||||
} else {
|
||||
$url = 'https://woo.com/product-category/themes/storefront-child-theme-themes/';
|
||||
$url = 'https://woocommerce.com/product-category/themes/storefront-child-theme-themes/';
|
||||
$text = __( 'View more Storefront child themes', 'woocommerce' );
|
||||
$utm_content = 'hasstorefrontchildtheme';
|
||||
}
|
||||
} else {
|
||||
$url = 'https://woo.com/storefront/';
|
||||
$url = 'https://woocommerce.com/storefront/';
|
||||
$text = __( 'Need a theme? Try Storefront', 'woocommerce' );
|
||||
$utm_content = 'nostorefront';
|
||||
}
|
||||
@@ -1014,11 +1015,11 @@ class WC_Admin_Addons {
|
||||
wp_kses_post(
|
||||
/* translators: a url */
|
||||
__(
|
||||
'To start growing your business, head over to <a href="%s">Woo.com</a>, where you\'ll find the most popular WooCommerce extensions.',
|
||||
'To start growing your business, head over to <a href="%s">WooCommerce.com</a>, where you\'ll find the most popular WooCommerce extensions.',
|
||||
'woocommerce'
|
||||
)
|
||||
),
|
||||
'https://woo.com/products/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=connectionerror'
|
||||
'https://woocommerce.com/products/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=connectionerror'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
@@ -1075,7 +1076,7 @@ class WC_Admin_Addons {
|
||||
// Check for existence of promotions and evaluate out if we should show them.
|
||||
if ( ! empty( $promotions ) ) {
|
||||
foreach ( $promotions as $promo_id => $promotion ) {
|
||||
$evaluator = new PromotionRuleEngine\RuleEvaluator();
|
||||
$evaluator = new RuleEvaluator();
|
||||
$passed = $evaluator->evaluate( $promotion->rules );
|
||||
if ( ! $passed ) {
|
||||
unset( $promotions[ $promo_id ] );
|
||||
@@ -1546,7 +1547,7 @@ class WC_Admin_Addons {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make wp_safe_remote_get request to Woo.com endpoint.
|
||||
* Make wp_safe_remote_get request to WooCommerce.com endpoint.
|
||||
* Optionally pass user auth token, locale or country.
|
||||
*
|
||||
* @param string $url URL to request.
|
||||
|
||||
@@ -586,7 +586,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
||||
'wc-admin-' . $script_name,
|
||||
WCAdminAssets::get_url( $script_path_name . '/' . $script_name, 'js' ),
|
||||
$script_assets['dependencies'],
|
||||
WCAdminAssets::get_file_version( 'js' ),
|
||||
WCAdminAssets::get_file_version( 'js', $script_assets['version'] ),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
use Automattic\Jetpack\Constants;
|
||||
use Automattic\WooCommerce\Admin\Features\Features;
|
||||
use Automattic\WooCommerce\Utilities\OrderUtil;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
@@ -81,23 +82,49 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
|
||||
private function get_top_seller() {
|
||||
global $wpdb;
|
||||
|
||||
$query = array();
|
||||
$query['fields'] = "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
|
||||
FROM {$wpdb->posts} as posts";
|
||||
$query['join'] = "INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id ";
|
||||
$query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id ";
|
||||
$query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id ";
|
||||
$query['where'] = "WHERE posts.post_type IN ( '" . implode( "','", wc_get_order_types( 'order-count' ) ) . "' ) ";
|
||||
$query['where'] .= "AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' ) ";
|
||||
$hpos_enabled = OrderUtil::custom_orders_table_usage_is_enabled();
|
||||
$orders_table = OrderUtil::get_table_for_orders();
|
||||
$orders_column_id = $hpos_enabled ? 'id' : 'ID';
|
||||
$orders_column_type = $hpos_enabled ? 'type' : 'post_type';
|
||||
$orders_column_status = $hpos_enabled ? 'status' : 'post_status';
|
||||
$orders_column_date = $hpos_enabled ? 'date_created_gmt' : 'post_date_gmt';
|
||||
|
||||
$query = array();
|
||||
$query['fields'] = "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id FROM {$orders_table} AS orders";
|
||||
$query['join'] = "INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON orders.{$orders_column_id} = order_id ";
|
||||
$query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id ";
|
||||
$query['join'] .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id ";
|
||||
$query['where'] = "WHERE orders.{$orders_column_type} IN ( '" . implode( "','", wc_get_order_types( 'order-count' ) ) . "' ) ";
|
||||
|
||||
/**
|
||||
* Allows modifying the order statuses used in the top seller query inside the dashboard status widget.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @param string[] $order_statuses Order statuses.
|
||||
*/
|
||||
$order_statuses = apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) );
|
||||
$query['where'] .= "AND orders.{$orders_column_status} IN ( 'wc-" . implode( "','wc-", $order_statuses ) . "' ) ";
|
||||
|
||||
$query['where'] .= "AND order_item_meta.meta_key = '_qty' ";
|
||||
$query['where'] .= "AND order_item_meta_2.meta_key = '_product_id' ";
|
||||
$query['where'] .= "AND posts.post_date >= '" . gmdate( 'Y-m-01', current_time( 'timestamp' ) ) . "' ";
|
||||
$query['where'] .= "AND posts.post_date <= '" . gmdate( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) . "' ";
|
||||
$query['where'] .= "AND orders.{$orders_column_date} >= '" . gmdate( 'Y-m-01', current_time( 'timestamp' ) ) . "' "; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
$query['where'] .= "AND orders.{$orders_column_date} <= '" . gmdate( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) . "' "; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
$query['groupby'] = 'GROUP BY product_id';
|
||||
$query['orderby'] = 'ORDER BY qty DESC';
|
||||
$query['limits'] = 'LIMIT 1';
|
||||
|
||||
return $wpdb->get_row( implode( ' ', apply_filters( 'woocommerce_dashboard_status_widget_top_seller_query', $query ) ) ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
/**
|
||||
* Allows modification of the query to determine the top seller product in the dashboard status widget.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @param array $query SQL query parts.
|
||||
*/
|
||||
$query = apply_filters( 'woocommerce_dashboard_status_widget_top_seller_query', $query );
|
||||
|
||||
$sql = implode( ' ', $query );
|
||||
return $wpdb->get_row( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,9 +229,9 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
|
||||
$processing_count = 0;
|
||||
|
||||
foreach ( wc_get_order_types( 'order-count' ) as $type ) {
|
||||
$counts = (array) wp_count_posts( $type );
|
||||
$on_hold_count += isset( $counts['wc-on-hold'] ) ? $counts['wc-on-hold'] : 0;
|
||||
$processing_count += isset( $counts['wc-processing'] ) ? $counts['wc-processing'] : 0;
|
||||
$counts = OrderUtil::get_count_for_type( $type );
|
||||
$on_hold_count += $counts['wc-on-hold'];
|
||||
$processing_count += $counts['wc-processing'];
|
||||
}
|
||||
?>
|
||||
<li class="processing-orders">
|
||||
|
||||
@@ -45,16 +45,16 @@ class WC_Admin_Help {
|
||||
'<p>' . sprintf(
|
||||
/* translators: %s: Documentation URL */
|
||||
__( 'Should you need help understanding, using, or extending WooCommerce, <a href="%s">please read our documentation</a>. You will find all kinds of resources including snippets, tutorials and much more.', 'woocommerce' ),
|
||||
'https://woo.com/documentation/plugins/woocommerce/?utm_source=helptab&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin'
|
||||
'https://woocommerce.com/documentation/plugins/woocommerce/?utm_source=helptab&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin'
|
||||
) . '</p>' .
|
||||
'<p>' . sprintf(
|
||||
/* translators: %s: Forum URL */
|
||||
__( 'For further assistance with WooCommerce core, use the <a href="%1$s">community forum</a>. For help with premium extensions sold on Woo.com, <a href="%2$s">open a support request at Woo.com</a>.', 'woocommerce' ),
|
||||
__( 'For further assistance with WooCommerce core, use the <a href="%1$s">community forum</a>. For help with premium extensions sold on WooCommerce.com, <a href="%2$s">open a support request at WooCommerce.com</a>.', 'woocommerce' ),
|
||||
'https://wordpress.org/support/plugin/woocommerce',
|
||||
'https://woo.com/my-account/create-a-ticket/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin'
|
||||
'https://woocommerce.com/my-account/create-a-ticket/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin'
|
||||
) . '</p>' .
|
||||
'<p>' . __( 'Before asking for help, we recommend checking the system status page to identify any problems with your configuration.', 'woocommerce' ) . '</p>' .
|
||||
'<p><a href="' . admin_url( 'admin.php?page=wc-status' ) . '" class="button button-primary">' . __( 'System status', 'woocommerce' ) . '</a> <a href="https://wordpress.org/support/plugin/woocommerce" class="button">' . __( 'Community forum', 'woocommerce' ) . '</a> <a href="https://woo.com/my-account/create-a-ticket/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin" class="button">' . __( 'Woo.com support', 'woocommerce' ) . '</a></p>',
|
||||
'<p><a href="' . admin_url( 'admin.php?page=wc-status' ) . '" class="button button-primary">' . __( 'System status', 'woocommerce' ) . '</a> <a href="https://wordpress.org/support/plugin/woocommerce" class="button">' . __( 'Community forum', 'woocommerce' ) . '</a> <a href="https://woocommerce.com/my-account/create-a-ticket/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin" class="button">' . __( 'WooCommerce.com support', 'woocommerce' ) . '</a></p>',
|
||||
)
|
||||
);
|
||||
|
||||
@@ -73,11 +73,11 @@ class WC_Admin_Help {
|
||||
|
||||
$screen->set_help_sidebar(
|
||||
'<p><strong>' . __( 'For more information:', 'woocommerce' ) . '</strong></p>' .
|
||||
'<p><a href="https://woo.com/?utm_source=helptab&utm_medium=product&utm_content=about&utm_campaign=woocommerceplugin" target="_blank">' . __( 'About WooCommerce', 'woocommerce' ) . '</a></p>' .
|
||||
'<p><a href="https://woocommerce.com/?utm_source=helptab&utm_medium=product&utm_content=about&utm_campaign=woocommerceplugin" target="_blank">' . __( 'About WooCommerce', 'woocommerce' ) . '</a></p>' .
|
||||
'<p><a href="https://wordpress.org/plugins/woocommerce/" target="_blank">' . __( 'WordPress.org project', 'woocommerce' ) . '</a></p>' .
|
||||
'<p><a href="https://github.com/woocommerce/woocommerce/" target="_blank">' . __( 'GitHub project', 'woocommerce' ) . '</a></p>' .
|
||||
'<p><a href="https://woo.com/product-category/themes/?utm_source=helptab&utm_medium=product&utm_content=wcthemes&utm_campaign=woocommerceplugin" target="_blank">' . __( 'Official themes', 'woocommerce' ) . '</a></p>' .
|
||||
'<p><a href="https://woo.com/product-category/woocommerce-extensions/?utm_source=helptab&utm_medium=product&utm_content=wcextensions&utm_campaign=woocommerceplugin" target="_blank">' . __( 'Official extensions', 'woocommerce' ) . '</a></p>'
|
||||
'<p><a href="https://woocommerce.com/product-category/themes/?utm_source=helptab&utm_medium=product&utm_content=wcthemes&utm_campaign=woocommerceplugin" target="_blank">' . __( 'Official themes', 'woocommerce' ) . '</a></p>' .
|
||||
'<p><a href="https://woocommerce.com/product-category/woocommerce-extensions/?utm_source=helptab&utm_medium=product&utm_content=wcextensions&utm_campaign=woocommerceplugin" target="_blank">' . __( 'Official extensions', 'woocommerce' ) . '</a></p>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
*/
|
||||
class WC_Admin_Marketplace_Promotions {
|
||||
|
||||
const TRANSIENT_NAME = 'woocommerce_marketplace_promotions';
|
||||
const SCHEDULED_ACTION_HOOK = 'woocommerce_marketplace_fetch_promotions';
|
||||
const TRANSIENT_NAME = 'woocommerce_marketplace_promotions';
|
||||
const SCHEDULED_ACTION_HOOK = 'woocommerce_marketplace_fetch_promotions';
|
||||
const PROMOTIONS_API_URL = 'https://woocommerce.com/wp-json/wccom-extensions/3.0/promotions';
|
||||
const SCHEDULED_ACTION_INTERVAL = 12 * HOUR_IN_SECONDS;
|
||||
|
||||
/**
|
||||
* The user's locale, for example en_US.
|
||||
*
|
||||
@@ -26,69 +29,74 @@ class WC_Admin_Marketplace_Promotions {
|
||||
|
||||
/**
|
||||
* On all admin pages, schedule an action to fetch promotions data.
|
||||
* Add menu badge to WooCommerce Extensions item if the promotions
|
||||
* API requests one.
|
||||
* Shows notice and adds menu badge to WooCommerce Extensions item
|
||||
* if the promotions API requests them.
|
||||
*
|
||||
* WC_Admin calls this method when it is instantiated during
|
||||
* is_admin requests.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init_marketplace_promotions() {
|
||||
public static function init() {
|
||||
/**
|
||||
* Filter to suppress the requests for and showing of marketplace promotions.
|
||||
*
|
||||
* @since 8.8
|
||||
*/
|
||||
if ( apply_filters( 'woocommerce_marketplace_suppress_promotions', false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
register_deactivation_hook( WC_PLUGIN_FILE, array( __CLASS__, 'clear_scheduled_event' ) );
|
||||
|
||||
// Add the callback for our scheduled action.
|
||||
if ( ! has_action( self::SCHEDULED_ACTION_HOOK, array( __CLASS__, 'fetch_marketplace_promotions' ) ) ) {
|
||||
add_action( self::SCHEDULED_ACTION_HOOK, array( __CLASS__, 'fetch_marketplace_promotions' ) );
|
||||
}
|
||||
|
||||
if ( self::is_admin_page() ) {
|
||||
// Schedule the action twice a day, starting now.
|
||||
if ( false === wp_next_scheduled( self::SCHEDULED_ACTION_HOOK ) ) {
|
||||
wp_schedule_event( time(), 'twicedaily', self::SCHEDULED_ACTION_HOOK );
|
||||
}
|
||||
|
||||
self::$locale = ( self::$locale ?? get_user_locale() ) ?? 'en_US';
|
||||
self::maybe_show_bubble_promotions();
|
||||
if ( is_admin() ) {
|
||||
add_action( 'init', array( __CLASS__, 'schedule_promotion_fetch' ), 12 );
|
||||
}
|
||||
|
||||
register_deactivation_hook( WC_PLUGIN_FILE, array( __CLASS__, 'clear_scheduled_event' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the request is for an admin page, and not ajax.
|
||||
* We may want to add a menu bubble to WooCommerce Extensions
|
||||
* on any admin page, as the user may view the WooCommerce flyout
|
||||
* menu.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function is_admin_page(): bool {
|
||||
if (
|
||||
( defined( 'DOING_AJAX' ) && DOING_AJAX )
|
||||
|| ! is_admin()
|
||||
defined( 'DOING_AJAX' ) && DOING_AJAX
|
||||
|| defined( 'DOING_CRON' ) && DOING_CRON
|
||||
|| defined( 'WP_CLI' ) && WP_CLI
|
||||
) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
self::$locale = ( self::$locale ?? get_user_locale() ) ?? 'en_US';
|
||||
self::maybe_show_bubble_promotions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get promotions to show in the Woo in-app marketplace.
|
||||
* Only run on selected pages in the main WooCommerce menu in wp-admin.
|
||||
* Loads promotions in transient with one day life.
|
||||
* Schedule the action to fetch promotions data.
|
||||
*/
|
||||
public static function schedule_promotion_fetch() {
|
||||
// Schedule the action twice a day using Action Scheduler.
|
||||
if (
|
||||
function_exists( 'as_has_scheduled_action' )
|
||||
&& function_exists( 'as_schedule_recurring_action' )
|
||||
&& false === as_has_scheduled_action( self::SCHEDULED_ACTION_HOOK )
|
||||
) {
|
||||
as_schedule_recurring_action( time(), self::SCHEDULED_ACTION_INTERVAL, self::SCHEDULED_ACTION_HOOK );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get promotions to show in the Woo in-app marketplace and load them into a transient
|
||||
* with a 12-hour life. Run as a recurring scheduled action.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function fetch_marketplace_promotions() {
|
||||
$url = 'https://woo.com/wp-json/wccom-extensions/3.0/promotions';
|
||||
$promotions = get_transient( self::TRANSIENT_NAME );
|
||||
|
||||
if ( false !== $promotions ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch promotions from the API.
|
||||
$fetch_options = array(
|
||||
'auth' => true,
|
||||
'country' => true,
|
||||
);
|
||||
$raw_promotions = WC_Admin_Addons::fetch( $url, $fetch_options );
|
||||
$raw_promotions = WC_Admin_Addons::fetch( self::PROMOTIONS_API_URL, $fetch_options );
|
||||
|
||||
// phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
if ( is_wp_error( $raw_promotions ) ) {
|
||||
@@ -111,21 +119,21 @@ class WC_Admin_Marketplace_Promotions {
|
||||
}
|
||||
|
||||
$promotions = json_decode( wp_remote_retrieve_body( $raw_promotions ), true );
|
||||
if ( empty( $promotions ) || ! is_array( $promotions ) ) {
|
||||
if ( ! is_array( $promotions ) ) {
|
||||
$promotions = array();
|
||||
|
||||
/**
|
||||
* Allows connection error to be handled.
|
||||
*
|
||||
* @since 8.7
|
||||
*/
|
||||
do_action( 'woocommerce_page_wc-addons_connection_error', 'Empty or malformed response' );
|
||||
do_action( 'woocommerce_page_wc-addons_connection_error', 'Malformed response' );
|
||||
}
|
||||
// phpcs:enable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
|
||||
if ( $promotions ) {
|
||||
// Filter out any expired promotions.
|
||||
$promotions = self::get_active_promotions( $promotions );
|
||||
set_transient( self::TRANSIENT_NAME, $promotions, DAY_IN_SECONDS );
|
||||
}
|
||||
// Filter out any expired promotions.
|
||||
$active_promotions = self::get_active_promotions( $promotions );
|
||||
set_transient( self::TRANSIENT_NAME, $active_promotions, 12 * HOUR_IN_SECONDS );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,11 +250,11 @@ class WC_Admin_Marketplace_Promotions {
|
||||
* Adds a bubble to the menu item.
|
||||
*
|
||||
* @param array $menu_items Arrays representing items in nav menu.
|
||||
* @param ?array $promotion Data about a promotion from the Woo.com API.
|
||||
* @param ?array $promotion Data about a promotion from the WooCommerce.com API.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function filter_marketplace_menu_items( $menu_items, $promotion = array() ) {
|
||||
public static function filter_marketplace_menu_items( $menu_items, $promotion = array() ): array {
|
||||
if ( ! isset( $promotion['menu_item_id'] ) || ! isset( $promotion['content'] ) ) {
|
||||
return $menu_items;
|
||||
}
|
||||
@@ -256,7 +264,7 @@ class WC_Admin_Marketplace_Promotions {
|
||||
&& $promotion['menu_item_id'] === $menu_item['id']
|
||||
) {
|
||||
$bubble_text = $promotion['content'][ self::$locale ] ?? ( $promotion['content']['en_US'] ?? __( 'Sale', 'woocommerce' ) );
|
||||
$menu_items[ $index ]['title'] = $menu_item['title'] . self::append_bubble( $bubble_text );
|
||||
$menu_items[ $index ]['title'] = self::append_bubble( $menu_item['title'], $bubble_text );
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -268,12 +276,19 @@ class WC_Admin_Marketplace_Promotions {
|
||||
/**
|
||||
* Return the markup for a menu item bubble with a given text.
|
||||
*
|
||||
* @param string $bubble_text Text of bubble.
|
||||
* @param string $menu_item_text Text of menu item we want to change.
|
||||
* @param string $bubble_text Text of bubble.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function append_bubble( $bubble_text ) {
|
||||
return ' <span class="awaiting-mod update-plugins remaining-tasks-badge woocommerce-task-list-remaining-tasks-badge">' . esc_html( $bubble_text ) . '</span>';
|
||||
private static function append_bubble( string $menu_item_text, string $bubble_text ): string {
|
||||
// Strip out update count bubble added by Marketplace::get_marketplace_update_count_html.
|
||||
$menu_item_text = preg_replace( '|<span class="update-plugins count-[\d]+">[A-z0-9 <>="-]+</span>|', '', $menu_item_text );
|
||||
|
||||
return $menu_item_text
|
||||
. '<span class="awaiting-mod update-plugins remaining-tasks-badge woocommerce-task-list-remaining-tasks-badge">'
|
||||
. esc_html( $bubble_text )
|
||||
. '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,7 +297,13 @@ class WC_Admin_Marketplace_Promotions {
|
||||
* @return void
|
||||
*/
|
||||
public static function clear_scheduled_event() {
|
||||
$timestamp = wp_next_scheduled( self::SCHEDULED_ACTION_HOOK );
|
||||
wp_unschedule_event( $timestamp, self::SCHEDULED_ACTION_HOOK );
|
||||
if ( function_exists( 'as_unschedule_all_actions' ) ) {
|
||||
as_unschedule_all_actions( self::SCHEDULED_ACTION_HOOK );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch list of promotions from WooCommerce.com for WooCommerce admin UI.
|
||||
if ( ! has_action( 'init', array( 'WC_Admin_Marketplace_Promotions', 'init' ) ) ) {
|
||||
add_action( 'init', array( 'WC_Admin_Marketplace_Promotions', 'init' ), 11 );
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use Automattic\Jetpack\Constants;
|
||||
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
|
||||
use Automattic\WooCommerce\Internal\Utilities\Users;
|
||||
use Automattic\WooCommerce\Internal\Utilities\WebhookUtil;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
@@ -21,7 +22,10 @@ class WC_Admin_Notices {
|
||||
use AccessiblePrivateMethods;
|
||||
|
||||
/**
|
||||
* Stores notices.
|
||||
* Local notices cache.
|
||||
*
|
||||
* DON'T manipulate this field directly!
|
||||
* Always use get_notices and set_notices instead.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@@ -48,10 +52,18 @@ class WC_Admin_Notices {
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Stores a flag indicating if the code is running in a multisite setup.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static bool $is_multisite;
|
||||
|
||||
/**
|
||||
* Initializes the class.
|
||||
*/
|
||||
public static function init() {
|
||||
self::$notices = get_option( 'woocommerce_admin_notices', array() );
|
||||
self::$is_multisite = is_multisite();
|
||||
self::set_notices( get_option( 'woocommerce_admin_notices', array() ) );
|
||||
|
||||
add_action( 'switch_theme', array( __CLASS__, 'reset_admin_notices' ) );
|
||||
add_action( 'woocommerce_installed', array( __CLASS__, 'reset_admin_notices' ) );
|
||||
@@ -85,26 +97,50 @@ class WC_Admin_Notices {
|
||||
}
|
||||
|
||||
/**
|
||||
* Store notices to DB
|
||||
* Store the locally cached notices to DB.
|
||||
*/
|
||||
public static function store_notices() {
|
||||
update_option( 'woocommerce_admin_notices', self::get_notices() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notices
|
||||
* Get the value of the locally cached notices array for the current site.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_notices() {
|
||||
return self::$notices;
|
||||
if ( ! self::$is_multisite ) {
|
||||
return self::$notices;
|
||||
}
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
$notices = self::$notices[ $blog_id ] ?? null;
|
||||
if ( ! is_null( $notices ) ) {
|
||||
return $notices;
|
||||
}
|
||||
|
||||
self::$notices[ $blog_id ] = get_option( 'woocommerce_admin_notices', array() );
|
||||
return self::$notices[ $blog_id ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all notices.
|
||||
* Set the locally cached notices array for the current site.
|
||||
*
|
||||
* @param array $notices New value for the locally cached notices array.
|
||||
*/
|
||||
private static function set_notices( array $notices ) {
|
||||
if ( self::$is_multisite ) {
|
||||
self::$notices[ get_current_blog_id() ] = $notices;
|
||||
} else {
|
||||
self::$notices = $notices;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all notices from the locally cached notices array.
|
||||
*/
|
||||
public static function remove_all_notices() {
|
||||
self::$notices = array();
|
||||
self::set_notices( array() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +186,7 @@ class WC_Admin_Notices {
|
||||
wpautop( __( 'The WooCommerce Legacy REST API, <a href="%1$s">currently enabled in this site</a>, will be removed in WooCommerce 9.0. <a target="_blank" href="%2$s">A separate WooCommerce extension is available</a> to keep it enabled. <b><a target="_blank" href="%3$s">Learn more about this change.</a></b>', 'woocommerce' ) ),
|
||||
admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=legacy_api' ),
|
||||
'https://wordpress.org/plugins/woocommerce-legacy-rest-api/',
|
||||
'https://developer.woo.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
|
||||
'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -170,7 +206,7 @@ class WC_Admin_Notices {
|
||||
wpautop( __( 'The WooCommerce Legacy REST API will be removed in WooCommerce 9.0, and this will cause <a href="%1$s">webhooks on this site that are configured to use the Legacy REST API</a> to stop working. <a target="_blank" href="%2$s">A separate WooCommerce extension is available</a> to allow these webhooks to keep using the Legacy REST API without interruption. You can also edit these webhooks to use the current REST API version to generate the payload instead. <b><a target="_blank" href="%3$s">Learn more about this change.</a></b>', 'woocommerce' ) ),
|
||||
admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=webhooks&legacy=true' ),
|
||||
'https://wordpress.org/plugins/woocommerce-legacy-rest-api/',
|
||||
'https://developer.woo.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
|
||||
'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -182,7 +218,7 @@ class WC_Admin_Notices {
|
||||
* or if the Legacy REST API extension is installed, and remove the notice about Legacy webhooks
|
||||
* if no such webhooks exist anymore or if the Legacy REST API extension is installed.
|
||||
*
|
||||
* TODO: Change this method in WooCommerce 9.0 so that the notice gets removed if the Legacy REST API extension is installed and active.
|
||||
* TODO: Change this method in WooCommerce 9.0 so that the notice get removed if the Legacy REST API extension is installed and active.
|
||||
*/
|
||||
private static function maybe_remove_legacy_api_removal_notice() {
|
||||
$plugin_is_active = is_plugin_active( 'woocommerce-legacy-rest-api/woocommerce-legacy-rest-api.php' );
|
||||
@@ -194,6 +230,11 @@ class WC_Admin_Notices {
|
||||
if ( self::has_notice( 'legacy_webhooks_unsupported_in_woo_90' ) && ( $plugin_is_active || 0 === wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count() ) ) {
|
||||
self::remove_notice( 'legacy_webhooks_unsupported_in_woo_90' );
|
||||
}
|
||||
|
||||
if ( self::has_notice( 'legacy_rest_api_is_incompatible_with_hpos' ) &&
|
||||
! ( 'yes' === get_option( 'woocommerce_api_enabled' ) && 'yes' === get_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION ) ) ) {
|
||||
self::remove_notice( 'legacy_rest_api_is_incompatible_with_hpos' );
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:enable Generic.Commenting.Todo.TaskFound
|
||||
@@ -205,7 +246,7 @@ class WC_Admin_Notices {
|
||||
* @param bool $force_save Force saving inside this method instead of at the 'shutdown'.
|
||||
*/
|
||||
public static function add_notice( $name, $force_save = false ) {
|
||||
self::$notices = array_unique( array_merge( self::get_notices(), array( $name ) ) );
|
||||
self::set_notices( array_unique( array_merge( self::get_notices(), array( $name ) ) ) );
|
||||
|
||||
if ( $force_save ) {
|
||||
// Adding early save to prevent more race conditions with notices.
|
||||
@@ -220,7 +261,7 @@ class WC_Admin_Notices {
|
||||
* @param bool $force_save Force saving inside this method instead of at the 'shutdown'.
|
||||
*/
|
||||
public static function remove_notice( $name, $force_save = false ) {
|
||||
self::$notices = array_diff( self::get_notices(), array( $name ) );
|
||||
self::set_notices( array_diff( self::get_notices(), array( $name ) ) );
|
||||
delete_option( 'woocommerce_admin_notice_' . $name );
|
||||
|
||||
if ( $force_save ) {
|
||||
@@ -229,6 +270,28 @@ class WC_Admin_Notices {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given set of notices.
|
||||
*
|
||||
* An array of notice names or a regular expression string can be passed, in the later case
|
||||
* all the notices whose name matches the regular expression will be removed.
|
||||
*
|
||||
* @param array|string $names_array_or_regex An array of notice names, or a string representing a regular expression.
|
||||
* @param bool $force_save Force saving inside this method instead of at the 'shutdown'.
|
||||
* @return void
|
||||
*/
|
||||
public static function remove_notices( $names_array_or_regex, $force_save = false ) {
|
||||
if ( ! is_array( $names_array_or_regex ) ) {
|
||||
$names_array_or_regex = array_filter( self::get_notices(), fn( $notice_name ) => 1 === preg_match( $names_array_or_regex, $notice_name ) );
|
||||
}
|
||||
self::set_notices( array_diff( self::get_notices(), $names_array_or_regex ) );
|
||||
|
||||
if ( $force_save ) {
|
||||
// Adding early save to prevent more race conditions with notices.
|
||||
self::store_notices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See if a notice is being shown.
|
||||
*
|
||||
@@ -244,12 +307,12 @@ class WC_Admin_Notices {
|
||||
* Hide a notice if the GET variable is set.
|
||||
*/
|
||||
public static function hide_notices() {
|
||||
if ( isset( $_GET['wc-hide-notice'] ) && isset( $_GET['_wc_notice_nonce'] ) ) { // WPCS: input var ok, CSRF ok.
|
||||
if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['_wc_notice_nonce'] ) ), 'woocommerce_hide_notices_nonce' ) ) { // WPCS: input var ok, CSRF ok.
|
||||
if ( isset( $_GET['wc-hide-notice'] ) && isset( $_GET['_wc_notice_nonce'] ) ) {
|
||||
if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['_wc_notice_nonce'] ) ), 'woocommerce_hide_notices_nonce' ) ) {
|
||||
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$notice_name = sanitize_text_field( wp_unslash( $_GET['wc-hide-notice'] ) ); // WPCS: input var ok, CSRF ok.
|
||||
$notice_name = sanitize_text_field( wp_unslash( $_GET['wc-hide-notice'] ) );
|
||||
|
||||
/**
|
||||
* Filter the capability required to dismiss a given notice.
|
||||
@@ -356,7 +419,7 @@ class WC_Admin_Notices {
|
||||
$notice_html = get_option( 'woocommerce_admin_notice_' . $notice );
|
||||
|
||||
if ( $notice_html ) {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-custom.php';
|
||||
include __DIR__ . '/views/html-notice-custom.php';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,13 +439,14 @@ class WC_Admin_Notices {
|
||||
if ( WC_Install::needs_db_update() ) {
|
||||
$next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' );
|
||||
|
||||
if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) { // WPCS: input var ok, CSRF ok.
|
||||
include dirname( __FILE__ ) . '/views/html-notice-updating.php';
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) {
|
||||
include __DIR__ . '/views/html-notice-updating.php';
|
||||
} else {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-update.php';
|
||||
include __DIR__ . '/views/html-notice-update.php';
|
||||
}
|
||||
} else {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-updated.php';
|
||||
include __DIR__ . '/views/html-notice-updated.php';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +491,7 @@ class WC_Admin_Notices {
|
||||
}
|
||||
|
||||
if ( $outdated ) {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-template-check.php';
|
||||
include __DIR__ . '/views/html-notice-template-check.php';
|
||||
} else {
|
||||
self::remove_notice( 'template_files' );
|
||||
}
|
||||
@@ -450,7 +514,7 @@ class WC_Admin_Notices {
|
||||
}
|
||||
|
||||
if ( $enabled ) {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-legacy-shipping.php';
|
||||
include __DIR__ . '/views/html-notice-legacy-shipping.php';
|
||||
} else {
|
||||
self::remove_notice( 'template_files' );
|
||||
}
|
||||
@@ -460,12 +524,13 @@ class WC_Admin_Notices {
|
||||
* No shipping methods.
|
||||
*/
|
||||
public static function no_shipping_methods_notice() {
|
||||
if ( wc_shipping_enabled() && ( empty( $_GET['page'] ) || empty( $_GET['tab'] ) || 'wc-settings' !== $_GET['page'] || 'shipping' !== $_GET['tab'] ) ) { // WPCS: input var ok, CSRF ok.
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
if ( wc_shipping_enabled() && ( empty( $_GET['page'] ) || empty( $_GET['tab'] ) || 'wc-settings' !== $_GET['page'] || 'shipping' !== $_GET['tab'] ) ) {
|
||||
$product_count = wp_count_posts( 'product' );
|
||||
$method_count = wc_get_shipping_method_count();
|
||||
|
||||
if ( $product_count->publish > 0 && 0 === $method_count ) {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-no-shipping-methods.php';
|
||||
include __DIR__ . '/views/html-notice-no-shipping-methods.php';
|
||||
}
|
||||
|
||||
if ( $method_count > 0 ) {
|
||||
@@ -478,7 +543,7 @@ class WC_Admin_Notices {
|
||||
* Notice shown when regenerating thumbnails background process is running.
|
||||
*/
|
||||
public static function regenerating_thumbnails_notice() {
|
||||
include dirname( __FILE__ ) . '/views/html-notice-regenerating-thumbnails.php';
|
||||
include __DIR__ . '/views/html-notice-regenerating-thumbnails.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,7 +554,7 @@ class WC_Admin_Notices {
|
||||
return;
|
||||
}
|
||||
|
||||
include dirname( __FILE__ ) . '/views/html-notice-secure-connection.php';
|
||||
include __DIR__ . '/views/html-notice-secure-connection.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -504,7 +569,7 @@ class WC_Admin_Notices {
|
||||
return;
|
||||
}
|
||||
|
||||
include dirname( __FILE__ ) . '/views/html-notice-regenerating-lookup-table.php';
|
||||
include __DIR__ . '/views/html-notice-regenerating-lookup-table.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -591,7 +656,7 @@ class WC_Admin_Notices {
|
||||
return;
|
||||
}
|
||||
|
||||
include dirname( __FILE__ ) . '/views/html-notice-maxmind-license-key.php';
|
||||
include __DIR__ . '/views/html-notice-maxmind-license-key.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -605,7 +670,7 @@ class WC_Admin_Notices {
|
||||
return;
|
||||
}
|
||||
|
||||
include dirname( __FILE__ ) . '/views/html-notice-redirect-only-download.php';
|
||||
include __DIR__ . '/views/html-notice-redirect-only-download.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -619,7 +684,7 @@ class WC_Admin_Notices {
|
||||
return;
|
||||
}
|
||||
|
||||
include dirname( __FILE__ ) . '/views/html-notice-uploads-directory-is-unprotected.php';
|
||||
include __DIR__ . '/views/html-notice-uploads-directory-is-unprotected.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -634,7 +699,7 @@ class WC_Admin_Notices {
|
||||
self::remove_notice( 'base_tables_missing' );
|
||||
}
|
||||
|
||||
include dirname( __FILE__ ) . '/views/html-notice-base-table-missing.php';
|
||||
include __DIR__ . '/views/html-notice-base-table-missing.php';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -782,7 +782,7 @@ class WC_Admin_Post_Types {
|
||||
if ( $post && absint( $post->ID ) === $shop_page_id ) {
|
||||
echo '<div class="notice notice-info">';
|
||||
/* translators: %s: URL to read more about the shop page. */
|
||||
echo '<p>' . sprintf( wp_kses_post( __( 'This is the WooCommerce shop page. The shop page is a special archive that lists your products. <a href="%s">You can read more about this here</a>.', 'woocommerce' ) ), 'https://woo.com/document/woocommerce-pages/#section-4' ) . '</p>';
|
||||
echo '<p>' . sprintf( wp_kses_post( __( 'This is the WooCommerce shop page. The shop page is a special archive that lists your products. <a href="%s">You can read more about this here</a>.', 'woocommerce' ) ), 'https://woocommerce.com/document/woocommerce-pages/#section-4' ) . '</p>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-accounts.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-emails.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-integrations.php';
|
||||
if ( \Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'launch-your-store' ) ) {
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-site-visibility.php';
|
||||
}
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-advanced.php';
|
||||
|
||||
self::$settings = apply_filters( 'woocommerce_get_settings_pages', $settings );
|
||||
@@ -764,6 +767,15 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'slotfill_placeholder':
|
||||
?>
|
||||
<div
|
||||
id="<?php echo esc_attr( $value['id'] ); ?>"
|
||||
class="<?php echo esc_attr( $value['class'] ); ?>"
|
||||
>
|
||||
</div>
|
||||
<?php
|
||||
break;
|
||||
// Default: run an action.
|
||||
default:
|
||||
do_action( 'woocommerce_admin_field_' . $value['type'], $value );
|
||||
|
||||
@@ -350,7 +350,7 @@ class WC_Admin_Setup_Wizard {
|
||||
<?php do_action( 'admin_head' ); ?>
|
||||
</head>
|
||||
<body class="wc-setup wp-core-ui <?php echo esc_attr( 'wc-setup-step__' . $this->step ); ?> <?php echo esc_attr( $wp_version_class ); ?>">
|
||||
<h1 class="wc-logo"><a href="https://woo.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
|
||||
<h1 class="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
|
||||
<?php
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ class WC_Admin_Setup_Wizard {
|
||||
?>
|
||||
<div class="wc-setup-step__new_onboarding-wrapper">
|
||||
<p class="wc-setup-step__new_onboarding-welcome"><?php esc_html_e( 'Welcome to', 'woocommerce' ); ?></p>
|
||||
<h1 class="wc-logo"><a href="https://woo.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
|
||||
<h1 class="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
|
||||
<p><?php esc_html_e( 'Get your store up and running more quickly with our new and improved setup experience', 'woocommerce' ); ?></p>
|
||||
|
||||
<form method="post" class="activate-new-onboarding">
|
||||
@@ -630,7 +630,7 @@ class WC_Admin_Setup_Wizard {
|
||||
),
|
||||
)
|
||||
),
|
||||
'https://woo.com/usage-tracking/'
|
||||
'https://woocommerce.com/usage-tracking/'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
@@ -1114,7 +1114,7 @@ class WC_Admin_Setup_Wizard {
|
||||
)
|
||||
),
|
||||
esc_attr__( 'A live rate is the exact cost to ship an order, quoted directly from the shipping carrier.', 'woocommerce' ),
|
||||
'https://woo.com/product-category/woocommerce-extensions/shipping-methods/shipping-carriers/'
|
||||
'https://woocommerce.com/product-category/woocommerce-extensions/shipping-methods/shipping-carriers/'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
@@ -1377,27 +1377,27 @@ class WC_Admin_Setup_Wizard {
|
||||
$stripe_description = '<p>' . sprintf(
|
||||
/* translators: %s: URL */
|
||||
__( 'Accept debit and credit cards in 135+ currencies, methods such as Alipay, and one-touch checkout with Apple Pay. <a href="%s" target="_blank">Learn more</a>.', 'woocommerce' ),
|
||||
'https://woo.com/products/stripe/'
|
||||
'https://woocommerce.com/products/stripe/'
|
||||
) . '</p>';
|
||||
$paypal_checkout_description = '<p>' . sprintf(
|
||||
/* translators: %s: URL */
|
||||
__( 'Safe and secure payments using credit cards or your customer\'s PayPal account. <a href="%s" target="_blank">Learn more</a>.', 'woocommerce' ),
|
||||
'https://woo.com/products/woocommerce-gateway-paypal-checkout/'
|
||||
'https://woocommerce.com/products/woocommerce-gateway-paypal-checkout/'
|
||||
) . '</p>';
|
||||
$klarna_checkout_description = '<p>' . sprintf(
|
||||
/* translators: %s: URL */
|
||||
__( 'Full checkout experience with pay now, pay later and slice it. No credit card numbers, no passwords, no worries. <a href="%s" target="_blank">Learn more about Klarna</a>.', 'woocommerce' ),
|
||||
'https://woo.com/products/klarna-checkout/'
|
||||
'https://woocommerce.com/products/klarna-checkout/'
|
||||
) . '</p>';
|
||||
$klarna_payments_description = '<p>' . sprintf(
|
||||
/* translators: %s: URL */
|
||||
__( 'Choose the payment that you want, pay now, pay later or slice it. No credit card numbers, no passwords, no worries. <a href="%s" target="_blank">Learn more about Klarna</a>.', 'woocommerce' ),
|
||||
'https://woo.com/products/klarna-payments/ '
|
||||
'https://woocommerce.com/products/klarna-payments/ '
|
||||
) . '</p>';
|
||||
$square_description = '<p>' . sprintf(
|
||||
/* translators: %s: URL */
|
||||
__( 'Securely accept credit and debit cards with one low rate, no surprise fees (custom rates available). Sell online and in store and track sales and inventory in one place. <a href="%s" target="_blank">Learn more about Square</a>.', 'woocommerce' ),
|
||||
'https://woo.com/products/square/'
|
||||
'https://woocommerce.com/products/square/'
|
||||
) . '</p>';
|
||||
|
||||
return array(
|
||||
@@ -1893,7 +1893,7 @@ class WC_Admin_Setup_Wizard {
|
||||
'description' => sprintf(
|
||||
/* translators: %s: theme name. */
|
||||
__(
|
||||
'Design your store with deep WooCommerce integration. If toggled on, we’ll install <a href="https://woo.com/storefront/" target="_blank" rel="noopener noreferrer">Storefront</a>, and your current theme <em>%s</em> will be deactivated.',
|
||||
'Design your store with deep WooCommerce integration. If toggled on, we’ll install <a href="https://woocommerce.com/storefront/" target="_blank" rel="noopener noreferrer">Storefront</a>, and your current theme <em>%s</em> will be deactivated.',
|
||||
'woocommerce'
|
||||
),
|
||||
$theme_name
|
||||
@@ -2221,10 +2221,10 @@ class WC_Admin_Setup_Wizard {
|
||||
WC_Admin_Notices::remove_notice( 'install', true );
|
||||
|
||||
$user_email = $this->get_current_user_email();
|
||||
$docs_url = 'https://woo.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin';
|
||||
$docs_url = 'https://woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin';
|
||||
$help_text = sprintf(
|
||||
/* translators: %1$s: link to docs */
|
||||
__( 'Visit Woo.com to learn more about <a href="%1$s" target="_blank">getting started</a>.', 'woocommerce' ),
|
||||
__( 'Visit WooCommerce.com to learn more about <a href="%1$s" target="_blank">getting started</a>.', 'woocommerce' ),
|
||||
$docs_url
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -39,9 +39,6 @@ class WC_Admin {
|
||||
if ( isset( $_GET['page'] ) && 'wc-addons' === $_GET['page'] ) {
|
||||
add_filter( 'admin_body_class', array( 'WC_Admin_Addons', 'filter_admin_body_classes' ) );
|
||||
}
|
||||
|
||||
// Fetch list of promotions from Woo.com for WooCommerce admin UI. We need to fire earlier than admin_init so we can filter menu items.
|
||||
add_action( 'woocommerce_init', array( 'WC_Admin_Marketplace_Promotions', 'init_marketplace_promotions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,9 +77,6 @@ class WC_Admin {
|
||||
// Marketplace suggestions & related REST API.
|
||||
include_once __DIR__ . '/marketplace-suggestions/class-wc-marketplace-suggestions.php';
|
||||
include_once __DIR__ . '/marketplace-suggestions/class-wc-marketplace-updater.php';
|
||||
|
||||
// Marketplace promotions.
|
||||
include_once __DIR__ . '/class-wc-admin-marketplace-promotions.php';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Internal\Admin\Marketplace;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
@@ -14,7 +16,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
*
|
||||
* The main entry-point for all things related to the Helper.
|
||||
* The Helper manages the connection between the store and
|
||||
* an account on Woo.com.
|
||||
* an account on WooCommerce.com.
|
||||
*/
|
||||
class WC_Helper_Admin {
|
||||
|
||||
@@ -48,21 +50,29 @@ class WC_Helper_Admin {
|
||||
$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,
|
||||
'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 Woo.com.
|
||||
* 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
|
||||
@@ -116,7 +126,7 @@ class WC_Helper_Admin {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch featured products from Woo.com and serve them
|
||||
* Fetch featured products from WooCommerce.com and serve them
|
||||
* as JSON.
|
||||
*/
|
||||
public static function get_featured() {
|
||||
|
||||
@@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
/**
|
||||
* WC_Helper_API Class
|
||||
*
|
||||
* Provides a communication interface with the Woo.com Helper API.
|
||||
* Provides a communication interface with the WooCommerce.com Helper API.
|
||||
*/
|
||||
class WC_Helper_API {
|
||||
/**
|
||||
@@ -67,6 +67,61 @@ class WC_Helper_API {
|
||||
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.
|
||||
*
|
||||
@@ -81,24 +136,13 @@ class WC_Helper_API {
|
||||
return false;
|
||||
}
|
||||
|
||||
$request_uri = parse_url( $url, PHP_URL_PATH );
|
||||
$query_string = parse_url( $url, PHP_URL_QUERY );
|
||||
|
||||
if ( is_string( $query_string ) ) {
|
||||
$request_uri .= '?' . $query_string;
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'host' => parse_url( $url, PHP_URL_HOST ),
|
||||
'request_uri' => $request_uri,
|
||||
'method' => ! empty( $args['method'] ) ? $args['method'] : 'GET',
|
||||
$signature = self::create_request_signature(
|
||||
(string) $auth['access_token_secret'],
|
||||
$url,
|
||||
! empty( $args['method'] ) ? $args['method'] : 'GET',
|
||||
$args['body'] ?? null
|
||||
);
|
||||
|
||||
if ( ! empty( $args['body'] ) ) {
|
||||
$data['body'] = $args['body'];
|
||||
}
|
||||
|
||||
$signature = hash_hmac( 'sha256', json_encode( $data ), $auth['access_token_secret'] );
|
||||
if ( empty( $args['headers'] ) ) {
|
||||
$args['headers'] = array();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
/**
|
||||
* WC_Helper_Orders_API
|
||||
*
|
||||
* Pings Woo.com to create an order and pull in the necessary data to start the installation process.
|
||||
* Pings WooCommerce.com to create an order and pull in the necessary data to start the installation process.
|
||||
*/
|
||||
class WC_Helper_Orders_API {
|
||||
/**
|
||||
@@ -59,7 +59,7 @@ class WC_Helper_Orders_API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Core function to create an order on Woo.com. Pings the API and catches the exceptions if any.
|
||||
* 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.
|
||||
*
|
||||
|
||||
@@ -300,7 +300,10 @@ class WC_Helper_Subscriptions_API {
|
||||
);
|
||||
}
|
||||
|
||||
$install_url = WC_Helper::get_subscription_install_url( $subscription['product_key'] );
|
||||
$install_url = WC_Helper::get_subscription_install_url(
|
||||
$subscription['product_key'],
|
||||
$subscription['product_slug']
|
||||
);
|
||||
|
||||
if ( ! $install_url ) {
|
||||
wp_send_json_error(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* The update helper for Woo.com plugins.
|
||||
* The update helper for WooCommerce.com plugins.
|
||||
*
|
||||
* @class WC_Helper_Updater
|
||||
* @package WooCommerce\Admin\Helper
|
||||
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
* WC_Helper_Updater Class
|
||||
*
|
||||
* Contains the logic to fetch available updates and hook into Core's update
|
||||
* routines to serve Woo.com-provided packages.
|
||||
* routines to serve WooCommerce.com-provided packages.
|
||||
*/
|
||||
class WC_Helper_Updater {
|
||||
|
||||
@@ -26,6 +26,16 @@ class WC_Helper_Updater {
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,21 +63,25 @@ class WC_Helper_Updater {
|
||||
'plugin' => $filename,
|
||||
'new_version' => $data['version'],
|
||||
'url' => $data['url'],
|
||||
'package' => $data['package'],
|
||||
'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'];
|
||||
}
|
||||
|
||||
// We don't want to deliver a valid upgrade package when their subscription has expired.
|
||||
// To avoid the generic "no_package" error that empty strings give, we will store an
|
||||
// indication of expiration for the `upgrader_pre_download` filter to error on.
|
||||
if ( ! self::_has_active_subscription( $plugin['_product_id'] ) ) {
|
||||
$item['package'] = 'woocommerce-com-expired-' . $plugin['_product_id'];
|
||||
}
|
||||
|
||||
if ( $transient instanceof stdClass ) {
|
||||
if ( version_compare( $plugin['Version'], $data['version'], '<' ) ) {
|
||||
$transient->response[ $filename ] = (object) $item;
|
||||
@@ -89,7 +103,7 @@ class WC_Helper_Updater {
|
||||
|
||||
/**
|
||||
* Runs on pre_set_site_transient_update_themes, provides custom
|
||||
* packages for Woo.com-hosted extensions.
|
||||
* packages for WooCommerce.com-hosted extensions.
|
||||
*
|
||||
* @param object $transient The update_themes transient object.
|
||||
*
|
||||
@@ -113,9 +127,16 @@ class WC_Helper_Updater {
|
||||
'package' => '',
|
||||
);
|
||||
|
||||
if ( self::_has_active_subscription( $theme['_product_id'] ) ) {
|
||||
$item['package'] = $data['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;
|
||||
@@ -128,6 +149,88 @@ class WC_Helper_Updater {
|
||||
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.
|
||||
*
|
||||
@@ -236,15 +339,20 @@ class WC_Helper_Updater {
|
||||
}
|
||||
|
||||
// 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() ) );
|
||||
$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 ) {
|
||||
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 );
|
||||
}
|
||||
);
|
||||
@@ -267,16 +375,16 @@ class WC_Helper_Updater {
|
||||
);
|
||||
|
||||
foreach ( $active_for_translations as $active_plugin ) {
|
||||
$plugin = $plugins[ $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' => json_encode( $request_body ),
|
||||
'headers' => array( 'Content-Type: application/json' ),
|
||||
'timeout' => $timeout,
|
||||
'body' => wp_json_encode( $request_body ),
|
||||
'headers' => array( 'Content-Type: application/json' ),
|
||||
'timeout' => $timeout,
|
||||
)
|
||||
);
|
||||
|
||||
@@ -349,13 +457,22 @@ class WC_Helper_Updater {
|
||||
'errors' => array(),
|
||||
);
|
||||
|
||||
$request = WC_Helper_API::post(
|
||||
'update-check',
|
||||
array(
|
||||
'body' => wp_json_encode( array( 'products' => $payload ) ),
|
||||
'authenticated' => true,
|
||||
)
|
||||
);
|
||||
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';
|
||||
@@ -367,44 +484,6 @@ class WC_Helper_Updater {
|
||||
return $data['products'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for an active subscription.
|
||||
*
|
||||
* Checks a given product id against all subscriptions on
|
||||
* the current site. Returns true if at least one active
|
||||
* subscription is found.
|
||||
*
|
||||
* @param int $product_id The product id to look for.
|
||||
*
|
||||
* @return bool True if active subscription found.
|
||||
*/
|
||||
private static function _has_active_subscription( $product_id ) {
|
||||
if ( ! isset( $auth ) ) {
|
||||
$auth = WC_Helper_Options::get( 'auth' );
|
||||
}
|
||||
|
||||
if ( ! isset( $subscriptions ) ) {
|
||||
$subscriptions = WC_Helper::get_subscriptions();
|
||||
}
|
||||
|
||||
if ( empty( $auth['site_id'] ) || empty( $subscriptions ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for an active subscription.
|
||||
foreach ( $subscriptions as $subscription ) {
|
||||
if ( $subscription['product_id'] != $product_id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( in_array( absint( $auth['site_id'] ), $subscription['connections'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of products that have updates.
|
||||
*
|
||||
@@ -441,7 +520,7 @@ class WC_Helper_Updater {
|
||||
}
|
||||
|
||||
if ( version_compare( $plugin['Version'], $update_data[ $plugin['_product_id'] ]['version'], '<' ) ) {
|
||||
$count++;
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,26 +531,81 @@ class WC_Helper_Updater {
|
||||
}
|
||||
|
||||
if ( version_compare( $theme['Version'], $update_data[ $theme['_product_id'] ]['version'], '<' ) ) {
|
||||
$count++;
|
||||
++$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();
|
||||
if ( ! $count ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
@@ -516,7 +650,7 @@ class WC_Helper_Updater {
|
||||
return new WP_Error(
|
||||
'woocommerce_subscription_expired',
|
||||
sprintf(
|
||||
// translators: %s: URL of Woo.com subscriptions tab.
|
||||
// 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' ) )
|
||||
)
|
||||
|
||||
@@ -54,14 +54,15 @@ class WC_Helper {
|
||||
* Include supporting helper classes.
|
||||
*/
|
||||
protected static function includes() {
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-options.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-api.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-updater.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-plugin-info.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-compat.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-admin.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-subscriptions-api.php';
|
||||
include_once dirname( __FILE__ ) . '/class-wc-helper-orders-api.php';
|
||||
include_once __DIR__ . '/class-wc-helper-options.php';
|
||||
include_once __DIR__ . '/class-wc-helper-api.php';
|
||||
include_once __DIR__ . '/class-wc-woo-update-manager-plugin.php';
|
||||
include_once __DIR__ . '/class-wc-helper-updater.php';
|
||||
include_once __DIR__ . '/class-wc-plugin-api-updater.php';
|
||||
include_once __DIR__ . '/class-wc-helper-compat.php';
|
||||
include_once __DIR__ . '/class-wc-helper-admin.php';
|
||||
include_once __DIR__ . '/class-wc-helper-subscriptions-api.php';
|
||||
include_once __DIR__ . '/class-wc-helper-orders-api.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,7 +170,7 @@ class WC_Helper {
|
||||
}
|
||||
|
||||
$subscription['download_primary'] = true;
|
||||
$subscription['download_url'] = 'https://woo.com/my-account/downloads/';
|
||||
$subscription['download_url'] = 'https://woocommerce.com/my-account/downloads/';
|
||||
if ( ! $subscription['local']['installed'] && ! empty( $updates[ $subscription['product_id'] ] ) ) {
|
||||
$subscription['download_url'] = $updates[ $subscription['product_id'] ]['package'];
|
||||
}
|
||||
@@ -225,7 +226,7 @@ class WC_Helper {
|
||||
'message' => sprintf( __( 'This subscription has expired. Please <strong>renew</strong> to receive updates and support.', 'woocommerce' ) ),
|
||||
'button_label' => __( 'Renew', 'woocommerce' ),
|
||||
'button_url' => self::add_utm_params_to_url_for_subscription_link(
|
||||
'https://woo.com/my-account/my-subscriptions/',
|
||||
'https://woocommerce.com/my-account/my-subscriptions/',
|
||||
'renew'
|
||||
),
|
||||
'status' => 'expired',
|
||||
@@ -240,7 +241,7 @@ class WC_Helper {
|
||||
'message' => __( 'Subscription is <strong>expiring</strong> soon.', 'woocommerce' ),
|
||||
'button_label' => __( 'Enable auto-renew', 'woocommerce' ),
|
||||
'button_url' => self::add_utm_params_to_url_for_subscription_link(
|
||||
'https://woo.com/my-account/my-subscriptions/',
|
||||
'https://woocommerce.com/my-account/my-subscriptions/',
|
||||
'auto-renew'
|
||||
),
|
||||
'status' => 'expired',
|
||||
@@ -254,7 +255,7 @@ class WC_Helper {
|
||||
'message' => sprintf( __( 'This subscription is expiring soon. Please <strong>renew</strong> to continue receiving updates and support.', 'woocommerce' ) ),
|
||||
'button_label' => __( 'Renew', 'woocommerce' ),
|
||||
'button_url' => self::add_utm_params_to_url_for_subscription_link(
|
||||
'https://woo.com/my-account/my-subscriptions/',
|
||||
'https://woocommerce.com/my-account/my-subscriptions/',
|
||||
'renew'
|
||||
),
|
||||
'status' => 'expired',
|
||||
@@ -316,7 +317,7 @@ class WC_Helper {
|
||||
} else {
|
||||
$action = array(
|
||||
/* translators: 1: subscriptions docs 2: subscriptions docs */
|
||||
'message' => sprintf( __( 'To receive updates and support for this extension, you need to <strong>purchase</strong> a new subscription or consolidate your extensions to one connected account by <strong><a href="%1$s" title="Sharing Docs">sharing</a> or <a href="%2$s" title="Transferring Docs">transferring</a></strong> this extension to this connected account.', 'woocommerce' ), 'https://woo.com/document/managing-woocommerce-com-subscriptions/#section-10', 'https://woo.com/document/managing-woocommerce-com-subscriptions/#section-5' ),
|
||||
'message' => sprintf( __( 'To receive updates and support for this extension, you need to <strong>purchase</strong> a new subscription or consolidate your extensions to one connected account by <strong><a href="%1$s" title="Sharing Docs">sharing</a> or <a href="%2$s" title="Transferring Docs">transferring</a></strong> this extension to this connected account.', 'woocommerce' ), 'https://woocommerce.com/document/managing-woocommerce-com-subscriptions/#section-10', 'https://woocommerce.com/document/managing-woocommerce-com-subscriptions/#section-5' ),
|
||||
'button_label' => __( 'Purchase', 'woocommerce' ),
|
||||
'button_url' => self::add_utm_params_to_url_for_subscription_link(
|
||||
$data['_product_url'],
|
||||
@@ -354,7 +355,7 @@ class WC_Helper {
|
||||
/**
|
||||
* Add tracking parameters to buttons (Renew, Purchase, etc.) on subscriptions page
|
||||
*
|
||||
* @param string $url URL to product page or to https://woo.com/my-account/my-subscriptions/.
|
||||
* @param string $url URL to product page or to https://woocommerce.com/my-account/my-subscriptions/.
|
||||
* @param string $utm_content value of utm_content query parameter used for tracking
|
||||
*
|
||||
* @return string URL including utm parameters for tracking
|
||||
@@ -615,14 +616,14 @@ class WC_Helper {
|
||||
|
||||
case 'helper-connected':
|
||||
$notices[] = array(
|
||||
'message' => __( 'You have successfully connected your store to Woo.com', 'woocommerce' ),
|
||||
'message' => __( 'You have successfully connected your store to WooCommerce.com', 'woocommerce' ),
|
||||
'type' => 'updated',
|
||||
);
|
||||
break;
|
||||
|
||||
case 'helper-disconnected':
|
||||
$notices[] = array(
|
||||
'message' => __( 'You have successfully disconnected your store from Woo.com', 'woocommerce' ),
|
||||
'message' => __( 'You have successfully disconnected your store from WooCommerce.com', 'woocommerce' ),
|
||||
'type' => 'updated',
|
||||
);
|
||||
break;
|
||||
@@ -832,6 +833,7 @@ class WC_Helper {
|
||||
)
|
||||
)
|
||||
: '',
|
||||
'wum-installed' => WC_Woo_Update_Manager_Plugin::is_plugin_installed() ? '1' : '0',
|
||||
),
|
||||
WC_Helper_API::url( 'oauth/authorize' )
|
||||
);
|
||||
@@ -841,7 +843,7 @@ class WC_Helper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return from Woo.com OAuth flow.
|
||||
* Return from WooCommerce.com OAuth flow.
|
||||
*/
|
||||
private static function _helper_auth_return() {
|
||||
if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'connect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
@@ -910,7 +912,7 @@ class WC_Helper {
|
||||
WC_Tracker::send_tracking_data( true );
|
||||
}
|
||||
|
||||
// If connecting through in-app purchase, redirects back to Woo.com
|
||||
// If connecting through in-app purchase, redirects back to WooCommerce.com
|
||||
// for product installation.
|
||||
if ( ! empty( $_GET['wccom-install-url'] ) ) {
|
||||
wp_redirect( wp_unslash( $_GET['wccom-install-url'] ) );
|
||||
@@ -930,7 +932,7 @@ class WC_Helper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from Woo.com, clear OAuth tokens.
|
||||
* Disconnect from WooCommerce.com, clear OAuth tokens.
|
||||
*/
|
||||
private static function _helper_auth_disconnect() {
|
||||
if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'disconnect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
@@ -1193,34 +1195,18 @@ class WC_Helper {
|
||||
* Get a subscriptions install URL.
|
||||
*
|
||||
* @param string $product_key Subscription product key.
|
||||
* @param string $product_slug Subscription product slug.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_subscription_install_url( $product_key ) {
|
||||
$install_url_response = WC_Helper_API::post(
|
||||
'install-url',
|
||||
public static function get_subscription_install_url( $product_key, $product_slug ) {
|
||||
$install_url = add_query_arg(
|
||||
array(
|
||||
'authenticated' => true,
|
||||
'body' => wp_json_encode(
|
||||
array(
|
||||
'product_key' => $product_key,
|
||||
'wc_version' => WC()->version,
|
||||
)
|
||||
),
|
||||
)
|
||||
'product-key' => rawurlencode( $product_key ),
|
||||
),
|
||||
self::get_install_base_url() . "{$product_slug}/"
|
||||
);
|
||||
|
||||
$code = wp_remote_retrieve_response_code( $install_url_response );
|
||||
if ( 200 !== $code ) {
|
||||
self::log( sprintf( 'Install URL API call returned a non-200 response code (%d)', $code ) );
|
||||
return '';
|
||||
}
|
||||
|
||||
$body = json_decode( wp_remote_retrieve_body( $install_url_response ), true );
|
||||
if ( empty( $body['data']['url'] ) ) {
|
||||
self::log( sprintf( 'Install URL API call returned an invalid body: %s', wp_remote_retrieve_body( $install_url_response ) ) );
|
||||
return '';
|
||||
}
|
||||
return $body['data']['url'];
|
||||
return WC_Helper_API::add_auth_parameters( $install_url );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1517,6 +1503,8 @@ class WC_Helper {
|
||||
$source = 'inbox-notes';
|
||||
elseif ( stripos( $request_uri, 'admin-ajax.php' ) ) :
|
||||
$source = 'heartbeat-api';
|
||||
elseif ( stripos( $request_uri, 'installer' ) ) :
|
||||
$source = 'wccom-site-installer';
|
||||
elseif ( defined( 'WP_CLI' ) && WP_CLI ) :
|
||||
$source = 'wc-cli';
|
||||
endif;
|
||||
@@ -2257,6 +2245,22 @@ class WC_Helper {
|
||||
self::_flush_subscriptions_cache();
|
||||
self::_flush_updates_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base URL for plugin auto installer.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_install_base_url() {
|
||||
/**
|
||||
* Filter the base URL used to install the Woo hosted plugins.
|
||||
*
|
||||
* @since 8.7.0
|
||||
*/
|
||||
$woo_com_base_url = apply_filters( 'woo_com_base_url', 'https://woocommerce.com/' );
|
||||
|
||||
return $woo_com_base_url . 'auto-install-init/';
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper::load();
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Helper Plugin Info
|
||||
* Updates the Product API response from WP.org.
|
||||
*
|
||||
* @class WC_Plugin_Api_Updater
|
||||
* @package WooCommerce\Admin\Helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WC_Helper_Plugin_Info Class
|
||||
*
|
||||
* Provides the "View Information" core modals with data for Woo.com
|
||||
* hosted extensions.
|
||||
* Class WC_Plugin_Api_Updater
|
||||
*/
|
||||
class WC_Helper_Plugin_Info {
|
||||
class WC_Plugin_Api_Updater {
|
||||
|
||||
/**
|
||||
* Loads the class, runs on init.
|
||||
@@ -38,7 +34,8 @@ class WC_Helper_Plugin_Info {
|
||||
if ( 'plugin_information' !== $action ) {
|
||||
return $response;
|
||||
}
|
||||
return self::maybe_override_products_api( $response, $action, $args );
|
||||
|
||||
return self::override_products_api_response( $response, $action, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +49,8 @@ class WC_Helper_Plugin_Info {
|
||||
if ( 'theme_information' !== $action ) {
|
||||
return $response;
|
||||
}
|
||||
return self::maybe_override_products_api( $response, $action, $args );
|
||||
|
||||
return self::override_products_api_response( $response, $action, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,12 +60,12 @@ class WC_Helper_Plugin_Info {
|
||||
* @param string $action The requested action.
|
||||
* @param object $args Arguments passed to the API.
|
||||
*/
|
||||
public static function maybe_override_products_api( $response, $action, $args ) {
|
||||
public static function override_products_api_response( $response, $action, $args ) {
|
||||
if ( empty( $args->slug ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Only for slugs that start with woo-
|
||||
// Only for slugs that start with woocommerce-com-.
|
||||
if ( 0 !== strpos( $args->slug, 'woocommerce-com-' ) ) {
|
||||
return $response;
|
||||
}
|
||||
@@ -105,4 +103,4 @@ class WC_Helper_Plugin_Info {
|
||||
}
|
||||
}
|
||||
|
||||
WC_Helper_Plugin_Info::load();
|
||||
WC_Plugin_Api_Updater::load();
|
||||
@@ -0,0 +1,130 @@
|
||||
<?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();
|
||||
@@ -21,9 +21,9 @@
|
||||
<?php
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: Introduction to list of Woo.com extensions the merchant has subscriptions for. */
|
||||
/* translators: Introduction to list of WooCommerce.com extensions the merchant has subscriptions for. */
|
||||
__(
|
||||
'Below is a list of extensions available on your Woo.com account. To receive extension updates please make sure the extension is installed, and its subscription activated and connected to your Woo.com account. Extensions can be activated from the <a href="%s">Plugins</a> screen.',
|
||||
'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(
|
||||
@@ -135,7 +135,7 @@
|
||||
</td>
|
||||
<td class="wp-list-table__ext-actions">
|
||||
<?php if ( ! $subscription['active'] && $subscription['maxed'] ) : ?>
|
||||
<a class="button" href="https://woo.com/my-account/my-subscriptions/" target="_blank"><?php esc_html_e( 'Upgrade', 'woocommerce' ); ?></a>
|
||||
<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'] ) : ?>
|
||||
@@ -190,7 +190,7 @@
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr>
|
||||
<td colspan="3"><em><?php esc_html_e( 'Could not find any subscriptions on your Woo.com account', 'woocommerce' ); ?></td>
|
||||
<td colspan="3"><em><?php esc_html_e( 'Could not find any subscriptions on your WooCommerce.com account', 'woocommerce' ); ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
@@ -198,7 +198,7 @@
|
||||
|
||||
<?php if ( ! empty( $no_subscriptions ) ) : ?>
|
||||
<h2><?php esc_html_e( 'Installed Extensions without a Subscription', 'woocommerce' ); ?></h2>
|
||||
<p>Below is a list of Woo.com products available on your site - but are either out-dated or do not have a valid subscription.</p>
|
||||
<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. */ ?>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin -> WooCommerce -> Extensions -> Woo.com Subscriptions main page.
|
||||
* Admin -> WooCommerce -> Extensions -> WooCommerce.com Subscriptions main page.
|
||||
*
|
||||
* @package WooCommerce\Views
|
||||
*/
|
||||
@@ -23,7 +23,7 @@ defined( 'ABSPATH' ) || exit();
|
||||
<?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 Woo.com purchases will be listed here.', 'woocommerce' ); ?></p>
|
||||
<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>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<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 Woo.com', 'woocommerce' ); ?> <span class="chevron dashicons dashicons-arrow-down-alt2"></span></p>
|
||||
<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://woo.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="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>
|
||||
|
||||
@@ -21,7 +21,7 @@ defined( 'ABSPATH' ) || exit(); ?>
|
||||
|
||||
<?php
|
||||
$count_html = WC_Helper_Updater::get_updates_count_html();
|
||||
/* translators: %s: Woo.com Subscriptions tab 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>
|
||||
|
||||
@@ -45,7 +45,7 @@ class WC_Admin_List_Table_Coupons extends WC_Admin_List_Table {
|
||||
echo '<div class="woocommerce-BlankState">';
|
||||
echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'Coupons are a great way to offer discounts and rewards to your customers. They will appear here once created.', 'woocommerce' ) . '</h2>';
|
||||
echo '<a class="woocommerce-BlankState-cta button-primary button" href="' . esc_url( admin_url( 'post-new.php?post_type=shop_coupon' ) ) . '">' . esc_html__( 'Create your first coupon', 'woocommerce' ) . '</a>';
|
||||
echo '<a class="woocommerce-BlankState-cta button" target="_blank" href="https://woo.com/document/coupon-management/?utm_source=blankslate&utm_medium=product&utm_content=couponsdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about coupons', 'woocommerce' ) . '</a>';
|
||||
echo '<a class="woocommerce-BlankState-cta button" target="_blank" href="https://woocommerce.com/document/coupon-management/?utm_source=blankslate&utm_medium=product&utm_content=couponsdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about coupons', 'woocommerce' ) . '</a>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
|
||||
add_filter( 'views_edit-product', array( $this, 'product_views' ) );
|
||||
add_filter( 'get_search_query', array( $this, 'search_label' ) );
|
||||
add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10, 2 );
|
||||
add_action( 'manage_product_posts_custom_column', array( $this, 'add_sample_product_badge' ), 9, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -658,4 +659,19 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
|
||||
return $pieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a sample product badge to the product list table.
|
||||
*
|
||||
* @param string $column_name Column name.
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @since 8.8.0
|
||||
*/
|
||||
public function add_sample_product_badge( $column_name, $post_id ) {
|
||||
$is_sample_product = 'product' === get_post_type( $post_id ) && get_post_meta( $post_id, '_headstart_post', true );
|
||||
|
||||
if ( $is_sample_product && 'name' === $column_name ) {
|
||||
echo '<span class="sample-product-badge" style="margin-right: 6px;border-radius: 4px; background: #F6F7F7; padding: 4px; color: #3C434A;font-size: 12px;font-style: normal;font-weight: 400;line-height: 16px; height: 24px;">' . esc_html__( 'Sample', 'woocommerce' ) . '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-footer' );
|
||||
?>
|
||||
<div class="marketplace-suggestions-metabox-nosuggestions-placeholder hidden">
|
||||
<img src="https://woo.com/wp-content/plugins/wccom-plugins/marketplace-suggestions/icons/get_more_options.svg" class="marketplace-suggestion-icon">
|
||||
<img src="https://woocommerce.com/wp-content/plugins/wccom-plugins/marketplace-suggestions/icons/get_more_options.svg" class="marketplace-suggestion-icon">
|
||||
<div class="marketplace-suggestion-placeholder-content">
|
||||
<h4><?php esc_html_e( 'Enhance your products', 'woocommerce' ); ?></h4>
|
||||
<p><?php esc_html_e( 'Extensions can add new functionality to your product pages that make your store stand out', 'woocommerce' ); ?></p>
|
||||
</div>
|
||||
<a href="https://woo.com/product-category/woocommerce-extensions/?utm_source=editproduct&utm_campaign=marketplacesuggestions&utm_medium=product" target="blank" class="button"><?php esc_html_e( 'Browse the Marketplace', 'woocommerce' ); ?></a><br />
|
||||
<a href="https://woocommerce.com/product-category/woocommerce-extensions/?utm_source=editproduct&utm_campaign=marketplacesuggestions&utm_medium=product" target="blank" class="button"><?php esc_html_e( 'Browse the Marketplace', 'woocommerce' ); ?></a><br />
|
||||
<a class="marketplace-suggestion-manage-link" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=woocommerce_com' ) ); ?>"><?php esc_html_e( 'Manage suggestions', 'woocommerce' ); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -104,7 +104,7 @@ class WC_Meta_Box_Coupon_Data {
|
||||
'id' => 'free_shipping',
|
||||
'label' => __( 'Allow free shipping', 'woocommerce' ),
|
||||
// translators: %s: URL to free shipping document.
|
||||
'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://woo.com/document/free-shipping/' ),
|
||||
'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://woocommerce.com/document/free-shipping/' ),
|
||||
'value' => wc_bool_to_string( $coupon->get_free_shipping( 'edit' ) ),
|
||||
)
|
||||
);
|
||||
|
||||
@@ -199,7 +199,7 @@ class WC_Meta_Box_Order_Actions {
|
||||
*/
|
||||
private static function get_available_order_actions_for_order( $order ) {
|
||||
$actions = array(
|
||||
'send_order_details' => __( 'Email invoice / order details to customer', 'woocommerce' ),
|
||||
'send_order_details' => __( 'Send order details to customer', 'woocommerce' ),
|
||||
'send_order_details_admin' => __( 'Resend new order notification', 'woocommerce' ),
|
||||
'regenerate_download_permissions' => __( 'Regenerate download permissions', 'woocommerce' ),
|
||||
);
|
||||
|
||||
@@ -37,10 +37,17 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
|
||||
if ( 'select' === $attribute_taxonomy->attribute_type ) {
|
||||
$attribute_orderby = ! empty( $attribute_taxonomy->attribute_orderby ) ? $attribute_taxonomy->attribute_orderby : 'name';
|
||||
/**
|
||||
* Filter the length (number of terms) rendered in the list.
|
||||
*
|
||||
* @since 8.8.0
|
||||
* @param int $term_limit The maximum number of terms to display in the list.
|
||||
*/
|
||||
$term_limit = absint( apply_filters( 'woocommerce_admin_terms_metabox_datalimit', 50 ) );
|
||||
?>
|
||||
<select multiple="multiple"
|
||||
data-minimum_input_length="0"
|
||||
data-limit="50" data-return_id="id"
|
||||
data-limit="<?php echo esc_attr( $term_limit ); ?>" data-return_id="id"
|
||||
data-placeholder="<?php esc_attr_e( 'Select values', 'woocommerce' ); ?>"
|
||||
data-orderby="<?php echo esc_attr( $attribute_orderby ); ?>"
|
||||
class="multiselect attribute_values wc-taxonomy-term-search"
|
||||
|
||||
@@ -124,7 +124,7 @@ defined( 'ABSPATH' ) || exit;
|
||||
printf(
|
||||
/* translators: 1: opening link tag, 2: closing link tag. */
|
||||
esc_html__( 'The indicated downloads have been disabled (invalid location or filetype—%1$slearn more%2$s).', 'woocommerce' ),
|
||||
'<a href="https://woo.com/document/approved-download-directories" target="_blank">',
|
||||
'<a href="https://woocommerce.com/document/approved-download-directories" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -32,7 +32,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<div class="inline notice woocommerce-message show_if_variable">
|
||||
<img class="info-icon" src="<?php echo esc_url( $info_img_url ); ?>" />
|
||||
<p>
|
||||
<?php echo esc_html_e( 'Settings below apply to all variations without manual stock management enabled. ', 'woocommerce' ); ?> <a target="_blank" href="https://woo.com/document/variable-product/"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a>
|
||||
<?php echo esc_html_e( 'Settings below apply to all variations without manual stock management enabled. ', 'woocommerce' ); ?> <a target="_blank" href="https://woocommerce.com/document/variable-product/"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
@@ -27,7 +27,7 @@ $arrow_img_url = WC_ADMIN_IMAGES_FOLDER_URL . '/product_data/no-variati
|
||||
/* translators: %1$s: url for attributes tab, %2$s: url for variable product documentation */
|
||||
__( 'Add some attributes in the <a class="variations-add-attributes-link" href="%1$s">Attributes</a> tab to generate variations. Make sure to check the <b>Used for variations</b> box. <a class="variations-learn-more-link" href="%2$s" target="_blank" rel="noreferrer">Learn more</a>', 'woocommerce' ),
|
||||
esc_url( '#product_attributes' ),
|
||||
esc_url( 'https://woo.com/document/variable-product/' )
|
||||
esc_url( 'https://woocommerce.com/document/variable-product/' )
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -450,7 +450,7 @@ defined( 'ABSPATH' ) || exit;
|
||||
printf(
|
||||
/* translators: 1: opening link tag, 2: closing link tag. */
|
||||
esc_html__( 'The indicated downloads have been disabled (invalid location or filetype—%1$slearn more%2$s).', 'woocommerce' ),
|
||||
'<a href="https://woo.com/document/approved-download-directories" target="_blank">',
|
||||
'<a href="https://woocommerce.com/document/approved-download-directories" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -130,7 +130,7 @@ class WC_Notes_Run_Db_Update {
|
||||
array(
|
||||
'name' => 'update-db_learn-more',
|
||||
'label' => __( 'Learn more about updates', 'woocommerce' ),
|
||||
'url' => 'https://woo.com/document/how-to-update-woocommerce/',
|
||||
'url' => 'https://woocommerce.com/document/how-to-update-woocommerce/',
|
||||
'status' => 'unactioned',
|
||||
'primary' => false,
|
||||
),
|
||||
|
||||
@@ -41,7 +41,7 @@ $untested_plugins_msg = sprintf(
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p><?php esc_html_e( 'We strongly recommend creating a backup of your site before updating.', 'woocommerce' ); ?> <a href="https://woo.com/2017/05/create-use-backups-woocommerce/" target="_blank"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a></p>
|
||||
<p><?php esc_html_e( 'We strongly recommend creating a backup of your site before updating.', 'woocommerce' ); ?> <a href="https://woocommerce.com/2017/05/create-use-backups-woocommerce/" target="_blank"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a></p>
|
||||
|
||||
<?php if ( current_user_can( 'update_plugins' ) ) : ?>
|
||||
<div class="actions">
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\Features\Features;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
@@ -41,7 +43,7 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
'keys' => __( 'REST API', 'woocommerce' ),
|
||||
'webhooks' => __( 'Webhooks', 'woocommerce' ),
|
||||
'legacy_api' => __( 'Legacy API', 'woocommerce' ),
|
||||
'woocommerce_com' => __( 'Woo.com', 'woocommerce' ),
|
||||
'woocommerce_com' => __( 'WooCommerce.com', 'woocommerce' ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -153,7 +155,7 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
'checkboxgroup' => 'start',
|
||||
'show_if_checked' => 'option',
|
||||
/* Translators: %s Docs URL. */
|
||||
'desc_tip' => sprintf( __( 'Force SSL (HTTPS) on the checkout pages (<a href="%s" target="_blank">an SSL Certificate is required</a>).', 'woocommerce' ), 'https://woo.com/document/ssl-and-https/#section-3' ),
|
||||
'desc_tip' => sprintf( __( 'Force SSL (HTTPS) on the checkout pages (<a href="%s" target="_blank">an SSL Certificate is required</a>).', 'woocommerce' ), 'https://woocommerce.com/document/ssl-and-https/#section-3' ),
|
||||
),
|
||||
|
||||
'unforce_ssl_checkout' => array(
|
||||
@@ -322,12 +324,12 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings for the Woo.com section.
|
||||
* Get settings for the WooCommerce.com section.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_settings_for_woocommerce_com_section() {
|
||||
$tracking_info_text = sprintf( '<a href="%s" target="_blank">%s</a>', 'https://woo.com/usage-tracking', esc_html__( 'Woo.com Usage Tracking Documentation', 'woocommerce' ) );
|
||||
$tracking_info_text = sprintf( '<a href="%s" target="_blank">%s</a>', 'https://woocommerce.com/usage-tracking', esc_html__( 'WooCommerce.com Usage Tracking Documentation', 'woocommerce' ) );
|
||||
|
||||
$settings =
|
||||
array(
|
||||
@@ -335,7 +337,7 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
'title' => esc_html__( 'Usage Tracking', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'id' => 'tracking_options',
|
||||
'desc' => __( 'Gathering usage data allows us to make WooCommerce better — your store will be considered as we evaluate new features, judge the quality of an update, or determine if an improvement makes sense.', 'woocommerce' ),
|
||||
'desc' => __( 'Gathering usage data allows us to tailor your store setup experience, offer more relevant content, and help make WooCommerce better for everyone.', 'woocommerce' ),
|
||||
),
|
||||
array(
|
||||
'title' => __( 'Enable tracking', 'woocommerce' ),
|
||||
@@ -361,7 +363,7 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
array(
|
||||
'title' => __( 'Show Suggestions', 'woocommerce' ),
|
||||
'desc' => __( 'Display suggestions within WooCommerce', 'woocommerce' ),
|
||||
'desc_tip' => esc_html__( 'Leave this box unchecked if you do not want to pull suggested extensions from Woo.com. You will see a static list of extensions instead.', 'woocommerce' ),
|
||||
'desc_tip' => esc_html__( 'Leave this box unchecked if you do not want to pull suggested extensions from WooCommerce.com. You will see a static list of extensions instead.', 'woocommerce' ),
|
||||
'id' => 'woocommerce_show_marketplace_suggestions',
|
||||
'type' => 'checkbox',
|
||||
'checkboxgroup' => 'start',
|
||||
@@ -400,7 +402,7 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
),
|
||||
'https://wordpress.org/plugins/woocommerce-legacy-rest-api/',
|
||||
admin_url( 'admin.php?page=wc-status&tab=logs' ),
|
||||
'https://developer.woo.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
|
||||
'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class WC_Settings_Emails extends WC_Settings_Page {
|
||||
/* translators: %1$s: Link to WP Mail Logging plugin, %2$s: Link to Email FAQ support page. */
|
||||
__( 'To ensure your store’s notifications arrive in your and your customers’ inboxes, we recommend connecting your email address to your domain and setting up a dedicated SMTP server. If something doesn’t seem to be sending correctly, install the <a href="%1$s">WP Mail Logging Plugin</a> or check the <a href="%2$s">Email FAQ page</a>.', 'woocommerce' ),
|
||||
'https://wordpress.org/plugins/wp-mail-logging/',
|
||||
'https://woo.com/document/email-faq'
|
||||
'https://woocommerce.com/document/email-faq'
|
||||
);
|
||||
$settings =
|
||||
array(
|
||||
|
||||
@@ -36,7 +36,7 @@ class WC_Settings_General extends WC_Settings_Page {
|
||||
$currency_code_options = get_woocommerce_currencies();
|
||||
|
||||
foreach ( $currency_code_options as $code => $name ) {
|
||||
$currency_code_options[ $code ] = $name . ' (' . get_woocommerce_currency_symbol( $code ) . ')';
|
||||
$currency_code_options[ $code ] = $name . ' (' . get_woocommerce_currency_symbol( $code ) . ') — ' . esc_html( $code );
|
||||
}
|
||||
|
||||
$settings =
|
||||
|
||||
@@ -39,6 +39,7 @@ if ( ! class_exists( 'WC_Settings_Page', false ) ) :
|
||||
add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections' ) );
|
||||
add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
|
||||
add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
|
||||
add_action( 'woocommerce_admin_field_add_settings_slot', array( $this, 'add_settings_slot' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +62,15 @@ if ( ! class_exists( 'WC_Settings_Page', false ) ) :
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the React mount point for settings slot.
|
||||
*/
|
||||
public function add_settings_slot() {
|
||||
?>
|
||||
<div id="wc_settings_slotfill"> </div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this page to settings.
|
||||
*
|
||||
@@ -153,7 +163,13 @@ if ( ! class_exists( 'WC_Settings_Page', false ) ) :
|
||||
*/
|
||||
public function get_sections() {
|
||||
$sections = $this->get_own_sections();
|
||||
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
|
||||
/**
|
||||
* Filters the sections for this settings page.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @param array $sections The sections for this settings page.
|
||||
*/
|
||||
return (array) apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -112,7 +112,7 @@ class WC_Settings_Payment_Gateways extends WC_Settings_Page {
|
||||
*/
|
||||
public function payment_gateways_banner() {
|
||||
?>
|
||||
<div id="wc_payment_gateways_banner_slotfill"> </div>
|
||||
<div id="wc_payments_settings_slotfill"> </div>
|
||||
<?php
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ class WC_Settings_Payment_Gateways extends WC_Settings_Page {
|
||||
echo '<tr>';
|
||||
// phpcs:ignore -- ignoring the error since the value is harded.
|
||||
echo "<td style='border-top: 1px solid #c3c4c7; background-color: #fff' colspan='{$columns_count}'>";
|
||||
echo "<a id='settings-other-payment-methods' href='https://woo.com/product-category/woocommerce-extensions/payment-gateways/?utm_source=payments_recommendations' target='_blank' class='components-button is-tertiary'>";
|
||||
echo "<a id='settings-other-payment-methods' href='https://woocommerce.com/product-category/woocommerce-extensions/payment-gateways/?utm_source=payments_recommendations' target='_blank' class='components-button is-tertiary'>";
|
||||
// phpcs:ignore
|
||||
echo $link_text;
|
||||
// phpcs:ignore
|
||||
|
||||
@@ -378,7 +378,7 @@ class WC_Settings_Products extends WC_Settings_Page {
|
||||
'desc' => sprintf(
|
||||
// translators: Link to WooCommerce Docs.
|
||||
__( "If you are using X-Accel-Redirect download method along with NGINX server, make sure that you have applied settings as described in <a href='%s'>Digital/Downloadable Product Handling</a> guide.", 'woocommerce' ),
|
||||
'https://woo.com/document/digital-downloadable-product-handling#nginx-setting'
|
||||
'https://woocommerce.com/document/digital-downloadable-product-handling#nginx-setting'
|
||||
),
|
||||
'options' => array(
|
||||
'force' => __( 'Force downloads', 'woocommerce' ),
|
||||
@@ -396,7 +396,7 @@ class WC_Settings_Products extends WC_Settings_Page {
|
||||
'desc_tip' => sprintf(
|
||||
/* translators: %1$s is a link to the WooCommerce documentation. */
|
||||
__( 'If the "Force Downloads" or "X-Accel-Redirect/X-Sendfile" download method is selected but does not work, the system will use the "Redirect" method as a last resort. <a href="%1$s">See this guide</a> for more details.', 'woocommerce' ),
|
||||
'https://woo.com/document/digital-downloadable-product-handling/'
|
||||
'https://woocommerce.com/document/digital-downloadable-product-handling/'
|
||||
),
|
||||
'checkboxgroup' => 'start',
|
||||
'autoload' => false,
|
||||
@@ -442,7 +442,7 @@ class WC_Settings_Products extends WC_Settings_Page {
|
||||
'desc_tip' => sprintf(
|
||||
// translators: Link to WooCommerce Docs.
|
||||
__( "Not required if your download directory is protected. <a href='%s'>See this guide</a> for more details. Files already uploaded will not be affected.", 'woocommerce' ),
|
||||
'https://woo.com/document/digital-downloadable-product-handling#unique-string'
|
||||
'https://woocommerce.com/document/digital-downloadable-product-handling#unique-string'
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce site visibility settings
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Settings for API.
|
||||
*/
|
||||
if ( class_exists( 'WC_Settings_Site_Visibility', false ) ) {
|
||||
return new WC_Settings_Site_Visibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Settings_Advanced.
|
||||
*/
|
||||
class WC_Settings_Site_Visibility extends WC_Settings_Page {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'site-visibility';
|
||||
$this->label = __( 'Site visibility', 'woocommerce' );
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get settings for the default section.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_settings_for_default_section() {
|
||||
$settings =
|
||||
array(
|
||||
array(
|
||||
'id' => 'wc_settings_site_visibility_slotfill',
|
||||
'type' => 'slotfill_placeholder',
|
||||
),
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new WC_Settings_Site_Visibility();
|
||||
@@ -44,7 +44,7 @@ class WC_Settings_Tax extends WC_Settings_Page {
|
||||
<th scope="row" class="titledesc woocommerce_admin_tax_settings_slotfill_th">
|
||||
</th>
|
||||
<td class="forminp forminp-text woocommerce_admin_tax_settings_slotfill_td">
|
||||
<div id="wc_conflict_error_slotfill"> </div>
|
||||
<div id="wc_tax_settings_slotfill"> </div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
* @package WooCommerce\Admin\Shipping
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
|
||||
use Automattic\WooCommerce\Blocks\Shipping\ShippingController;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
@@ -15,7 +18,10 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<span class="wc-shipping-zone-name"><?php echo esc_html( $zone->get_zone_name() ? $zone->get_zone_name() : __( 'Zone', 'woocommerce' ) ); ?></span>
|
||||
</h2>
|
||||
|
||||
<?php do_action( 'woocommerce_shipping_zone_before_methods_table', $zone ); ?>
|
||||
<?php
|
||||
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
|
||||
do_action( 'woocommerce_shipping_zone_before_methods_table', $zone );
|
||||
?>
|
||||
|
||||
<table class="form-table wc-shipping-zone-settings">
|
||||
<tbody>
|
||||
@@ -52,7 +58,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<div class="wc-shipping-zone-postcodes">
|
||||
<textarea name="zone_postcodes" data-attribute="zone_postcodes" id="zone_postcodes" placeholder="<?php esc_attr_e( 'List 1 postcode per line', 'woocommerce' ); ?>" class="input-text large-text" cols="25" rows="5"><?php echo esc_textarea( implode( "\n", $postcodes ) ); ?></textarea>
|
||||
<?php /* translators: WooCommerce link to setting up shipping zones */ ?>
|
||||
<span class="description"><?php printf( __( 'Postcodes containing wildcards (e.g. CB23*) or fully numeric ranges (e.g. <code>90210...99000</code>) are also supported. Please see the shipping zones <a href="%s" target="_blank">documentation</a> for more information.', 'woocommerce' ), 'https://woo.com/document/setting-up-shipping-zones/#section-3' ); ?></span><?php // @codingStandardsIgnoreLine. ?>
|
||||
<span class="description"><?php printf( __( 'Postcodes containing wildcards (e.g. CB23*) or fully numeric ranges (e.g. <code>90210...99000</code>) are also supported. Please see the shipping zones <a href="%s" target="_blank">documentation</a> for more information.', 'woocommerce' ), 'https://woocommerce.com/document/setting-up-shipping-zones/#section-3' ); ?></span><?php // @codingStandardsIgnoreLine. ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -90,7 +96,10 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php do_action( 'woocommerce_shipping_zone_after_methods_table', $zone ); ?>
|
||||
<?php
|
||||
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
|
||||
do_action( 'woocommerce_shipping_zone_after_methods_table', $zone );
|
||||
?>
|
||||
|
||||
<p class="submit">
|
||||
<button type="submit" name="submit" id="submit" class="button button-primary button-large wc-shipping-zone-method-save" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>" disabled><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
|
||||
@@ -198,6 +207,10 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
$methods_placed_in_order = array_merge( $methods_placed_in_order, array_values( $methods ) );
|
||||
|
||||
foreach ( $methods_placed_in_order as $method ) {
|
||||
if ( CartCheckoutUtils::is_checkout_block_default() && ! ShippingController::is_legacy_local_pickup_active() && 'local_pickup' === $method->id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! $method->supports( 'shipping-zones' ) ) {
|
||||
continue;
|
||||
}
|
||||
@@ -214,7 +227,36 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
|
||||
echo '<div id=' . esc_attr( $method->id ) . '-description class="wc-shipping-zone-method-input-help-text"><span>' . wp_kses_post( wpautop( $method->get_method_description() ) ) . '</span></div>';
|
||||
}
|
||||
echo '</div>'
|
||||
|
||||
if ( CartCheckoutUtils::is_checkout_block_default() ) {
|
||||
echo '<p class="wc-shipping-legacy-local-pickup-help-text-container">';
|
||||
|
||||
if ( ShippingController::is_legacy_local_pickup_active() ) {
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: %s: Local pickup settings page URL. */
|
||||
__( 'Explore a new enhanced delivery method that allows you to easily offer one or more pickup locations to your customers in the <a href="%s">Local pickup settings page</a>.', 'woocommerce' ),
|
||||
array( 'a' => array( 'href' => array() ) )
|
||||
),
|
||||
esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=pickup_location' ) )
|
||||
);
|
||||
|
||||
} else {
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: %s: Local pickup settings page URL. */
|
||||
__( 'Local pickup: Set up pickup locations in the <a href="%s">Local pickup settings page</a>.', 'woocommerce' ),
|
||||
array( 'a' => array( 'href' => array() ) )
|
||||
),
|
||||
esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=pickup_location' ) )
|
||||
);
|
||||
}
|
||||
|
||||
echo '</p>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
?>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
@@ -98,6 +98,7 @@ $settings = array(
|
||||
),
|
||||
|
||||
array( 'type' => 'conflict_error' ), // React mount point for embedded banner slotfill.
|
||||
array( 'type' => 'add_settings_slot' ), // React mount point for settings slotfill.
|
||||
|
||||
array(
|
||||
'title' => __( 'Price display suffix', 'woocommerce' ),
|
||||
|
||||
@@ -57,7 +57,7 @@ $current_section_name = __( 'Browse Categories', 'woocommerce' );
|
||||
>
|
||||
<?php
|
||||
$count_html = WC_Helper_Updater::get_updates_count_html();
|
||||
/* translators: %s: Woo.com Subscriptions tab count HTML. */
|
||||
/* translators: %s: WooCommerce.com Subscriptions tab count HTML. */
|
||||
echo ( wp_kses_post( sprintf( __( 'My Subscriptions %s', 'woocommerce' ), $count_html ) ) );
|
||||
?>
|
||||
</a>
|
||||
@@ -131,12 +131,12 @@ $current_section_name = __( 'Browse Categories', 'woocommerce' );
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<?php /* translators: a url */ ?>
|
||||
<p><?php printf( wp_kses_post( __( 'Our catalog of WooCommerce Extensions can be found on Woo.com here: <a href="%s">WooCommerce Extensions Catalog</a>', 'woocommerce' ) ), 'https://woo.com/product-category/woocommerce-extensions/' ); ?></p>
|
||||
<p><?php printf( wp_kses_post( __( 'Our catalog of WooCommerce Extensions can be found on WooCommerce.com here: <a href="%s">WooCommerce Extensions Catalog</a>', 'woocommerce' ) ), 'https://woocommerce.com/product-category/woocommerce-extensions/' ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( 'Storefront' !== $theme['Name'] && '_featured' !== $current_section ) : ?>
|
||||
<?php
|
||||
$storefront_url = WC_Admin_Addons::add_in_app_purchase_url_params( 'https://woo.com/products/storefront/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddon' );
|
||||
$storefront_url = WC_Admin_Addons::add_in_app_purchase_url_params( 'https://woocommerce.com/products/storefront/?utm_source=extensionsscreen&utm_medium=product&utm_campaign=wcaddon' );
|
||||
?>
|
||||
<div class="storefront">
|
||||
<h2><?php esc_html_e( 'Looking for a WooCommerce theme?', 'woocommerce' ); ?></h2>
|
||||
|
||||
@@ -15,7 +15,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<strong>
|
||||
<?php
|
||||
/* translators: 1: Link URL */
|
||||
echo wp_kses_post( sprintf( __( 'With the release of WooCommerce 4.0, these reports are being replaced. There is a new and better Analytics section available for users running WordPress 5.3+. Head on over to the <a href="%1$s">WooCommerce Analytics</a> or learn more about the new experience in the <a href="https://woo.com/document/woocommerce-analytics/" target="_blank">WooCommerce Analytics documentation</a>.', 'woocommerce' ), esc_url( wc_admin_url( '&path=/analytics/overview' ) ) ) );
|
||||
echo wp_kses_post( sprintf( __( 'With the release of WooCommerce 4.0, these reports are being replaced. There is a new and better Analytics section available for users running WordPress 5.3+. Head on over to the <a href="%1$s">WooCommerce Analytics</a> or learn more about the new experience in the <a href="https://woocommerce.com/document/woocommerce-analytics/" target="_blank">WooCommerce Analytics documentation</a>.', 'woocommerce' ), esc_url( wc_admin_url( '&path=/analytics/overview' ) ) ) );
|
||||
?>
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
* @package WooCommerce\Admin\Logs
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Utilities\LoggingUtil;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$log_directory = LoggingUtil::get_log_directory();
|
||||
|
||||
?>
|
||||
<?php if ( $logs ) : ?>
|
||||
<div id="log-viewer-select">
|
||||
@@ -25,7 +29,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<select class="wc-enhanced-select" name="log_file">
|
||||
<?php foreach ( $logs as $log_key => $log_file ) : ?>
|
||||
<?php
|
||||
$timestamp = filemtime( WC_LOG_DIR . $log_file );
|
||||
$timestamp = filemtime( $log_directory . $log_file );
|
||||
$date = sprintf(
|
||||
/* translators: 1: last access date 2: last access time 3: last access timezone abbreviation */
|
||||
__( '%1$s at %2$s %3$s', 'woocommerce' ),
|
||||
@@ -43,7 +47,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<div id="log-viewer">
|
||||
<pre><?php echo esc_html( file_get_contents( WC_LOG_DIR . $viewed_log ) ); ?></pre>
|
||||
<pre><?php echo esc_html( file_get_contents( $log_directory . $viewed_log ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents ?></pre>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="updated woocommerce-message inline"><p><?php esc_html_e( 'There are currently no logs to view.', 'woocommerce' ); ?></p></div>
|
||||
|
||||
@@ -36,7 +36,7 @@ $inactive_plugins_count = is_countable( $inactive_plugins ) ? count( $inactive_p
|
||||
</p>
|
||||
<p class="submit">
|
||||
<a href="#" class="button-primary debug-report"><?php esc_html_e( 'Get system report', 'woocommerce' ); ?></a>
|
||||
<a class="button-secondary docs" href="https://woo.com/document/understanding-the-woocommerce-system-status-report/" target="_blank">
|
||||
<a class="button-secondary docs" href="https://woocommerce.com/document/understanding-the-woocommerce-system-status-report/" target="_blank">
|
||||
<?php esc_html_e( 'Understanding the status report', 'woocommerce' ); ?>
|
||||
</a>
|
||||
</p>
|
||||
@@ -120,8 +120,14 @@ $inactive_plugins_count = is_countable( $inactive_plugins ) ? count( $inactive_p
|
||||
if ( $environment['log_directory_writable'] ) {
|
||||
echo '<mark class="yes"><span class="dashicons dashicons-yes"></span> <code class="private">' . esc_html( $environment['log_directory'] ) . '</code></mark> ';
|
||||
} else {
|
||||
/* Translators: %1$s: Log directory, %2$s: Log directory constant */
|
||||
echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'To allow logging, make %1$s writable or define a custom %2$s.', 'woocommerce' ), '<code>' . esc_html( $environment['log_directory'] ) . '</code>', '<code>WC_LOG_DIR</code>' ) . '</mark>';
|
||||
printf(
|
||||
'<mark class="error"><span class="dashicons dashicons-warning"></span> %s</mark>',
|
||||
sprintf(
|
||||
// Translators: %s: Log directory path.
|
||||
esc_html__( 'To allow logging, make %s writable.', 'woocommerce' ),
|
||||
'<code>' . esc_html( $environment['log_directory'] ) . '</code>'
|
||||
)
|
||||
);
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
@@ -446,7 +452,7 @@ $inactive_plugins_count = is_countable( $inactive_plugins ) ? count( $inactive_p
|
||||
<?php
|
||||
if ( strlen( $database['database_prefix'] ) > 20 ) {
|
||||
/* Translators: %1$s: Database prefix, %2$s: Docs link. */
|
||||
echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%1$s - We recommend using a prefix with less than 20 characters. See: %2$s', 'woocommerce' ), esc_html( $database['database_prefix'] ), '<a href="https://woo.com/document/completed-order-email-doesnt-contain-download-links/#section-2" target="_blank">' . esc_html__( 'How to update your database table prefix', 'woocommerce' ) . '</a>' ) . '</mark>';
|
||||
echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%1$s - We recommend using a prefix with less than 20 characters. See: %2$s', 'woocommerce' ), esc_html( $database['database_prefix'] ), '<a href="https://woocommerce.com/document/completed-order-email-doesnt-contain-download-links/#section-2" target="_blank">' . esc_html__( 'How to update your database table prefix', 'woocommerce' ) . '</a>' ) . '</mark>';
|
||||
} else {
|
||||
echo '<mark class="yes">' . esc_html( $database['database_prefix'] ) . '</mark>';
|
||||
}
|
||||
@@ -557,7 +563,7 @@ $inactive_plugins_count = is_countable( $inactive_plugins ) ? count( $inactive_p
|
||||
<mark class="error"><span class="dashicons dashicons-warning"></span>
|
||||
<?php
|
||||
/* Translators: %s: docs link. */
|
||||
echo wp_kses_post( sprintf( __( 'Your store is not using HTTPS. <a href="%s" target="_blank">Learn more about HTTPS and SSL Certificates</a>.', 'woocommerce' ), 'https://woo.com/document/ssl-and-https/' ) );
|
||||
echo wp_kses_post( sprintf( __( 'Your store is not using HTTPS. <a href="%s" target="_blank">Learn more about HTTPS and SSL Certificates</a>.', 'woocommerce' ), 'https://woocommerce.com/document/ssl-and-https/' ) );
|
||||
?>
|
||||
</mark>
|
||||
<?php endif; ?>
|
||||
@@ -725,8 +731,8 @@ if ( 0 < $mu_plugins_count ) :
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-export-label="Connected to Woo.com"><?php esc_html_e( 'Connected to Woo.com', 'woocommerce' ); ?>:</td>
|
||||
<td class="help"><?php echo wc_help_tip( esc_html__( 'Is your site connected to Woo.com?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
|
||||
<td data-export-label="Connected to WooCommerce.com"><?php esc_html_e( 'Connected to WooCommerce.com', 'woocommerce' ); ?>:</td>
|
||||
<td class="help"><?php echo wc_help_tip( esc_html__( 'Is your site connected to WooCommerce.com?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
|
||||
<td><?php echo 'yes' === $settings['woocommerce_com_connected'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">–</mark>'; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -735,11 +741,6 @@ if ( 0 < $mu_plugins_count ) :
|
||||
<td><?php echo $settings['enforce_approved_download_dirs'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">–</mark>'; ?></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td data-export-label="HPOS feature screen enabled"><?php esc_html_e( 'HPOS feature screen enabled:', 'woocommerce' ); ?></td>
|
||||
<td class="help"><?php echo wc_help_tip( esc_html__( 'Is HPOS feature screen enabled?', 'woocommerce' ) ); ?></td>
|
||||
<td><?php echo $settings['HPOS_feature_screen_enabled'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">–</mark>'; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-export-label="HPOS feature enabled"><?php esc_html_e( 'HPOS enabled:', 'woocommerce' ); ?></td>
|
||||
<td class="help"><?php echo wc_help_tip( esc_html__( 'Is HPOS enabled?', 'woocommerce' ) ); ?></td>
|
||||
@@ -1006,7 +1007,7 @@ if ( 0 < $mu_plugins_count ) :
|
||||
<mark class="error">
|
||||
<span class="dashicons dashicons-warning"></span>
|
||||
</mark>
|
||||
<a href="https://woo.com/document/fix-outdated-templates-woocommerce/" target="_blank">
|
||||
<a href="https://woocommerce.com/document/fix-outdated-templates-woocommerce/" target="_blank">
|
||||
<?php esc_html_e( 'Learn how to update', 'woocommerce' ); ?>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -12,7 +12,7 @@ defined( 'ABSPATH' ) || exit;
|
||||
<p>
|
||||
<?php
|
||||
$settings_screen_link = '<a href="' . esc_url( get_admin_url( null, 'admin.php?page=wc-settings&tab=products§ion=download_urls' ) ) . '">';
|
||||
$documentation_link = '<a href="https://woo.com/document/approved-download-directories">';
|
||||
$documentation_link = '<a href="https://woocommerce.com/document/approved-download-directories">';
|
||||
$closing_link = '</a>';
|
||||
|
||||
printf(
|
||||
|
||||
@@ -27,7 +27,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<?php esc_html_e( 'Setup shipping zones', 'woocommerce' ); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<a class="button-secondary" href="https://woo.com/document/setting-up-shipping-zones/">
|
||||
<a class="button-secondary" href="https://woocommerce.com/document/setting-up-shipping-zones/">
|
||||
<?php esc_html_e( 'Learn more about shipping zones', 'woocommerce' ); ?>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -30,7 +30,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<a class="button-primary" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ); ?>">
|
||||
<?php esc_html_e( 'Setup shipping zones', 'woocommerce' ); ?>
|
||||
</a>
|
||||
<a class="button-secondary" href="https://woo.com/document/setting-up-shipping-zones/">
|
||||
<a class="button-secondary" href="https://woocommerce.com/document/setting-up-shipping-zones/">
|
||||
<?php esc_html_e( 'Learn more about shipping zones', 'woocommerce' ); ?>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -16,7 +16,7 @@ defined( 'ABSPATH' ) || exit;
|
||||
echo wp_kses_post( sprintf(
|
||||
/* translators: %s: documentation URL */
|
||||
__( 'Your store does not appear to be using a secure connection. We highly recommend serving your entire website over an HTTPS connection to help keep customer data secure. <a href="%s">Learn more here.</a>', 'woocommerce' ),
|
||||
'https://woo.com/document/ssl-and-https/'
|
||||
'https://woocommerce.com/document/ssl-and-https/'
|
||||
) );
|
||||
?>
|
||||
</p>
|
||||
|
||||
@@ -23,7 +23,7 @@ $theme = wp_get_theme();
|
||||
</ol>
|
||||
</p>
|
||||
<p class="submit">
|
||||
<a class="button-primary" href="https://woo.com/document/template-structure/" target="_blank"><?php esc_html_e( 'Learn more about templates', 'woocommerce' ); ?></a>
|
||||
<a class="button-primary" href="https://woocommerce.com/document/template-structure/" target="_blank"><?php esc_html_e( 'Learn more about templates', 'woocommerce' ); ?></a>
|
||||
<a class="button-primary" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-status' ) ); ?>" target="_blank"><?php esc_html_e( 'View affected templates', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@ $update_url = wp_nonce_url(
|
||||
<a href="<?php echo esc_url( $update_url ); ?>" class="wc-update-now button-primary">
|
||||
<?php esc_html_e( 'Update WooCommerce Database', 'woocommerce' ); ?>
|
||||
</a>
|
||||
<a href="https://woo.com/document/how-to-update-woocommerce/" class="button-secondary">
|
||||
<a href="https://woocommerce.com/document/how-to-update-woocommerce/" class="button-secondary">
|
||||
<?php esc_html_e( 'Learn more about updates', 'woocommerce' ); ?>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -21,7 +21,7 @@ $uploads = wp_get_upload_dir();
|
||||
/* translators: 1: uploads directory URL 2: documentation URL */
|
||||
__( 'Your store\'s uploads directory is <a href="%1$s">browsable via the web</a>. We strongly recommend <a href="%2$s">configuring your web server to prevent directory indexing</a>.', 'woocommerce' ),
|
||||
esc_url( $uploads['baseurl'] . '/woocommerce_uploads' ),
|
||||
'https://woo.com/document/digital-downloadable-product-handling/#protecting-your-uploads-directory'
|
||||
'https://woocommerce.com/document/digital-downloadable-product-handling/#protecting-your-uploads-directory'
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -22,7 +22,7 @@ defined( 'ABSPATH' ) || exit;
|
||||
'utm_campaign' => 'woocommerceplugin',
|
||||
'utm_content' => 'docs',
|
||||
),
|
||||
'https://woo.com/document/update-php-wordpress/'
|
||||
'https://woocommerce.com/document/update-php-wordpress/'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -245,7 +245,13 @@ class WC_AJAX {
|
||||
|
||||
check_ajax_referer( 'apply-coupon', 'security' );
|
||||
|
||||
$coupon_code = ArrayUtil::get_value_or_default( $_POST, 'coupon_code' );
|
||||
$coupon_code = ArrayUtil::get_value_or_default( $_POST, 'coupon_code' );
|
||||
$billing_email = ArrayUtil::get_value_or_default( $_POST, 'billing_email' );
|
||||
|
||||
if ( is_string( $billing_email ) && is_email( $billing_email ) ) {
|
||||
wc()->customer->set_billing_email( $billing_email );
|
||||
}
|
||||
|
||||
if ( ! StringUtil::is_null_or_whitespace( $coupon_code ) ) {
|
||||
WC()->cart->add_discount( wc_format_coupon_code( wp_unslash( $coupon_code ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
} else {
|
||||
|
||||
@@ -385,19 +385,20 @@ class WC_Auth {
|
||||
wc_get_template(
|
||||
'auth/form-grant-access.php',
|
||||
array(
|
||||
'app_name' => wc_clean( $data['app_name'] ),
|
||||
'return_url' => add_query_arg(
|
||||
'app_name' => wc_clean( $data['app_name'] ),
|
||||
'callback_url' => $this->get_formatted_url( $data['callback_url'] ),
|
||||
'return_url' => add_query_arg(
|
||||
array(
|
||||
'success' => 0,
|
||||
'user_id' => wc_clean( $data['user_id'] ),
|
||||
),
|
||||
$this->get_formatted_url( $data['return_url'] )
|
||||
),
|
||||
'scope' => $this->get_i18n_scope( wc_clean( $data['scope'] ) ),
|
||||
'permissions' => $this->get_permissions_in_scope( wc_clean( $data['scope'] ) ),
|
||||
'granted_url' => wp_nonce_url( $this->build_url( $data, 'access_granted' ), 'wc_auth_grant_access', 'wc_auth_nonce' ),
|
||||
'logout_url' => wp_logout_url( $this->build_url( $data, 'login' ) ),
|
||||
'user' => wp_get_current_user(),
|
||||
'scope' => $this->get_i18n_scope( wc_clean( $data['scope'] ) ),
|
||||
'permissions' => $this->get_permissions_in_scope( wc_clean( $data['scope'] ) ),
|
||||
'granted_url' => wp_nonce_url( $this->build_url( $data, 'access_granted' ), 'wc_auth_grant_access', 'wc_auth_nonce' ),
|
||||
'logout_url' => wp_logout_url( $this->build_url( $data, 'login' ) ),
|
||||
'user' => wp_get_current_user(),
|
||||
)
|
||||
);
|
||||
exit;
|
||||
|
||||
@@ -1050,11 +1050,11 @@ class WC_Checkout {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store Order ID in session so it can be re-used after payment failure.
|
||||
// Store Order ID in session, so it can be re-used after payment failure.
|
||||
WC()->session->set( 'order_awaiting_payment', $order_id );
|
||||
|
||||
// We save the session early because if the payment gateway hangs
|
||||
// the request will never finish, thus the session data will neved be saved,
|
||||
// the request will never finish, thus the session data will never be saved,
|
||||
// and this can lead to duplicate orders if the user submits the order again.
|
||||
WC()->session->save_data();
|
||||
|
||||
@@ -1073,6 +1073,7 @@ class WC_Checkout {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Using wp_send_json will gracefully handle any problem encoding data.
|
||||
wp_send_json( $result );
|
||||
}
|
||||
}
|
||||
@@ -1287,6 +1288,7 @@ class WC_Checkout {
|
||||
* since it could be empty see:
|
||||
* https://github.com/woocommerce/woocommerce/issues/24631
|
||||
*/
|
||||
|
||||
if ( apply_filters( 'woocommerce_cart_needs_payment', $order->needs_payment(), WC()->cart ) ) {
|
||||
$this->process_order_payment( $order_id, $posted_data['payment_method'] );
|
||||
} else {
|
||||
|
||||
@@ -81,6 +81,18 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
||||
*/
|
||||
protected $cache_group = 'coupons';
|
||||
|
||||
/**
|
||||
* Error message.
|
||||
*
|
||||
* This property should not be considered public API, and should not be accessed directly.
|
||||
* It is being added to supress PHP > 8.0 warnings against dynamic property creation, and all access
|
||||
* should be through the getter and setter methods, namely `get_error_message()` and `set_error_message()`.
|
||||
* In the future, the access modifier may be changed back to protected.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $error_message;
|
||||
|
||||
/**
|
||||
* Sorting.
|
||||
*
|
||||
@@ -864,6 +876,17 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
||||
return $this->error_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error_message string.
|
||||
*
|
||||
* @param string $message Message string.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_error_message( string $message ) {
|
||||
$this->error_message = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a coupon is valid for the cart.
|
||||
*
|
||||
@@ -899,7 +922,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
||||
* @return bool
|
||||
*/
|
||||
public function is_valid_for_product( $product, $values = array() ) {
|
||||
if ( ! $this->is_type( wc_get_product_coupon_types() ) ) {
|
||||
if ( ! $this->is_type( wc_get_product_coupon_types() ) || ! is_a( $product, WC_Product::class ) ) {
|
||||
return apply_filters( 'woocommerce_coupon_is_valid_for_product', false, $product, $this, $values );
|
||||
}
|
||||
|
||||
@@ -944,20 +967,27 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
||||
* Converts one of the WC_Coupon message/error codes to a message string and.
|
||||
* displays the message/error.
|
||||
*
|
||||
* @param int $msg_code Message/error code.
|
||||
* @param int $msg_code Message/error code.
|
||||
* @param string $notice_type Notice type.
|
||||
*/
|
||||
public function add_coupon_message( $msg_code ) {
|
||||
$msg = $msg_code < 200 ? $this->get_coupon_error( $msg_code ) : $this->get_coupon_message( $msg_code );
|
||||
public function add_coupon_message( $msg_code, $notice_type = 'success' ) {
|
||||
if ( $msg_code < 200 ) {
|
||||
$msg = $this->get_coupon_error( $msg_code );
|
||||
$notice_type = 'error';
|
||||
} else {
|
||||
$msg = $this->get_coupon_message( $msg_code );
|
||||
}
|
||||
|
||||
if ( ! $msg ) {
|
||||
if ( empty( $msg ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $msg_code < 200 ) {
|
||||
wc_add_notice( $msg, 'error' );
|
||||
} else {
|
||||
wc_add_notice( $msg );
|
||||
// Since coupon validation is done multiple times (e.g. to ensure a valid cart), we need to check for dupes.
|
||||
if ( wc_has_notice( $msg, $notice_type ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wc_add_notice( $msg, $notice_type );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1001,8 +1031,15 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
||||
$err = sprintf( __( 'Sorry, it seems the coupon "%s" is invalid - it has now been removed from your order.', 'woocommerce' ), esc_html( $this->get_code() ) );
|
||||
break;
|
||||
case self::E_WC_COUPON_NOT_YOURS_REMOVED:
|
||||
/* translators: %s: coupon code */
|
||||
$err = sprintf( __( 'Sorry, it seems the coupon "%s" is not yours - it has now been removed from your order.', 'woocommerce' ), esc_html( $this->get_code() ) );
|
||||
// We check for supplied billing email. On shortcode, this will be present for checkout requests.
|
||||
$billing_email = \Automattic\WooCommerce\Utilities\ArrayUtil::get_value_or_default( $_POST, 'billing_email' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
if ( ! is_null( $billing_email ) ) {
|
||||
/* translators: %s: coupon code */
|
||||
$err = sprintf( __( 'Please enter a valid email to use coupon code "%s".', 'woocommerce' ), esc_html( $this->get_code() ) );
|
||||
} else {
|
||||
/* translators: %s: coupon code */
|
||||
$err = sprintf( __( 'Please enter a valid email at checkout to use coupon code "%s".', 'woocommerce' ), esc_html( $this->get_code() ) );
|
||||
}
|
||||
break;
|
||||
case self::E_WC_COUPON_ALREADY_APPLIED:
|
||||
$err = __( 'Coupon code already applied!', 'woocommerce' );
|
||||
@@ -1152,4 +1189,26 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
||||
$this->set_amount( $info[3] ?? 0 );
|
||||
$this->set_free_shipping( $info[4] ?? false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns alternate error messages based on context (eg. Cart and Checkout).
|
||||
*
|
||||
* @param int $err_code Message/error code.
|
||||
*
|
||||
* @return array Context based alternate error messages.
|
||||
*/
|
||||
public function get_context_based_coupon_errors( $err_code = null ) {
|
||||
|
||||
switch ( $err_code ) {
|
||||
case self::E_WC_COUPON_NOT_YOURS_REMOVED:
|
||||
return array(
|
||||
/* translators: %s: coupon code */
|
||||
'cart' => sprintf( __( 'Please enter a valid email at checkout to use coupon code "%s".', 'woocommerce' ), esc_html( $this->get_code() ) ),
|
||||
/* translators: %s: coupon code */
|
||||
'checkout' => sprintf( __( 'Please enter a valid email to use coupon code "%s".', 'woocommerce' ), esc_html( $this->get_code() ) ),
|
||||
);
|
||||
default:
|
||||
return array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +333,20 @@ class WC_Discounts {
|
||||
|
||||
$items_to_apply[] = $item_to_apply;
|
||||
}
|
||||
return $items_to_apply;
|
||||
|
||||
/**
|
||||
* Filters the items that a coupon should be applied to.
|
||||
*
|
||||
* This filter allows you to modify the items that a coupon will be applied to before the discount calculations take place.
|
||||
*
|
||||
* @since 8.8.0
|
||||
* @param array $items_to_apply The items that the coupon will be applied to.
|
||||
* @param WC_Coupon $coupon The coupon object.
|
||||
* @param WC_Discounts $this The discounts instance.
|
||||
*
|
||||
* @return array The modified list of items that the coupon should be applied to.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_coupon_get_items_to_apply', $items_to_apply, $coupon, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -939,6 +952,50 @@ class WC_Discounts {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure coupon is valid for allowed emails or throw exception.
|
||||
*
|
||||
* @since 8.6.0
|
||||
* @throws Exception Error message.
|
||||
* @param WC_Coupon $coupon Coupon data.
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_coupon_allowed_emails( $coupon ) {
|
||||
|
||||
$restrictions = $coupon->get_email_restrictions();
|
||||
|
||||
if ( ! is_array( $restrictions ) || empty( $restrictions ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$user = wp_get_current_user();
|
||||
$check_emails = array( $user->get_billing_email(), $user->get_email() );
|
||||
|
||||
if ( $this->object instanceof WC_Cart ) {
|
||||
$check_emails[] = $this->object->get_customer()->get_billing_email();
|
||||
} elseif ( $this->object instanceof WC_Order ) {
|
||||
$check_emails[] = $this->object->get_billing_email();
|
||||
}
|
||||
|
||||
$check_emails = array_unique(
|
||||
array_filter(
|
||||
array_map(
|
||||
'strtolower',
|
||||
array_map(
|
||||
'sanitize_email',
|
||||
$check_emails
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ( ! WC()->cart->is_coupon_emails_allowed( $check_emails, $restrictions ) ) {
|
||||
throw new Exception( $coupon->get_coupon_error( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED ), WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object subtotal
|
||||
*
|
||||
@@ -981,10 +1038,11 @@ class WC_Discounts {
|
||||
* - 113: Excluded products.
|
||||
* - 114: Excluded categories.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @throws Exception Error message.
|
||||
* @param WC_Coupon $coupon Coupon data.
|
||||
* @param WC_Coupon $coupon Coupon data.
|
||||
*
|
||||
* @return bool|WP_Error
|
||||
* @throws Exception Error message.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function is_coupon_valid( $coupon ) {
|
||||
try {
|
||||
@@ -998,9 +1056,10 @@ class WC_Discounts {
|
||||
$this->validate_coupon_product_categories( $coupon );
|
||||
$this->validate_coupon_excluded_items( $coupon );
|
||||
$this->validate_coupon_eligible_items( $coupon );
|
||||
$this->validate_coupon_allowed_emails( $coupon );
|
||||
|
||||
if ( ! apply_filters( 'woocommerce_coupon_is_valid', true, $coupon, $this ) ) {
|
||||
throw new Exception( __( 'Coupon is not valid.', 'woocommerce' ), 100 );
|
||||
throw new Exception( __( 'Coupon is not valid.', 'woocommerce' ), WC_Coupon::E_WC_COUPON_INVALID_FILTERED );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
/**
|
||||
@@ -1012,14 +1071,23 @@ class WC_Discounts {
|
||||
*/
|
||||
$message = apply_filters( 'woocommerce_coupon_error', is_numeric( $e->getMessage() ) ? $coupon->get_coupon_error( $e->getMessage() ) : $e->getMessage(), $e->getCode(), $coupon );
|
||||
|
||||
$additional_data = array(
|
||||
'status' => 400,
|
||||
);
|
||||
|
||||
$context_coupon_errors = $coupon->get_context_based_coupon_errors( $e->getCode() );
|
||||
|
||||
if ( ! empty( $context_coupon_errors ) ) {
|
||||
$additional_data['details'] = $context_coupon_errors;
|
||||
}
|
||||
|
||||
return new WP_Error(
|
||||
'invalid_coupon',
|
||||
$message,
|
||||
array(
|
||||
'status' => 400,
|
||||
)
|
||||
$additional_data,
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ class WC_Emails {
|
||||
*/
|
||||
public function init() {
|
||||
// Include email classes.
|
||||
include_once dirname( __FILE__ ) . '/emails/class-wc-email.php';
|
||||
include_once __DIR__ . '/emails/class-wc-email.php';
|
||||
|
||||
$this->emails['WC_Email_New_Order'] = include __DIR__ . '/emails/class-wc-email-new-order.php';
|
||||
$this->emails['WC_Email_Cancelled_Order'] = include __DIR__ . '/emails/class-wc-email-cancelled-order.php';
|
||||
@@ -302,8 +302,8 @@ class WC_Emails {
|
||||
$this->get_blogname(),
|
||||
$domain,
|
||||
$domain,
|
||||
'<a href="https://woo.com">WooCommerce</a>',
|
||||
'<a href="https://woo.com">WooCommerce</a>',
|
||||
'<a href="https://woocommerce.com">WooCommerce</a>',
|
||||
'<a href="https://woocommerce.com">WooCommerce</a>',
|
||||
),
|
||||
$string
|
||||
);
|
||||
@@ -610,8 +610,8 @@ class WC_Emails {
|
||||
|
||||
$checkout_fields = Package::container()->get( CheckoutFields::class );
|
||||
$fields = array_merge(
|
||||
$checkout_fields->get_order_additional_fields_with_values( $order, 'contact', '', 'view' ),
|
||||
$checkout_fields->get_order_additional_fields_with_values( $order, 'additional', '', 'view' ),
|
||||
$checkout_fields->get_order_additional_fields_with_values( $order, 'contact', 'other', 'view' ),
|
||||
$checkout_fields->get_order_additional_fields_with_values( $order, 'order', 'other', 'view' ),
|
||||
);
|
||||
|
||||
if ( ! $fields ) {
|
||||
|
||||
@@ -541,7 +541,9 @@ class WC_Frontend_Scripts {
|
||||
'checkout_url' => WC_AJAX::get_endpoint( 'checkout' ),
|
||||
'is_checkout' => is_checkout() && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) ? 1 : 0,
|
||||
'debug_mode' => Constants::is_true( 'WP_DEBUG' ),
|
||||
'i18n_checkout_error' => esc_attr__( 'Error processing checkout. Please try again.', 'woocommerce' ),
|
||||
/* translators: %s: Order history URL on My Account section */
|
||||
'i18n_checkout_error' => sprintf( esc_attr__( 'There was an error processing your order. Please check for any charges in your payment method and review your <a href="%s">order history</a> before placing the order again.', 'woocommerce' ), esc_url( wc_get_account_endpoint_url( 'orders' ) ) ),
|
||||
|
||||
);
|
||||
break;
|
||||
case 'wc-address-i18n':
|
||||
|
||||
@@ -18,6 +18,7 @@ use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil;
|
||||
use Automattic\WooCommerce\Internal\WCCom\ConnectionHelper as WCConnectionHelper;
|
||||
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
|
||||
use Automattic\WooCommerce\Utilities\OrderUtil;
|
||||
use Automattic\WooCommerce\Internal\Utilities\PluginInstaller;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
@@ -247,6 +248,10 @@ class WC_Install {
|
||||
'8.7.0' => array(
|
||||
'wc_update_870_prevent_listing_of_transient_files_directory',
|
||||
),
|
||||
'8.9.0' => array(
|
||||
'wc_update_890_update_connect_to_woocommerce_note',
|
||||
'wc_update_890_update_paypal_standard_load_eligibility',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -281,6 +286,7 @@ class WC_Install {
|
||||
add_filter( 'wpmu_drop_tables', array( __CLASS__, 'wpmu_drop_tables' ) );
|
||||
add_filter( 'cron_schedules', array( __CLASS__, 'cron_schedules' ) );
|
||||
self::add_action( 'admin_init', array( __CLASS__, 'newly_installed' ) );
|
||||
self::add_action( 'woocommerce_activate_legacy_rest_api_plugin', array( __CLASS__, 'maybe_install_legacy_api_plugin' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,7 +369,7 @@ class WC_Install {
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public static function run_update_callback( $update_callback ) {
|
||||
include_once dirname( __FILE__ ) . '/wc-update-functions.php';
|
||||
include_once __DIR__ . '/wc-update-functions.php';
|
||||
|
||||
if ( is_callable( $update_callback ) ) {
|
||||
self::run_update_callback_start( $update_callback );
|
||||
@@ -453,6 +459,7 @@ class WC_Install {
|
||||
self::update_wc_version();
|
||||
self::maybe_update_db_version();
|
||||
self::maybe_set_store_id();
|
||||
self::maybe_install_legacy_api_plugin();
|
||||
|
||||
delete_transient( 'wc_installing' );
|
||||
|
||||
@@ -550,7 +557,8 @@ class WC_Install {
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private static function remove_admin_notices() {
|
||||
include_once dirname( __FILE__ ) . '/admin/class-wc-admin-notices.php';
|
||||
include_once __DIR__ . '/admin/class-wc-admin-notices.php';
|
||||
|
||||
WC_Admin_Notices::remove_all_notices();
|
||||
}
|
||||
|
||||
@@ -679,7 +687,7 @@ class WC_Install {
|
||||
),
|
||||
'woocommerce-db-updates'
|
||||
);
|
||||
$loop++;
|
||||
++$loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -792,10 +800,14 @@ class WC_Install {
|
||||
* Create pages that the plugin relies on, storing page IDs in variables.
|
||||
*/
|
||||
public static function create_pages() {
|
||||
// WordPress sets fresh_site to 0 after a page gets published.
|
||||
// Prevent fresh_site option from being set to 0 so that we can use it for further customizations.
|
||||
remove_action( 'publish_page', '_delete_option_fresh_site', 0 );
|
||||
|
||||
// Set the locale to the store locale to ensure pages are created in the correct language.
|
||||
wc_switch_to_site_locale();
|
||||
|
||||
include_once dirname( __FILE__ ) . '/admin/wc-admin-functions.php';
|
||||
include_once __DIR__ . '/admin/wc-admin-functions.php';
|
||||
|
||||
/**
|
||||
* Determines the cart shortcode tag used for the cart page.
|
||||
@@ -883,7 +895,7 @@ class WC_Install {
|
||||
*/
|
||||
private static function create_options() {
|
||||
// Include settings so that we can run through defaults.
|
||||
include_once dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php';
|
||||
include_once __DIR__ . '/admin/class-wc-admin-settings.php';
|
||||
|
||||
$settings = WC_Admin_Settings::get_settings_pages();
|
||||
|
||||
@@ -1159,6 +1171,136 @@ class WC_Install {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install and activate the WooCommerce Legacy REST API plugin from the WordPress.org directory if all the following is true:
|
||||
*
|
||||
* 1. We are in a WooCommerce upgrade process (not a new install).
|
||||
* 2. The 'woocommerce_skip_legacy_rest_api_plugin_auto_install' filter returns false (which is the default).
|
||||
* 3. The plugin is not installed and active already (but see note about multisite below).
|
||||
* 4. The Legacy REST API is enabled in the site OR the site has at least one webhook defined that uses the Legacy REST API payload format (disabled webhooks also count).
|
||||
*
|
||||
* In multisite setups it could happen that the plugin was installed by an installation process performed in another site.
|
||||
* In this case we check if the plugin was autoinstalled in such a way, and if so we activate it if the conditions are fulfilled.
|
||||
*/
|
||||
private static function maybe_install_legacy_api_plugin() {
|
||||
if ( self::is_new_install() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to skip the automatic installation of the WooCommerce Legacy REST API plugin
|
||||
* from the WordPress.org plugins directory.
|
||||
*
|
||||
* @since 8.8.0
|
||||
*
|
||||
* @param bool $skip_auto_install False, defaulting to "don't skip the plugin automatic installation".
|
||||
* @returns bool True to skip the plugin automatic installation, false to install the plugin if necessary.
|
||||
*/
|
||||
if ( apply_filters( 'woocommerce_skip_legacy_rest_api_plugin_auto_install', false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( 'yes' !== get_option( 'woocommerce_api_enabled' ) &&
|
||||
0 === wc_get_container()->get( Automattic\WooCommerce\Internal\Utilities\WebhookUtil::class )->get_legacy_webhooks_count( true ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$plugin_name = 'woocommerce-legacy-rest-api/woocommerce-legacy-rest-api.php';
|
||||
|
||||
wp_clean_plugins_cache();
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
if ( isset( get_plugins()[ $plugin_name ] ) ) {
|
||||
if ( ! ( get_site_option( 'woocommerce_autoinstalled_plugins', array() )[ $plugin_name ] ?? null ) ) {
|
||||
// The plugin was installed manually so let's not interfere.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( in_array( $plugin_name, wp_get_active_and_valid_plugins(), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The plugin was automatically installed in a different installation process - can happen in multisite.
|
||||
$install_ok = true;
|
||||
} else {
|
||||
$install_result = wc_get_container()->get( PluginInstaller::class )->install_plugin(
|
||||
'https://downloads.wordpress.org/plugin/woocommerce-legacy-rest-api.latest-stable.zip',
|
||||
array(
|
||||
'info_link' => 'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/',
|
||||
)
|
||||
);
|
||||
|
||||
if ( $install_result['already_installing'] ?? null ) {
|
||||
// The plugin is in the process of being installed already (can happen in multisite),
|
||||
// but we still need to activate it for ourselves once it's installed.
|
||||
as_schedule_single_action( time() + 10, 'woocommerce_activate_legacy_rest_api_plugin' );
|
||||
return;
|
||||
}
|
||||
|
||||
$install_ok = $install_result['install_ok'];
|
||||
}
|
||||
|
||||
$plugin_page_url = 'https://wordpress.org/plugins/woocommerce-legacy-rest-api/';
|
||||
$blog_post_url = 'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/';
|
||||
$site_legacy_api_settings_url = get_admin_url( null, '/admin.php?page=wc-settings&tab=advanced§ion=legacy_api' );
|
||||
$site_webhooks_settings_url = get_admin_url( null, '/admin.php?page=wc-settings&tab=advanced§ion=webhooks' );
|
||||
$site_logs_url = get_admin_url( null, '/admin.php?page=wc-status&tab=logs' );
|
||||
|
||||
if ( $install_ok ) {
|
||||
$activation_result = activate_plugin( $plugin_name );
|
||||
if ( $activation_result instanceof \WP_Error ) {
|
||||
$message = sprintf(
|
||||
/* translators: 1 = URL of Legacy REST API plugin page, 2 = URL of Legacy API settings in current site, 3 = URL of webhooks settings in current site, 4 = URL of logs page in current site, 5 = URL of plugins page in current site, 6 = URL of blog post about the Legacy REST API removal */
|
||||
__( '⚠️ WooCommerce installed <a href="%1$s">the Legacy REST API plugin</a> because this site has <a href="%2$s">the Legacy REST API enabled</a> or has <a href="%3$s">legacy webhooks defined</a>, but it failed to activate it (see error details in <a href="%4$s">the WooCommerce logs</a>). Please go to <a href="%5$s">the plugins page</a> and activate it manually. <a href="%6$s">More information</a>', 'woocommerce' ),
|
||||
$plugin_page_url,
|
||||
$site_legacy_api_settings_url,
|
||||
$site_webhooks_settings_url,
|
||||
$site_logs_url,
|
||||
get_admin_url( null, '/plugins.php' ),
|
||||
$blog_post_url
|
||||
);
|
||||
$notice_name = 'woocommerce_legacy_rest_api_plugin_activation_failed';
|
||||
wc_get_logger()->error(
|
||||
__( 'WooCommerce installed the Legacy REST API plugin but failed to activate it, see context for more details.', 'woocommerce' ),
|
||||
array(
|
||||
'source' => 'plugin_auto_installs',
|
||||
'error' => $activation_result,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$message = sprintf(
|
||||
/* translators: 1 = URL of Legacy REST API plugin page, 2 = URL of Legacy API settings in current site, 3 = URL of webhooks settings in current site, 4 = URL of blog post about the Legacy REST API removal */
|
||||
__( 'ℹ️ WooCommerce installed and activated <a href="%1$s">the Legacy REST API plugin</a> because this site has <a href="%2$s">the Legacy REST API enabled</a> or has <a href="%3$s">legacy webhooks defined</a>. <a href="%4$s">More information</a>', 'woocommerce' ),
|
||||
$plugin_page_url,
|
||||
$site_legacy_api_settings_url,
|
||||
$site_webhooks_settings_url,
|
||||
$blog_post_url
|
||||
);
|
||||
$notice_name = 'woocommerce_legacy_rest_api_plugin_activated';
|
||||
wc_get_logger()->info( 'WooCommerce activated the Legacy REST API plugin in this site.', array( 'source' => 'plugin_auto_installs' ) );
|
||||
}
|
||||
|
||||
\WC_Admin_Notices::add_custom_notice( $notice_name, $message );
|
||||
} else {
|
||||
$message = sprintf(
|
||||
/* translators: 1 = URL of Legacy REST API plugin page, 2 = URL of Legacy API settings in current site, 3 = URL of webhooks settings in current site, 4 = URL of logs page in current site, 5 = URL of blog post about the Legacy REST API removal */
|
||||
__( '⚠️ WooCommerce attempted to install <a href="%1$s">the Legacy REST API plugin</a> because this site has <a href="%2$s">the Legacy REST API enabled</a> or has <a href="%3$s">legacy webhooks defined</a>, but the installation failed (see error details in <a href="%4$s">the WooCommerce logs</a>). Please install and activate the plugin manually. <a href="%5$s">More information</a>', 'woocommerce' ),
|
||||
$plugin_page_url,
|
||||
$site_legacy_api_settings_url,
|
||||
$site_webhooks_settings_url,
|
||||
$site_logs_url,
|
||||
$blog_post_url
|
||||
);
|
||||
|
||||
\WC_Admin_Notices::add_custom_notice( 'woocommerce_legacy_rest_api_plugin_install_failed', $message );
|
||||
|
||||
// Note that we aren't adding an entry to the error log because PluginInstaller->install_plugin will have done that already.
|
||||
}
|
||||
|
||||
\WC_Admin_Notices::store_notices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the database tables which the plugin needs to function.
|
||||
* WARNING: If you are modifying this method, make sure that its safe to call regardless of the state of database.
|
||||
@@ -1368,7 +1510,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_locations (
|
||||
location_code varchar(200) NOT NULL,
|
||||
location_type varchar(40) NOT NULL,
|
||||
PRIMARY KEY (location_id),
|
||||
KEY location_id (location_id),
|
||||
KEY zone_id (zone_id),
|
||||
KEY location_type_code (location_type(10),location_code(20))
|
||||
) $collate;
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods (
|
||||
@@ -1876,16 +2018,6 @@ $hpos_table_schema;
|
||||
'file' => 'index.html',
|
||||
'content' => '',
|
||||
),
|
||||
array(
|
||||
'base' => WC_LOG_DIR,
|
||||
'file' => '.htaccess',
|
||||
'content' => 'deny from all',
|
||||
),
|
||||
array(
|
||||
'base' => WC_LOG_DIR,
|
||||
'file' => 'index.html',
|
||||
'content' => '',
|
||||
),
|
||||
array(
|
||||
'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
|
||||
'file' => '.htaccess',
|
||||
@@ -1995,14 +2127,14 @@ $hpos_table_schema;
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
$docs_url = apply_filters( 'woocommerce_docs_url', 'https://woo.com/documentation/plugins/woocommerce/' );
|
||||
$docs_url = apply_filters( 'woocommerce_docs_url', 'https://woocommerce.com/documentation/plugins/woocommerce/' );
|
||||
|
||||
/**
|
||||
* The WooCommerce API documentation URL.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
$api_docs_url = apply_filters( 'woocommerce_apidocs_url', 'https://woo.com/wc-apidocs/' );
|
||||
$api_docs_url = apply_filters( 'woocommerce_apidocs_url', 'https://woocommerce.com/wc-apidocs/' );
|
||||
|
||||
/**
|
||||
* The community WooCommerce support URL.
|
||||
@@ -2014,9 +2146,9 @@ $hpos_table_schema;
|
||||
/**
|
||||
* The premium support URL.
|
||||
*
|
||||
* @since
|
||||
* @since 6.7.0
|
||||
*/
|
||||
$support_url = apply_filters( 'woocommerce_support_url', 'https://woo.com/my-account/create-a-ticket/' );
|
||||
$support_url = apply_filters( 'woocommerce_support_url', 'https://woocommerce.com/my-account/create-a-ticket/' );
|
||||
|
||||
$row_meta = array(
|
||||
'docs' => '<a href="' . esc_url( $docs_url ) . '" aria-label="' . esc_attr__( 'View WooCommerce documentation', 'woocommerce' ) . '">' . esc_html__( 'Docs', 'woocommerce' ) . '</a>',
|
||||
@@ -2294,9 +2426,9 @@ $hpos_table_schema;
|
||||
<p><b>This is a sample page.</b></p>
|
||||
<!-- /wp:paragraph -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<h3>Overview</h3>
|
||||
<!-- /wp:paragraph -->
|
||||
<!-- wp:heading -->
|
||||
<h2 class="wp-block-heading">Overview</h2>
|
||||
<!-- /wp:heading -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<p>Our refund and returns policy lasts 30 days. If 30 days have passed since your purchase, we can’t offer you a full refund or exchange.</p>
|
||||
@@ -2355,9 +2487,9 @@ $hpos_table_schema;
|
||||
<p>If you are approved, then your refund will be processed, and a credit will automatically be applied to your credit card or original method of payment, within a certain amount of days.</p>
|
||||
<!-- /wp:paragraph -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<b>Late or missing refunds</b>
|
||||
<!-- /wp:paragraph -->
|
||||
<!-- wp:heading -->
|
||||
<h3 class="wp-block-heading">Late or missing refunds</h3>
|
||||
<!-- /wp:heading -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<p>If you haven’t received a refund yet, first check your bank account again.</p>
|
||||
@@ -2375,9 +2507,9 @@ $hpos_table_schema;
|
||||
<p>If you’ve done all of this and you still have not received your refund yet, please contact us at {email address}.</p>
|
||||
<!-- /wp:paragraph -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<b>Sale items</b>
|
||||
<!-- /wp:paragraph -->
|
||||
<!-- wp:heading -->
|
||||
<h3 class="wp-block-heading">Sale items</h3>
|
||||
<!-- /wp:heading -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<p>Only regular priced items may be refunded. Sale items cannot be refunded.</p>
|
||||
|
||||
@@ -36,7 +36,24 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
* @param string $threshold Optional. Define an explicit threshold. May be configured via WC_LOG_THRESHOLD. By default, all logs will be processed.
|
||||
*/
|
||||
public function __construct( $handlers = null, $threshold = null ) {
|
||||
if ( null === $handlers ) {
|
||||
if ( is_array( $handlers ) ) {
|
||||
$this->handlers = $handlers;
|
||||
}
|
||||
|
||||
if ( is_string( $threshold ) ) {
|
||||
$this->threshold = $threshold;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of log handler instances.
|
||||
*
|
||||
* @return WC_Log_Handler_Interface[]
|
||||
*/
|
||||
protected function get_handlers() {
|
||||
if ( ! is_null( $this->handlers ) ) {
|
||||
$handlers = $this->handlers;
|
||||
} else {
|
||||
$default_handler = LoggingUtil::get_default_handler();
|
||||
$handler_instance = new $default_handler();
|
||||
|
||||
@@ -50,12 +67,12 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
$handlers = apply_filters( 'woocommerce_register_log_handlers', array( $handler_instance ) );
|
||||
}
|
||||
|
||||
$register_handlers = array();
|
||||
$registered_handlers = array();
|
||||
|
||||
if ( ! empty( $handlers ) && is_array( $handlers ) ) {
|
||||
foreach ( $handlers as $handler ) {
|
||||
if ( $handler instanceof WC_Log_Handler_Interface ) {
|
||||
$register_handlers[] = $handler;
|
||||
$registered_handlers[] = $handler;
|
||||
} else {
|
||||
wc_doing_it_wrong(
|
||||
__METHOD__,
|
||||
@@ -71,12 +88,22 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
}
|
||||
}
|
||||
|
||||
return $registered_handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log threshold as a numerical level severity.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function get_threshold() {
|
||||
$threshold = $this->threshold;
|
||||
|
||||
if ( ! WC_Log_Levels::is_valid_level( $threshold ) ) {
|
||||
$threshold = LoggingUtil::get_level_threshold();
|
||||
}
|
||||
|
||||
$this->handlers = $register_handlers;
|
||||
$this->threshold = WC_Log_Levels::get_level_severity( $threshold );
|
||||
return WC_Log_Levels::get_level_severity( $threshold );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,11 +117,9 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null === $this->threshold ) {
|
||||
return true;
|
||||
}
|
||||
$threshold = $this->get_threshold();
|
||||
|
||||
return $this->threshold <= WC_Log_Levels::get_level_severity( $level );
|
||||
return $threshold <= WC_Log_Levels::get_level_severity( $level );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +173,7 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
if ( $this->should_handle( $level ) ) {
|
||||
$timestamp = time();
|
||||
|
||||
foreach ( $this->handlers as $handler ) {
|
||||
foreach ( $this->get_handlers() as $handler ) {
|
||||
/**
|
||||
* Filter the logging message. Returning null will prevent logging from occurring since 5.3.
|
||||
*
|
||||
@@ -296,11 +321,13 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
if ( ! $source ) {
|
||||
return false;
|
||||
}
|
||||
foreach ( $this->handlers as $handler ) {
|
||||
|
||||
foreach ( $this->get_handlers() as $handler ) {
|
||||
if ( is_callable( array( $handler, 'clear' ) ) ) {
|
||||
$handler->clear( $source );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -313,7 +340,7 @@ class WC_Logger implements WC_Logger_Interface {
|
||||
$days = LoggingUtil::get_retention_period();
|
||||
$timestamp = strtotime( "-{$days} days" );
|
||||
|
||||
foreach ( $this->handlers as $handler ) {
|
||||
foreach ( $this->get_handlers() as $handler ) {
|
||||
if ( is_callable( array( $handler, 'delete_logs_before_timestamp' ) ) ) {
|
||||
$handler->delete_logs_before_timestamp( $timestamp );
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class WC_Order_Factory {
|
||||
$order_cache = wc_get_container()->get( OrderCache::class );
|
||||
$order = $order_cache->get( $order_id );
|
||||
if ( ! is_null( $order ) ) {
|
||||
return $order;
|
||||
return 0 === $order->get_id() ? false : $order;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,21 @@ defined( 'ABSPATH' ) || exit;
|
||||
* Order item class.
|
||||
*/
|
||||
class WC_Order_Item extends WC_Data implements ArrayAccess {
|
||||
/**
|
||||
* Legacy cart item values.
|
||||
*
|
||||
* @deprecated 4.4.0 For legacy actions.
|
||||
* @var array
|
||||
*/
|
||||
public $legacy_values;
|
||||
|
||||
/**
|
||||
* Legacy cart item keys.
|
||||
*
|
||||
* @deprecated 4.4.0 For legacy actions.
|
||||
* @var string
|
||||
*/
|
||||
public $legacy_cart_item_key;
|
||||
|
||||
/**
|
||||
* Order Data array. This is the core order data exposed in APIs since 3.0.0.
|
||||
|
||||
@@ -2302,9 +2302,15 @@ class WC_Order extends WC_Abstract_Order {
|
||||
$refunds = $this->get_refunds();
|
||||
if ( $refunds ) {
|
||||
foreach ( $refunds as $id => $refund ) {
|
||||
$reason = trim( $refund->get_reason() );
|
||||
|
||||
if ( strlen( $reason ) > 0 ) {
|
||||
$reason = "<br><small>$reason</small>";
|
||||
}
|
||||
|
||||
$total_rows[ 'refund_' . $id ] = array(
|
||||
'label' => $refund->get_reason() ? $refund->get_reason() : __( 'Refund', 'woocommerce' ) . ':',
|
||||
'value' => wc_price( '-' . $refund->get_amount(), array( 'currency' => $this->get_currency() ) ),
|
||||
'label' => __( 'Refund', 'woocommerce' ) . ':',
|
||||
'value' => wc_price( '-' . $refund->get_amount(), array( 'currency' => $this->get_currency() ) ) . $reason,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ class WC_Payment_Gateways {
|
||||
The payment gateway "%2$s" was just enabled on this site:
|
||||
%3$s
|
||||
|
||||
If this was intentional you can safely ignore and delete this email.
|
||||
If this was intentional you can safely ignore and delete this email.
|
||||
|
||||
If you did not enable this payment gateway, please log in to your site and consider disabling it here:
|
||||
%4$s
|
||||
@@ -400,6 +400,8 @@ All at %6$s
|
||||
* @return bool Whether PayPal Standard should be loaded or not.
|
||||
*/
|
||||
protected function should_load_paypal_standard() {
|
||||
// Tech debt: This class needs to be initialized to make sure any existing subscriptions gets processed as expected, even if the gateway is not enabled for new orders.
|
||||
// Eventually, we want to load this via a singleton pattern to avoid unnecessary instantiation.
|
||||
$paypal = new WC_Gateway_Paypal();
|
||||
return $paypal->should_load();
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ class WC_Product_Download implements ArrayAccess {
|
||||
/* translators: %1$s is the downloadable file path, %2$s is an opening link tag, %3%s is a closing link tag. */
|
||||
__( 'The downloadable file %s cannot be used as it does not exist on the server, or is not located within an approved directory. Please contact a site administrator for help. %2$sLearn more.%3$s', 'woocommerce' ),
|
||||
'<code>' . $download_file . '</code>',
|
||||
'<a href="https://woo.com/document/approved-download-directories">',
|
||||
'<a href="https://woocommerce.com/document/approved-download-directories">',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
|
||||
@@ -108,6 +108,20 @@ class WC_Session_Handler extends WC_Session {
|
||||
$this->_dirty = true;
|
||||
$this->save_data( $guest_session_id );
|
||||
$this->set_customer_session_cookie( true );
|
||||
|
||||
/**
|
||||
* Fires after a customer has logged in, and their guest session id has been
|
||||
* deleted with its data migrated to a customer id.
|
||||
*
|
||||
* This hook gives extensions the chance to connect the old session id to the
|
||||
* customer id, if the key is being used externally.
|
||||
*
|
||||
* @since 8.8.0
|
||||
*
|
||||
* @param string $guest_session_id The former session ID, as generated by `::generate_customer_id()`.
|
||||
* @param int $customer_id The Customer ID that the former session was converted to.
|
||||
*/
|
||||
do_action( 'woocommerce_guest_session_to_user_id', $guest_session_id, $this->_customer_id );
|
||||
}
|
||||
|
||||
// Update session if its close to expiring.
|
||||
|
||||
@@ -15,6 +15,8 @@ use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
||||
use Automattic\WooCommerce\Utilities\{ FeaturesUtil, OrderUtil, PluginUtil };
|
||||
use Automattic\WooCommerce\Internal\Utilities\BlocksUtil;
|
||||
use Automattic\WooCommerce\Proxies\LegacyProxy;
|
||||
use Automattic\WooCommerce\Blocks\Package;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFields;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
@@ -364,7 +366,7 @@ class WC_Tracker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the helper is connected to Woo.com
|
||||
* Check to see if the helper is connected to WooCommerce.com
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -958,7 +960,6 @@ class WC_Tracker {
|
||||
'enable_myaccount_registration' => get_option( 'woocommerce_enable_myaccount_registration' ),
|
||||
'registration_generate_username' => get_option( 'woocommerce_registration_generate_username' ),
|
||||
'registration_generate_password' => get_option( 'woocommerce_registration_generate_password' ),
|
||||
'hpos_enabled' => get_option( 'woocommerce_feature_custom_order_tables_enabled' ),
|
||||
'hpos_sync_enabled' => get_option( 'woocommerce_custom_orders_table_data_sync_enabled' ),
|
||||
'hpos_cot_authoritative' => get_option( 'woocommerce_custom_orders_table_enabled' ),
|
||||
'hpos_transactions_enabled' => get_option( 'woocommerce_use_db_transactions_for_custom_orders_table_data_sync' ),
|
||||
@@ -1090,6 +1091,19 @@ class WC_Tracker {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tracker data for additional fields on the checkout page.
|
||||
*
|
||||
* @return array Array of fields count and names.
|
||||
*/
|
||||
public static function get_checkout_additional_fields_data() {
|
||||
$additional_fields_controller = Package::container()->get( CheckoutFields::class );
|
||||
|
||||
return array(
|
||||
'fields_count' => count( $additional_fields_controller->get_additional_fields() ),
|
||||
'fields_names' => array_keys( $additional_fields_controller->get_additional_fields() ),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Get info about the cart & checkout pages.
|
||||
*
|
||||
@@ -1104,6 +1118,8 @@ class WC_Tracker {
|
||||
|
||||
$pickup_location_data = self::get_pickup_location_data();
|
||||
|
||||
$additional_fields_data = self::get_checkout_additional_fields_data();
|
||||
|
||||
return array(
|
||||
'cart_page_contains_cart_shortcode' => self::post_contains_text(
|
||||
$cart_page_id,
|
||||
@@ -1119,6 +1135,7 @@ class WC_Tracker {
|
||||
'checkout_page_contains_checkout_block' => $checkout_block_data['page_contains_block'],
|
||||
'checkout_block_attributes' => $checkout_block_data['block_attributes'],
|
||||
'pickup_location' => $pickup_location_data,
|
||||
'additional_fields' => $additional_fields_data,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class WC_Validation {
|
||||
break;
|
||||
case 'CZ':
|
||||
case 'SK':
|
||||
$valid = (bool) preg_match( '/^([0-9]{3})(\s?)([0-9]{2})$/', $postcode );
|
||||
$valid = (bool) preg_match( "/^($country-)?([0-9]{3})(\s?)([0-9]{2})$/", $postcode );
|
||||
break;
|
||||
case 'NL':
|
||||
$valid = (bool) preg_match( '/^([1-9][0-9]{3})(\s?)(?!SA|SD|SS)[A-Z]{2}$/i', $postcode );
|
||||
|
||||
@@ -10,6 +10,8 @@ defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Internal\AssignDefaultCategory;
|
||||
use Automattic\WooCommerce\Internal\BatchProcessing\BatchProcessingController;
|
||||
use Automattic\WooCommerce\Internal\ComingSoon\ComingSoonCacheInvalidator;
|
||||
use Automattic\WooCommerce\Internal\ComingSoon\ComingSoonRequestHandler;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
|
||||
use Automattic\WooCommerce\Internal\DownloadPermissionsAdjuster;
|
||||
use Automattic\WooCommerce\Internal\Features\FeaturesController;
|
||||
@@ -23,7 +25,9 @@ use Automattic\WooCommerce\Internal\Settings\OptionSanitizer;
|
||||
use Automattic\WooCommerce\Internal\Utilities\WebhookUtil;
|
||||
use Automattic\WooCommerce\Internal\Admin\Marketplace;
|
||||
use Automattic\WooCommerce\Proxies\LegacyProxy;
|
||||
use Automattic\WooCommerce\Utilities\TimeUtil;
|
||||
use Automattic\WooCommerce\Utilities\{ LoggingUtil, TimeUtil };
|
||||
use Automattic\WooCommerce\Admin\WCAdminHelper;
|
||||
use Automattic\WooCommerce\Admin\Features\Features;
|
||||
|
||||
/**
|
||||
* Main WooCommerce Class.
|
||||
@@ -37,7 +41,7 @@ final class WooCommerce {
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $version = '8.7.0';
|
||||
public $version = '8.9.0';
|
||||
|
||||
/**
|
||||
* WooCommerce Schema version.
|
||||
@@ -269,6 +273,8 @@ final class WooCommerce {
|
||||
$container->get( WebhookUtil::class );
|
||||
$container->get( Marketplace::class );
|
||||
$container->get( TimeUtil::class );
|
||||
$container->get( ComingSoonCacheInvalidator::class );
|
||||
$container->get( ComingSoonRequestHandler::class );
|
||||
|
||||
/**
|
||||
* These classes have a register method for attaching hooks.
|
||||
@@ -366,10 +372,19 @@ final class WooCommerce {
|
||||
$this->define( 'WC_DISCOUNT_ROUNDING_MODE', 2 );
|
||||
$this->define( 'WC_TAX_ROUNDING_MODE', 'yes' === get_option( 'woocommerce_prices_include_tax', 'no' ) ? 2 : 1 );
|
||||
$this->define( 'WC_DELIMITER', '|' );
|
||||
$this->define( 'WC_LOG_DIR', $upload_dir['basedir'] . '/wc-logs/' );
|
||||
$this->define( 'WC_SESSION_CACHE_GROUP', 'wc_session_id' );
|
||||
$this->define( 'WC_TEMPLATE_DEBUG_MODE', false );
|
||||
|
||||
/**
|
||||
* As of 8.8.0, it is preferable to use the `woocommerce_log_directory` filter hook to change the log
|
||||
* directory. WC_LOG_DIR_CUSTOM is a back-compatibility measure so we can tell if `WC_LOG_DIR` has been
|
||||
* defined outside of WC Core.
|
||||
*/
|
||||
if ( defined( 'WC_LOG_DIR' ) ) {
|
||||
$this->define( 'WC_LOG_DIR_CUSTOM', true );
|
||||
}
|
||||
$this->define( 'WC_LOG_DIR', LoggingUtil::get_log_directory() );
|
||||
|
||||
// These three are kept defined for compatibility, but are no longer used.
|
||||
$this->define( 'WC_NOTICE_MIN_PHP_VERSION', '7.2' );
|
||||
$this->define( 'WC_NOTICE_MIN_WP_VERSION', '5.2' );
|
||||
@@ -386,7 +401,6 @@ final class WooCommerce {
|
||||
* The SSR in the name is preserved for bw compatibility, as this was initially used in System Status Report.
|
||||
*/
|
||||
$this->define( 'WC_SSR_PLUGIN_UPDATE_RELEASE_VERSION_TYPE', 'none' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,6 +650,10 @@ final class WooCommerce {
|
||||
include_once WC_ABSPATH . 'includes/admin/class-wc-admin.php';
|
||||
}
|
||||
|
||||
if ( $this->is_request( 'admin' ) || $this->is_request( 'cron' ) ) {
|
||||
include_once WC_ABSPATH . 'includes/admin/class-wc-admin-marketplace-promotions.php';
|
||||
}
|
||||
|
||||
// We load frontend includes in the post editor, because they may be invoked via pre-loading of blocks.
|
||||
$in_post_editor = doing_action( 'load-post.php' ) || doing_action( 'load-post-new.php' );
|
||||
|
||||
@@ -974,7 +992,7 @@ final class WooCommerce {
|
||||
* @param string $filename The filename of the activated plugin.
|
||||
*/
|
||||
public function activated_plugin( $filename ) {
|
||||
include_once dirname( __FILE__ ) . '/admin/helper/class-wc-helper.php';
|
||||
include_once __DIR__ . '/admin/helper/class-wc-helper.php';
|
||||
|
||||
if ( '/woocommerce.php' === substr( $filename, -16 ) ) {
|
||||
set_transient( 'woocommerce_activated_plugin', $filename );
|
||||
@@ -990,7 +1008,7 @@ final class WooCommerce {
|
||||
* @param string $filename The filename of the deactivated plugin.
|
||||
*/
|
||||
public function deactivated_plugin( $filename ) {
|
||||
include_once dirname( __FILE__ ) . '/admin/helper/class-wc-helper.php';
|
||||
include_once __DIR__ . '/admin/helper/class-wc-helper.php';
|
||||
|
||||
WC_Helper::deactivated_plugin( $filename );
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
* @package WooCommerce
|
||||
*/
|
||||
class WC_CLI_COM_Command {
|
||||
const APPLICATION_PASSWORD_SECTION_URL = 'https://woo.com/my-account/#application-passwords';
|
||||
const APPLICATION_PASSWORD_SECTION_URL = 'https://woocommerce.com/my-account/#application-passwords';
|
||||
|
||||
/**
|
||||
* Registers a commands for managing Woo.com extensions.
|
||||
* Registers a commands for managing WooCommerce.com extensions.
|
||||
*/
|
||||
public static function register_commands() {
|
||||
WP_CLI::add_command( 'wc com extension list', array( 'WC_CLI_COM_Command', 'list_extensions' ) );
|
||||
@@ -112,16 +112,16 @@ class WC_CLI_COM_Command {
|
||||
*/
|
||||
public static function disconnect( array $args, array $assoc_args ) {
|
||||
if ( ! WC_Helper::is_site_connected() ) {
|
||||
WP_CLI::error( __( 'Your store is not connected to Woo.com. Run `wp wc com connect` command.', 'woocommerce' ) );
|
||||
WP_CLI::error( __( 'Your store is not connected to WooCommerce.com. Run `wp wc com connect` command.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
WP_CLI::confirm( __( 'Are you sure you want to disconnect your store from Woo.com?', 'woocommerce' ), $assoc_args );
|
||||
WP_CLI::confirm( __( 'Are you sure you want to disconnect your store from WooCommerce.com?', 'woocommerce' ), $assoc_args );
|
||||
WC_Helper::disconnect();
|
||||
WP_CLI::success( __( 'You have successfully disconnected your store from Woo.com', 'woocommerce' ) );
|
||||
WP_CLI::success( __( 'You have successfully disconnected your store from WooCommerce.com', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to Woo.com with application-password.
|
||||
* Connects to WooCommerce.com with application-password.
|
||||
*
|
||||
* [--password]
|
||||
* : If set, password won't be prompt.
|
||||
@@ -161,13 +161,13 @@ class WC_CLI_COM_Command {
|
||||
}
|
||||
|
||||
if ( empty( $password ) ) {
|
||||
// translators: %s is the URL for the application-password section in Woo.com.
|
||||
// translators: %s is the URL for the application-password section in WooCommerce.com.
|
||||
WP_CLI::log( sprintf( __( 'If you don\'t have an application password (not your account password), generate a password from %s', 'woocommerce' ), esc_url( self::APPLICATION_PASSWORD_SECTION_URL ) ) );
|
||||
$password = self::ask( __( 'Connection password:', 'woocommerce' ) );
|
||||
}
|
||||
$password = sanitize_text_field( $password );
|
||||
if ( empty( $password ) ) {
|
||||
// translators: %s is the URL for the application-password section in Woo.com.
|
||||
// translators: %s is the URL for the application-password section in WooCommerce.com.
|
||||
WP_CLI::error( sprintf( __( 'Invalid password. Generate a new one from %s.', 'woocommerce' ), esc_url( self::APPLICATION_PASSWORD_SECTION_URL ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ if ( ! class_exists( 'Plugin_Command' ) ) {
|
||||
*/
|
||||
class WC_CLI_COM_Extension_Command extends Plugin_Command {
|
||||
/**
|
||||
* Registers a commands for managing Woo.com extensions.
|
||||
* Registers a commands for managing WooCommerce.com extensions.
|
||||
*/
|
||||
public static function register_commands() {
|
||||
WP_CLI::add_command( 'wc com extension', 'WC_CLI_COM_Extension_Command' );
|
||||
@@ -50,7 +50,7 @@ class WC_CLI_COM_Extension_Command extends Plugin_Command {
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* # Install the latest version from Woo.com and activate
|
||||
* # Install the latest version from WooCommerce.com and activate
|
||||
* $ wp wc com extension install automatewoo --activate
|
||||
* Downloading install package from http://s3.amazonaws.com/bucketname/automatewoo.zip?AWSAccessKeyId=123&Expires=456&Signature=abcdef......
|
||||
* Using cached file '/home/vagrant/.wp-cli/cache/plugin/automatewoo.zip'...
|
||||
|
||||
@@ -20,6 +20,7 @@ class WC_Shop_Customizer {
|
||||
add_action( 'customize_register', array( $this, 'add_sections' ) );
|
||||
add_action( 'customize_controls_print_styles', array( $this, 'add_styles' ) );
|
||||
add_action( 'customize_controls_print_scripts', array( $this, 'add_scripts' ), 30 );
|
||||
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'add_frontend_scripts' ) );
|
||||
}
|
||||
|
||||
@@ -58,9 +59,34 @@ class WC_Shop_Customizer {
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS styles to improve our form.
|
||||
* CSS styles to disable the Checkout section, when the default checkout page contains the
|
||||
* Checkout block, and to enhance form visuals.
|
||||
*/
|
||||
public function add_styles() {
|
||||
if ( $this->has_block_checkout() ) {
|
||||
?>
|
||||
<style type="text/css">
|
||||
li#accordion-section-woocommerce_checkout {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
li#accordion-section-woocommerce_checkout .accordion-section-title {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
ul#sub-accordion-panel-woocommerce .notice {
|
||||
border-color: #007cba;
|
||||
border-bottom: 0;
|
||||
border-right: 0;
|
||||
border-top: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
<style type="text/css">
|
||||
.woocommerce-cropping-control {
|
||||
@@ -249,6 +275,32 @@ class WC_Shop_Customizer {
|
||||
} );
|
||||
</script>
|
||||
<?php
|
||||
|
||||
if ( $this->has_block_checkout() ) {
|
||||
$message = sprintf(
|
||||
/* translators: %s: Link to the editor page with the Checkout block. */
|
||||
__( 'Checkout can be customized <a href="%s">in the Editor</a> with your active theme.', 'woocommerce' ),
|
||||
admin_url( 'post.php?post=' . get_option( 'woocommerce_checkout_page_id' ) . '&action=edit' )
|
||||
);
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery( document ).ready( function( $ ) {
|
||||
const message = <?php echo wp_json_encode( $message ); ?>;
|
||||
$( "#sub-accordion-panel-woocommerce" ).append( "<li class='notice notice-info'>" + message + "</li>" );
|
||||
} );
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts for the customizer.
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
$handle = 'custom-notice';
|
||||
wp_register_script( $handle, false, array( 'customize-controls' ), WC_VERSION, false );
|
||||
wp_enqueue_script( $handle );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,6 +322,7 @@ class WC_Shop_Customizer {
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_default_catalog_orderby( $value ) {
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
$options = apply_filters(
|
||||
'woocommerce_default_catalog_orderby_options',
|
||||
array(
|
||||
@@ -432,6 +485,7 @@ class WC_Shop_Customizer {
|
||||
)
|
||||
);
|
||||
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
$wp_customize->add_control(
|
||||
'woocommerce_default_catalog_orderby',
|
||||
array(
|
||||
@@ -525,8 +579,10 @@ class WC_Shop_Customizer {
|
||||
private function add_product_images_section( $wp_customize ) {
|
||||
if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) ) {
|
||||
$regen_description = ''; // Nothing to report; Jetpack will handle magically.
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
} elseif ( apply_filters( 'woocommerce_background_image_regeneration', true ) && ! is_multisite() ) {
|
||||
$regen_description = __( 'After publishing your changes, new image sizes will be generated automatically.', 'woocommerce' );
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
} elseif ( apply_filters( 'woocommerce_background_image_regeneration', true ) && is_multisite() ) {
|
||||
/* translators: 1: tools URL 2: regen thumbs url */
|
||||
$regen_description = sprintf( __( 'After publishing your changes, new image sizes may not be shown until you regenerate thumbnails. You can do this from the <a href="%1$s" target="_blank">tools section in WooCommerce</a> or by using a plugin such as <a href="%2$s" target="_blank">Regenerate Thumbnails</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-status&tab=tools' ), 'https://en-gb.wordpress.org/plugins/regenerate-thumbnails/' );
|
||||
@@ -883,11 +939,21 @@ class WC_Shop_Customizer {
|
||||
public function has_terms_and_conditions_page_id() {
|
||||
return wc_terms_and_conditions_page_id() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Weather or not the checkout page contains the Checkout block.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function has_block_checkout() {
|
||||
$post = get_post( get_option( 'woocommerce_checkout_page_id' ) );
|
||||
return strpos( $post->post_content, '<!-- wp:woocommerce/checkout' ) !== false;
|
||||
}
|
||||
}
|
||||
|
||||
global $pagenow;
|
||||
if (
|
||||
$pagenow === 'customize.php' ||
|
||||
'customize.php' === $pagenow ||
|
||||
isset( $_REQUEST['customize_theme'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
! wc_current_theme_is_fse_theme()
|
||||
) {
|
||||
|
||||
@@ -12,6 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// phpcs:disable Squiz.Classes.ClassFileName.NoMatch, Squiz.Classes.ValidClassName.NotCamelCaps -- Backward compatibility.
|
||||
/**
|
||||
* Abstract Order Data Store: Stored in CPT.
|
||||
*
|
||||
@@ -80,6 +81,13 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
}
|
||||
|
||||
$id = wp_insert_post(
|
||||
/**
|
||||
* Filters the data for a new order before it is inserted into the database.
|
||||
*
|
||||
* @param array $data Array of data for the new order.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*/
|
||||
apply_filters(
|
||||
'woocommerce_new_order_data',
|
||||
array(
|
||||
@@ -115,7 +123,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
* @param int $order_id The order id to check.
|
||||
* @return bool True if an order exists with the given name.
|
||||
*/
|
||||
public function order_exists( $order_id ) : bool {
|
||||
public function order_exists( $order_id ): bool {
|
||||
if ( ! $order_id ) {
|
||||
return false;
|
||||
}
|
||||
@@ -135,7 +143,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
$order->set_defaults();
|
||||
$post_object = get_post( $order->get_id() );
|
||||
if ( ! $order->get_id() || ! $post_object || ! in_array( $post_object->post_type, wc_get_order_types(), true ) ) {
|
||||
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
|
||||
throw new Exception( esc_html__( 'Invalid order.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$this->set_order_props(
|
||||
@@ -291,7 +299,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
/**
|
||||
* Fires immediately after an order is deleted.
|
||||
*
|
||||
* @since
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param int $order_id ID of the order that has been deleted.
|
||||
*/
|
||||
@@ -317,7 +325,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
/**
|
||||
* Fires immediately after an order is trashed.
|
||||
*
|
||||
* @since
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param int $order_id ID of the order that has been trashed.
|
||||
*/
|
||||
@@ -345,6 +353,13 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
$order_status = $order->get_status( 'edit' );
|
||||
|
||||
if ( ! $order_status ) {
|
||||
/**
|
||||
* Filters the default order status to use when creating a new order.
|
||||
*
|
||||
* @param string $order_status Default order status.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
$order_status = apply_filters( 'woocommerce_default_order_status', 'pending' );
|
||||
}
|
||||
|
||||
@@ -352,7 +367,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
$valid_statuses = get_post_stati();
|
||||
|
||||
// Add a wc- prefix to the status, but exclude some core statuses which should not be prefixed.
|
||||
// @todo In the future this should only happen based on `wc_is_order_status`, but in order to
|
||||
// In the future this should only happen based on `wc_is_order_status`, but in order to
|
||||
// preserve back-compatibility this happens to all statuses except a select few. A doing_it_wrong
|
||||
// Notice will be needed here, followed by future removal.
|
||||
if ( ! in_array( $post_status, array( 'auto-draft', 'draft', 'trash' ), true ) && in_array( 'wc-' . $post_status, $valid_statuses, true ) ) {
|
||||
@@ -380,7 +395,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
protected function get_post_title() {
|
||||
// @codingStandardsIgnoreStart
|
||||
/* translators: %s: Order date */
|
||||
return sprintf( __( 'Order – %s', 'woocommerce' ), (new DateTime('now'))->format( _x( 'M d, Y @ h:i A', 'Order date parsed by DateTime::format', 'woocommerce' ) ) );
|
||||
return sprintf( __( 'Order – %s', 'woocommerce' ), ( new DateTime( 'now' ) )->format( _x( 'M d, Y @ h:i A', 'Order date parsed by DateTime::format', 'woocommerce' ) ) );
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
@@ -466,6 +481,14 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action fired after updating order properties.
|
||||
*
|
||||
* @param WC_Abstract_Order $order Order object.
|
||||
* @param string[] $updated_props Array of updated properties.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
do_action( 'woocommerce_order_object_updated_props', $order, $updated_props );
|
||||
}
|
||||
|
||||
@@ -491,6 +514,11 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||
public function read_items( $order, $type ) {
|
||||
global $wpdb;
|
||||
|
||||
// When the order is not yet saved, we cannot get the items from DB. Trying to do so will risk reading items of different orders that were saved incorrectly.
|
||||
if ( 0 === $order->get_id() ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Get from cache if available.
|
||||
$items = 0 < $order->get_id() ? wp_cache_get( 'order-items-' . $order->get_id(), 'orders' ) : false;
|
||||
|
||||
|
||||
@@ -95,14 +95,24 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
|
||||
* @param WC_Customer $customer The customer object.
|
||||
*/
|
||||
$allowed_keys = apply_filters( 'woocommerce_customer_allowed_session_meta_keys', array(), $customer );
|
||||
$session_value = wp_json_encode(
|
||||
array_filter(
|
||||
$customer->get_meta_data(),
|
||||
function( $meta_data ) use ( $allowed_keys ) {
|
||||
return in_array( $meta_data->key, $allowed_keys, true );
|
||||
}
|
||||
$session_value = maybe_serialize(
|
||||
array_map(
|
||||
function ( $meta_data ) {
|
||||
// Data comes to us a WC_Meta_Data, we cast it to an array to ensure it is serializable.
|
||||
return array(
|
||||
'key' => $meta_data->key,
|
||||
'value' => $meta_data->value,
|
||||
);
|
||||
},
|
||||
array_filter(
|
||||
$customer->get_meta_data(),
|
||||
function ( $meta_data ) use ( $allowed_keys ) {
|
||||
return in_array( $meta_data->key, $allowed_keys, true );
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
} else {
|
||||
$session_value = $customer->{"get_$function_key"}( 'edit' );
|
||||
}
|
||||
@@ -137,7 +147,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
|
||||
}
|
||||
if ( ! empty( $data[ $session_key ] ) && is_callable( array( $customer, "set_{$function_key}" ) ) ) {
|
||||
if ( 'meta_data' === $session_key ) {
|
||||
$meta_data_values = json_decode( wp_unslash( $data[ $session_key ] ), true );
|
||||
$meta_data_values = maybe_unserialize( $data[ $session_key ] );
|
||||
if ( $meta_data_values ) {
|
||||
foreach ( $meta_data_values as $meta_data_value ) {
|
||||
if ( ! isset( $meta_data_value['key'], $meta_data_value['value'] ) ) {
|
||||
|
||||
@@ -1099,6 +1099,11 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
||||
* @return int Matching variation ID or 0.
|
||||
*/
|
||||
public function find_matching_product_variation( $product, $match_attributes = array() ) {
|
||||
if ( 'variation' === $product->get_type() ) {
|
||||
// Can't get a variation of a variation.
|
||||
return 0;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$meta_attribute_names = array();
|
||||
@@ -1188,10 +1193,11 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
||||
* @todo Add to interface in 4.0.
|
||||
* @param WC_Product $product Variable product.
|
||||
* @param int $limit Limit the number of created variations.
|
||||
* @param array $default_values Key value pairs to set on created variations.
|
||||
* @param array $default_values Key value pairs to set on created variations.
|
||||
* @param array $metadata Key value pairs to set as meta data on created variations.
|
||||
* @return int Number of created variations.
|
||||
*/
|
||||
public function create_all_product_variations( $product, $limit = -1, $default_values = array() ) {
|
||||
public function create_all_product_variations( $product, $limit = -1, $default_values = array(), $metadata = array() ) {
|
||||
$count = 0;
|
||||
|
||||
if ( ! $product ) {
|
||||
@@ -1221,6 +1227,9 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
||||
}
|
||||
$variation = wc_get_product_object( 'variation' );
|
||||
$variation->set_props( $default_values );
|
||||
foreach ( $metadata as $meta ) {
|
||||
$variation->add_meta_data( $meta['key'], $meta['value'] );
|
||||
}
|
||||
$variation->set_parent_id( $product->get_id() );
|
||||
$variation->set_attributes( $possible_attribute );
|
||||
$variation_id = $variation->save();
|
||||
|
||||
@@ -12,9 +12,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
if ( ! class_exists( 'WC_Email_Customer_Invoice', false ) ) :
|
||||
|
||||
/**
|
||||
* Customer Invoice.
|
||||
* Order details email.
|
||||
*
|
||||
* An email sent to the customer via admin.
|
||||
* An email sent to the customer via admin, that summarizes the details of their order. This was
|
||||
* historically referred to as the 'invoice', and for backwards compatibility reasons that is still
|
||||
* reflected in the class name (although on a user-level we have moved away from that nomenclature).
|
||||
*
|
||||
* @class WC_Email_Customer_Invoice
|
||||
* @version 3.5.0
|
||||
@@ -29,8 +31,8 @@ if ( ! class_exists( 'WC_Email_Customer_Invoice', false ) ) :
|
||||
public function __construct() {
|
||||
$this->id = 'customer_invoice';
|
||||
$this->customer_email = true;
|
||||
$this->title = __( 'Customer invoice / Order details', 'woocommerce' );
|
||||
$this->description = __( 'Customer invoice emails can be sent to customers containing their order information and payment links.', 'woocommerce' );
|
||||
$this->title = __( 'Order details', 'woocommerce' );
|
||||
$this->description = __( 'Order detail emails can be sent to customers containing their order information and payment links.', 'woocommerce' );
|
||||
$this->template_html = 'emails/customer-invoice.php';
|
||||
$this->template_plain = 'emails/plain/customer-invoice.php';
|
||||
$this->placeholders = array(
|
||||
@@ -52,11 +54,7 @@ if ( ! class_exists( 'WC_Email_Customer_Invoice', false ) ) :
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_subject( $paid = false ) {
|
||||
if ( $paid ) {
|
||||
return __( 'Invoice for order #{order_number} on {site_title}', 'woocommerce' );
|
||||
} else {
|
||||
return __( 'Your latest {site_title} invoice', 'woocommerce' );
|
||||
}
|
||||
return __( 'Details for order #{order_number} on {site_title}', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,11 +65,7 @@ if ( ! class_exists( 'WC_Email_Customer_Invoice', false ) ) :
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_heading( $paid = false ) {
|
||||
if ( $paid ) {
|
||||
return __( 'Invoice for order #{order_number}', 'woocommerce' );
|
||||
} else {
|
||||
return __( 'Your invoice for order #{order_number}', 'woocommerce' );
|
||||
}
|
||||
return __( 'Details for order #{order_number}', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -139,7 +139,7 @@ if ( ! class_exists( 'WC_Email_Failed_Order', false ) ) :
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_additional_content() {
|
||||
return __( 'Hopefully they’ll be back. Read more about <a href="https://woo.com/document/managing-orders/">troubleshooting failed payments</a>.', 'woocommerce' );
|
||||
return __( 'Hopefully they’ll be back. Read more about <a href="https://woocommerce.com/document/managing-orders/">troubleshooting failed payments</a>.', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -527,27 +527,32 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
|
||||
$should_load = $this->get_option( $option_key );
|
||||
|
||||
if ( '' === $should_load ) {
|
||||
|
||||
// New installs without PayPal Standard enabled don't load it.
|
||||
if ( 'no' === $this->enabled && WC_Install::is_new_install() ) {
|
||||
$should_load = false;
|
||||
} else {
|
||||
$should_load = true;
|
||||
}
|
||||
// Set default `_should_load` to 'yes' on existing stores with PayPal Standard enabled or with existing PayPal Standard orders.
|
||||
$should_load = 'yes' === $this->enabled || $this->has_paypal_orders();
|
||||
|
||||
$this->update_option( $option_key, wc_bool_to_string( $should_load ) );
|
||||
} else {
|
||||
$should_load = wc_string_to_bool( $should_load );
|
||||
// Enabled always takes precedence over the option.
|
||||
$should_load = wc_string_to_bool( $this->enabled ) || wc_string_to_bool( $should_load );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow third-parties to filter whether PayPal Standard should be loaded or not.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param bool $should_load Whether PayPal Standard should be loaded.
|
||||
* @param WC_Gateway_Paypal $this The WC_Gateway_Paypal instance.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_should_load_paypal_standard', $should_load, $this );
|
||||
return $should_load;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the store has at least one PayPal Standand order.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_paypal_orders() {
|
||||
$paypal_orders = wc_get_orders(
|
||||
array(
|
||||
'limit' => 1,
|
||||
'return' => 'ids',
|
||||
'payment_method' => 'paypal',
|
||||
)
|
||||
);
|
||||
|
||||
return is_countable( $paypal_orders ) ? 1 === count( $paypal_orders ) : false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -747,7 +747,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
|
||||
// Unlimited, set to 32GB.
|
||||
$memory_limit = '32000M';
|
||||
}
|
||||
return intval( $memory_limit ) * 1024 * 1024;
|
||||
return wp_convert_hr_to_bytes( $memory_limit );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -106,7 +106,7 @@ class WC_Integration_MaxMind_Geolocation extends WC_Integration {
|
||||
'The key that will be used when dealing with MaxMind Geolocation services. You can read how to generate one in <a href="%1$s">MaxMind Geolocation Integration documentation</a>.',
|
||||
'woocommerce'
|
||||
),
|
||||
'https://woo.com/document/maxmind-geolocation-integration/'
|
||||
'https://woocommerce.com/document/maxmind-geolocation-integration/'
|
||||
),
|
||||
'desc_tip' => false,
|
||||
'default' => '',
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
use Automattic\Jetpack\Constants;
|
||||
use Automattic\WooCommerce\Utilities\LoggingUtil;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
@@ -251,13 +252,14 @@ class WC_Log_Handler_File extends WC_Log_Handler {
|
||||
* @return bool
|
||||
*/
|
||||
public function remove( $handle ) {
|
||||
$removed = false;
|
||||
$logs = $this->get_log_files();
|
||||
$handle = sanitize_title( $handle );
|
||||
$removed = false;
|
||||
$logs = $this->get_log_files();
|
||||
$log_directory = LoggingUtil::get_log_directory();
|
||||
$handle = sanitize_title( $handle );
|
||||
|
||||
if ( isset( $logs[ $handle ] ) && $logs[ $handle ] ) {
|
||||
$file = realpath( trailingslashit( WC_LOG_DIR ) . $logs[ $handle ] );
|
||||
if ( 0 === stripos( $file, realpath( trailingslashit( WC_LOG_DIR ) ) ) && is_file( $file ) && is_writable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
|
||||
$file = realpath( trailingslashit( $log_directory ) . $logs[ $handle ] );
|
||||
if ( 0 === stripos( $file, realpath( trailingslashit( $log_directory ) ) ) && is_file( $file ) && is_writable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
|
||||
$this->close( $file ); // Close first to be certain no processes keep it alive after it is unlinked.
|
||||
$removed = unlink( $file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink
|
||||
}
|
||||
@@ -349,8 +351,10 @@ class WC_Log_Handler_File extends WC_Log_Handler {
|
||||
* @return bool|string The log file path or false if path cannot be determined.
|
||||
*/
|
||||
public static function get_log_file_path( $handle ) {
|
||||
$log_directory = LoggingUtil::get_log_directory();
|
||||
|
||||
if ( function_exists( 'wp_hash' ) ) {
|
||||
return trailingslashit( WC_LOG_DIR ) . self::get_log_file_name( $handle );
|
||||
return trailingslashit( $log_directory ) . self::get_log_file_name( $handle );
|
||||
} else {
|
||||
wc_doing_it_wrong( __METHOD__, __( 'This method should not be called before plugins_loaded.', 'woocommerce' ), '3.0' );
|
||||
return false;
|
||||
@@ -410,13 +414,14 @@ class WC_Log_Handler_File extends WC_Log_Handler {
|
||||
return;
|
||||
}
|
||||
|
||||
$log_files = self::get_log_files();
|
||||
$log_files = self::get_log_files();
|
||||
$log_directory = LoggingUtil::get_log_directory();
|
||||
|
||||
foreach ( $log_files as $log_file ) {
|
||||
$last_modified = filemtime( trailingslashit( WC_LOG_DIR ) . $log_file );
|
||||
$last_modified = filemtime( trailingslashit( $log_directory ) . $log_file );
|
||||
|
||||
if ( $last_modified < $timestamp ) {
|
||||
@unlink( trailingslashit( WC_LOG_DIR ) . $log_file ); // @codingStandardsIgnoreLine.
|
||||
@unlink( trailingslashit( $log_directory ) . $log_file ); // @codingStandardsIgnoreLine.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,7 +433,9 @@ class WC_Log_Handler_File extends WC_Log_Handler {
|
||||
* @return array
|
||||
*/
|
||||
public static function get_log_files() {
|
||||
$files = @scandir( WC_LOG_DIR ); // @codingStandardsIgnoreLine.
|
||||
$log_directory = LoggingUtil::get_log_directory();
|
||||
|
||||
$files = @scandir( $log_directory ); // @codingStandardsIgnoreLine.
|
||||
$result = array();
|
||||
|
||||
if ( ! empty( $files ) ) {
|
||||
|
||||
@@ -9,7 +9,7 @@ if ( ! function_exists( 'wc_admin_get_feature_config' ) ) {
|
||||
'product-block-editor' => true,
|
||||
'coupons' => true,
|
||||
'core-profiler' => true,
|
||||
'customize-store' => false,
|
||||
'customize-store' => true,
|
||||
'customer-effort-score-tracks' => true,
|
||||
'import-products-task' => true,
|
||||
'experimental-fashion-sample-products' => true,
|
||||
@@ -28,7 +28,8 @@ if ( ! function_exists( 'wc_admin_get_feature_config' ) ) {
|
||||
'product-external-affiliate' => true,
|
||||
'product-grouped' => true,
|
||||
'product-linked' => true,
|
||||
'product-pre-publish-modal' => false,
|
||||
'product-pre-publish-modal' => true,
|
||||
'product-custom-fields' => true,
|
||||
'remote-inbox-notifications' => true,
|
||||
'remote-free-extensions' => true,
|
||||
'payment-gateway-suggestions' => true,
|
||||
@@ -41,6 +42,7 @@ if ( ! function_exists( 'wc_admin_get_feature_config' ) ) {
|
||||
'wc-pay-promotion' => true,
|
||||
'wc-pay-welcome-page' => true,
|
||||
'async-product-editor-category-field' => false,
|
||||
'launch-your-store' => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,7 +558,7 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
),
|
||||
),
|
||||
'wccom_connected' => array(
|
||||
'description' => __( 'Is store connected to Woo.com?', 'woocommerce' ),
|
||||
'description' => __( 'Is store connected to WooCommerce.com?', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
@@ -569,12 +569,6 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'HPOS_feature_screen_enabled' => array(
|
||||
'description' => __( 'Is HPOS feature screen enabled?', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'HPOS_enabled' => array(
|
||||
'description' => __( 'Is HPOS enabled?', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
@@ -855,7 +849,7 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
|
||||
if ( false === $get_response_code || is_wp_error( $get_response_code ) ) {
|
||||
$response = wp_safe_remote_get(
|
||||
'https://woo.com/wc-api/product-key-api?request=ping&network=' . ( is_multisite() ? '1' : '0' ),
|
||||
'https://woocommerce.com/wc-api/product-key-api?request=ping&network=' . ( is_multisite() ? '1' : '0' ),
|
||||
array(
|
||||
'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ),
|
||||
)
|
||||
@@ -870,6 +864,7 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
}
|
||||
|
||||
$database_version = wc_get_server_database_version();
|
||||
$log_directory = LoggingUtil::get_log_directory();
|
||||
|
||||
// Return all environment info. Described by JSON Schema.
|
||||
return array(
|
||||
@@ -877,8 +872,8 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
'site_url' => get_option( 'siteurl' ),
|
||||
'store_id' => get_option( \WC_Install::STORE_ID_OPTION, null ),
|
||||
'version' => WC()->version,
|
||||
'log_directory' => WC_LOG_DIR,
|
||||
'log_directory_writable' => (bool) @fopen( WC_LOG_DIR . 'test-log.log', 'a' ), // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
|
||||
'log_directory' => $log_directory,
|
||||
'log_directory_writable' => wp_is_writable( $log_directory ),
|
||||
'wp_version' => get_bloginfo( 'version' ),
|
||||
'wp_multisite' => is_multisite(),
|
||||
'wp_memory_limit' => $wp_memory_limit,
|
||||
@@ -1069,7 +1064,7 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of inplugins active on the site.
|
||||
* Get a list of inactive plugins.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -1348,7 +1343,6 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
||||
'woocommerce_com_connected' => ConnectionHelper::is_connected() ? 'yes' : 'no',
|
||||
'enforce_approved_download_dirs' => wc_get_container()->get( Download_Directories::class )->get_mode() === Download_Directories::MODE_ENABLED,
|
||||
'order_datastore' => WC_Data_Store::load( 'order' )->get_current_class_name(),
|
||||
'HPOS_feature_screen_enabled' => wc_get_container()->get( Automattic\WooCommerce\Internal\Features\FeaturesController::class )->feature_is_enabled( 'custom_order_tables' ),
|
||||
'HPOS_enabled' => OrderUtil::custom_orders_table_usage_is_enabled(),
|
||||
'HPOS_sync_enabled' => wc_get_container()->get( Order_DataSynchronizer::class )->data_sync_is_enabled(),
|
||||
);
|
||||
|
||||
@@ -1121,8 +1121,9 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Product_Variations_V
|
||||
$response = array();
|
||||
$product = wc_get_product( $product_id );
|
||||
$default_values = isset( $request['default_values'] ) ? $request['default_values'] : array();
|
||||
$meta_data = isset( $request['meta_data'] ) ? $request['meta_data'] : array();
|
||||
$data_store = $product->get_data_store();
|
||||
$response['count'] = $data_store->create_all_product_variations( $product, Constants::get_constant( 'WC_MAX_LINKED_VARIATIONS' ), $default_values );
|
||||
$response['count'] = $data_store->create_all_product_variations( $product, Constants::get_constant( 'WC_MAX_LINKED_VARIATIONS' ), $default_values, $meta_data );
|
||||
|
||||
if ( isset( $request['delete'] ) && $request['delete'] ) {
|
||||
$deleted_count = $this->delete_unmatched_product_variations( $product );
|
||||
|
||||
@@ -62,6 +62,54 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\d]+)/duplicate',
|
||||
array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'duplicate_product' ),
|
||||
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a product and returns the duplicated product.
|
||||
* The product status is set to "draft" and the name includes a "(copy)" at the end by default.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function duplicate_product( $request ) {
|
||||
$product_id = $request->get_param( 'id' );
|
||||
$product = wc_get_product( $product_id );
|
||||
|
||||
if ( ! $product ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_invalid_id', __( 'Invalid product ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
// Creating product object from request data in preparation for copying.
|
||||
$updated_product = $this->prepare_object_for_database( $request );
|
||||
$duplicated_product = ( new WC_Admin_Duplicate_Product() )->product_duplicate( $updated_product );
|
||||
|
||||
if ( is_wp_error( $duplicated_product ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_duplicate_error', $duplicated_product->get_error_message(), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$response_data = $duplicated_product->get_data();
|
||||
|
||||
return new WP_REST_Response( $response_data, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,7 +373,7 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
||||
global $wpdb;
|
||||
if ( ! empty( $this->search_sku_in_product_lookup_table ) ) {
|
||||
$like_search = '%' . $wpdb->esc_like( $this->search_sku_in_product_lookup_table ) . '%';
|
||||
$where .= ' AND ' . $wpdb->prepare( '(wc_product_meta_lookup.sku LIKE %s)', $like_search );
|
||||
$where .= ' AND ' . $wpdb->prepare( '(wc_product_meta_lookup.sku LIKE %s)', $like_search );
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
@@ -1112,7 +1160,7 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'low_stock_amount' => array(
|
||||
'low_stock_amount' => array(
|
||||
'description' => __( 'Low Stock amount for the product.', 'woocommerce' ),
|
||||
'type' => array( 'integer', 'null' ),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
@@ -1344,7 +1392,7 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
||||
),
|
||||
),
|
||||
),
|
||||
'has_options' => array(
|
||||
'has_options' => array(
|
||||
'description' => __( 'Shows if the product needs to be configured before it can be bought.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Utilities\OrderUtil;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
@@ -39,18 +41,18 @@ class WC_REST_Report_Orders_Totals_Controller extends WC_REST_Reports_Controller
|
||||
* @return array
|
||||
*/
|
||||
protected function get_reports() {
|
||||
$totals = wp_count_posts( 'shop_order' );
|
||||
$totals = OrderUtil::get_count_for_type( 'shop_order' );
|
||||
$data = array();
|
||||
|
||||
foreach ( wc_get_order_statuses() as $slug => $name ) {
|
||||
if ( ! isset( $totals->$slug ) ) {
|
||||
if ( ! array_key_exists( $slug, $totals ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = array(
|
||||
'slug' => str_replace( 'wc-', '', $slug ),
|
||||
'name' => $name,
|
||||
'total' => (int) $totals->$slug,
|
||||
'total' => (int) $totals[ $slug ],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$cost_desc = __( 'Enter a cost (excl. tax) or sum, e.g. <code>10.00 * [qty]</code>.', 'woocommerce' ) . '<br/><br/>' . __( 'Use <code>[qty]</code> for the number of items, <br/><code>[cost]</code> for the total cost of items, and <code>[fee percent="10" min_fee="20" max_fee=""]</code> for percentage based fees.', 'woocommerce' );
|
||||
$cost_link = sprintf( '<span id="wc-shipping-advanced-costs-help-text">%s <a target="_blank" href="https://woo.com/document/flat-rate-shipping/#advanced-costs">%s</a>.</span>', __( 'Charge a flat rate per item, or enter a cost formula to charge a percentage based cost or a minimum fee. Learn more about', 'woocommerce' ), __( 'advanced costs', 'woocommerce' ) );
|
||||
$cost_link = sprintf( '<span id="wc-shipping-advanced-costs-help-text">%s <a target="_blank" href="https://woocommerce.com/document/flat-rate-shipping/#advanced-costs">%s</a>.</span>', __( 'Charge a flat rate per item, or enter a cost formula to charge a percentage based cost or a minimum fee. Learn more about', 'woocommerce' ), __( 'advanced costs', 'woocommerce' ) );
|
||||
|
||||
$settings = array(
|
||||
'title' => array(
|
||||
@@ -49,7 +49,7 @@ if ( ! empty( $shipping_classes ) ) {
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
/* translators: %s: URL for link */
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the <a target="_blank" href="%s">product shipping class</a>. Learn more about <a target="_blank" href="https://woo.com/document/flat-rate-shipping/#shipping-classes">setting shipping class costs</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=classes' ) ),
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the <a target="_blank" href="%s">product shipping class</a>. Learn more about <a target="_blank" href="https://woocommerce.com/document/flat-rate-shipping/#shipping-classes">setting shipping class costs</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=classes' ) ),
|
||||
);
|
||||
foreach ( $shipping_classes as $shipping_class ) {
|
||||
if ( ! isset( $shipping_class->term_id ) ) {
|
||||
|
||||
@@ -16,6 +16,12 @@ require_once WC_ABSPATH . 'includes/admin/wc-admin-functions.php';
|
||||
* This class adds actions to track usage of WooCommerce Products.
|
||||
*/
|
||||
class WC_Products_Tracking {
|
||||
|
||||
/**
|
||||
* Tracks source.
|
||||
*/
|
||||
const TRACKS_SOURCE = 'product-legacy-editor';
|
||||
|
||||
/**
|
||||
* Init tracking.
|
||||
*/
|
||||
@@ -118,9 +124,13 @@ class WC_Products_Tracking {
|
||||
return;
|
||||
}
|
||||
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
$source = apply_filters( 'woocommerce_product_source', self::TRACKS_SOURCE );
|
||||
$properties = array(
|
||||
'product_id' => $product_id,
|
||||
'source' => $source,
|
||||
);
|
||||
/* phpcs: enable */
|
||||
|
||||
WC_Tracks::record_event( 'product_edit', $properties );
|
||||
}
|
||||
@@ -331,7 +341,7 @@ class WC_Products_Tracking {
|
||||
'product_type_options' => $product_type_options_string,
|
||||
'purchase_note' => $product->get_purchase_note() ? 'yes' : 'no',
|
||||
'sale_price' => $product->get_sale_price() ? 'yes' : 'no',
|
||||
'source' => apply_filters( 'woocommerce_product_source', '' ),
|
||||
'source' => apply_filters( 'woocommerce_product_source', self::TRACKS_SOURCE ),
|
||||
'short_description' => $product->get_short_description() ? 'yes' : 'no',
|
||||
'tags' => count( $product->get_tag_ids() ),
|
||||
'upsells' => ! empty( $product->get_upsell_ids() ) ? 'yes' : 'no',
|
||||
|
||||
@@ -393,7 +393,7 @@ function wc_get_account_saved_payment_methods_list_item_cc( $item, $payment_toke
|
||||
|
||||
$card_type = $payment_token->get_card_type();
|
||||
$item['method']['last4'] = $payment_token->get_last4();
|
||||
$item['method']['brand'] = ( ! empty( $card_type ) ? ucfirst( $card_type ) : esc_html__( 'Credit card', 'woocommerce' ) );
|
||||
$item['method']['brand'] = ( ! empty( $card_type ) ? ucwords( str_replace( '_', ' ', $card_type ) ) : esc_html__( 'Credit card', 'woocommerce' ) );
|
||||
$item['expires'] = $payment_token->get_expiry_month() . '/' . substr( $payment_token->get_expiry_year(), -2 );
|
||||
|
||||
return $item;
|
||||
|
||||
@@ -283,8 +283,6 @@ function wc_cart_totals_coupon_html( $coupon ) {
|
||||
$coupon = new WC_Coupon( $coupon );
|
||||
}
|
||||
|
||||
$discount_amount_html = '';
|
||||
|
||||
$amount = WC()->cart->get_coupon_discount_amount( $coupon->get_code(), WC()->cart->display_cart_ex_tax );
|
||||
$discount_amount_html = '-' . wc_price( $amount );
|
||||
|
||||
|
||||
@@ -1539,12 +1539,18 @@ function wc_get_credit_card_type_label( $type ) {
|
||||
'visa' => _x( 'Visa', 'Name of credit card', 'woocommerce' ),
|
||||
'discover' => _x( 'Discover', 'Name of credit card', 'woocommerce' ),
|
||||
'american express' => _x( 'American Express', 'Name of credit card', 'woocommerce' ),
|
||||
'cartes bancaires' => _x( 'Cartes Bancaires', 'Name of credit card', 'woocommerce' ),
|
||||
'diners' => _x( 'Diners', 'Name of credit card', 'woocommerce' ),
|
||||
'jcb' => _x( 'JCB', 'Name of credit card', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
return apply_filters( 'woocommerce_get_credit_card_type_label', ( array_key_exists( $type, $labels ) ? $labels[ $type ] : ucfirst( $type ) ) );
|
||||
/**
|
||||
* Fallback to title case, uppercasing the first letter of each word.
|
||||
*
|
||||
* @since 8.9.0
|
||||
*/
|
||||
return apply_filters( 'woocommerce_get_credit_card_type_label', ( array_key_exists( $type, $labels ) ? $labels[ $type ] : ucwords( $type ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1554,7 +1560,7 @@ function wc_get_credit_card_type_label( $type ) {
|
||||
* @param string $url URL of the page to return to.
|
||||
*/
|
||||
function wc_back_link( $label, $url ) {
|
||||
echo '<small class="wc-admin-breadcrumb"><a href="' . esc_url( $url ) . '" aria-label="' . esc_attr( $label ) . '">⤴</a></small>';
|
||||
echo '<small class="wc-admin-breadcrumb"><a href="' . esc_url( $url ) . '" aria-label="' . esc_attr( $label ) . '">⤴︎</a></small>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1894,7 +1900,16 @@ function wc_get_rounding_precision() {
|
||||
if ( $precision < absint( WC_ROUNDING_PRECISION ) ) {
|
||||
$precision = absint( WC_ROUNDING_PRECISION );
|
||||
}
|
||||
return $precision;
|
||||
|
||||
/**
|
||||
* Filter the rounding precision for internal WC calculations. This is different from the number of decimals used for display.
|
||||
* Generally, this filter can be used to decrease the precision, but if you choose to decrease, there maybe side effects such as off by one rounding errors for certain tax rate combinations.
|
||||
*
|
||||
* @since 8.8.0
|
||||
*
|
||||
* @param int $precision The number of decimals to round to.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_internal_rounding_precision', $precision );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1156,7 +1156,7 @@ function wc_register_default_log_handler( $handlers = array() ) {
|
||||
function wc_get_log_file_path( $handle ) {
|
||||
wc_deprecated_function( 'wc_get_log_file_path', '8.6.0' );
|
||||
|
||||
$directory = trailingslashit( realpath( Constants::get_constant( 'WC_LOG_DIR' ) ) );
|
||||
$directory = LoggingUtil::get_log_directory();
|
||||
$file_id = LoggingUtil::generate_log_file_id( $handle, null, time() );
|
||||
$hash = LoggingUtil::generate_log_file_hash( $file_id );
|
||||
|
||||
|
||||
@@ -979,6 +979,9 @@ function wc_format_postcode( $postcode, $country ) {
|
||||
$postcode = wc_normalize_postcode( $postcode ?? '' );
|
||||
|
||||
switch ( $country ) {
|
||||
case 'SE':
|
||||
$postcode = substr_replace( $postcode, ' ', -2, 0 );
|
||||
break;
|
||||
case 'CA':
|
||||
case 'GB':
|
||||
$postcode = substr_replace( $postcode, ' ', -3, 0 );
|
||||
@@ -1004,9 +1007,12 @@ function wc_format_postcode( $postcode, $country ) {
|
||||
$postcode = substr_replace( $postcode, ' ', 4, 0 );
|
||||
break;
|
||||
case 'LV':
|
||||
if ( preg_match( '/(?:LV)?-?(\d+)/i', $postcode, $matches ) ) {
|
||||
$postcode = count( $matches ) >= 2 ? "LV-$matches[1]" : $postcode;
|
||||
}
|
||||
$postcode = preg_replace( '/^(LV)?-?(\d+)$/', 'LV-${2}', $postcode );
|
||||
break;
|
||||
case 'CZ':
|
||||
case 'SK':
|
||||
$postcode = preg_replace( "/^({$country})-?(\d+)$/", '${1}-${2}', $postcode );
|
||||
$postcode = substr_replace( $postcode, ' ', -2, 0 );
|
||||
break;
|
||||
case 'DK':
|
||||
$postcode = preg_replace( '/^(DK)(.+)$/', '${1}-${2}', $postcode );
|
||||
@@ -1290,7 +1296,28 @@ function wc_format_stock_quantity_for_display( $stock_quantity, $product ) {
|
||||
* @return string
|
||||
*/
|
||||
function wc_format_sale_price( $regular_price, $sale_price ) {
|
||||
$price = '<del aria-hidden="true">' . ( is_numeric( $regular_price ) ? wc_price( $regular_price ) : $regular_price ) . '</del> <ins>' . ( is_numeric( $sale_price ) ? wc_price( $sale_price ) : $sale_price ) . '</ins>';
|
||||
// Format the prices.
|
||||
$formatted_regular_price = is_numeric( $regular_price ) ? wc_price( $regular_price ) : $regular_price;
|
||||
$formatted_sale_price = is_numeric( $sale_price ) ? wc_price( $sale_price ) : $sale_price;
|
||||
|
||||
// Strikethrough pricing.
|
||||
$price = '<del aria-hidden="true">' . $formatted_regular_price . '</del> ';
|
||||
|
||||
// For accessibility (a11y) we'll also display that information to screen readers.
|
||||
$price .= '<span class="screen-reader-text">';
|
||||
// translators: %s is a product's regular price.
|
||||
$price .= esc_html( sprintf( __( 'Original price was: %s.', 'woocommerce' ), wp_strip_all_tags( $formatted_regular_price ) ) );
|
||||
$price .= '</span>';
|
||||
|
||||
// Add the sale price.
|
||||
$price .= '<ins aria-hidden="true">' . $formatted_sale_price . '</ins>';
|
||||
|
||||
// For accessibility (a11y) we'll also display that information to screen readers.
|
||||
$price .= '<span class="screen-reader-text">';
|
||||
// translators: %s is a product's current (sale) price.
|
||||
$price .= esc_html( sprintf( __( 'Current price is: %s.', 'woocommerce' ), wp_strip_all_tags( $formatted_sale_price ) ) );
|
||||
$price .= '</span>';
|
||||
|
||||
return apply_filters( 'woocommerce_format_sale_price', $price, $regular_price, $sale_price );
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user