<?php if (!defined('ABSPATH')) { exit; } abstract class WC_Shipping_Method extends WC_Settings_API { public $supports = array('settings'); public $id = ''; public $method_title = ''; public $method_description = ''; public $enabled = 'yes'; public $title; public $rates = array(); public $tax_status = 'taxable'; public $fee = null; public $minimum_fee = null; public $instance_id = 0; public $instance_form_fields = array(); public $instance_settings = array(); public $availability; public $countries = array(); public function __construct($instance_id = 0) { $this->instance_id = absint($instance_id); } public function supports($feature) { return apply_filters('woocommerce_shipping_method_supports', in_array($feature, $this->supports), $feature, $this); } public function calculate_shipping($package = array()) { } public function is_taxable() { return wc_tax_enabled() && 'taxable' === $this->tax_status && (WC()->customer && !WC()->customer->get_is_vat_exempt()); } public function is_enabled() { return 'yes' === $this->enabled; } public function get_instance_id() { return $this->instance_id; } public function get_method_title() { return apply_filters('woocommerce_shipping_method_title', $this->method_title, $this); } public function get_method_description() { return apply_filters('woocommerce_shipping_method_description', $this->method_description, $this); } public function get_title() { return apply_filters('woocommerce_shipping_method_title', $this->title, $this->id); } public function get_rates_for_package($package) { $this->rates = array(); if ($this->is_available($package) && (empty($package['ship_via']) || in_array($this->id, $package['ship_via']))) { $this->calculate_shipping($package); } return $this->rates; } public function get_rate_id($suffix = '') { $rate_id = array($this->id); if ($this->instance_id) { $rate_id[] = $this->instance_id; } if ($suffix) { $rate_id[] = $suffix; } return implode(':', $rate_id); } public function add_rate($args = array()) { $args = apply_filters('woocommerce_shipping_method_add_rate_args', wp_parse_args($args, array('id' => $this->get_rate_id(), 'label' => '', 'cost' => '0', 'taxes' => '', 'calc_tax' => 'per_order', 'meta_data' => array(), 'package' => false, 'price_decimals' => wc_get_price_decimals())), $this); if (!$args['id'] || !$args['label']) { return; } $total_cost = is_array($args['cost']) ? array_sum($args['cost']) : $args['cost']; $taxes = $args['taxes']; if (!is_array($taxes) && false !== $taxes && $total_cost > 0 && $this->is_taxable()) { $taxes = 'per_item' === $args['calc_tax'] ? $this->get_taxes_per_item($args['cost']) : WC_Tax::calc_shipping_tax($total_cost, WC_Tax::get_shipping_tax_rates()); } $total_cost = wc_format_decimal($total_cost, $args['price_decimals']); $rate = new WC_Shipping_Rate(); $rate->set_id($args['id']); $rate->set_method_id($this->id); $rate->set_instance_id($this->instance_id); $rate->set_label($args['label']); $rate->set_cost($total_cost); $rate->set_taxes($taxes); if (!empty($args['meta_data'])) { foreach ($args['meta_data'] as $key => $value) { $rate->add_meta_data($key, $value); } } if ($args['package']) { $items_in_package = array(); foreach ($args['package']['contents'] as $item) { $product = $item['data']; $items_in_package[] = $product->get_name() . ' &times; ' . $item['quantity']; } $rate->add_meta_data(__('Items', 'woocommerce'), implode(', ', $items_in_package)); } $this->rates[$args['id']] = apply_filters('woocommerce_shipping_method_add_rate', $rate, $args, $this); } protected function get_taxes_per_item($costs) { $taxes = array(); if (is_array($costs)) { $cart = WC()->cart->get_cart(); foreach ($costs as $cost_key => $amount) { if (!isset($cart[$cost_key])) { continue; } $item_taxes = WC_Tax::calc_shipping_tax($amount, WC_Tax::get_shipping_tax_rates($cart[$cost_key]['data']->get_tax_class())); foreach (array_keys($taxes + $item_taxes) as $key) { $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0); } } if (isset($costs['order'])) { $item_taxes = WC_Tax::calc_shipping_tax($costs['order'], WC_Tax::get_shipping_tax_rates()); foreach (array_keys($taxes + $item_taxes) as $key) { $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0); } } } return $taxes; } public function is_available($package) { $available = $this->is_enabled(); if (!$this->instance_id && $available) { $countries = is_array($this->countries) ? $this->countries : array(); switch ($this->availability) { case 'specific': case 'including': $available = in_array($package['destination']['country'], array_intersect($countries, array_keys(WC()->countries->get_shipping_countries()))); break; case 'excluding': $available = in_array($package['destination']['country'], array_diff(array_keys(WC()->countries->get_shipping_countries()), $countries)); break; default: $available = in_array($package['destination']['country'], array_keys(WC()->countries->get_shipping_countries())); break; } } return apply_filters('woocommerce_shipping_' . $this->id . '_is_available', $available, $package, $this); } public function get_fee($fee, $total) { if (strstr($fee, '%')) { $fee = $total / 100 * str_replace('%', '', $fee); } if (!empty($this->minimum_fee) && $this->minimum_fee > $fee) { $fee = $this->minimum_fee; } return $fee; } public function has_settings() { return $this->instance_id ? $this->supports('instance-settings') : $this->supports('settings'); } public function get_admin_options_html() { if ($this->instance_id) { $settings_html = $this->generate_settings_html($this->get_instance_form_fields(), false); } else { $settings_html = $this->generate_settings_html($this->get_form_fields(), false); } return '<table class="form-table">' . $settings_html . '</table>'; } public function admin_options() { if (!$this->instance_id) { echo '<h2>' . esc_html($this->get_method_title()) . '</h2>'; } echo wp_kses_post(wpautop($this->get_method_description())); echo $this->get_admin_options_html(); } public function get_option($key, $empty_value = null) { if ($this->instance_id && array_key_exists($key, $this->get_instance_form_fields())) { return $this->get_instance_option($key, $empty_value); } $option = apply_filters('woocommerce_shipping_' . $this->id . '_option', parent::get_option($key, $empty_value), $key, $this); return $option; } public function get_instance_option($key, $empty_value = null) { if (empty($this->instance_settings)) { $this->init_instance_settings(); } if (!isset($this->instance_settings[$key])) { $form_fields = $this->get_instance_form_fields(); $this->instance_settings[$key] = $this->get_field_default($form_fields[$key]); } if (!is_null($empty_value) && '' === $this->instance_settings[$key]) { $this->instance_settings[$key] = $empty_value; } $instance_option = apply_filters('woocommerce_shipping_' . $this->id . '_instance_option', $this->instance_settings[$key], $key, $this); return $instance_option; } public function get_instance_form_fields() { return apply_filters('woocommerce_shipping_instance_form_fields_' . $this->id, array_map(array($this, 'set_defaults'), $this->instance_form_fields)); } public function get_instance_option_key() { return $this->instance_id ? $this->plugin_id . $this->id . '_' . $this->instance_id . '_settings' : ''; } public function init_instance_settings() { $this->instance_settings = get_option($this->get_instance_option_key(), null); if (!is_array($this->instance_settings)) { $form_fields = $this->get_instance_form_fields(); $this->instance_settings = array_merge(array_fill_keys(array_keys($form_fields), ''), wp_list_pluck($form_fields, 'default')); } } public function process_admin_options() { if (!$this->instance_id) { return parent::process_admin_options(); } if (!isset($_REQUEST['instance_id']) || absint($_REQUEST['instance_id']) !== $this->instance_id) { return false; } $this->init_instance_settings(); $post_data = $this->get_post_data(); foreach ($this->get_instance_form_fields() as $key => $field) { if ('title' !== $this->get_field_type($field)) { try { $this->instance_settings[$key] = $this->get_field_value($key, $field, $post_data); } catch (Exception $e) { $this->add_error($e->getMessage()); } } } return update_option($this->get_instance_option_key(), apply_filters('woocommerce_shipping_' . $this->id . '_instance_settings_values', $this->instance_settings, $this), 'yes'); } }