<?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\GoogleListingsAndAds\Shipping;
defined( 'ABSPATH' ) || exit;
/**
* Class LocationRatesProcessor
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Shipping
*
* @since 2.1.0
*/
class LocationRatesProcessor {
/**
* Process the shipping rates data for output.
*
* @param LocationRate[] $location_rates Array of shipping rates belonging to a specific location.
*
* @return LocationRate[] Array of processed location rates.
*/
public function process( array $location_rates ): array {
/** @var LocationRate[] $grouped_rates */
$grouped_rates = [];
foreach ( $location_rates as $location_rate ) {
$shipping_rate = $location_rate->get_shipping_rate();
$type = 'flat_rate';
// If there are conditional free shipping rates, we need to group and compare them together.
if ( $shipping_rate->is_free() && $shipping_rate->has_min_order_amount() ) {
$type = 'conditional_free';
}
// Append the shipping class names to the type key to group and compare the class rates together.
$classes = ! empty( $shipping_rate->get_applicable_classes() ) ? join( ',', $shipping_rate->get_applicable_classes() ) : '';
$type .= $classes;
if ( ! isset( $grouped_rates[ $type ] ) || $this->should_rate_be_replaced( $shipping_rate, $grouped_rates[ $type ]->get_shipping_rate() ) ) {
$grouped_rates[ $type ] = $location_rate;
}
}
// Ignore the conditional free rate if there are no flat rate or if the existing flat rate is free.
if ( ! isset( $grouped_rates['flat_rate'] ) || $grouped_rates['flat_rate']->get_shipping_rate()->is_free() ) {
unset( $grouped_rates['conditional_free'] );
}
return array_values( $grouped_rates );
}
/**
* Checks whether the existing shipping rate should be replaced with a more suitable one. Used when grouping the rates.
*
* @param ShippingRate $new_rate
* @param ShippingRate $existing_rate
*
* @return bool
*/
protected function should_rate_be_replaced( ShippingRate $new_rate, ShippingRate $existing_rate ): bool {
return $new_rate->get_rate() > $existing_rate->get_rate() ||
(float) $new_rate->get_min_order_amount() > (float) $existing_rate->get_min_order_amount();
}
}