<?php declare( strict_types=1 ); namespace Automattic\WooCommerce\GoogleListingsAndAds\Shipping; use Automattic\WooCommerce\GoogleListingsAndAds\API\Google\Settings as GoogleSettings; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobRepository; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\UpdateShippingSettings; use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\MerchantCenterService; defined( 'ABSPATH' ) || exit; /** * Class SyncerHooks * * Hooks to various WooCommerce and WordPress actions to automatically sync shipping settings. * * @package Automattic\WooCommerce\GoogleListingsAndAds\Shipping * * @since 2.1.0 */ class SyncerHooks implements Service, Registerable { /** * This property is used to avoid scheduling duplicate jobs in the same request. * * @var bool */ protected $already_scheduled = false; /** * @var GoogleSettings */ protected $google_settings; /** * @var MerchantCenterService */ protected $merchant_center; /** * @var UpdateShippingSettings */ protected $update_shipping_job; /** * SyncerHooks constructor. * * @param MerchantCenterService $merchant_center * @param GoogleSettings $google_settings * @param JobRepository $job_repository */ public function __construct( MerchantCenterService $merchant_center, GoogleSettings $google_settings, JobRepository $job_repository ) { $this->google_settings = $google_settings; $this->merchant_center = $merchant_center; $this->update_shipping_job = $job_repository->get( UpdateShippingSettings::class ); } /** * Register the service. */ public function register(): void { // only register the hooks if Merchant Center account is connected and the user has chosen for the shipping rates to be synced from WooCommerce settings. if ( ! $this->merchant_center->is_connected() || ! $this->google_settings->should_get_shipping_rates_from_woocommerce() ) { return; } $update_settings = function () { $this->handle_update_shipping_settings(); }; // After a shipping zone object is saved to database. add_action( 'woocommerce_after_shipping_zone_object_save', $update_settings, 90 ); // After a shipping zone is deleted. add_action( 'woocommerce_delete_shipping_zone', $update_settings, 90 ); // After a shipping method is added to or deleted from a shipping zone. add_action( 'woocommerce_shipping_zone_method_added', $update_settings, 90 ); add_action( 'woocommerce_shipping_zone_method_deleted', $update_settings, 90 ); // After a shipping method is enabled or disabled. add_action( 'woocommerce_shipping_zone_method_status_toggled', $update_settings, 90 ); // After a shipping class is updated/deleted. add_action( 'woocommerce_shipping_classes_save_class', $update_settings, 90 ); add_action( 'saved_product_shipping_class', $update_settings, 90 ); add_action( 'delete_product_shipping_class', $update_settings, 90 ); // After free_shipping and flat_rate method options are updated. add_action( 'woocommerce_update_options_shipping_free_shipping', $update_settings, 90 ); add_action( 'woocommerce_update_options_shipping_flat_rate', $update_settings, 90 ); // The shipping options can also be updated using other methods (e.g. by calling WC_Shipping_Method::process_admin_options). // Those methods may not fire any hooks, so we need to watch the base WordPress hooks for when those options are updated. $on_option_change = function ( $option ) { /** * This Regex checks for the shipping options key generated by the `WC_Shipping_Method::get_instance_option_key` method. * We check for the shipping method IDs supported by GLA (flat_rate or free_shipping), and an integer instance_id. * * @see \WC_Shipping_Method::get_instance_option_key for more information about this key. */ if ( preg_match( '/^woocommerce_(flat_rate|free_shipping)_\d+_settings$/', $option ) ) { $this->handle_update_shipping_settings(); } }; add_action( 'updated_option', $on_option_change, 90 ); add_action( 'added_option', $on_option_change, 90 ); } /** * Handle updating of Merchant Center shipping settings. * * @return void */ protected function handle_update_shipping_settings() { // Bail if an event is already scheduled in the current request if ( $this->already_scheduled ) { return; } $this->update_shipping_job->schedule(); $this->already_scheduled = true; } }