Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save damiencarbery/6d339c2d283fbe94c09be67050077dda to your computer and use it in GitHub Desktop.
Save damiencarbery/6d339c2d283fbe94c09be67050077dda to your computer and use it in GitHub Desktop.
<?php
/*
Plugin Name: Free Shipping by Cart Quantity
Plugin URI: https://www.damiencarbery.com/2018/05/free-shipping-when-one-item-in-cart/
Description: Apply a free shipping coupon when the cart contains only one item.
Author: Damien Carbery
Author URI: https://www.damiencarbery.com
Version: 0.1
*/
class FreeShippingByCartQuantity {
private $coupon_code;
private $coupon_description;
public function __construct() {
$this->coupon_code = 'free_for_one_item';
$this->coupon_description = 'Free shipping for when the cart has a single item.';
$this->init();
}
public function init() {
register_activation_hook( __FILE__, array( $this, 'create_free_for_one_coupon' ) );
add_filter( 'woocommerce_package_rates', array( $this, 'unset_shipping_when_free_is_available' ), 10, 2 );
add_action( 'woocommerce_before_cart', array( $this, 'check_cart_and_apply_coupon' ) );
add_filter( 'woocommerce_cart_totals_coupon_label', array( $this, 'hide_coupon_code' ), 10, 2 );
add_filter( 'woocommerce_cart_totals_coupon_html', array( $this, 'change_coupon_html' ), 10, 3 );
}
// Create the coupon when the plugin is activated.
// Based on: https://docs.woocommerce.com/document/create-a-coupon-programatically/
public function create_free_for_one_coupon() {
// Do not create a duplicate coupon.
$id = wc_get_coupon_id_by_code( $this->coupon_code );
if ( 0 != $id ) return;
$coupon = array(
'post_title' => $this->coupon_code,
'post_content' => '',
'post_excerpt' => $this->coupon_description,
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
// Add meta
update_post_meta( $new_coupon_id, 'free_shipping', 'yes' );
update_post_meta( $new_coupon_id, 'discount_type', 'fixed_cart' );
update_post_meta( $new_coupon_id, 'coupon_amount', 0 );
update_post_meta( $new_coupon_id, 'individual_use', 'no' );
update_post_meta( $new_coupon_id, 'product_ids', '' );
update_post_meta( $new_coupon_id, 'exclude_product_ids', '' );
update_post_meta( $new_coupon_id, 'usage_limit', '' );
update_post_meta( $new_coupon_id, 'expiry_date', '' );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'no' );
}
// Check whether free shipping is available for the current cart.
// Enhanced version of: https://businessbloomer.com/woocommerce-hide-shipping-options-free-shipping-available/
public function unset_shipping_when_free_is_available( $rates, $package ) {
$free_shipping_available = false;
// Determine whether free shipping is available.
foreach ( array_keys( $rates ) as $rate_key ) {
if ( 0 === strpos( $rate_key, 'free_shipping' ) ) {
$free_shipping_available = true;
//error_log( 'Free shipping is available:' . $rate_key );
}
}
// Hide other methods if free shipping available.
if ( true == $free_shipping_available ) {
foreach ( array_keys( $rates ) as $rate_key ) {
if ( false === strpos( $rate_key, 'free_shipping' ) ) {
unset( $rates[ $rate_key ] );
}
}
}
return $rates;
}
// Add the coupon if there is a single item in the cart. Otherwise remove the coupon.
// Inspired by: https://businessbloomer.com/woocommerce-apply-coupon-programmatically-product-cart/
public function check_cart_and_apply_coupon() {
//error_log( "Cart contents count: " . WC()->cart->get_cart_contents_count() );
if ( WC()->cart->get_cart_contents_count() == 1 ) {
//error_log( 'Coupon applied (going to add)? ' . var_export( WC()->cart->has_discount( $this->coupon_code ), true ) );
if ( ! WC()->cart->has_discount( $this->coupon_code ) ) {
//error_log( 'Apply coupon' );
WC()->cart->apply_coupon( $this->coupon_code );
}
else {
//error_log( 'Skip applying coupon' );
}
// This CSS can be used to hide the table row with the 'Coupon: Free Shipping!' text.
if ( true ) { // Can be disabled by changing 'true' to 'false'
?>
<style>tr.cart-discount.coupon-<?php echo esc_attr( sanitize_title( $this->coupon_code ) ) ?> { display: none; }</style>
<?php
}
}
else {
//error_log( 'Coupon applied (about to remove)? ' . var_export( WC()->cart->has_discount( $this->coupon_code ), true ) );
if ( WC()->cart->has_discount( $this->coupon_code ) ) {
// Remove coupon.
//error_log( 'Remove coupon' );
WC()->cart->remove_coupon( $this->coupon_code );
}
else {
//error_log( 'Skip removing coupon' );
}
}
}
// Change the text in the left column where it shows the coupon code.
// Based on: https://businessbloomer.com/woocommerce-hide-coupon-code-cartcheckout-page/
public function hide_coupon_code( $coupon_label, $coupon ) {
// Change from 'Coupon: free_for_one_item'
if ( 'free_for_one_item' == $coupon->get_code() ) {
echo 'Coupon';
}
}
// Change text describing the coupon.
public function change_coupon_html( $coupon_html, $coupon, $discount_amount_html ) {
//error_log( "Coupon html: " . var_export( $coupon->get_code(), true ) );
// Change from: 'Free shipping coupon [Remove]'
if ( 'free_for_one_item' == $coupon->get_code() ) {
return 'Free shipping!';
}
return $coupon_html;
}
}
$FreeShippingByCartQuantity = new FreeShippingByCartQuantity();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment