diff --git a/.eslintrc.js b/.eslintrc.js index 4e6ab961b0..f857fd24a5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,6 +29,7 @@ module.exports = { '@wordpress/stylelint-config', '@pmmmwh/react-refresh-webpack-plugin', 'react-transition-group', + 'jquery', ], 'import/resolver': { webpack: webpackResolver }, }, diff --git a/.externalized.json b/.externalized.json index a1ea74111d..362d44cf08 100644 --- a/.externalized.json +++ b/.externalized.json @@ -1 +1 @@ -["@woocommerce/components","@woocommerce/currency","@woocommerce/customer-effort-score","@woocommerce/data","@woocommerce/date","@woocommerce/navigation","@woocommerce/number","@woocommerce/settings","@woocommerce/tracks","@wordpress/api-fetch","@wordpress/components","@wordpress/compose","@wordpress/data","@wordpress/data-controls","@wordpress/date","@wordpress/dom","@wordpress/element","@wordpress/hooks","@wordpress/html-entities","@wordpress/i18n","@wordpress/primitives","@wordpress/url","lodash","react","react-dom"] \ No newline at end of file +["@woocommerce/components","@woocommerce/currency","@woocommerce/customer-effort-score","@woocommerce/data","@woocommerce/date","@woocommerce/navigation","@woocommerce/number","@woocommerce/settings","@woocommerce/tracks","@wordpress/api-fetch","@wordpress/components","@wordpress/compose","@wordpress/data","@wordpress/data-controls","@wordpress/date","@wordpress/dom","@wordpress/element","@wordpress/hooks","@wordpress/html-entities","@wordpress/i18n","@wordpress/primitives","@wordpress/url","jquery","lodash","react","react-dom"] \ No newline at end of file diff --git a/js/src/constants.js b/js/src/constants.js index bf7bb544a9..d6285b936f 100644 --- a/js/src/constants.js +++ b/js/src/constants.js @@ -1,5 +1,10 @@ +// An inline script data only available for the admin pages of this extension. export const glaData = window.glaData; +// An inline script data only available for the UI blocks that are added to the +// product editing page by this extension. +export const glaProductData = window.glaProductData; + export const FREE_LISTINGS_PROGRAM_ID = 0; // Products report related diff --git a/js/src/custom-inputs/index.js b/js/src/product-attributes/custom-inputs.js similarity index 80% rename from js/src/custom-inputs/index.js rename to js/src/product-attributes/custom-inputs.js index a6ae5a7e41..fac9a8d61a 100644 --- a/js/src/custom-inputs/index.js +++ b/js/src/product-attributes/custom-inputs.js @@ -1,9 +1,14 @@ +/** + * External dependencies + */ +import $ from 'jquery'; + /** * Internal dependencies */ import selectWithText from './select-with-text-input'; -window.jQuery( function ( $ ) { +$( function () { 'use strict'; const init = () => { diff --git a/js/src/product-attributes/index.js b/js/src/product-attributes/index.js index 621f7adb3e..c549b8461d 100644 --- a/js/src/product-attributes/index.js +++ b/js/src/product-attributes/index.js @@ -1,4 +1,39 @@ +/** + * External dependencies + */ +import $ from 'jquery'; + /** * Internal dependencies */ +import { glaProductData } from '.~/constants'; +import './custom-inputs'; import './index.scss'; + +// Originally, this extension relied on a WooCommerce core processing to show or hide +// the product data tab and meta box added to the product editing page. +// +// However, WooCommerce Subscriptions has an additional processing, which overrides +// the associated processed result in WooCommerce core. +// +// Since there is no available way to continue to work around it with `show_if_{productType}` +// or `hide_if_{productType}` CSS classes, a jQuery custom event dispatched by WooCommerce core +// is used to handle show or hide them instead. +// +// See: +// - https://github.com/woocommerce/google-listings-and-ads/issues/2086 +// +// Ref: +// - https://github.com/woocommerce/woocommerce/blob/8.0.3/plugins/woocommerce/client/legacy/js/admin/meta-boxes-product.js#L204-L243 +// - https://github.com/Automattic/woocommerce-subscriptions-core/blob/6.2.0/assets/js/admin/admin.js#L18-L88 +// - https://github.com/woocommerce/woocommerce/blob/8.0.3/plugins/woocommerce/client/legacy/js/admin/meta-boxes-product.js#L130-L158 +$( document ).on( + 'woocommerce-product-type-change', + 'body', + ( e, productType ) => { + const shouldDisplay = + glaProductData.applicableProductTypes.includes( productType ); + + $( '.gla_attributes_tab, .gla_meta_box' ).toggle( shouldDisplay ); + } +); diff --git a/js/src/custom-inputs/select-with-text-input/index.js b/js/src/product-attributes/select-with-text-input/index.js similarity index 100% rename from js/src/custom-inputs/select-with-text-input/index.js rename to js/src/product-attributes/select-with-text-input/index.js diff --git a/src/Admin/Admin.php b/src/Admin/Admin.php index 1c9b5faf44..4aefb25c6a 100644 --- a/src/Admin/Admin.php +++ b/src/Admin/Admin.php @@ -5,7 +5,6 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Admin\MetaBox\MetaBoxInterface; use Automattic\WooCommerce\GoogleListingsAndAds\Ads\AdsService; -use Automattic\WooCommerce\GoogleListingsAndAds\Assets\AdminScriptAsset; use Automattic\WooCommerce\GoogleListingsAndAds\Assets\AdminScriptWithBuiltDependenciesAsset; use Automattic\WooCommerce\GoogleListingsAndAds\Assets\AdminStyleAsset; use Automattic\WooCommerce\GoogleListingsAndAds\Assets\Asset; @@ -17,6 +16,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\ViewFactory; use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\MerchantCenterService; use Automattic\WooCommerce\GoogleListingsAndAds\PluginHelper; +use Automattic\WooCommerce\GoogleListingsAndAds\Product\ProductSyncer; use Automattic\WooCommerce\GoogleListingsAndAds\Value\BuiltScriptDependencyArray; use Automattic\WooCommerce\GoogleListingsAndAds\View\ViewException; use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsAwareInterface; @@ -72,8 +72,6 @@ public function __construct( AssetsHandlerInterface $assets_handler, ViewFactory * Register a service. */ public function register(): void { - $this->assets_handler->add_many( $this->get_assets() ); - add_action( 'admin_enqueue_scripts', function() { @@ -82,7 +80,10 @@ function() { wp_enqueue_media(); } - $this->assets_handler->enqueue_many( $this->get_assets() ); + $assets = $this->get_assets(); + + $this->assets_handler->register_many( $assets ); + $this->assets_handler->enqueue_many( $assets ); } ); @@ -135,7 +136,6 @@ protected function get_assets(): array { 'dateFormat' => get_option( 'date_format' ), 'timeFormat' => get_option( 'time_format' ), 'siteLogoUrl' => wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'full' ), - ] ); @@ -152,13 +152,24 @@ protected function get_assets(): array { return ( null !== $screen && 'product' === $screen->id ); }; - $assets[] = ( new AdminScriptAsset( - 'gla-custom-inputs', - 'js/build/custom-inputs', - [], - '', + $assets[] = ( new AdminScriptWithBuiltDependenciesAsset( + 'gla-product-attributes', + 'js/build/product-attributes', + "{$this->get_root_dir()}/js/build/product-attributes.asset.php", + new BuiltScriptDependencyArray( + [ + 'dependencies' => [], + 'version' => (string) filemtime( "{$this->get_root_dir()}/js/build/product-attributes.js" ), + ] + ), $product_condition - ) ); + ) )->add_inline_script( + 'glaProductData', + [ + 'applicableProductTypes' => ProductSyncer::get_supported_product_types(), + ] + ); + $assets[] = ( new AdminStyleAsset( 'gla-product-attributes-css', 'js/build/product-attributes', diff --git a/src/Admin/MetaBox/ChannelVisibilityMetaBox.php b/src/Admin/MetaBox/ChannelVisibilityMetaBox.php index 8cdf974fca..d2d61134d5 100644 --- a/src/Admin/MetaBox/ChannelVisibilityMetaBox.php +++ b/src/Admin/MetaBox/ChannelVisibilityMetaBox.php @@ -103,21 +103,7 @@ public function get_context(): string { * @return array */ public function get_classes(): array { - $shown_types = array_map( - function ( string $product_type ) { - return "show_if_{$product_type}"; - }, - ProductSyncer::get_supported_product_types() - ); - - $hidden_types = array_map( - function ( string $product_type ) { - return "hide_if_{$product_type}"; - }, - ProductSyncer::get_hidden_product_types() - ); - - return array_merge( $shown_types, $hidden_types ); + return [ 'gla_meta_box' ]; } /** diff --git a/src/Admin/Product/Attributes/AttributesTab.php b/src/Admin/Product/Attributes/AttributesTab.php index 60db105323..a70f6d4618 100644 --- a/src/Admin/Product/Attributes/AttributesTab.php +++ b/src/Admin/Product/Attributes/AttributesTab.php @@ -100,25 +100,9 @@ function () { * @return array An array with product tabs with the Yoast SEO tab added. */ private function add_tab( array $tabs ): array { - $shown_types = array_map( - function ( string $product_type ) { - return "show_if_{$product_type}"; - }, - $this->get_applicable_product_types() - ); - - $hidden_types = array_map( - function ( string $product_type ) { - return "hide_if_{$product_type}"; - }, - ProductSyncer::get_hidden_product_types() - ); - - $classes = array_merge( [ 'gla' ], $shown_types, $hidden_types ); - $tabs['gla_attributes'] = [ 'label' => 'Google Listings and Ads', - 'class' => join( ' ', $classes ), + 'class' => 'gla', 'target' => 'gla_attributes', ]; diff --git a/src/Assets/AssetsHandler.php b/src/Assets/AssetsHandler.php index 46a0227d79..01e8b1d87b 100644 --- a/src/Assets/AssetsHandler.php +++ b/src/Assets/AssetsHandler.php @@ -4,14 +4,13 @@ namespace Automattic\WooCommerce\GoogleListingsAndAds\Assets; use Automattic\WooCommerce\GoogleListingsAndAds\Exception\InvalidAsset; -use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable; /** * Class AssetsHandler * * @package Automattic\WooCommerce\GoogleListingsAndAds\Assets */ -final class AssetsHandler implements Registerable, AssetsHandlerInterface { +final class AssetsHandler implements AssetsHandlerInterface { /** * Assets known to this asset handler. @@ -21,32 +20,24 @@ final class AssetsHandler implements Registerable, AssetsHandlerInterface { private $assets = []; /** - * Add a single asset to the asset handler. + * Register a single asset. * - * @param Asset $asset Asset to add. + * @param Asset $asset Asset to register. */ - public function add( Asset $asset ): void { + public function register( Asset $asset ): void { $this->validate_handle_not_exists( $asset->get_handle() ); $this->assets[ $asset->get_handle() ] = $asset; + $asset->register(); } /** - * Add multiple assets to the asset handler. + * Register multiple assets. * - * @param Asset[] $assets Array of assets to add. + * @param Asset[] $assets Array of assets to register. */ - public function add_many( array $assets ): void { + public function register_many( array $assets ): void { foreach ( $assets as $asset ) { - $this->add( $asset ); - } - } - - /** - * Register a service. - */ - public function register(): void { - foreach ( $this->assets as $asset ) { - $asset->register(); + $this->register( $asset ); } } @@ -57,8 +48,8 @@ public function register(): void { * * @throws InvalidAsset If the passed-in asset is not valid. * - * @see AssetsHandlerInterface::add To add assets. - * @see AssetsHandlerInterface::add_many To add multiple assets. + * @see AssetsHandlerInterface::register To register assets. + * @see AssetsHandlerInterface::register_many To register multiple assets. */ public function enqueue( Asset $asset ): void { $this->enqueue_handle( $asset->get_handle() ); @@ -71,8 +62,8 @@ public function enqueue( Asset $asset ): void { * * @throws InvalidAsset If any of the passed-in assets are not valid. * - * @see AssetsHandlerInterface::add To add assets. - * @see AssetsHandlerInterface::add_many To add multiple assets. + * @see AssetsHandlerInterface::register To register assets. + * @see AssetsHandlerInterface::register_many To register multiple assets. */ public function enqueue_many( array $assets ): void { foreach ( $assets as $asset ) { diff --git a/src/Assets/AssetsHandlerInterface.php b/src/Assets/AssetsHandlerInterface.php index 57467fd795..52b516a625 100644 --- a/src/Assets/AssetsHandlerInterface.php +++ b/src/Assets/AssetsHandlerInterface.php @@ -13,18 +13,18 @@ interface AssetsHandlerInterface { /** - * Add a single asset to the asset handler. + * Register a single asset. * - * @param Asset $asset Asset to add. + * @param Asset $asset Asset to register. */ - public function add( Asset $asset ): void; + public function register( Asset $asset ): void; /** - * Add multiple assets to the asset handler. + * Register multiple assets. * - * @param Asset[] $assets Array of assets to add. + * @param Asset[] $assets Array of assets to register. */ - public function add_many( array $assets ): void; + public function register_many( array $assets ): void; /** * Enqueue a single asset. @@ -33,8 +33,8 @@ public function add_many( array $assets ): void; * * @throws InvalidAsset If the passed-in asset is not valid. * - * @see AssetsHandlerInterface::add To add assets. - * @see AssetsHandlerInterface::add_many To add multiple assets. + * @see AssetsHandlerInterface::register To register assets. + * @see AssetsHandlerInterface::register_many To register multiple assets. */ public function enqueue( Asset $asset ): void; @@ -45,8 +45,8 @@ public function enqueue( Asset $asset ): void; * * @throws InvalidAsset If any of the passed-in assets are not valid. * - * @see AssetsHandlerInterface::add To add assets. - * @see AssetsHandlerInterface::add_many To add multiple assets. + * @see AssetsHandlerInterface::register To register assets. + * @see AssetsHandlerInterface::register_many To register multiple assets. */ public function enqueue_many( array $assets ): void; diff --git a/src/Google/GlobalSiteTag.php b/src/Google/GlobalSiteTag.php index c158001063..3f36892e92 100644 --- a/src/Google/GlobalSiteTag.php +++ b/src/Google/GlobalSiteTag.php @@ -189,7 +189,7 @@ function () { } ); - $this->assets_handler->add( $gtag_events ); + $this->assets_handler->register( $gtag_events ); add_action( 'wp_footer', diff --git a/src/Infrastructure/GoogleListingsAndAdsPlugin.php b/src/Infrastructure/GoogleListingsAndAdsPlugin.php index 3503d8894d..315d230d67 100644 --- a/src/Infrastructure/GoogleListingsAndAdsPlugin.php +++ b/src/Infrastructure/GoogleListingsAndAdsPlugin.php @@ -3,7 +3,6 @@ namespace Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure; -use Automattic\WooCommerce\GoogleListingsAndAds\Assets\AssetsHandlerInterface; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobInitializer; use Automattic\WooCommerce\GoogleListingsAndAds\Internal\Requirements\PluginValidator; use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsInterface; @@ -102,8 +101,6 @@ function() { add_action( 'init', function() { - $this->container->get( AssetsHandlerInterface::class )->register(); - // register the job initializer only if it is available. see JobInitializer::is_needed. if ( $this->container->has( JobInitializer::class ) ) { $this->container->get( JobInitializer::class )->register(); diff --git a/src/Integration/WooCommerceSubscriptions.php b/src/Integration/WooCommerceSubscriptions.php deleted file mode 100644 index 1cbc793e62..0000000000 --- a/src/Integration/WooCommerceSubscriptions.php +++ /dev/null @@ -1,43 +0,0 @@ -share_with_tags( YoastWooCommerceSeo::class ); $this->share_with_tags( WooCommerceBrands::class, WP::class ); $this->share_with_tags( WooCommerceProductBundles::class, AttributeManager::class ); - $this->share_with_tags( WooCommerceSubscriptions::class ); $this->share_with_tags( WooCommercePreOrders::class, ProductHelper::class ); $this->share_with_tags( diff --git a/src/Product/ProductSyncer.php b/src/Product/ProductSyncer.php index 323020aaa6..f0f1618c55 100644 --- a/src/Product/ProductSyncer.php +++ b/src/Product/ProductSyncer.php @@ -264,17 +264,6 @@ public static function get_supported_product_types(): array { return (array) apply_filters( 'woocommerce_gla_supported_product_types', [ 'simple', 'variable', 'variation' ] ); } - /** - * Return the list of product types we will hide functionality for (default none). - * - * @since 1.2.0 - * - * @return array - */ - public static function get_hidden_product_types(): array { - return (array) apply_filters( 'woocommerce_gla_hidden_product_types', [] ); - } - /** * @param BatchInvalidProductEntry[] $invalid_products */ diff --git a/webpack.config.js b/webpack.config.js index 330941d488..96afd3b681 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -74,11 +74,6 @@ const webpackConfig = { ], entry: { index: path.resolve( process.cwd(), 'js/src', 'index.js' ), - 'custom-inputs': path.resolve( - process.cwd(), - 'js/src/custom-inputs', - 'index.js' - ), 'product-attributes': path.resolve( process.cwd(), 'js/src/product-attributes',