diff --git a/changelog.txt b/changelog.txt index dcff8051d..94bd4aa32 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,14 @@ *** WooCommerce Shipping & Tax Changelog *** += 2.7.0 - 2024-07-25 = +* Add - Parallel compatibility with WooCommerce Shipping plugin. + += 2.6.2 - 2024-07-16 = +* Fix - Require HS Tariff number on customs form for EU destination countries. + += 2.6.1 - 2024-07-02 = +* Tweak - WooCommerce 9.0 and WordPress 6.6 compatibility. + = 2.6.0 - 2024-06-04 = * Add - Logger for "Live Rates" feature on the front-end. diff --git a/classes/class-wc-connect-help-view.php b/classes/class-wc-connect-help-view.php index 7e22327a5..9ba0e907a 100644 --- a/classes/class-wc-connect-help-view.php +++ b/classes/class-wc-connect-help-view.php @@ -119,6 +119,10 @@ protected function get_health_items() { return $health_items; } + protected function is_shipping_loaded() { + return ! in_array( 'woocommerce-shipping/woocommerce-shipping.php', get_option( 'active_plugins' ) ); + } + protected function get_services_items() { $available_service_method_ids = $this->service_schemas_store->get_all_shipping_method_ids(); if ( empty( $available_service_method_ids ) ) { @@ -261,16 +265,17 @@ public function status_tabs( $tabs ) { */ protected function get_form_data() { return array( - 'health_items' => $this->get_health_items(), - 'services' => $this->get_services_items(), - 'logging_enabled' => $this->logger->is_logging_enabled(), - 'debug_enabled' => $this->logger->is_debug_enabled(), - 'logs' => array( + 'health_items' => $this->get_health_items(), + 'services' => $this->get_services_items(), + 'logging_enabled' => $this->logger->is_logging_enabled(), + 'debug_enabled' => $this->logger->is_debug_enabled(), + 'logs' => array( 'shipping' => $this->get_debug_log_data( 'shipping' ), 'taxes' => $this->get_debug_log_data( 'taxes' ), 'other' => $this->get_debug_log_data(), ), - 'tax_rate_backups' => WC_Connect_Functions::get_backed_up_tax_rate_files(), + 'tax_rate_backups' => WC_Connect_Functions::get_backed_up_tax_rate_files(), + 'is_shipping_loaded' => $this->is_shipping_loaded(), ); } @@ -296,8 +301,9 @@ public function page() { 'enqueue_wc_connect_script', 'wc-connect-admin-test-print', array( - 'storeOptions' => $this->service_settings_store->get_store_options(), - 'paperSize' => $this->service_settings_store->get_preferred_paper_size(), + 'isShippingLoaded' => $this->is_shipping_loaded(), + 'storeOptions' => $this->service_settings_store->get_store_options(), + 'paperSize' => $this->service_settings_store->get_preferred_paper_size(), ) ); } @@ -308,42 +314,42 @@ public function page() { protected function get_tax_health_item() { $store_country = WC()->countries->get_base_country(); if ( ! $this->taxjar_integration->is_supported_country( $store_country ) ) { - return [ + return array( 'state' => 'error', 'settings_link_type' => '', 'message' => sprintf( __( 'Your store\'s country (%s) is not supported. Automated taxes functionality is disabled', 'woocommerce-services' ), $store_country ), - ]; + ); } if ( class_exists( 'WC_Taxjar' ) ) { - return [ + return array( 'state' => 'error', 'settings_link_type' => '', 'message' => __( 'TaxJar extension detected. Automated taxes functionality is disabled', 'woocommerce-services' ), - ]; + ); } if ( ! wc_tax_enabled() ) { - return [ + return array( 'state' => 'error', 'settings_link_type' => 'general', 'message' => __( 'The core WooCommerce taxes functionality is disabled. Please ensure the "Enable tax rates and calculations" setting is turned "on" in the WooCommerce settings page', 'woocommerce-services' ), - ]; + ); } if ( ! $this->taxjar_integration->is_enabled() ) { - return [ + return array( 'state' => 'error', 'settings_link_type' => 'tax', 'message' => __( 'The automated taxes functionality is disabled. Enable the "Automated taxes" setting on the WooCommerce settings page', 'woocommerce-services' ), - ]; + ); } - return [ + return array( 'state' => 'success', 'settings_link_type' => 'tax', 'message' => __( 'Automated taxes are enabled', 'woocommerce-services' ), - ]; + ); } } diff --git a/classes/class-wc-connect-shipping-label.php b/classes/class-wc-connect-shipping-label.php index b3513bf25..195989163 100644 --- a/classes/class-wc-connect-shipping-label.php +++ b/classes/class-wc-connect-shipping-label.php @@ -598,6 +598,7 @@ public function meta_box( $post, $args ) { 'packagesSettings' => $this->package_settings->get(), 'shippingLabelData' => $this->get_label_payload( $order->get_id() ), 'continents' => $this->continents->get(), + 'euCountries' => WC()->countries->get_european_union_countries(), 'context' => $args['args']['context'], 'items' => $items_count, ), diff --git a/client/apps/plugin-status/health.js b/client/apps/plugin-status/health.js index 681fe5d27..af064238a 100644 --- a/client/apps/plugin-status/health.js +++ b/client/apps/plugin-status/health.js @@ -14,7 +14,7 @@ import WooCommerceServicesIndicator from './woocommerce-services-indicator'; import SettingsGroupCard from 'woocommerce/woocommerce-services/components/settings-group-card'; import FormSettingExplanation from 'components/forms/form-setting-explanation'; -const HealthView = ( { translate, healthItems } ) => { +const HealthView = ( { translate, healthItems, isShippingLoaded } ) => { return ( { - + + { isShippingLoaded && } ); @@ -71,5 +72,6 @@ const HealthView = ( { translate, healthItems } ) => { export default connect( ( state ) => ( { healthItems: state.status.health_items, + isShippingLoaded: state.status.is_shipping_loaded } ) )( localize( HealthView ) ); diff --git a/client/apps/plugin-status/test/health.test.js b/client/apps/plugin-status/test/health.test.js index cf35c144e..1f94083b9 100644 --- a/client/apps/plugin-status/test/health.test.js +++ b/client/apps/plugin-status/test/health.test.js @@ -50,7 +50,8 @@ const Wrapper = ({ children, healthStoreOverrides }) => ( health_items: { ...defaultHealthStoreValues, ...healthStoreOverrides, - } + }, + is_shipping_loaded: true, }, })}> {children} diff --git a/client/apps/plugin-status/view.js b/client/apps/plugin-status/view.js index cc3bcdff8..cbca52cb1 100644 --- a/client/apps/plugin-status/view.js +++ b/client/apps/plugin-status/view.js @@ -22,7 +22,7 @@ import { toggleDebugging, } from './state/actions'; -const StatusView = ( { onLoggingToggle, onDebuggingToggle, isLoggingEnabled, isDebuggingEnabled, taxRateBackups, translate } ) => { +const StatusView = ( { onLoggingToggle, onDebuggingToggle, isLoggingEnabled, isDebuggingEnabled, taxRateBackups, translate, isShippingLoaded } ) => { return (
@@ -47,9 +47,7 @@ const StatusView = ( { onLoggingToggle, onDebuggingToggle, isLoggingEnabled, isD falseText={ translate( 'Disabled' ) } onUpdate={ onLoggingToggle } /> - + { isShippingLoaded && } @@ -112,6 +110,7 @@ const mapStateToProps = ( state ) => ( { isLoggingEnabled: Boolean( state.status.logging_enabled ), isDebuggingEnabled: Boolean( state.status.debug_enabled ), taxRateBackups: state.status.tax_rate_backups, + isShippingLoaded: state.status.is_shipping_loaded, } ); const mapDispatchToProps = { diff --git a/client/apps/print-test-label/index.js b/client/apps/print-test-label/index.js index 39829515e..53a10dac7 100644 --- a/client/apps/print-test-label/index.js +++ b/client/apps/print-test-label/index.js @@ -10,7 +10,7 @@ import './style.scss'; import PrintTestLabelView from './view'; import reducer from './state/reducer'; -export default ( { paperSize, storeOptions } ) => ( { +export default ( { paperSize, storeOptions, isShippingLoaded } ) => ( { getReducer() { return reducer; }, @@ -19,6 +19,7 @@ export default ( { paperSize, storeOptions } ) => ( { return { paperSize, country: storeOptions.origin_country, + isShippingLoaded, }; }, diff --git a/client/apps/print-test-label/view.js b/client/apps/print-test-label/view.js index 183d2fd60..9e826f195 100644 --- a/client/apps/print-test-label/view.js +++ b/client/apps/print-test-label/view.js @@ -32,9 +32,14 @@ class PrintTestLabelView extends Component { onPaperSizeChange = ( event ) => this.props.updatePaperSize( event.target.value ); render() { - const { paperSize, country, printingInProgress, error, print } = this.props; + const { paperSize, country, printingInProgress, error, print, isShippingLoaded } = this.props; const paperSizes = getPaperSizes( country ); + // Bail early if shipping is not enabled since it no longer makes sense to do label test prints. + if ( ! isShippingLoaded ) { + return null; + } + return ( { error && { error } } diff --git a/client/apps/shipping-label/index.js b/client/apps/shipping-label/index.js index 002185c1b..5d0a35069 100644 --- a/client/apps/shipping-label/index.js +++ b/client/apps/shipping-label/index.js @@ -29,7 +29,7 @@ import { mergeHandlers } from 'state/action-watchers/utils'; import initializeLabelsState from 'woocommerce/woocommerce-services/lib/initialize-labels-state'; import './style.scss'; -export default ( { order, accountSettings, packagesSettings, shippingLabelData, continents, context, items } ) => { +export default ( { order, accountSettings, packagesSettings, shippingLabelData, continents, euCountries, context, items } ) => { const orderId = order ? order.id : null; const isPreloaded = ( undefined !== accountSettings ); @@ -81,6 +81,7 @@ export default ( { order, accountSettings, packagesSettings, shippingLabelData, } initialState.extensions.woocommerce.sites[1].data = { locations: continents, + euCountries } return initialState; diff --git a/client/extensions/woocommerce/state/sites/data/locations/selectors.js b/client/extensions/woocommerce/state/sites/data/locations/selectors.js index da22198bd..eb5a98712 100644 --- a/client/extensions/woocommerce/state/sites/data/locations/selectors.js +++ b/client/extensions/woocommerce/state/sites/data/locations/selectors.js @@ -94,6 +94,15 @@ export const getAllCountries = ( state, siteId = getSelectedSiteId( state ) ) => return sortBy( allCountries, 'name' ); }; +/** + * @param {Object} state Whole Redux state tree + * @param {Number} [siteId] Site ID to check. If not provided, the Site ID selected in the UI will be used + * @return {Array} An array of EU countries represented by { code, name, states } objects. Sorted alphabetically by name. + */ +export const getEUCountries = ( state, siteId = getSelectedSiteId( state ) ) => { + return get( state, [ 'extensions', 'woocommerce', 'sites', siteId, 'data', 'euCountries' ] ); +}; + /** * @param {Object} state Whole Redux state tree * @param {String} continentCode 2-letter continent code diff --git a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js index df7f26342..9b312b505 100644 --- a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js +++ b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js @@ -51,6 +51,7 @@ import { areLocationsErrored, getCountryName, getAllCountryNames, + getEUCountries, getStates, hasStates, } from 'woocommerce/state/sites/data/locations/selectors'; @@ -339,7 +340,9 @@ export const getCustomsErrors = ( packages, customs, destinationCountryCode, - destinationCountryName + destinationCountryName, + state, + siteId = getSelectedSiteId( state ) ) => { const usedProductIds = uniq( flatten( map( packages, pckg => map( pckg.items, 'product_id' ) ) ) @@ -437,6 +440,8 @@ export const getCustomsErrors = ( } if ( itemData.tariffNumber && 6 !== itemData.tariffNumber.length ) { itemErrors.tariffNumber = translate( 'The tariff number must be 6 digits long' ); + } else if ( ! itemData.tariffNumber && isEUCountry( state, destinationCountryCode, siteId ) ) { + itemErrors.tariffNumber = translate( 'The tariff number is required for EU countries destination' ); } return itemErrors; } ), @@ -501,7 +506,9 @@ export const getFormErrors = createSelector( form.packages.selected, form.customs, destinationCountryCode, - destinationCountryName + destinationCountryName, + state, + siteId ), rates: getRatesErrors( form.rates ), sidebar: getSidebarErrors( paperSize ), @@ -536,6 +543,16 @@ export const isAddressUsable = createSelector( ] ); +export const isEUCountry = ( state, destinationCountryCode, siteId = getSelectedSiteId( state ) ) => { + const EUCountries = getEUCountries( state, siteId ); + + return includes( EUCountries, destinationCountryCode ); +} + +export const getTariffNumberPlaceholder = ( state, destinationCountryCode, siteId = getSelectedSiteId( state ) ) => { + return ! isEUCountry( state, destinationCountryCode, siteId ) ? translate( 'Optional' ) : ''; +} + export const isCustomsFormStepSubmitted = ( state, orderId, diff --git a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/item-row.js b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/item-row.js index 794b3f1c5..bc7bbba7c 100644 --- a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/item-row.js +++ b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/item-row.js @@ -19,6 +19,7 @@ import { } from 'woocommerce/woocommerce-services/state/shipping-label/actions'; import { getShippingLabel, + getTariffNumberPlaceholder, isLoaded, getFormErrors, } from 'woocommerce/woocommerce-services/state/shipping-label/selectors'; @@ -40,6 +41,7 @@ const ItemRow = props => { value, tariffNumber, originCountry, + TariffNumberPlaceholder, countryNames, weightUnit, } = props; @@ -59,7 +61,7 @@ const ItemRow = props => { id={ packageId + '_' + productId + '_tariffNumber' } className="customs-step__item-code-column" title={ } - placeholder={ translate( 'Optional' ) } + placeholder={ TariffNumberPlaceholder } value={ tariffNumber } updateValue={ props.setCustomsItemTariffNumber } error={ errors.tariffNumber } @@ -104,6 +106,7 @@ ItemRow.propTypes = { weight: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number ] ).isRequired, value: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number ] ).isRequired, originCountry: PropTypes.string.isRequired, + TariffNumberPlaceholder: PropTypes.string.isRequired, errors: PropTypes.object, countryNames: PropTypes.object.isRequired, setCustomsItemDescription: PropTypes.func.isRequired, @@ -116,6 +119,8 @@ ItemRow.propTypes = { const mapStateToProps = ( state, { orderId, siteId, productId } ) => { const isShippingLabelLoaded = isLoaded( state, orderId, siteId ); const shippingLabel = getShippingLabel( state, orderId, siteId ); + const destinationCountry = shippingLabel.form.destination.values.country; + const TariffNumberPlaceholder = getTariffNumberPlaceholder( state, destinationCountry, siteId ); const { description, defaultDescription, @@ -132,6 +137,7 @@ const mapStateToProps = ( state, { orderId, siteId, productId } ) => { weight, value, originCountry, + TariffNumberPlaceholder, errors: isShippingLabelLoaded ? getFormErrors( state, orderId, siteId ).customs.items[ productId ] : {}, diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index ab7521e39..7eacaf57d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "woocommerce-services", - "version": "2.6.0", + "version": "2.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 05b168a7d..1a8012d62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woocommerce-services", - "version": "2.6.0", + "version": "2.7.0", "scripts": { "start": "cross-env NODE_ENV=development CALYPSO_CLIENT=true webpack-dev-server --hot --inline --watch --content-base dist --port 8085", "prepare": "cd wp-calypso && npm ci && cd .. && husky install", diff --git a/readme.txt b/readme.txt index f34b69d6f..32a16c61d 100644 --- a/readme.txt +++ b/readme.txt @@ -2,12 +2,12 @@ Contributors: woocommerce, automattic, woothemes, allendav, kellychoffman, jkudish, jeffstieler, nabsul, robobot3000, danreylop, mikeyarce, shaunkuschel, orangesareorange, pauldechov, dappermountain, radogeorgiev, bor0, royho, cshultz88, bartoszbudzanowski, harriswong, ferdev, superdav42 Tags: shipping, stamps, usps, woocommerce, taxes, payment, dhl, labels Requires PHP: 7.4 -Requires at least: 6.3 +Requires at least: 6.4 Requires Plugins: woocommerce -Tested up to: 6.5 -WC requires at least: 8.7 -WC tested up to: 8.9 -Stable tag: 2.6.0 +Tested up to: 6.6 +WC requires at least: 8.8 +WC tested up to: 9.0 +Stable tag: 2.7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -79,6 +79,15 @@ The source code is freely available [in GitHub](https://github.com/Automattic/wo == Changelog == += 2.7.0 - 2024-07-25 = +* Add - Parallel compatibility with WooCommerce Shipping plugin. + += 2.6.2 - 2024-07-16 = +* Fix - Require HS Tariff number on customs form for EU destination countries. + += 2.6.1 - 2024-07-02 = +* Tweak - WooCommerce 9.0 and WordPress 6.6 compatibility. + = 2.6.0 - 2024-06-04 = * Add - Logger for "Live Rates" feature on the front-end. diff --git a/woocommerce-services.php b/woocommerce-services.php index 19d44f297..f5cf7cafb 100644 --- a/woocommerce-services.php +++ b/woocommerce-services.php @@ -8,11 +8,11 @@ * Author URI: https://woocommerce.com/ * Text Domain: woocommerce-services * Domain Path: /i18n/languages/ - * Version: 2.6.0 - * Requires at least: 6.3 - * Tested up to: 6.5 - * WC requires at least: 8.7 - * WC tested up to: 8.9 + * Version: 2.7.0 + * Requires at least: 6.4 + * Tested up to: 6.6 + * WC requires at least: 8.8 + * WC tested up to: 9.0 * * Copyright (c) 2017-2023 Automattic * @@ -371,19 +371,26 @@ function () { ); add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ) ); + add_action( 'plugins_loaded', array( $this, 'jetpack_on_plugins_loaded' ), 1 ); + /** + * Used to let WC Tax know WCS&T will handle the plugin's coexistence. + * + * WCS&T does it by not registering its functionality and displaying an appropriate notice + * in WP admin. + * + * The filter also includes "woo_shipping" in its name, but we've since implemented conditional + * loading of all shipping functionality inside WCS&T, so there's no special need for any + * "parallel support" being done in WC Shipping anymore. + * + * This new feature is represented via the "wc_services_will_disable_shipping_logic" hook. + */ if ( $this->are_woo_shipping_and_woo_tax_active() ) { - /** - * Used to let Woo Shipping and Woo Tax know WCS&T will handle the plugins' coexistence. - * - * WCS&T does it by not registering its functionality and displaying an appropriate notice - * in WP admin. - */ add_filter( 'wc_services_will_handle_coexistence_with_woo_shipping_and_woo_tax', '__return_true' ); - return; } - add_action( 'plugins_loaded', array( $this, 'jetpack_on_plugins_loaded' ), 1 ); + // Let WC Shipping know that the current version of WCS&T supports conditional shipping logic loading. + add_filter( 'wc_services_will_disable_shipping_logic', '__return_true' ); } public function get_logger() { @@ -628,7 +635,7 @@ public function on_plugins_loaded() { /** * Allow third party logic to determine if this plugin should initiate its logic. * - * The primary purpose here is to allow a smooth transition between the new Woo Shipping / Woo Tax plugins + * The primary purpose here is to allow a smooth transition between the new WC Tax plugin * and WooCommerce Shipping & Tax (this plugin), by letting them take over all responsibilities if all three * plugins are activated at the same time. * @@ -637,7 +644,10 @@ public function on_plugins_loaded() { * @param bool $status The value will determine if we should initiate the plugins logic or not. */ if ( apply_filters( 'wc_services_will_handle_coexistence_with_woo_shipping_and_woo_tax', false ) ) { + // Show message that WCS&T is no longer doing anything. add_action( 'admin_notices', array( $this, 'display_woo_shipping_and_woo_tax_are_active_notice' ) ); + + // Bail, so none of our tax and shipping logic will be initiated. return; } @@ -738,6 +748,10 @@ protected function add_method_to_shipping_zone( $zone_id, $method_id ) { } public function init_core_wizard_shipping_config() { + if ( $this->is_wc_shipping_activated() ) { + return; + } + $store_currency = get_woocommerce_currency(); if ( 'USD' === $store_currency ) { @@ -831,7 +845,6 @@ public function load_dependencies() { $shipping_label = new WC_Connect_Shipping_Label( $api_client, $settings_store, $schemas_store, $payment_methods_store ); $nux = new WC_Connect_Nux( $tracks, $shipping_label ); $taxjar = new WC_Connect_TaxJar_Integration( $api_client, $taxes_logger, $this->wc_connect_base_url ); - $options = new WC_Connect_Options(); $paypal_ec = new WC_Connect_PayPal_EC( $api_client, $nux ); $label_reports = new WC_Connect_Label_Reports( $settings_store ); @@ -863,10 +876,6 @@ public function load_admin_dependencies() { require_once __DIR__ . '/classes/class-wc-connect-debug-tools.php'; new WC_Connect_Debug_Tools( $this->api_client ); - require_once __DIR__ . '/classes/class-wc-connect-settings-pages.php'; - $settings_pages = new WC_Connect_Settings_Pages( $this->api_client, $this->get_service_schemas_store() ); - $this->set_settings_pages( $settings_pages ); - $schema = $this->get_service_schemas_store(); $settings = $this->get_service_settings_store(); $logger = $this->get_logger(); @@ -874,10 +883,18 @@ public function load_admin_dependencies() { add_action( 'admin_notices', array( WC_Connect_Error_Notice::instance(), 'render_notice' ) ); add_action( 'admin_notices', array( $this, 'render_schema_notices' ) ); - // Add WC Admin Notices. - if ( self::can_add_wc_admin_notice() ) { - require_once __DIR__ . '/classes/class-wc-connect-note-dhl-live-rates-available.php'; - WC_Connect_Note_DHL_Live_Rates_Available::init( $schema ); + if ( ! $this->is_wc_shipping_activated() ) { + // We only use the settings page for shipping since tax settings are part of + // the core "WooCommerce > Settings > Tax" tab. + require_once __DIR__ . '/classes/class-wc-connect-settings-pages.php'; + $settings_pages = new WC_Connect_Settings_Pages( $this->api_client, $this->get_service_schemas_store() ); + $this->set_settings_pages( $settings_pages ); + + // Add WC Admin Notices. + if ( self::can_add_wc_admin_notice() ) { + require_once __DIR__ . '/classes/class-wc-connect-note-dhl-live-rates-available.php'; + WC_Connect_Note_DHL_Live_Rates_Available::init( $schema ); + } } } @@ -885,9 +902,44 @@ public function load_admin_dependencies() { * Hook plugin classes into WP/WC core. */ public function attach_hooks() { + add_action( 'rest_api_init', array( $this, 'rest_api_init' ) ); + + add_action( 'admin_enqueue_scripts', array( $this->nux, 'show_pointers' ) ); + add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'add_plugin_action_links' ) ); + add_action( 'enqueue_wc_connect_script', array( $this, 'enqueue_wc_connect_script' ), 10, 2 ); + + $tracks = $this->get_tracks(); + $tracks->init(); + + $this->taxjar->init(); + $this->paypal_ec->init(); + + // Primary condition to initiate shipping. + if ( ! $this->is_wc_shipping_activated() ) { + add_action( 'rest_api_init', array( $this, 'wc_api_dev_init' ), 9999 ); + + $this->init_shipping(); + } + + if ( is_admin() ) { + $this->load_admin_dependencies(); + } + } + + public function init_shipping() { $schemas_store = $this->get_service_schemas_store(); $schemas = $schemas_store->get_service_schemas(); + add_filter( 'woocommerce_admin_reports', array( $this, 'reports_tabs' ) ); + + // Changing the postcode, currency, weight or dimension units affect the returned schema from the server. + // Make sure to update the service schemas when these options change. + // TODO: Add other options that change the schema here, or figure out a way to do it automatically. + add_action( 'update_option_woocommerce_store_postcode', array( $this, 'queue_service_schema_refresh' ) ); + add_action( 'update_option_woocommerce_currency', array( $this, 'queue_service_schema_refresh' ) ); + add_action( 'update_option_woocommerce_weight_unit', array( $this, 'queue_service_schema_refresh' ) ); + add_action( 'update_option_woocommerce_dimension_unit', array( $this, 'queue_service_schema_refresh' ) ); + if ( $schemas ) { add_filter( 'woocommerce_shipping_methods', array( $this, 'woocommerce_shipping_methods' ) ); add_action( 'woocommerce_load_shipping_methods', array( $this, 'woocommerce_load_shipping_methods' ) ); @@ -906,42 +958,18 @@ public function attach_hooks() { } } - // Changing the postcode, currency, weight or dimension units affect the returned schema from the server. - // Make sure to update the service schemas when these options change. - // TODO: Add other options that change the schema here, or figure out a way to do it automatically. - add_action( 'update_option_woocommerce_store_postcode', array( $this, 'queue_service_schema_refresh' ) ); - add_action( 'update_option_woocommerce_currency', array( $this, 'queue_service_schema_refresh' ) ); - add_action( 'update_option_woocommerce_weight_unit', array( $this, 'queue_service_schema_refresh' ) ); - add_action( 'update_option_woocommerce_dimension_unit', array( $this, 'queue_service_schema_refresh' ) ); - - add_action( 'rest_api_init', array( $this, 'rest_api_init' ) ); - add_action( 'rest_api_init', array( $this, 'wc_api_dev_init' ), 9999 ); add_action( 'wc_connect_fetch_service_schemas', array( $schemas_store, 'fetch_service_schemas_from_connect_server' ) ); - add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'hide_wc_connect_package_meta_data' ) ); - add_filter( 'is_protected_meta', array( $this, 'hide_wc_connect_order_meta_data' ), 10, 3 ); add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 5, 2 ); - add_filter( 'woocommerce_shipping_fields', array( $this, 'add_shipping_phone_to_checkout' ) ); add_action( 'woocommerce_admin_shipping_fields', array( $this, 'add_shipping_phone_to_order_fields' ) ); - add_filter( 'woocommerce_get_order_address', array( $this, 'get_shipping_or_billing_phone_from_order' ), 10, 3 ); - add_action( 'admin_enqueue_scripts', array( $this->nux, 'show_pointers' ) ); - add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'add_plugin_action_links' ) ); - add_action( 'enqueue_wc_connect_script', array( $this, 'enqueue_wc_connect_script' ), 10, 2 ); add_filter( 'wc_connect_shipping_service_settings', array( $this, 'shipping_service_settings' ), 10, 3 ); + add_filter( 'woocommerce_shipping_fields', array( $this, 'add_shipping_phone_to_checkout' ) ); + add_filter( 'woocommerce_get_order_address', array( $this, 'get_shipping_or_billing_phone_from_order' ), 10, 3 ); add_action( 'woocommerce_email_after_order_table', array( $this, 'add_tracking_info_to_emails' ), 10, 3 ); - add_filter( 'woocommerce_admin_reports', array( $this, 'reports_tabs' ) ); add_action( 'woocommerce_checkout_order_processed', array( $this, 'track_completed_order' ), 10, 3 ); add_action( 'admin_print_footer_scripts', array( $this, 'add_sift_js_tracker' ) ); + add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'hide_wc_connect_package_meta_data' ) ); + add_filter( 'is_protected_meta', array( $this, 'hide_wc_connect_order_meta_data' ), 10, 3 ); add_action( 'current_screen', array( $this, 'maybe_render_upgrade_banner' ) ); - - $tracks = $this->get_tracks(); - $tracks->init(); - - $this->taxjar->init(); - $this->paypal_ec->init(); - - if ( is_admin() ) { - $this->load_admin_dependencies(); - } } /** @@ -982,16 +1010,12 @@ public function rest_api_init() { if ( ! class_exists( 'WP_REST_Controller' ) ) { $this->logger->debug( 'Error. WP_REST_Controller could not be found', __FUNCTION__ ); + return; } require_once __DIR__ . '/classes/class-wc-rest-connect-base-controller.php'; - require_once __DIR__ . '/classes/class-wc-rest-connect-packages-controller.php'; - $rest_packages_controller = new WC_REST_Connect_Packages_Controller( $this->api_client, $settings_store, $logger, $this->service_schemas_store ); - $this->set_rest_packages_controller( $rest_packages_controller ); - $rest_packages_controller->register_routes(); - require_once __DIR__ . '/classes/class-wc-rest-connect-account-settings-controller.php'; $rest_account_settings_controller = new WC_REST_Connect_Account_Settings_Controller( $this->api_client, $settings_store, $logger, $this->payment_methods_store ); $this->set_rest_account_settings_controller( $rest_account_settings_controller ); @@ -1012,51 +1036,78 @@ public function rest_api_init() { $rest_service_data_refresh_controller->set_service_schemas_store( $this->get_service_schemas_store() ); $rest_service_data_refresh_controller->register_routes(); - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-controller.php'; - $rest_shipping_label_controller = new WC_REST_Connect_Shipping_Label_Controller( $this->api_client, $settings_store, $logger, $this->shipping_label, $this->payment_methods_store ); - $this->set_rest_shipping_label_controller( $rest_shipping_label_controller ); - $rest_shipping_label_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-status-controller.php'; - $rest_shipping_label_status_controller = new WC_REST_Connect_Shipping_Label_Status_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_shipping_label_status_controller( $rest_shipping_label_status_controller ); - $rest_shipping_label_status_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-refund-controller.php'; - $rest_shipping_label_refund_controller = new WC_REST_Connect_Shipping_Label_Refund_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_shipping_label_refund_controller( $rest_shipping_label_refund_controller ); - $rest_shipping_label_refund_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-preview-controller.php'; - $rest_shipping_label_preview_controller = new WC_REST_Connect_Shipping_Label_Preview_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_shipping_label_preview_controller( $rest_shipping_label_preview_controller ); - $rest_shipping_label_preview_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-print-controller.php'; - $rest_shipping_label_print_controller = new WC_REST_Connect_Shipping_Label_Print_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_shipping_label_print_controller( $rest_shipping_label_print_controller ); - $rest_shipping_label_print_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-rates-controller.php'; - $rest_shipping_rates_controller = new WC_REST_Connect_Shipping_Rates_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_shipping_rates_controller( $rest_shipping_rates_controller ); - $rest_shipping_rates_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-address-normalization-controller.php'; - $rest_address_normalization_controller = new WC_REST_Connect_Address_Normalization_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_address_normalization_controller( $rest_address_normalization_controller ); - $rest_address_normalization_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-assets-controller.php'; - $rest_assets_controller = new WC_REST_Connect_Assets_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_assets_controller( $rest_assets_controller ); - $rest_assets_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carrier-controller.php'; - $rest_carrier_controller = new WC_REST_Connect_Shipping_Carrier_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_carrier_controller( $rest_carrier_controller ); - $rest_carrier_controller->register_routes(); - + if ( ! $this->is_wc_shipping_activated() ) { + + require_once __DIR__ . '/classes/class-wc-rest-connect-packages-controller.php'; + $rest_packages_controller = new WC_REST_Connect_Packages_Controller( $this->api_client, $settings_store, $logger, $this->service_schemas_store ); + $this->set_rest_packages_controller( $rest_packages_controller ); + $rest_packages_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-controller.php'; + $rest_shipping_label_controller = new WC_REST_Connect_Shipping_Label_Controller( $this->api_client, $settings_store, $logger, $this->shipping_label, $this->payment_methods_store ); + $this->set_rest_shipping_label_controller( $rest_shipping_label_controller ); + $rest_shipping_label_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-status-controller.php'; + $rest_shipping_label_status_controller = new WC_REST_Connect_Shipping_Label_Status_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_shipping_label_status_controller( $rest_shipping_label_status_controller ); + $rest_shipping_label_status_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-refund-controller.php'; + $rest_shipping_label_refund_controller = new WC_REST_Connect_Shipping_Label_Refund_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_shipping_label_refund_controller( $rest_shipping_label_refund_controller ); + $rest_shipping_label_refund_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-preview-controller.php'; + $rest_shipping_label_preview_controller = new WC_REST_Connect_Shipping_Label_Preview_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_shipping_label_preview_controller( $rest_shipping_label_preview_controller ); + $rest_shipping_label_preview_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-label-print-controller.php'; + $rest_shipping_label_print_controller = new WC_REST_Connect_Shipping_Label_Print_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_shipping_label_print_controller( $rest_shipping_label_print_controller ); + $rest_shipping_label_print_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-rates-controller.php'; + $rest_shipping_rates_controller = new WC_REST_Connect_Shipping_Rates_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_shipping_rates_controller( $rest_shipping_rates_controller ); + $rest_shipping_rates_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-address-normalization-controller.php'; + $rest_address_normalization_controller = new WC_REST_Connect_Address_Normalization_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_address_normalization_controller( $rest_address_normalization_controller ); + $rest_address_normalization_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-assets-controller.php'; + $rest_assets_controller = new WC_REST_Connect_Assets_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_assets_controller( $rest_assets_controller ); + $rest_assets_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carrier-controller.php'; + $rest_carrier_controller = new WC_REST_Connect_Shipping_Carrier_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_carrier_controller( $rest_carrier_controller ); + $rest_carrier_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-subscription-activate-controller.php'; + $rest_subscription_activate_controller = new WC_REST_Connect_Subscription_activate_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_subscription_activate_controller( $rest_subscription_activate_controller ); + $rest_subscription_activate_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carrier-delete-controller.php'; + $rest_carrier_delete_controller = new WC_REST_Connect_Shipping_Carrier_Delete_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_carrier_delete_controller( $rest_carrier_delete_controller ); + $rest_carrier_delete_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carrier-types-controller.php'; + $rest_carrier_types_controller = new WC_REST_Connect_Shipping_Carrier_Types_Controller( $this->api_client, $settings_store, $logger ); + $this->set_carrier_types_controller( $rest_carrier_types_controller ); + $rest_carrier_types_controller->register_routes(); + + require_once __DIR__ . '/classes/class-wc-rest-connect-migration-flag-controller.php'; + $rest_migration_flag_controller = new WC_REST_Connect_Migration_Flag_Controller( $this->api_client, $settings_store, $logger, $this->tracks ); + $this->set_rest_migration_flag_controller( $rest_migration_flag_controller ); + $rest_migration_flag_controller->register_routes(); + } require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carriers-controller.php'; $rest_carriers_controller = new WC_REST_Connect_Shipping_Carriers_Controller( $this->api_client, $settings_store, $logger ); $this->set_rest_carriers_controller( $rest_carriers_controller ); @@ -1067,26 +1118,6 @@ public function rest_api_init() { $this->set_rest_subscriptions_controller( $rest_subscriptions_controller ); $rest_subscriptions_controller->register_routes(); - require_once __DIR__ . '/classes/class-wc-rest-connect-subscription-activate-controller.php'; - $rest_subscription_activate_controller = new WC_REST_Connect_Subscription_activate_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_subscription_activate_controller( $rest_subscription_activate_controller ); - $rest_subscription_activate_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carrier-delete-controller.php'; - $rest_carrier_delete_controller = new WC_REST_Connect_Shipping_Carrier_Delete_Controller( $this->api_client, $settings_store, $logger ); - $this->set_rest_carrier_delete_controller( $rest_carrier_delete_controller ); - $rest_carrier_delete_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-shipping-carrier-types-controller.php'; - $rest_carrier_types_controller = new WC_REST_Connect_Shipping_Carrier_Types_Controller( $this->api_client, $settings_store, $logger ); - $this->set_carrier_types_controller( $rest_carrier_types_controller ); - $rest_carrier_types_controller->register_routes(); - - require_once __DIR__ . '/classes/class-wc-rest-connect-migration-flag-controller.php'; - $rest_migration_flag_controller = new WC_REST_Connect_Migration_Flag_Controller( $this->api_client, $settings_store, $logger, $this->tracks ); - $this->set_rest_migration_flag_controller( $rest_migration_flag_controller ); - $rest_migration_flag_controller->register_routes(); - add_filter( 'rest_request_before_callbacks', array( $this, 'log_rest_api_errors' ), 10, 3 ); } @@ -1886,16 +1917,24 @@ public function render_schema_notices() { } } + /** + * Check if WooCommerce Shipping has been activated. + * + * @return bool + */ + public function is_wc_shipping_activated() { + return in_array( 'woocommerce-shipping/woocommerce-shipping.php', get_option( 'active_plugins' ) ); + } + /** * Returns if both Woo Shipping and Woo Tax are active. * * @return bool */ public function are_woo_shipping_and_woo_tax_active() { - $is_woo_shipping_active = in_array( 'woocommerce-shipping/woocommerce-shipping.php', get_option( 'active_plugins' ) ); - $is_woo_tax_active = in_array( 'woocommerce-tax/woocommerce-tax.php', get_option( 'active_plugins' ) ); + $is_woo_tax_active = in_array( 'woocommerce-tax/woocommerce-tax.php', get_option( 'active_plugins' ) ); - return $is_woo_shipping_active && $is_woo_tax_active; + return $this->is_wc_shipping_activated() && $is_woo_tax_active; } /** @@ -1906,7 +1945,7 @@ public function are_woo_shipping_and_woo_tax_active() { * @return void */ public function display_woo_shipping_and_woo_tax_are_active_notice() { - echo '

' . esc_html__( 'Woo Shipping and Woo Tax plugins are already active. Please deactivate WooCommerce Shipping & Tax.', 'woocommerce-services' ) . '

'; + echo '

' . esc_html__( 'WC Shipping and WC Tax plugins are already active. Please deactivate WooCommerce Shipping & Tax.', 'woocommerce-services' ) . '

'; } /**