initial commit
This commit is contained in:
284
includes/shipping/flat-rate/class-wc-shipping-flat-rate.php
Normal file
284
includes/shipping/flat-rate/class-wc-shipping-flat-rate.php
Normal file
@ -0,0 +1,284 @@
|
||||
<?php
|
||||
/**
|
||||
* Flat Rate Shipping Method.
|
||||
*
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WC_Shipping_Flat_Rate class.
|
||||
*/
|
||||
class WC_Shipping_Flat_Rate extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Cost passed to [fee] shortcode.
|
||||
*
|
||||
* @var string Cost.
|
||||
*/
|
||||
protected $fee_cost = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $instance_id Shipping method instance ID.
|
||||
*/
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->id = 'flat_rate';
|
||||
$this->instance_id = absint( $instance_id );
|
||||
$this->method_title = __( 'Flat rate', 'woocommerce' );
|
||||
$this->method_description = __( 'Lets you charge a fixed rate for shipping.', 'woocommerce' );
|
||||
$this->supports = array(
|
||||
'shipping-zones',
|
||||
'instance-settings',
|
||||
'instance-settings-modal',
|
||||
);
|
||||
$this->init();
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Init user set variables.
|
||||
*/
|
||||
public function init() {
|
||||
$this->instance_form_fields = include __DIR__ . '/includes/settings-flat-rate.php';
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->tax_status = $this->get_option( 'tax_status' );
|
||||
$this->cost = $this->get_option( 'cost' );
|
||||
$this->type = $this->get_option( 'type', 'class' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a cost from a sum/string.
|
||||
*
|
||||
* @param string $sum Sum of shipping.
|
||||
* @param array $args Args, must contain `cost` and `qty` keys. Having `array()` as default is for back compat reasons.
|
||||
* @return string
|
||||
*/
|
||||
protected function evaluate_cost( $sum, $args = array() ) {
|
||||
// Add warning for subclasses.
|
||||
if ( ! is_array( $args ) || ! array_key_exists( 'qty', $args ) || ! array_key_exists( 'cost', $args ) ) {
|
||||
wc_doing_it_wrong( __FUNCTION__, '$args must contain `cost` and `qty` keys.', '4.0.1' );
|
||||
}
|
||||
|
||||
include_once WC()->plugin_path() . '/includes/libraries/class-wc-eval-math.php';
|
||||
|
||||
// Allow 3rd parties to process shipping cost arguments.
|
||||
$args = apply_filters( 'woocommerce_evaluate_shipping_cost_args', $args, $sum, $this );
|
||||
$locale = localeconv();
|
||||
$decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'], ',' );
|
||||
$this->fee_cost = $args['cost'];
|
||||
|
||||
// Expand shortcodes.
|
||||
add_shortcode( 'fee', array( $this, 'fee' ) );
|
||||
|
||||
$sum = do_shortcode(
|
||||
str_replace(
|
||||
array(
|
||||
'[qty]',
|
||||
'[cost]',
|
||||
),
|
||||
array(
|
||||
$args['qty'],
|
||||
$args['cost'],
|
||||
),
|
||||
$sum
|
||||
)
|
||||
);
|
||||
|
||||
remove_shortcode( 'fee', array( $this, 'fee' ) );
|
||||
|
||||
// Remove whitespace from string.
|
||||
$sum = preg_replace( '/\s+/', '', $sum );
|
||||
|
||||
// Remove locale from string.
|
||||
$sum = str_replace( $decimals, '.', $sum );
|
||||
|
||||
// Trim invalid start/end characters.
|
||||
$sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );
|
||||
|
||||
// Do the math.
|
||||
return $sum ? WC_Eval_Math::evaluate( $sum ) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out fee (shortcode).
|
||||
*
|
||||
* @param array $atts Attributes.
|
||||
* @return string
|
||||
*/
|
||||
public function fee( $atts ) {
|
||||
$atts = shortcode_atts(
|
||||
array(
|
||||
'percent' => '',
|
||||
'min_fee' => '',
|
||||
'max_fee' => '',
|
||||
),
|
||||
$atts,
|
||||
'fee'
|
||||
);
|
||||
|
||||
$calculated_fee = 0;
|
||||
|
||||
if ( $atts['percent'] ) {
|
||||
$calculated_fee = $this->fee_cost * ( floatval( $atts['percent'] ) / 100 );
|
||||
}
|
||||
|
||||
if ( $atts['min_fee'] && $calculated_fee < $atts['min_fee'] ) {
|
||||
$calculated_fee = $atts['min_fee'];
|
||||
}
|
||||
|
||||
if ( $atts['max_fee'] && $calculated_fee > $atts['max_fee'] ) {
|
||||
$calculated_fee = $atts['max_fee'];
|
||||
}
|
||||
|
||||
return $calculated_fee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the shipping costs.
|
||||
*
|
||||
* @param array $package Package of items from cart.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$rate = array(
|
||||
'id' => $this->get_rate_id(),
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'package' => $package,
|
||||
);
|
||||
|
||||
// Calculate the costs.
|
||||
$has_costs = false; // True when a cost is set. False if all costs are blank strings.
|
||||
$cost = $this->get_option( 'cost' );
|
||||
|
||||
if ( '' !== $cost ) {
|
||||
$has_costs = true;
|
||||
$rate['cost'] = $this->evaluate_cost(
|
||||
$cost,
|
||||
array(
|
||||
'qty' => $this->get_package_item_qty( $package ),
|
||||
'cost' => $package['contents_cost'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add shipping class costs.
|
||||
$shipping_classes = WC()->shipping()->get_shipping_classes();
|
||||
|
||||
if ( ! empty( $shipping_classes ) ) {
|
||||
$found_shipping_classes = $this->find_shipping_classes( $package );
|
||||
$highest_class_cost = 0;
|
||||
|
||||
foreach ( $found_shipping_classes as $shipping_class => $products ) {
|
||||
// Also handles BW compatibility when slugs were used instead of ids.
|
||||
$shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
|
||||
$class_cost_string = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );
|
||||
|
||||
if ( '' === $class_cost_string ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$has_costs = true;
|
||||
$class_cost = $this->evaluate_cost(
|
||||
$class_cost_string,
|
||||
array(
|
||||
'qty' => array_sum( wp_list_pluck( $products, 'quantity' ) ),
|
||||
'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( 'class' === $this->type ) {
|
||||
$rate['cost'] += $class_cost;
|
||||
} else {
|
||||
$highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost;
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'order' === $this->type && $highest_class_cost ) {
|
||||
$rate['cost'] += $highest_class_cost;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $has_costs ) {
|
||||
$this->add_rate( $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Developers can add additional flat rates based on this one via this action since @version 2.4.
|
||||
*
|
||||
* Previously there were (overly complex) options to add additional rates however this was not user.
|
||||
* friendly and goes against what Flat Rate Shipping was originally intended for.
|
||||
*/
|
||||
do_action( 'woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get items in package.
|
||||
*
|
||||
* @param array $package Package of items from cart.
|
||||
* @return int
|
||||
*/
|
||||
public function get_package_item_qty( $package ) {
|
||||
$total_quantity = 0;
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
|
||||
$total_quantity += $values['quantity'];
|
||||
}
|
||||
}
|
||||
return $total_quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns shipping classes and the products with said class.
|
||||
*
|
||||
* @param mixed $package Package of items from cart.
|
||||
* @return array
|
||||
*/
|
||||
public function find_shipping_classes( $package ) {
|
||||
$found_shipping_classes = array();
|
||||
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['data']->needs_shipping() ) {
|
||||
$found_class = $values['data']->get_shipping_class();
|
||||
|
||||
if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
|
||||
$found_shipping_classes[ $found_class ] = array();
|
||||
}
|
||||
|
||||
$found_shipping_classes[ $found_class ][ $item_id ] = $values;
|
||||
}
|
||||
}
|
||||
|
||||
return $found_shipping_classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the cost field.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $value Unsanitized value.
|
||||
* @throws Exception Last error triggered.
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_cost( $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
$value = wp_kses_post( trim( wp_unslash( $value ) ) );
|
||||
$value = str_replace( array( get_woocommerce_currency_symbol(), html_entity_decode( get_woocommerce_currency_symbol() ) ), '', $value );
|
||||
// Thrown an error on the front end if the evaluate_cost will fail.
|
||||
$dummy_cost = $this->evaluate_cost(
|
||||
$value,
|
||||
array(
|
||||
'cost' => 1,
|
||||
'qty' => 1,
|
||||
)
|
||||
);
|
||||
if ( false === $dummy_cost ) {
|
||||
throw new Exception( WC_Eval_Math::$last_error );
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
89
includes/shipping/flat-rate/includes/settings-flat-rate.php
Normal file
89
includes/shipping/flat-rate/includes/settings-flat-rate.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Settings for flat rate shipping.
|
||||
*
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$cost_desc = __( 'Enter a cost (excl. tax) or sum, e.g. <code>10.00 * [qty]</code>.', 'woocommerce' ) . '<br/><br/>' . __( 'Use <code>[qty]</code> for the number of items, <br/><code>[cost]</code> for the total cost of items, and <code>[fee percent="10" min_fee="20" max_fee=""]</code> for percentage based fees.', 'woocommerce' );
|
||||
|
||||
$settings = array(
|
||||
'title' => array(
|
||||
'title' => __( 'Method title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Flat rate', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'tax_status' => array(
|
||||
'title' => __( 'Tax status', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'taxable',
|
||||
'options' => array(
|
||||
'taxable' => __( 'Taxable', 'woocommerce' ),
|
||||
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'cost' => array(
|
||||
'title' => __( 'Cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '',
|
||||
'description' => $cost_desc,
|
||||
'default' => '0',
|
||||
'desc_tip' => true,
|
||||
'sanitize_callback' => array( $this, 'sanitize_cost' ),
|
||||
),
|
||||
);
|
||||
|
||||
$shipping_classes = WC()->shipping()->get_shipping_classes();
|
||||
|
||||
if ( ! empty( $shipping_classes ) ) {
|
||||
$settings['class_costs'] = array(
|
||||
'title' => __( 'Shipping class costs', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
/* translators: %s: URL for link. */
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the <a href="%s">product shipping class</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=classes' ) ),
|
||||
);
|
||||
foreach ( $shipping_classes as $shipping_class ) {
|
||||
if ( ! isset( $shipping_class->term_id ) ) {
|
||||
continue;
|
||||
}
|
||||
$settings[ 'class_cost_' . $shipping_class->term_id ] = array(
|
||||
/* translators: %s: shipping class name */
|
||||
'title' => sprintf( __( '"%s" shipping class cost', 'woocommerce' ), esc_html( $shipping_class->name ) ),
|
||||
'type' => 'text',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'description' => $cost_desc,
|
||||
'default' => $this->get_option( 'class_cost_' . $shipping_class->slug ), // Before 2.5.0, we used slug here which caused issues with long setting names.
|
||||
'desc_tip' => true,
|
||||
'sanitize_callback' => array( $this, 'sanitize_cost' ),
|
||||
);
|
||||
}
|
||||
|
||||
$settings['no_class_cost'] = array(
|
||||
'title' => __( 'No shipping class cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'description' => $cost_desc,
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
'sanitize_callback' => array( $this, 'sanitize_cost' ),
|
||||
);
|
||||
|
||||
$settings['type'] = array(
|
||||
'title' => __( 'Calculation type', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'class',
|
||||
'options' => array(
|
||||
'class' => __( 'Per class: Charge shipping for each shipping class individually', 'woocommerce' ),
|
||||
'order' => __( 'Per order: Charge shipping for the most expensive shipping class', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return $settings;
|
@ -0,0 +1,245 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Free_Shipping file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Utilities\NumberUtil;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free Shipping Method.
|
||||
*
|
||||
* A simple shipping method for free shipping.
|
||||
*
|
||||
* @class WC_Shipping_Free_Shipping
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Free_Shipping extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Min amount to be valid.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $min_amount = 0;
|
||||
|
||||
/**
|
||||
* Requires option.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $requires = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $instance_id Shipping method instance.
|
||||
*/
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->id = 'free_shipping';
|
||||
$this->instance_id = absint( $instance_id );
|
||||
$this->method_title = __( 'Free shipping', 'woocommerce' );
|
||||
$this->method_description = __( 'Free shipping is a special method which can be triggered with coupons and minimum spends.', 'woocommerce' );
|
||||
$this->supports = array(
|
||||
'shipping-zones',
|
||||
'instance-settings',
|
||||
'instance-settings-modal',
|
||||
);
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize free shipping.
|
||||
*/
|
||||
public function init() {
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables.
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->min_amount = $this->get_option( 'min_amount', 0 );
|
||||
$this->requires = $this->get_option( 'requires' );
|
||||
$this->ignore_discounts = $this->get_option( 'ignore_discounts' );
|
||||
|
||||
// Actions.
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
add_action( 'admin_footer', array( 'WC_Shipping_Free_Shipping', 'enqueue_admin_js' ), 10 ); // Priority needs to be higher than wc_print_js (25).
|
||||
}
|
||||
|
||||
/**
|
||||
* Init form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->instance_form_fields = array(
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => $this->method_title,
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'requires' => array(
|
||||
'title' => __( 'Free shipping requires...', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => '',
|
||||
'options' => array(
|
||||
'' => __( 'N/A', 'woocommerce' ),
|
||||
'coupon' => __( 'A valid free shipping coupon', 'woocommerce' ),
|
||||
'min_amount' => __( 'A minimum order amount', 'woocommerce' ),
|
||||
'either' => __( 'A minimum order amount OR a coupon', 'woocommerce' ),
|
||||
'both' => __( 'A minimum order amount AND a coupon', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'min_amount' => array(
|
||||
'title' => __( 'Minimum order amount', 'woocommerce' ),
|
||||
'type' => 'price',
|
||||
'placeholder' => wc_format_localized_price( 0 ),
|
||||
'description' => __( 'Users will need to spend this amount to get free shipping (if enabled above).', 'woocommerce' ),
|
||||
'default' => '0',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'ignore_discounts' => array(
|
||||
'title' => __( 'Coupons discounts', 'woocommerce' ),
|
||||
'label' => __( 'Apply minimum order rule before coupon discount', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'description' => __( 'If checked, free shipping would be available based on pre-discount order amount.', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setting form fields for instances of this shipping method within zones.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_instance_form_fields() {
|
||||
return parent::get_instance_form_fields();
|
||||
}
|
||||
|
||||
/**
|
||||
* See if free shipping is available based on the package and cart.
|
||||
*
|
||||
* @param array $package Shipping package.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
$has_coupon = false;
|
||||
$has_met_min_amount = false;
|
||||
|
||||
if ( in_array( $this->requires, array( 'coupon', 'either', 'both' ), true ) ) {
|
||||
$coupons = WC()->cart->get_coupons();
|
||||
|
||||
if ( $coupons ) {
|
||||
foreach ( $coupons as $code => $coupon ) {
|
||||
if ( $coupon->is_valid() && $coupon->get_free_shipping() ) {
|
||||
$has_coupon = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( in_array( $this->requires, array( 'min_amount', 'either', 'both' ), true ) ) {
|
||||
$total = WC()->cart->get_displayed_subtotal();
|
||||
|
||||
if ( WC()->cart->display_prices_including_tax() ) {
|
||||
$total = $total - WC()->cart->get_discount_tax();
|
||||
}
|
||||
|
||||
if ( 'no' === $this->ignore_discounts ) {
|
||||
$total = $total - WC()->cart->get_discount_total();
|
||||
}
|
||||
|
||||
$total = NumberUtil::round( $total, wc_get_price_decimals() );
|
||||
|
||||
if ( $total >= $this->min_amount ) {
|
||||
$has_met_min_amount = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $this->requires ) {
|
||||
case 'min_amount':
|
||||
$is_available = $has_met_min_amount;
|
||||
break;
|
||||
case 'coupon':
|
||||
$is_available = $has_coupon;
|
||||
break;
|
||||
case 'both':
|
||||
$is_available = $has_met_min_amount && $has_coupon;
|
||||
break;
|
||||
case 'either':
|
||||
$is_available = $has_met_min_amount || $has_coupon;
|
||||
break;
|
||||
default:
|
||||
$is_available = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to calculate shipping rates for this method. Rates can be added using the add_rate() method.
|
||||
*
|
||||
* @uses WC_Shipping_Method::add_rate()
|
||||
*
|
||||
* @param array $package Shipping package.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$this->add_rate(
|
||||
array(
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'taxes' => false,
|
||||
'package' => $package,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue JS to handle free shipping options.
|
||||
*
|
||||
* Static so that's enqueued only once.
|
||||
*/
|
||||
public static function enqueue_admin_js() {
|
||||
wc_enqueue_js(
|
||||
"jQuery( function( $ ) {
|
||||
function wcFreeShippingShowHideMinAmountField( el ) {
|
||||
var form = $( el ).closest( 'form' );
|
||||
var minAmountField = $( '#woocommerce_free_shipping_min_amount', form ).closest( 'tr' );
|
||||
var ignoreDiscountField = $( '#woocommerce_free_shipping_ignore_discounts', form ).closest( 'tr' );
|
||||
if ( 'coupon' === $( el ).val() || '' === $( el ).val() ) {
|
||||
minAmountField.hide();
|
||||
ignoreDiscountField.hide();
|
||||
} else {
|
||||
minAmountField.show();
|
||||
ignoreDiscountField.show();
|
||||
}
|
||||
}
|
||||
|
||||
$( document.body ).on( 'change', '#woocommerce_free_shipping_requires', function() {
|
||||
wcFreeShippingShowHideMinAmountField( this );
|
||||
});
|
||||
|
||||
// Change while load.
|
||||
$( '#woocommerce_free_shipping_requires' ).trigger( 'change' );
|
||||
$( document.body ).on( 'wc_backbone_modal_loaded', function( evt, target ) {
|
||||
if ( 'wc-modal-shipping-method-settings' === target ) {
|
||||
wcFreeShippingShowHideMinAmountField( $( '#wc-backbone-modal-dialog #woocommerce_free_shipping_requires', evt.currentTarget ) );
|
||||
}
|
||||
} );
|
||||
});"
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,411 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Legacy_Flat_Rate file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flat Rate Shipping Method.
|
||||
*
|
||||
* This class is here for backwards compatibility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.4.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Legacy_Flat_Rate extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Cost passed to [fee] shortcode.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fee_cost = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_flat_rate';
|
||||
$this->method_title = __( 'Flat rate (legacy)', 'woocommerce' );
|
||||
/* translators: %s: Admin shipping settings URL */
|
||||
$this->method_description = '<strong>' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping zones</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ) . '</strong>';
|
||||
$this->init();
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
add_action( 'woocommerce_flat_rate_shipping_add_rate', array( $this, 'calculate_extra_shipping' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and redirect if disabled.
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
parent::process_admin_options();
|
||||
|
||||
if ( 'no' === $this->settings['enabled'] ) {
|
||||
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'flat_rate_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*/
|
||||
public function init() {
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables.
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->tax_status = $this->get_option( 'tax_status' );
|
||||
$this->cost = $this->get_option( 'cost' );
|
||||
$this->type = $this->get_option( 'type', 'class' );
|
||||
$this->options = $this->get_option( 'options', false ); // @deprecated 2.4.0
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Settings Form Fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = include __DIR__ . '/includes/settings-flat-rate.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a cost from a sum/string.
|
||||
*
|
||||
* @param string $sum Sum to evaluate.
|
||||
* @param array $args Arguments.
|
||||
* @return string
|
||||
*/
|
||||
protected function evaluate_cost( $sum, $args = array() ) {
|
||||
include_once WC()->plugin_path() . '/includes/libraries/class-wc-eval-math.php';
|
||||
|
||||
$locale = localeconv();
|
||||
$decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] );
|
||||
|
||||
$this->fee_cost = $args['cost'];
|
||||
|
||||
// Expand shortcodes.
|
||||
add_shortcode( 'fee', array( $this, 'fee' ) );
|
||||
|
||||
$sum = do_shortcode(
|
||||
str_replace(
|
||||
array(
|
||||
'[qty]',
|
||||
'[cost]',
|
||||
),
|
||||
array(
|
||||
$args['qty'],
|
||||
$args['cost'],
|
||||
),
|
||||
$sum
|
||||
)
|
||||
);
|
||||
|
||||
remove_shortcode( 'fee', array( $this, 'fee' ) );
|
||||
|
||||
// Remove whitespace from string.
|
||||
$sum = preg_replace( '/\s+/', '', $sum );
|
||||
|
||||
// Remove locale from string.
|
||||
$sum = str_replace( $decimals, '.', $sum );
|
||||
|
||||
// Trim invalid start/end characters.
|
||||
$sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );
|
||||
|
||||
// Do the math.
|
||||
return $sum ? WC_Eval_Math::evaluate( $sum ) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out fee (shortcode).
|
||||
*
|
||||
* @param array $atts Shortcode attributes.
|
||||
* @return string
|
||||
*/
|
||||
public function fee( $atts ) {
|
||||
$atts = shortcode_atts(
|
||||
array(
|
||||
'percent' => '',
|
||||
'min_fee' => '',
|
||||
),
|
||||
$atts,
|
||||
'fee'
|
||||
);
|
||||
|
||||
$calculated_fee = 0;
|
||||
|
||||
if ( $atts['percent'] ) {
|
||||
$calculated_fee = $this->fee_cost * ( floatval( $atts['percent'] ) / 100 );
|
||||
}
|
||||
|
||||
if ( $atts['min_fee'] && $calculated_fee < $atts['min_fee'] ) {
|
||||
$calculated_fee = $atts['min_fee'];
|
||||
}
|
||||
|
||||
return $calculated_fee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate shipping.
|
||||
*
|
||||
* @param array $package (default: array()).
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'package' => $package,
|
||||
);
|
||||
|
||||
// Calculate the costs.
|
||||
$has_costs = false; // True when a cost is set. False if all costs are blank strings.
|
||||
$cost = $this->get_option( 'cost' );
|
||||
|
||||
if ( '' !== $cost ) {
|
||||
$has_costs = true;
|
||||
$rate['cost'] = $this->evaluate_cost(
|
||||
$cost,
|
||||
array(
|
||||
'qty' => $this->get_package_item_qty( $package ),
|
||||
'cost' => $package['contents_cost'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add shipping class costs.
|
||||
$found_shipping_classes = $this->find_shipping_classes( $package );
|
||||
$highest_class_cost = 0;
|
||||
|
||||
foreach ( $found_shipping_classes as $shipping_class => $products ) {
|
||||
// Also handles BW compatibility when slugs were used instead of ids.
|
||||
$shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
|
||||
$class_cost_string = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );
|
||||
|
||||
if ( '' === $class_cost_string ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$has_costs = true;
|
||||
$class_cost = $this->evaluate_cost(
|
||||
$class_cost_string,
|
||||
array(
|
||||
'qty' => array_sum( wp_list_pluck( $products, 'quantity' ) ),
|
||||
'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( 'class' === $this->type ) {
|
||||
$rate['cost'] += $class_cost;
|
||||
} else {
|
||||
$highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost;
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'order' === $this->type && $highest_class_cost ) {
|
||||
$rate['cost'] += $highest_class_cost;
|
||||
}
|
||||
|
||||
$rate['package'] = $package;
|
||||
|
||||
// Add the rate.
|
||||
if ( $has_costs ) {
|
||||
$this->add_rate( $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Developers can add additional flat rates based on this one via this action since @version 2.4.
|
||||
*
|
||||
* Previously there were (overly complex) options to add additional rates however this was not user.
|
||||
* friendly and goes against what Flat Rate Shipping was originally intended for.
|
||||
*
|
||||
* This example shows how you can add an extra rate based on this flat rate via custom function:
|
||||
*
|
||||
* add_action( 'woocommerce_flat_rate_shipping_add_rate', 'add_another_custom_flat_rate', 10, 2 );
|
||||
*
|
||||
* function add_another_custom_flat_rate( $method, $rate ) {
|
||||
* $new_rate = $rate;
|
||||
* $new_rate['id'] .= ':' . 'custom_rate_name'; // Append a custom ID.
|
||||
* $new_rate['label'] = 'Rushed Shipping'; // Rename to 'Rushed Shipping'.
|
||||
* $new_rate['cost'] += 2; // Add $2 to the cost.
|
||||
*
|
||||
* // Add it to WC.
|
||||
* $method->add_rate( $new_rate );
|
||||
* }.
|
||||
*/
|
||||
do_action( 'woocommerce_flat_rate_shipping_add_rate', $this, $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get items in package.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
* @return int
|
||||
*/
|
||||
public function get_package_item_qty( $package ) {
|
||||
$total_quantity = 0;
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
|
||||
$total_quantity += $values['quantity'];
|
||||
}
|
||||
}
|
||||
return $total_quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns shipping classes and the products with said class.
|
||||
*
|
||||
* @param mixed $package Package information.
|
||||
* @return array
|
||||
*/
|
||||
public function find_shipping_classes( $package ) {
|
||||
$found_shipping_classes = array();
|
||||
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['data']->needs_shipping() ) {
|
||||
$found_class = $values['data']->get_shipping_class();
|
||||
|
||||
if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
|
||||
$found_shipping_classes[ $found_class ] = array();
|
||||
}
|
||||
|
||||
$found_shipping_classes[ $found_class ][ $item_id ] = $values;
|
||||
}
|
||||
}
|
||||
|
||||
return $found_shipping_classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds extra calculated flat rates.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
*
|
||||
* Additional rates defined like this:
|
||||
* Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item).
|
||||
*
|
||||
* @param null $method Deprecated.
|
||||
* @param array $rate Rate information.
|
||||
*/
|
||||
public function calculate_extra_shipping( $method, $rate ) {
|
||||
if ( $this->options ) {
|
||||
$options = array_filter( (array) explode( "\n", $this->options ) );
|
||||
|
||||
foreach ( $options as $option ) {
|
||||
$this_option = array_map( 'trim', explode( WC_DELIMITER, $option ) );
|
||||
if ( count( $this_option ) !== 3 ) {
|
||||
continue;
|
||||
}
|
||||
$extra_rate = $rate;
|
||||
$extra_rate['id'] = $this->id . ':' . urldecode( sanitize_title( $this_option[0] ) );
|
||||
$extra_rate['label'] = $this_option[0];
|
||||
$extra_cost = $this->get_extra_cost( $this_option[1], $this_option[2], $rate['package'] );
|
||||
if ( is_array( $extra_rate['cost'] ) ) {
|
||||
$extra_rate['cost']['order'] = $extra_rate['cost']['order'] + $extra_cost;
|
||||
} else {
|
||||
$extra_rate['cost'] += $extra_cost;
|
||||
}
|
||||
|
||||
$this->add_rate( $extra_rate );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the percentage adjustment for each shipping rate.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
* @param float $cost Cost.
|
||||
* @param float $percent_adjustment Percent adjusment.
|
||||
* @param string $percent_operator Percent operator.
|
||||
* @param float $base_price Base price.
|
||||
* @return float
|
||||
*/
|
||||
public function calc_percentage_adjustment( $cost, $percent_adjustment, $percent_operator, $base_price ) {
|
||||
if ( '+' === $percent_operator ) {
|
||||
$cost += $percent_adjustment * $base_price;
|
||||
} else {
|
||||
$cost -= $percent_adjustment * $base_price;
|
||||
}
|
||||
return $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra cost.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
* @param string $cost_string Cost string.
|
||||
* @param string $type Type.
|
||||
* @param array $package Package information.
|
||||
* @return float
|
||||
*/
|
||||
public function get_extra_cost( $cost_string, $type, $package ) {
|
||||
$cost = $cost_string;
|
||||
$cost_percent = false;
|
||||
// @codingStandardsIgnoreStart
|
||||
$pattern =
|
||||
'/' . // Start regex.
|
||||
'(\d+\.?\d*)' . // Capture digits, optionally capture a `.` and more digits.
|
||||
'\s*' . // Match whitespace.
|
||||
'(\+|-)' . // Capture the operand.
|
||||
'\s*' . // Match whitespace.
|
||||
'(\d+\.?\d*)' . // Capture digits, optionally capture a `.` and more digits.
|
||||
'\%/'; // Match the percent sign & end regex.
|
||||
// @codingStandardsIgnoreEnd
|
||||
if ( preg_match( $pattern, $cost_string, $this_cost_matches ) ) {
|
||||
$cost_operator = $this_cost_matches[2];
|
||||
$cost_percent = $this_cost_matches[3] / 100;
|
||||
$cost = $this_cost_matches[1];
|
||||
}
|
||||
switch ( $type ) {
|
||||
case 'class':
|
||||
$cost = $cost * count( $this->find_shipping_classes( $package ) );
|
||||
break;
|
||||
case 'item':
|
||||
$cost = $cost * $this->get_package_item_qty( $package );
|
||||
break;
|
||||
}
|
||||
if ( $cost_percent ) {
|
||||
switch ( $type ) {
|
||||
case 'class':
|
||||
$shipping_classes = $this->find_shipping_classes( $package );
|
||||
foreach ( $shipping_classes as $shipping_class => $items ) {
|
||||
foreach ( $items as $item_id => $values ) {
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'item':
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['data']->needs_shipping() ) {
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'order':
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $package['contents_cost'] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $cost;
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/**
|
||||
* Legacy flat rate settings.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$cost_desc = __( 'Enter a cost (excl. tax) or sum, e.g. <code>10.00 * [qty]</code>.', 'woocommerce' ) . '<br/>' . __( 'Supports the following placeholders: <code>[qty]</code> = number of items, <code>[cost]</code> = cost of items, <code>[fee percent="10" min_fee="20"]</code> = Percentage based fee.', 'woocommerce' );
|
||||
|
||||
/**
|
||||
* Settings for flat rate shipping.
|
||||
*/
|
||||
$settings = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable/Disable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Method title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Flat rate', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 400px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'tax_status' => array(
|
||||
'title' => __( 'Tax status', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'taxable',
|
||||
'options' => array(
|
||||
'taxable' => __( 'Taxable', 'woocommerce' ),
|
||||
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'cost' => array(
|
||||
'title' => __( 'Cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '',
|
||||
'description' => $cost_desc,
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
);
|
||||
|
||||
$shipping_classes = WC()->shipping()->get_shipping_classes();
|
||||
|
||||
if ( ! empty( $shipping_classes ) ) {
|
||||
$settings['class_costs'] = array(
|
||||
'title' => __( 'Shipping class costs', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
/* translators: %s: Admin shipping settings URL */
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the <a href="%s">product shipping class</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=classes' ) ),
|
||||
);
|
||||
foreach ( $shipping_classes as $shipping_class ) {
|
||||
if ( ! isset( $shipping_class->term_id ) ) {
|
||||
continue;
|
||||
}
|
||||
$settings[ 'class_cost_' . $shipping_class->term_id ] = array(
|
||||
/* translators: %s: shipping class name */
|
||||
'title' => sprintf( __( '"%s" shipping class cost', 'woocommerce' ), esc_html( $shipping_class->name ) ),
|
||||
'type' => 'text',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'description' => $cost_desc,
|
||||
'default' => $this->get_option( 'class_cost_' . $shipping_class->slug ), // Before 2.5.0, we used slug here which caused issues with long setting names.
|
||||
'desc_tip' => true,
|
||||
);
|
||||
}
|
||||
$settings['no_class_cost'] = array(
|
||||
'title' => __( 'No shipping class cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'description' => $cost_desc,
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
);
|
||||
$settings['type'] = array(
|
||||
'title' => __( 'Calculation type', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'class',
|
||||
'options' => array(
|
||||
'class' => __( 'Per class: Charge shipping for each shipping class individually', 'woocommerce' ),
|
||||
'order' => __( 'Per order: Charge shipping for the most expensive shipping class', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_enable_deprecated_additional_flat_rates', $this->get_option( 'options', false ) ) ) {
|
||||
$settings['additional_rates'] = array(
|
||||
'title' => __( 'Additional rates', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
'description' => __( 'These rates are extra shipping options with additional costs (based on the flat rate).', 'woocommerce' ),
|
||||
);
|
||||
$settings['options'] = array(
|
||||
'title' => __( 'Additional rates', 'woocommerce' ),
|
||||
'type' => 'textarea',
|
||||
'description' => __( 'One per line: Option name | Additional cost [+- Percents] | Per cost type (order, class, or item) Example: <code>Priority mail | 6.95 [+ 0.2%] | order</code>.', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
'placeholder' => __( 'Option name | Additional cost [+- Percents%] | Per cost type (order, class, or item)', 'woocommerce' ),
|
||||
);
|
||||
}
|
||||
|
||||
return $settings;
|
@ -0,0 +1,252 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Legacy_Free_Shipping file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Utilities\NumberUtil;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Free Shipping Method.
|
||||
*
|
||||
* This class is here for backwards compatibility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.4.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Legacy_Free_Shipping extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Min amount to be valid.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
public $min_amount;
|
||||
|
||||
/**
|
||||
* Requires option.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $requires;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_free_shipping';
|
||||
$this->method_title = __( 'Free shipping (legacy)', 'woocommerce' );
|
||||
/* translators: %s: Admin shipping settings URL */
|
||||
$this->method_description = '<strong>' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping zones</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ) . '</strong>';
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and redirect if disabled.
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
parent::process_admin_options();
|
||||
|
||||
if ( 'no' === $this->settings['enabled'] ) {
|
||||
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'free_shipping_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables.
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->min_amount = $this->get_option( 'min_amount', 0 );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->requires = $this->get_option( 'requires' );
|
||||
|
||||
// Actions.
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Gateway Settings Form Fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable/Disable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Method title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Free Shipping', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 400px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'requires' => array(
|
||||
'title' => __( 'Free shipping requires...', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => '',
|
||||
'options' => array(
|
||||
'' => __( 'N/A', 'woocommerce' ),
|
||||
'coupon' => __( 'A valid free shipping coupon', 'woocommerce' ),
|
||||
'min_amount' => __( 'A minimum order amount', 'woocommerce' ),
|
||||
'either' => __( 'A minimum order amount OR a coupon', 'woocommerce' ),
|
||||
'both' => __( 'A minimum order amount AND a coupon', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'min_amount' => array(
|
||||
'title' => __( 'Minimum order amount', 'woocommerce' ),
|
||||
'type' => 'price',
|
||||
'placeholder' => wc_format_localized_price( 0 ),
|
||||
'description' => __( 'Users will need to spend this amount to get free shipping (if enabled above).', 'woocommerce' ),
|
||||
'default' => '0',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if package is available.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
if ( 'no' === $this->enabled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'specific' === $this->availability ) {
|
||||
$ship_to_countries = $this->countries;
|
||||
} else {
|
||||
$ship_to_countries = array_keys( WC()->countries->get_shipping_countries() );
|
||||
}
|
||||
|
||||
if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enabled logic.
|
||||
$is_available = false;
|
||||
$has_coupon = false;
|
||||
$has_met_min_amount = false;
|
||||
|
||||
if ( in_array( $this->requires, array( 'coupon', 'either', 'both' ), true ) ) {
|
||||
$coupons = WC()->cart->get_coupons();
|
||||
|
||||
if ( $coupons ) {
|
||||
foreach ( $coupons as $code => $coupon ) {
|
||||
if ( $coupon->is_valid() && $coupon->get_free_shipping() ) {
|
||||
$has_coupon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( in_array( $this->requires, array( 'min_amount', 'either', 'both' ), true ) ) {
|
||||
$total = WC()->cart->get_displayed_subtotal();
|
||||
|
||||
if ( WC()->cart->display_prices_including_tax() ) {
|
||||
$total = NumberUtil::round( $total - ( WC()->cart->get_discount_total() + WC()->cart->get_discount_tax() ), wc_get_price_decimals() );
|
||||
} else {
|
||||
$total = NumberUtil::round( $total - WC()->cart->get_discount_total(), wc_get_price_decimals() );
|
||||
}
|
||||
|
||||
if ( $total >= $this->min_amount ) {
|
||||
$has_met_min_amount = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $this->requires ) {
|
||||
case 'min_amount':
|
||||
if ( $has_met_min_amount ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
case 'coupon':
|
||||
if ( $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
case 'both':
|
||||
if ( $has_met_min_amount && $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
case 'either':
|
||||
if ( $has_met_min_amount || $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$is_available = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate shipping.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$args = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'taxes' => false,
|
||||
'package' => $package,
|
||||
);
|
||||
$this->add_rate( $args );
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Legacy_International_Delivery file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* International Delivery - Based on the Flat Rate Shipping Method.
|
||||
*
|
||||
* This class is here for backwards compatibility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.4.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Legacy_International_Delivery extends WC_Shipping_Legacy_Flat_Rate {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_international_delivery';
|
||||
$this->method_title = __( 'International flat rate (legacy)', 'woocommerce' );
|
||||
/* translators: %s: Admin shipping settings URL */
|
||||
$this->method_description = '<strong>' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping zones</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ) . '</strong>';
|
||||
$this->init();
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'international_delivery_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise settings form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
parent::init_form_fields();
|
||||
$this->form_fields['availability'] = array(
|
||||
'title' => __( 'Availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'description' => '',
|
||||
'default' => 'including',
|
||||
'options' => array(
|
||||
'including' => __( 'Selected countries', 'woocommerce' ),
|
||||
'excluding' => __( 'Excluding selected countries', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if package is available.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
if ( 'no' === $this->enabled ) {
|
||||
return false;
|
||||
}
|
||||
if ( 'including' === $this->availability ) {
|
||||
if ( is_array( $this->countries ) && ! in_array( $package['destination']['country'], $this->countries, true ) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( is_array( $this->countries ) && ( in_array( $package['destination']['country'], $this->countries, true ) || ! $package['destination']['country'] ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', true, $package, $this );
|
||||
}
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Legacy_Local_Delivery file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Delivery Shipping Method.
|
||||
*
|
||||
* This class is here for backwards compatibility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.3.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Legacy_Local_Delivery extends WC_Shipping_Local_Pickup {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_local_delivery';
|
||||
$this->method_title = __( 'Local delivery (legacy)', 'woocommerce' );
|
||||
/* translators: %s: Admin shipping settings URL */
|
||||
$this->method_description = '<strong>' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping zones</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ) . '</strong>';
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and redirect if disabled.
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
parent::process_admin_options();
|
||||
|
||||
if ( 'no' === $this->settings['enabled'] ) {
|
||||
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'local_delivery_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables.
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->type = $this->get_option( 'type' );
|
||||
$this->fee = $this->get_option( 'fee' );
|
||||
$this->type = $this->get_option( 'type' );
|
||||
$this->codes = $this->get_option( 'codes' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate_shipping function.
|
||||
*
|
||||
* @param array $package (default: array()).
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$shipping_total = 0;
|
||||
|
||||
switch ( $this->type ) {
|
||||
case 'fixed':
|
||||
$shipping_total = $this->fee;
|
||||
break;
|
||||
case 'percent':
|
||||
$shipping_total = $package['contents_cost'] * ( $this->fee / 100 );
|
||||
break;
|
||||
case 'product':
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
|
||||
$shipping_total += $this->fee * $values['quantity'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'cost' => $shipping_total,
|
||||
'package' => $package,
|
||||
);
|
||||
|
||||
$this->add_rate( $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Init form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Local delivery', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'title' => __( 'Fee type', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'description' => __( 'How to calculate delivery charges', 'woocommerce' ),
|
||||
'default' => 'fixed',
|
||||
'options' => array(
|
||||
'fixed' => __( 'Fixed amount', 'woocommerce' ),
|
||||
'percent' => __( 'Percentage of cart total', 'woocommerce' ),
|
||||
'product' => __( 'Fixed amount per product', 'woocommerce' ),
|
||||
),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'fee' => array(
|
||||
'title' => __( 'Delivery fee', 'woocommerce' ),
|
||||
'type' => 'price',
|
||||
'description' => __( 'What fee do you want to charge for local delivery, disregarded if you choose free. Leave blank to disable.', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
'placeholder' => wc_format_localized_price( 0 ),
|
||||
),
|
||||
'codes' => array(
|
||||
'title' => __( 'Allowed ZIP/post codes', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'desc_tip' => __( 'What ZIP/post codes are available for local delivery?', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'description' => __( 'Separate codes with a comma. Accepts wildcards, e.g. <code>P*</code> will match a postcode of PE30. Also accepts a pattern, e.g. <code>NG1___</code> would match NG1 1AA but not NG10 1AA', 'woocommerce' ),
|
||||
'placeholder' => 'e.g. 12345, 56789',
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 400px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Legacy_Local_Pickup file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Pickup Shipping Method.
|
||||
*
|
||||
* This class is here for backwards compatibility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.3.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Legacy_Local_Pickup extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_local_pickup';
|
||||
$this->method_title = __( 'Local pickup (legacy)', 'woocommerce' );
|
||||
/* translators: %s: Admin shipping settings URL */
|
||||
$this->method_description = '<strong>' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping zones</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ) . '</strong>';
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and redirect if disabled.
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
parent::process_admin_options();
|
||||
|
||||
if ( 'no' === $this->settings['enabled'] ) {
|
||||
wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=options' ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'local_pickup_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables.
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->codes = $this->get_option( 'codes' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
|
||||
// Actions.
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate shipping.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'package' => $package,
|
||||
);
|
||||
$this->add_rate( $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Local pickup', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'codes' => array(
|
||||
'title' => __( 'Allowed ZIP/post codes', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'desc_tip' => __( 'What ZIP/post codes are available for local pickup?', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'description' => __( 'Separate codes with a comma. Accepts wildcards, e.g. <code>P*</code> will match a postcode of PE30. Also accepts a pattern, e.g. <code>NG1___</code> would match NG1 1AA but not NG10 1AA', 'woocommerce' ),
|
||||
'placeholder' => 'e.g. 12345, 56789',
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 400px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get postcodes for this method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_valid_postcodes() {
|
||||
$codes = array();
|
||||
|
||||
if ( '' !== $this->codes ) {
|
||||
foreach ( explode( ',', $this->codes ) as $code ) {
|
||||
$codes[] = strtoupper( trim( $code ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $codes;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if a given postcode matches valid postcodes.
|
||||
*
|
||||
* @param string $postcode Postcode to check.
|
||||
* @param string $country code Code of the country to check postcode against.
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_valid_postcode( $postcode, $country ) {
|
||||
$codes = $this->get_valid_postcodes();
|
||||
$postcode = $this->clean( $postcode );
|
||||
$formatted_postcode = wc_format_postcode( $postcode, $country );
|
||||
|
||||
if ( in_array( $postcode, $codes, true ) || in_array( $formatted_postcode, $codes, true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern matching.
|
||||
foreach ( $codes as $c ) {
|
||||
$pattern = '/^' . str_replace( '_', '[0-9a-zA-Z]', preg_quote( $c ) ) . '$/i';
|
||||
if ( preg_match( $pattern, $postcode ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Wildcard search.
|
||||
$wildcard_postcode = $formatted_postcode . '*';
|
||||
$postcode_length = strlen( $formatted_postcode );
|
||||
|
||||
for ( $i = 0; $i < $postcode_length; $i++ ) {
|
||||
if ( in_array( $wildcard_postcode, $codes, true ) ) {
|
||||
return true;
|
||||
}
|
||||
$wildcard_postcode = substr( $wildcard_postcode, 0, -2 ) . '*';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the method is available.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
$is_available = 'yes' === $this->enabled;
|
||||
|
||||
if ( $is_available && $this->get_valid_postcodes() ) {
|
||||
$is_available = $this->is_valid_postcode( $package['destination']['postcode'], $package['destination']['country'] );
|
||||
}
|
||||
|
||||
if ( $is_available ) {
|
||||
if ( 'specific' === $this->availability ) {
|
||||
$ship_to_countries = $this->countries;
|
||||
} else {
|
||||
$ship_to_countries = array_keys( WC()->countries->get_shipping_countries() );
|
||||
}
|
||||
if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries, true ) ) {
|
||||
$is_available = false;
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean function.
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $code Code.
|
||||
* @return string
|
||||
*/
|
||||
public function clean( $code ) {
|
||||
return str_replace( '-', '', sanitize_title( $code ) ) . ( strstr( $code, '*' ) ? '*' : '' );
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Class WC_Shipping_Local_Pickup file.
|
||||
*
|
||||
* @package WooCommerce\Shipping
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Pickup Shipping Method.
|
||||
*
|
||||
* A simple shipping method allowing free pickup as a shipping method.
|
||||
*
|
||||
* @class WC_Shipping_Local_Pickup
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce\Classes\Shipping
|
||||
*/
|
||||
class WC_Shipping_Local_Pickup extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $instance_id Instance ID.
|
||||
*/
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->id = 'local_pickup';
|
||||
$this->instance_id = absint( $instance_id );
|
||||
$this->method_title = __( 'Local pickup', 'woocommerce' );
|
||||
$this->method_description = __( 'Allow customers to pick up orders themselves. By default, when using local pickup store base taxes will apply regardless of customer address.', 'woocommerce' );
|
||||
$this->supports = array(
|
||||
'shipping-zones',
|
||||
'instance-settings',
|
||||
'instance-settings-modal',
|
||||
);
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize local pickup.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables.
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->tax_status = $this->get_option( 'tax_status' );
|
||||
$this->cost = $this->get_option( 'cost' );
|
||||
|
||||
// Actions.
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate local pickup shipping.
|
||||
*
|
||||
* @param array $package Package information.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$this->add_rate(
|
||||
array(
|
||||
'label' => $this->title,
|
||||
'package' => $package,
|
||||
'cost' => $this->cost,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->instance_form_fields = array(
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Local pickup', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'tax_status' => array(
|
||||
'title' => __( 'Tax status', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'taxable',
|
||||
'options' => array(
|
||||
'taxable' => __( 'Taxable', 'woocommerce' ),
|
||||
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'cost' => array(
|
||||
'title' => __( 'Cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '0',
|
||||
'description' => __( 'Optional cost for local pickup.', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user