File "Settings.php"
Full Path: /home/warrior1/public_html/wp-content/plugins/google-listings-and-ads/src/API/Google/Settings.php
File size: 10.69 KB
MIME-type: text/x-php
Charset: utf-8
<?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\GoogleListingsAndAds\API\Google;
use Automattic\WooCommerce\GoogleListingsAndAds\DB\Query\ShippingRateQuery as RateQuery;
use Automattic\WooCommerce\GoogleListingsAndAds\DB\Query\ShippingTimeQuery as TimeQuery;
use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\TargetAudience;
use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsInterface;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WC;
use Automattic\WooCommerce\GoogleListingsAndAds\Shipping\CountryRatesCollection;
use Automattic\WooCommerce\GoogleListingsAndAds\Shipping\GoogleAdapter\DBShippingSettingsAdapter;
use Automattic\WooCommerce\GoogleListingsAndAds\Shipping\GoogleAdapter\WCShippingSettingsAdapter;
use Automattic\WooCommerce\GoogleListingsAndAds\Shipping\ShippingZone;
use Google\Service\ShoppingContent;
use Google\Service\ShoppingContent\AccountAddress;
use Google\Service\ShoppingContent\AccountTax;
use Google\Service\ShoppingContent\AccountTaxTaxRule as TaxRule;
use Google\Service\ShoppingContent\ShippingSettings;
use Psr\Container\ContainerInterface;
defined( 'ABSPATH' ) || exit;
/**
* Class Settings
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\API\Google
*/
class Settings {
use LocationIDTrait;
/** @var ContainerInterface */
protected $container;
/**
* Settings constructor.
*
* @param ContainerInterface $container
*/
public function __construct( ContainerInterface $container ) {
$this->container = $container;
}
/**
* Sync the shipping settings with Google.
*/
public function sync_shipping() {
if ( ! $this->should_sync_shipping() ) {
return;
}
$settings = $this->generate_shipping_settings();
$this->get_shopping_service()->shippingsettings->update(
$this->get_merchant_id(),
$this->get_account_id(),
$settings
);
}
/**
* Whether we should synchronize settings with the Merchant Center
*
* @return bool
*/
protected function should_sync_shipping(): bool {
$shipping_rate = $this->get_settings()['shipping_rate'] ?? '';
$shipping_time = $this->get_settings()['shipping_time'] ?? '';
return in_array( $shipping_rate, [ 'flat', 'automatic' ], true ) && 'flat' === $shipping_time;
}
/**
* Whether we should get the shipping settings from the WooCommerce settings.
*
* @return bool
*
* @since 1.12.0
*/
public function should_get_shipping_rates_from_woocommerce(): bool {
return 'automatic' === ( $this->get_settings()['shipping_rate'] ?? '' );
}
/**
* Generate a ShippingSettings object for syncing the store shipping settings to Merchant Center.
*
* @return ShippingSettings
*
* @since 2.1.0
*/
protected function generate_shipping_settings(): ShippingSettings {
$times = $this->get_shipping_times();
/** @var WC $wc_proxy */
$wc_proxy = $this->container->get( WC::class );
$currency = $wc_proxy->get_woocommerce_currency();
if ( $this->should_get_shipping_rates_from_woocommerce() ) {
return new WCShippingSettingsAdapter(
[
'currency' => $currency,
'rates_collections' => $this->get_shipping_rates_collections_from_woocommerce(),
'delivery_times' => $times,
'accountId' => $this->get_account_id(),
]
);
}
return new DBShippingSettingsAdapter(
[
'currency' => $currency,
'db_rates' => $this->get_shipping_rates_from_database(),
'delivery_times' => $times,
'accountId' => $this->get_account_id(),
]
);
}
/**
* Get the current tax settings from the API.
*
* @return AccountTax
*/
public function get_taxes(): AccountTax {
return $this->get_shopping_service()->accounttax->get(
$this->get_merchant_id(),
$this->get_account_id()
);
}
/**
* Whether we should sync tax settings.
*
* This depends on the store being in the US
*
* @return bool
*/
protected function should_sync_taxes(): bool {
if ( 'US' !== $this->get_store_country() ) {
return false;
}
return 'destination' === ( $this->get_settings()['tax_rate'] ?? 'destination' );
}
/**
* Sync tax setting with Google.
*/
public function sync_taxes() {
if ( ! $this->should_sync_taxes() ) {
return;
}
$taxes = new AccountTax();
$taxes->setAccountId( $this->get_account_id() );
$tax_rule = new TaxRule();
$tax_rule->setUseGlobalRate( true );
$tax_rule->setLocationId( $this->get_state_id( $this->get_store_state() ) );
$tax_rule->setCountry( $this->get_store_country() );
$taxes->setRules( [ $tax_rule ] );
$this->get_shopping_service()->accounttax->update(
$this->get_merchant_id(),
$this->get_account_id(),
$taxes
);
}
/**
* Get shipping time data.
*
* @return array
*/
protected function get_shipping_times(): array {
static $times = null;
if ( null === $times ) {
$time_query = $this->container->get( TimeQuery::class );
$times = array_column( $time_query->get_results(), 'time', 'country' );
}
return $times;
}
/**
* Get shipping rate data.
*
* @return array
*/
protected function get_shipping_rates_from_database(): array {
$rate_query = $this->container->get( RateQuery::class );
return $rate_query->get_results();
}
/**
* Get shipping rate data from WooCommerce shipping settings.
*
* @return CountryRatesCollection[] Array of rates collections for each target country specified in settings.
*/
protected function get_shipping_rates_collections_from_woocommerce(): array {
/** @var TargetAudience $target_audience */
$target_audience = $this->container->get( TargetAudience::class );
$target_countries = $target_audience->get_target_countries();
/** @var ShippingZone $shipping_zone */
$shipping_zone = $this->container->get( ShippingZone::class );
$rates = [];
foreach ( $target_countries as $country ) {
$location_rates = $shipping_zone->get_shipping_rates_for_country( $country );
$rates[ $country ] = new CountryRatesCollection( $country, $location_rates );
}
return $rates;
}
/**
* @return OptionsInterface
*/
protected function get_options_object(): OptionsInterface {
return $this->container->get( OptionsInterface::class );
}
/**
* Get the Merchant ID
*
* @return int
*/
protected function get_merchant_id(): int {
return $this->get_options_object()->get( OptionsInterface::MERCHANT_ID );
}
/**
* Get the account ID.
*
* @return int
*/
protected function get_account_id(): int {
// todo: there are some cases where this might be different than the Merchant ID.
return $this->get_merchant_id();
}
/**
* Get the Shopping Service object.
*
* @return ShoppingContent
*/
protected function get_shopping_service(): ShoppingContent {
return $this->container->get( ShoppingContent::class );
}
/**
* Get the country for the store.
*
* @return string
*/
protected function get_store_country(): string {
/** @var WC $wc */
$wc = $this->container->get( WC::class );
return $wc->get_wc_countries()->get_base_country();
}
/**
* Get the state for the store.
*
* @return string
*/
protected function get_store_state(): string {
/** @var WC $wc */
$wc = $this->container->get( WC::class );
return $wc->get_wc_countries()->get_base_state();
}
/**
* Get the WooCommerce store physical address.
*
* @return AccountAddress
*
* @since 1.4.0
*/
public function get_store_address(): AccountAddress {
/** @var WC $wc */
$wc = $this->container->get( WC::class );
$countries = $wc->get_wc_countries();
$postal_code = ! empty( $countries->get_base_postcode() ) ? $countries->get_base_postcode() : null;
$locality = ! empty( $countries->get_base_city() ) ? $countries->get_base_city() : null;
$country = ! empty( $countries->get_base_country() ) ? $countries->get_base_country() : null;
$region = ! empty( $countries->get_base_state() ) ? $countries->get_base_state() : null;
$mc_address = new AccountAddress();
$mc_address->setPostalCode( $postal_code );
$mc_address->setLocality( $locality );
$mc_address->setCountry( $country );
if ( ! empty( $region ) && ! empty( $country ) ) {
$mc_address->setRegion( $this->maybe_get_state_name( $region, $country ) );
}
$address = ! empty( $countries->get_base_address() ) ? $countries->get_base_address() : null;
$address_2 = ! empty( $countries->get_base_address_2() ) ? $countries->get_base_address_2() : null;
$separator = ! empty( $address ) && ! empty( $address_2 ) ? "\n" : '';
$address = sprintf( '%s%s%s', $countries->get_base_address(), $separator, $countries->get_base_address_2() );
if ( ! empty( $address ) ) {
$mc_address->setStreetAddress( $address );
}
return $mc_address;
}
/**
* Check whether the address has errors
*
* @param AccountAddress $address to be validated.
*
* @return array
*/
public function wc_address_errors( AccountAddress $address ): array {
/** @var WC $wc */
$wc = $this->container->get( WC::class );
$countries = $wc->get_wc_countries();
$locale = $countries->get_country_locale();
$locale_settings = $locale[ $address->getCountry() ] ?? [];
$fields_to_validate = [
'address_1' => $address->getStreetAddress(),
'city' => $address->getLocality(),
'country' => $address->getCountry(),
'postcode' => $address->getPostalCode(),
];
return $this->validate_address( $fields_to_validate, $locale_settings );
}
/**
* Check whether the required address fields are empty
*
* @param array $address_fields to be validated.
* @param array $locale_settings locale settings
* @return array
*/
public function validate_address( array $address_fields, array $locale_settings ): array {
$errors = array_filter(
$address_fields,
function ( $field ) use ( $locale_settings, $address_fields ) {
$is_required = $locale_settings[ $field ]['required'] ?? true;
return $is_required && empty( $address_fields[ $field ] );
},
ARRAY_FILTER_USE_KEY
);
return array_keys( $errors );
}
/**
* Return a state name.
*
* @param string $state_code State code.
* @param string $country Country code.
*
* @return string
*
* @since 1.4.0
*/
protected function maybe_get_state_name( string $state_code, string $country ): string {
/** @var WC $wc */
$wc = $this->container->get( WC::class );
$states = $country ? array_filter( (array) $wc->get_wc_countries()->get_states( $country ) ) : [];
if ( ! empty( $states ) ) {
$state_code = wc_strtoupper( $state_code );
if ( isset( $states[ $state_code ] ) ) {
return $states[ $state_code ];
}
}
return $state_code;
}
/**
* Get the array of settings for the Merchant Center.
*
* @return array
*/
protected function get_settings(): array {
$settings = $this->get_options_object()->get( OptionsInterface::MERCHANT_CENTER );
return is_array( $settings ) ? $settings : [];
}
}