+
' . __( 'Welcome to the store', 'woocommerce-admin' ) . '
-
-
' . __( 'Write a short welcome message here', 'woocommerce-admin' ) . '
+
+
' . __( 'Write a short welcome message here', 'woocommerce-admin' ) . '
@@ -319,12 +319,7 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
$industry_images = array();
$industries = Onboarding::get_allowed_industries();
foreach ( $industries as $industry_slug => $label ) {
- $file_path = WC_ADMIN_ABSPATH . 'images/onboarding/' . $industry_slug . '.jpg';
- if ( 'other' === $industry_slug || ! file_exists( $file_path ) ) {
- $industry_images[ $industry_slug ] = apply_filters( 'woocommerce_admin_onboarding_industry_image', plugins_url( 'images/onboarding/other.jpg', WC_ADMIN_PLUGIN_FILE ), $industry_slug );
- continue;
- }
- $industry_images[ $industry_slug ] = apply_filters( 'woocommerce_admin_onboarding_industry_image', plugins_url( 'images/onboarding/' . $industry_slug . '.jpg', WC_ADMIN_PLUGIN_FILE ), $industry_slug );
+ $industry_images[ $industry_slug ] = apply_filters( 'woocommerce_admin_onboarding_industry_image', plugins_url( 'images/onboarding/other-small.jpg', WC_ADMIN_PLUGIN_FILE ), $industry_slug );
}
return $industry_images;
}
@@ -347,14 +342,25 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
if ( ! empty( $profile['industry'] ) ) {
foreach ( $profile['industry'] as $selected_industry ) {
- $images_to_sideload[] = ! empty( $available_images[ $selected_industry ] ) ? $available_images[ $selected_industry ] : $available_images['other'];
+ if ( is_string( $selected_industry ) ) {
+ $industry_slug = $selected_industry;
+ } elseif ( is_array( $selected_industry ) && ! empty( $selected_industry['slug'] ) ) {
+ $industry_slug = $selected_industry['slug'];
+ } else {
+ continue;
+ }
+ // Capture the first industry for use in our minimum images logic.
+ $first_industry = isset( $first_industry ) ? $first_industry : $industry_slug;
+ $images_to_sideload[] = ! empty( $available_images[ $industry_slug ] ) ? $available_images[ $industry_slug ] : $available_images['other'];
}
}
// Make sure we have at least {$number_of_images} images.
if ( count( $images_to_sideload ) < $number_of_images ) {
for ( $i = count( $images_to_sideload ); $i < $number_of_images; $i++ ) {
- $images_to_sideload[] = ! empty( $profile['industry'] ) && ! empty( $available_images[ $profile['industry'][0] ] ) ? $available_images[ $profile['industry'][0] ] : $available_images['other'];
+ // Fill up missing image slots with the first selected industry, or other.
+ $industry = isset( $first_industry ) ? $first_industry : 'other';
+ $images_to_sideload[] = empty( $available_images[ $industry ] ) ? $available_images['other'] : $available_images[ $industry ];
}
}
@@ -402,7 +408,7 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
array(
'post_title' => __( 'Homepage', 'woocommerce-admin' ),
'post_type' => 'page',
- 'post_status' => 'draft',
+ 'post_status' => 'publish',
'post_content' => '', // Template content is updated below, so images can be attached to the post.
)
);
@@ -417,11 +423,13 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
)
);
+ update_option( 'show_on_front', 'page' );
+ update_option( 'page_on_front', $post_id );
update_option( 'woocommerce_onboarding_homepage_post_id', $post_id );
return array(
'status' => 'success',
- 'message' => __( 'Homepage created successfully.', 'woocommerce-admin' ),
+ 'message' => __( 'Homepage created.', 'woocommerce-admin' ),
'post_id' => $post_id,
'edit_post_link' => htmlspecialchars_decode( get_edit_post_link( $post_id ) ),
);
diff --git a/plugins/woocommerce-admin/src/API/Products.php b/plugins/woocommerce-admin/src/API/Products.php
index 7b8e867e950..ecc207eccde 100644
--- a/plugins/woocommerce-admin/src/API/Products.php
+++ b/plugins/woocommerce-admin/src/API/Products.php
@@ -127,6 +127,7 @@ class Products extends \WC_REST_Products_Controller {
if ( $request->get_param( 'low_in_stock' ) && is_numeric( $object_data['low_stock_amount'] ) ) {
$data->data['low_stock_amount'] = $object_data['low_stock_amount'];
}
+ $data->data['name'] = wp_strip_all_tags( $data->data['name'] );
return $data;
}
diff --git a/plugins/woocommerce-admin/src/API/Reports/Products/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Products/Controller.php
index 6e01cf98cb1..067b5fc80d8 100644
--- a/plugins/woocommerce-admin/src/API/Reports/Products/Controller.php
+++ b/plugins/woocommerce-admin/src/API/Reports/Products/Controller.php
@@ -70,7 +70,10 @@ class Controller extends \WC_REST_Reports_Controller implements ExportableInterf
$data = array();
foreach ( $products_data->data as $product_data ) {
- $item = $this->prepare_item_for_response( $product_data, $request );
+ $item = $this->prepare_item_for_response( $product_data, $request );
+ if ( isset( $item->data['extended_info']['name'] ) ) {
+ $item->data['extended_info']['name'] = wp_strip_all_tags( $item->data['extended_info']['name'] );
+ }
$data[] = $this->prepare_response_for_collection( $item );
}
diff --git a/plugins/woocommerce-admin/src/API/Reports/Stock/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Stock/Controller.php
index 7088fc281d0..99190a47b4b 100644
--- a/plugins/woocommerce-admin/src/API/Reports/Stock/Controller.php
+++ b/plugins/woocommerce-admin/src/API/Reports/Stock/Controller.php
@@ -290,7 +290,7 @@ class Controller extends \WC_REST_Reports_Controller implements ExportableInterf
$data = array(
'id' => $product->get_id(),
'parent_id' => $product->get_parent_id(),
- 'name' => $product->get_name(),
+ 'name' => wp_strip_all_tags( $product->get_name() ),
'sku' => $product->get_sku(),
'stock_status' => $product->get_stock_status(),
'stock_quantity' => (float) $product->get_stock_quantity(),
diff --git a/plugins/woocommerce-admin/src/FeaturePlugin.php b/plugins/woocommerce-admin/src/FeaturePlugin.php
index 32edccfea1d..98bf7a79a51 100644
--- a/plugins/woocommerce-admin/src/FeaturePlugin.php
+++ b/plugins/woocommerce-admin/src/FeaturePlugin.php
@@ -148,7 +148,7 @@ class FeaturePlugin {
$this->define( 'WC_ADMIN_PLUGIN_FILE', WC_ADMIN_ABSPATH . 'woocommerce-admin.php' );
// WARNING: Do not directly edit this version number constant.
// It is updated as part of the prebuild process from the package.json value.
- $this->define( 'WC_ADMIN_VERSION_NUMBER', '0.25.1' );
+ $this->define( 'WC_ADMIN_VERSION_NUMBER', '0.26.1' );
}
/**
diff --git a/plugins/woocommerce-admin/src/Features/ActivityPanels.php b/plugins/woocommerce-admin/src/Features/ActivityPanels.php
index ffbfa02f588..249b367e8ea 100644
--- a/plugins/woocommerce-admin/src/Features/ActivityPanels.php
+++ b/plugins/woocommerce-admin/src/Features/ActivityPanels.php
@@ -22,6 +22,11 @@ class ActivityPanels {
*/
protected static $instance = null;
+ /**
+ * Low Stock Transient Name.
+ */
+ const LOW_STOCK_TRANSIENT_NAME = 'woocommerce_admin_low_out_of_stock_count';
+
/**
* Get class instance.
*/
@@ -42,6 +47,7 @@ class ActivityPanels {
// New settings injection.
add_filter( 'woocommerce_shared_settings', array( $this, 'component_settings' ), 20 );
add_action( 'woocommerce_updated', array( $this, 'woocommerce_updated_note' ) );
+ add_action( 'woocommerce_update_product', array( __CLASS__, 'clear_low_out_of_stock_count_transient' ) );
}
/**
@@ -60,13 +66,55 @@ class ActivityPanels {
);
}
+ /**
+ * Determines if there are out of stock or low stock products.
+ *
+ * @return boolean
+ */
+ public function has_low_stock_products() {
+ global $wpdb;
+
+ // Bail early if store does not manage stock, or Woo version < 3.6 needs lookup tables.
+ if (
+ 'yes' !== get_option( 'woocommerce_manage_stock' ) ||
+ version_compare( get_option( 'woocommerce_db_version', null ), '3.6', '<' )
+ ) {
+ return false;
+ }
+
+ $low_stock_out_of_stock_count = get_transient( self::LOW_STOCK_TRANSIENT_NAME );
+
+ if ( false === $low_stock_out_of_stock_count ) {
+ $low_stock_out_of_stock_count = (int) $wpdb->get_var(
+ "SELECT COUNT( product_id )
+ FROM {$wpdb->wc_product_meta_lookup} AS lookup
+ INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
+ WHERE stock_status IN ( 'onbackorder', 'outofstock' )
+ AND posts.post_status = 'publish'"
+ );
+ set_transient( self::LOW_STOCK_TRANSIENT_NAME, $low_stock_out_of_stock_count, HOUR_IN_SECONDS );
+ }
+ return $low_stock_out_of_stock_count > 0;
+ }
+
+ /**
+ * Clears transient for out of stock indicator
+ *
+ * @return boolean
+ */
+ public static function clear_low_out_of_stock_count_transient() {
+ delete_transient( self::LOW_STOCK_TRANSIENT_NAME );
+ return true;
+ }
+
/**
* Add alert count to the component settings.
*
* @param array $settings Component settings.
*/
public function component_settings( $settings ) {
- $settings['alertCount'] = WC_Admin_Notes::get_notes_count( array( 'error', 'update' ), array( 'unactioned' ) );
+ $settings['alertCount'] = WC_Admin_Notes::get_notes_count( array( 'error', 'update' ), array( 'unactioned' ) );
+ $settings['hasLowStock'] = $this->has_low_stock_products();
return $settings;
}
diff --git a/plugins/woocommerce-admin/src/Features/Onboarding.php b/plugins/woocommerce-admin/src/Features/Onboarding.php
index 197cc716a10..f75eda79b7c 100644
--- a/plugins/woocommerce-admin/src/Features/Onboarding.php
+++ b/plugins/woocommerce-admin/src/Features/Onboarding.php
@@ -182,16 +182,50 @@ class Onboarding {
* @return array
*/
public static function get_allowed_industries() {
+ /* With "use_description" we turn the description input on. With "description_label" we set the input label */
return apply_filters(
'woocommerce_admin_onboarding_industries',
array(
- 'fashion-apparel-accessories' => __( 'Fashion, apparel, and accessories', 'woocommerce-admin' ),
- 'health-beauty' => __( 'Health and beauty', 'woocommerce-admin' ),
- 'art-music-photography' => __( 'Art, music, and photography', 'woocommerce-admin' ),
- 'electronics-computers' => __( 'Electronics and computers', 'woocommerce-admin' ),
- 'food-drink' => __( 'Food and drink', 'woocommerce-admin' ),
- 'home-furniture-garden' => __( 'Home, furniture, and garden', 'woocommerce-admin' ),
- 'other' => __( 'Other', 'woocommerce-admin' ),
+ 'fashion-apparel-accessories' => array(
+ 'label' => __( 'Fashion, apparel, and accessories', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'health-beauty' => array(
+ 'label' => __( 'Health and beauty', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'art-music-photography' => array(
+ 'label' => __( 'Art, music, and photography', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'electronics-computers' => array(
+ 'label' => __( 'Electronics and computers', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'food-drink' => array(
+ 'label' => __( 'Food and drink', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'home-furniture-garden' => array(
+ 'label' => __( 'Home, furniture, and garden', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'cbd-other-hemp-derived-products' => array(
+ 'label' => __( 'CBD and other hemp-derived products', 'woocommerce-admin' ),
+ 'use_description' => false,
+ 'description_label' => '',
+ ),
+ 'other' => array(
+ 'label' => __( 'Other', 'woocommerce-admin' ),
+ 'use_description' => true,
+ 'description_label' => 'Description',
+ ),
)
);
}
diff --git a/plugins/woocommerce-admin/src/Notes/WC_Admin_Notes_Deactivate_Plugin.php b/plugins/woocommerce-admin/src/Notes/WC_Admin_Notes_Deactivate_Plugin.php
new file mode 100644
index 00000000000..31ff8e7403c
--- /dev/null
+++ b/plugins/woocommerce-admin/src/Notes/WC_Admin_Notes_Deactivate_Plugin.php
@@ -0,0 +1,82 @@
+get_notes_with_name( self::NOTE_NAME );
+ if ( ! empty( $note_ids ) ) {
+ return;
+ }
+
+ $note = new WC_Admin_Note();
+ $note->set_title( __( 'Deactivate old WooCommerce Admin version', 'woocommerce-admin' ) );
+ $note->set_content( __( 'Your current version of WooCommerce Admin is outdated and a newer version is included with WooCommerce. We recommend deactivating the plugin and using the stable version included with WooCommerce.', 'woocommerce-admin' ) );
+ $note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_UPDATE );
+ $note->set_icon( 'warning' );
+ $note->set_name( self::NOTE_NAME );
+ $note->set_content_data( (object) array() );
+ $note->set_source( 'woocommerce-admin' );
+ $note->add_action(
+ 'deactivate-feature-plugin',
+ __( 'Deactivate', 'woocommerce-admin' ),
+ wc_admin_url( '&action=deactivate-feature-plugin' ),
+ 'unactioned',
+ true
+ );
+ $note->save();
+ }
+
+ /**
+ * Delete the note if the version is higher than the included.
+ */
+ public static function delete_note() {
+ WC_Admin_Notes::delete_notes_with_name( self::NOTE_NAME );
+ }
+
+ /**
+ * Deactivate feature plugin.
+ */
+ public function deactivate_feature_plugin() {
+ /* phpcs:disable WordPress.Security.NonceVerification */
+ if (
+ ! isset( $_GET['page'] ) ||
+ 'wc-admin' !== $_GET['page'] ||
+ ! isset( $_GET['action'] ) ||
+ 'deactivate-feature-plugin' !== $_GET['action'] ||
+ ! defined( 'WC_ADMIN_PLUGIN_FILE' )
+ ) {
+ return;
+ }
+ /* phpcs:enable */
+
+ $deactivate_url = admin_url( 'plugins.php?action=deactivate&plugin=' . rawurlencode( WC_ADMIN_PLUGIN_FILE ) . '&plugin_status=all&paged=1&_wpnonce=' . wp_create_nonce( 'deactivate-plugin_' . WC_ADMIN_PLUGIN_FILE ) );
+ wp_safe_redirect( $deactivate_url );
+ exit;
+ }
+}
diff --git a/plugins/woocommerce-admin/src/Package.php b/plugins/woocommerce-admin/src/Package.php
index 1aeed33b92f..6e2801161cf 100644
--- a/plugins/woocommerce-admin/src/Package.php
+++ b/plugins/woocommerce-admin/src/Package.php
@@ -5,10 +5,17 @@
* @package Automattic/WooCommerce/WCAdmin
*/
-namespace Automattic\WooCommerce\Admin;
+/**
+ * This namespace isn't compatible with the PSR-4
+ * which ensures that the copy in the standalone plugin will not be autoloaded.
+ */
+namespace Automattic\WooCommerce\Admin\Composer;
defined( 'ABSPATH' ) || exit;
+use Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Deactivate_Plugin;
+use Automattic\WooCommerce\Admin\FeaturePlugin;
+
/**
* Main package class.
*/
@@ -19,7 +26,14 @@ class Package {
*
* @var string
*/
- const VERSION = '0.25.1';
+ const VERSION = '0.26.1';
+
+ /**
+ * Package active.
+ *
+ * @var bool
+ */
+ private static $package_active = false;
/**
* Init the package.
@@ -39,9 +53,20 @@ class Package {
// Avoid double initialization when the feature plugin is in use.
if ( defined( 'WC_ADMIN_VERSION_NUMBER' ) ) {
+ $update_version = new WC_Admin_Notes_Deactivate_Plugin();
+ if ( version_compare( WC_ADMIN_VERSION_NUMBER, self::VERSION, '<' ) ) {
+ $update_version::add_note();
+ } else {
+ $update_version::delete_note();
+ }
+
+ // Register a deactivation hook for the feature plugin.
+ register_deactivation_hook( WC_ADMIN_PLUGIN_FILE, array( __CLASS__, 'on_deactivation' ) );
+
return;
}
+ self::$package_active = true;
FeaturePlugin::instance()->init();
}
@@ -54,6 +79,24 @@ class Package {
return self::VERSION;
}
+ /**
+ * Return the active version of WC Admin.
+ *
+ * @return string
+ */
+ public static function get_active_version() {
+ return self::$package_active ? self::VERSION : WC_ADMIN_VERSION_NUMBER;
+ }
+
+ /**
+ * Return whether the package is active.
+ *
+ * @return bool
+ */
+ public static function is_package_active() {
+ return self::$package_active;
+ }
+
/**
* Return the path to the package.
*
@@ -62,4 +105,12 @@ class Package {
public static function get_path() {
return dirname( __DIR__ );
}
+
+ /**
+ * Add deactivation hook for versions of the plugin that don't have the deactivation note.
+ */
+ public static function on_deactivation() {
+ $update_version = new WC_Admin_Notes_Deactivate_Plugin();
+ $update_version::delete_note();
+ }
}
diff --git a/plugins/woocommerce-admin/woocommerce-admin.php b/plugins/woocommerce-admin/woocommerce-admin.php
index c64566cb4a0..80669c614d2 100755
--- a/plugins/woocommerce-admin/woocommerce-admin.php
+++ b/plugins/woocommerce-admin/woocommerce-admin.php
@@ -7,7 +7,7 @@
* Author URI: https://woocommerce.com/
* Text Domain: woocommerce-admin
* Domain Path: /languages
- * Version: 0.25.1
+ * Version: 0.26.1
* Requires at least: 5.3.0
* Requires PHP: 5.6.20
*