Settings > Shipping) */ public $has_settings = true; /** @var array Features this method supports. */ public $supports = array(); /** @var array This is an array of rates - methods must populate this array to register shipping costs */ public $rates = array(); /** * Whether or not we need to calculate tax on top of the shipping rate * * @return boolean */ public function is_taxable() { return ( wc_tax_enabled() && $this->tax_status == 'taxable' && ! WC()->customer->is_vat_exempt() ); } /** * Add a rate * * Add a shipping rate. If taxes are not set they will be calculated based on cost. * * @param array $args (default: array()) */ public function add_rate( $args = array() ) { $defaults = array( 'id' => '', // ID for the rate 'label' => '', // Label for the rate 'cost' => '0', // Amount or array of costs (per item shipping) 'taxes' => '', // Pass taxes, nothing to have it calculated for you, or 'false' to calc no tax 'calc_tax' => 'per_order' // Calc tax per_order or per_item. Per item needs an array of costs ); $args = wp_parse_args( $args, $defaults ); extract( $args ); // Id and label are required if ( ! $id || ! $label ) { return; } // Handle cost $total_cost = is_array( $cost ) ? array_sum( $cost ) : $cost; // Taxes - if not an array and not set to false, calc tax based on cost and passed calc_tax variable // This saves shipping methods having to do complex tax calculations if ( ! is_array( $taxes ) && $taxes !== false && $total_cost > 0 && $this->is_taxable() ) { $taxes = array(); switch ( $calc_tax ) { case "per_item" : // If we have an array of costs we can look up each items tax class and add tax accordingly if ( is_array( $cost ) ) { $cart = WC()->cart->get_cart(); foreach ( $cost as $cost_key => $amount ) { if ( ! isset( $cart[ $cost_key ] ) ) { continue; } $_product = $cart[ $cost_key ]['data']; $rates = WC_Tax::get_shipping_tax_rates( $_product->get_tax_class() ); $item_taxes = WC_Tax::calc_shipping_tax( $amount, $rates ); // Sum the item taxes foreach ( array_keys( $taxes + $item_taxes ) as $key ) { $taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 ); } } // Add any cost for the order - order costs are in the key 'order' if ( isset( $cost['order'] ) ) { $rates = WC_Tax::get_shipping_tax_rates(); $item_taxes = WC_Tax::calc_shipping_tax( $cost['order'], $rates ); // Sum the item taxes foreach ( array_keys( $taxes + $item_taxes ) as $key ) { $taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 ); } } } break; default : $rates = WC_Tax::get_shipping_tax_rates(); $taxes = WC_Tax::calc_shipping_tax( $total_cost, $rates ); break; } } $this->rates[] = new WC_Shipping_Rate( $id, $label, $total_cost, $taxes, $this->id ); } /** * has_settings function. * * @return bool */ public function has_settings() { return $this->has_settings; } /** * is_available function. * * @param array $package * @return bool */ public function is_available( $package ) { if ( 'no' == $this->enabled ) { return false; } // Country availability $countries = is_array( $this->countries ) ? $this->countries : array(); switch ( $this->availability ) { case 'specific' : case 'including' : $ship_to_countries = array_intersect( $countries, array_keys( WC()->countries->get_shipping_countries() ) ); break; case 'excluding' : $ship_to_countries = array_diff( array_keys( WC()->countries->get_shipping_countries() ), $countries ); break; default : $ship_to_countries = array_keys( WC()->countries->get_shipping_countries() ); break; } if ( ! in_array( $package['destination']['country'], $ship_to_countries ) ) { return false; } return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', true, $package ); } /** * Return the shipping method title * * @return string */ public function get_title() { return apply_filters( 'woocommerce_shipping_method_title', $this->title, $this->id ); } /** * get_fee function. * * @param mixed $fee * @param mixed $total * @return float */ 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; } /** * Check if a shipping method supports a given feature. * * Methods should override this to declare support (or lack of support) for a feature. * * @param $feature string The name of a feature to test support for. * @return bool True if the gateway supports the feature, false otherwise. * @since 1.5.7 */ public function supports( $feature ) { return apply_filters( 'woocommerce_shipping_method_supports', in_array( $feature, $this->supports ) ? true : false, $feature, $this ); } }