<?php
namespace WPDesk\FS\TableRate\ShippingMethodsIntegration;
use FSVendor\WPDesk\FS\TableRate\Logger\NoticeLogger;
use FSVendor\WPDesk\FS\TableRate\Logger\ShippingMethodLogger;
use FSVendor\WPDesk\FS\TableRate\Settings\MethodSettings;
use FSVendor\WPDesk\FS\TableRate\Settings\MethodSettingsFactory;
use FSVendor\WPDesk\PluginBuilder\Plugin\Hookable;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use WPDesk\FS\TableRate\Rule\Condition\ConditionsFactory;
use WPDesk\FS\TableRate\Rule\Cost\RuleAdditionalCostFactory;
use WPDesk\FS\TableRate\Rule\Cost\RuleCostFieldsFactory;
use WPDesk\FS\TableRate\Rule\CostsCalculator;
use WPDesk\FS\TableRate\Rule\ShippingContents\DestinationAddressFactory;
use WPDesk\FS\TableRate\Rule\ShippingContents\ShippingContentsImplementation;
use WPDesk\FS\TableRate\Rule\SpecialAction\SpecialActionFactory;
/**
* Class ShippingRate
*/
class ShippingRate implements Hookable {
const FS_CANCEL = 'fs_cancel';
/**
* Logger provided by Flexible Shipping plugin.
*
* @var LoggerInterface
*/
protected static $fs_logger;
private array $package;
/**
* Set logger. This logger is set by Flexible Shipping plugin.
*
* @param LoggerInterface $fs_logger .
*/
public static function set_fs_logger( LoggerInterface $fs_logger ) {
static::$fs_logger = $fs_logger;
}
public function hooks() {
add_filter( 'woocommerce_shipping_method_add_rate_args', [ $this, 'add_table_rate_shipping_rate' ], 10, 3 );
add_action( 'woocommerce_before_get_rates_for_package', [ $this, 'save_package' ], 10 );
add_filter( 'woocommerce_package_rates', [ $this, 'remove_canceled_rates' ] );
}
/**
* @param array $rates
*
* @return array
*/
public function remove_canceled_rates( $rates ) {
$meta_key = self::FS_CANCEL;
return array_filter(
$rates,
function ( $rate ) use ( $meta_key ) {
return ! ( $rate->get_meta_data()[ $meta_key ] ?? false );
}
);
}
/**
* @param array $package
*/
public function save_package( $package ): void {
$this->package = $package;
}
/**
* @param array $args
* @param \WC_Shipping_Method $shipping_method
*
* @return array
*/
public function add_table_rate_shipping_rate( $args, $shipping_method ) {
if ( ! is_array( $args ) || $shipping_method->get_option( SettingsFields::FS_CALCULATION_ENABLED, 'no' ) === 'no' ) {
return $args;
}
$cost_calculator = $this->prepare_cost_calculator( $shipping_method, $this->package );
$cost_calculator->process_rules();
if ( ! is_array( $args['meta_data'] ) ) {
$args['meta_data'] = [];
}
if ( $cost_calculator->is_cancel() ) {
$args['meta_data'][ self::FS_CANCEL ] = true;
} else {
if ( ! is_array( $args['cost'] ) ) {
$args['cost'] = [ $args['cost'] ];
}
$args['meta_data'][ OrderMetaData::META_KEY ] = OrderMetaData::prepare_meta_value(
(float) array_sum( $args['cost'] ),
$cost_calculator->get_calculated_cost()
);
$args['cost'][] = $cost_calculator->get_calculated_cost();
}
return $args;
}
private function prepare_cost_calculator( $shipping_method, $package ): CostsCalculator {
$available_conditions = ( new ConditionsFactory() )->get_conditions();
$cost_fields = ( new RuleCostFieldsFactory() )->get_fields();
$available_additional_costs = ( new RuleAdditionalCostFactory() )->get_additional_costs();
$available_special_actions = ( new SpecialActionFactory() )->get_special_actions();
$shop_currency = get_option( 'woocommerce_currency' );
$rules = $shipping_method->get_option( SettingsFields::SETTING_METHOD_RULES, '[]' );
$method_settings = MethodSettingsFactory::create_from_array( [ 'method_rules' => json_decode( $rules, true ) ] );
$shipping_contents = new ShippingContentsImplementation(
$package['contents'],
WC()->cart->display_prices_including_tax(),
wc_get_price_decimals(),
DestinationAddressFactory::create_from_package_destination( $package['destination'] ?? [] ),
get_woocommerce_currency()
);
return new CostsCalculator(
$method_settings,
$shipping_contents,
$available_conditions,
$cost_fields,
$available_additional_costs,
$available_special_actions,
wc_get_price_decimals(),
$shop_currency,
$this->prepare_shipping_method_calculation_logger( $method_settings, $shipping_method->instance_id )
);
}
private function prepare_shipping_method_calculation_logger( MethodSettings $shipping_method_settings, int $instance_id ): ShippingMethodLogger {
$method_debug_mode = $shipping_method_settings->get_debug_mode();
$shipping_method_title = $shipping_method_settings->get_title();
$shipping_method_url = admin_url(
'admin.php?page=wc-settings&tab=shipping&instance_id=' . sanitize_key( $instance_id ) . '&action=edit&method_id=' . sanitize_key( $shipping_method_settings->get_id() )
);
if ( null !== static::$fs_logger ) {
$fs_logger = static::$fs_logger;
} else {
$fs_logger = new NullLogger();
}
return new ShippingMethodLogger(
$fs_logger,
new NoticeLogger(
$shipping_method_title,
$shipping_method_url,
'yes' === $method_debug_mode && current_user_can( 'manage_woocommerce' )
)
);
}
}