Skip to content

Instantly share code, notes, and snippets.

@spivurno
Last active October 6, 2021 16:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save spivurno/351f6a936285604f5802 to your computer and use it in GitHub Desktop.
Save spivurno/351f6a936285604f5802 to your computer and use it in GitHub Desktop.
Gravity Wiz // Gravity Forms Coupons // Exclude Products from Coupon Discount
<?php
/**
* Gravity Wiz // Gravity Forms Coupons // Exclude Products from Coupon Discount
*
* Exclude specific products when calculating discounts with the Gravity Forms Coupons add-on.
*
* Requires Gravity Forms Coupons v1.1
*
* @version 1.2
* @author David Smith <david@gravitywiz.com>
* @license GPL-2.0+
* @link http://gravitywiz.com/...
*/
class GW_Coupons_Exclude_Products {
protected static $is_script_output = false;
public static $excluded_total = null;
public $_args = array();
public function __construct( $args ) {
// set our default arguments, parse against the provided arguments, and store for use throughout the class
$this->_args = wp_parse_args( $args, array(
'form_id' => false,
'exclude_fields' => array()
) );
// do version check in the init to make sure if GF is going to be loaded, it is already loaded
add_action( 'init', array( $this, 'init' ) );
}
function init() {
$has_gravity_forms = property_exists( 'GFCommon', 'version' ) && version_compare( GFCommon::$version, '1.8', '>=' );
$has_gf_coupons = class_exists( 'GFCoupons' );
// make sure we're running the required minimum version of Gravity Forms and GF Coupons
if( ! $has_gravity_forms || ! $has_gf_coupons ) {
return;
}
// render
add_filter( 'gform_pre_render', array( $this, 'load_form_script' ) );
add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ) );
// submission
add_action( 'gform_product_info', array( $this, 'stash_excluded_total' ), 4 /* Coupons run on 5 */, 2 );
add_filter( 'gform_coupons_discount_amount', array( $this, 'modify_coupon_discount_amount' ), 10, 3 );
}
function load_form_script( $form ) {
if( $this->is_applicable_form( $form ) && ! self::$is_script_output ) {
$this->output_script();
}
return $form;
}
function output_script() {
?>
<script type="text/javascript">
( function( $ ) {
if( window.gform ) {
gform.addFilter( 'gform_coupons_discount_amount', function( discount, couponType, couponAmount, price, totalDiscount ) {
// pretty hacky... work our way up the chain to see if the 4th func up is the expected func
var caller = arguments.callee.caller.caller.caller.caller;
if( caller.name != 'PopulateDiscountInfo' ) {
return discount;
}
var formId = caller.arguments[1],
price = price - getExcludedAmount( formId );
if( couponType == 'percentage' ) {
discount = price * Number( ( couponAmount / 100 ) );
} else if( couponType == 'flat' ) {
discount = Number( couponAmount );
if( discount > price ) {
discount = price;
}
}
if( ! window.onTimeout && window.applyingCoupon ) {
window.onTimeout = setTimeout( function() {
window.onTimeout = false;
window.applyingCoupon = false;
$( document ).trigger( 'gform_post_conditional_logic' );
}, 1 );
}
return discount;
} );
}
function getExcludedAmount( formId ) {
var excludeFields = gf_global.gfcep[ formId ],
amount = 0;
if( ! excludeFields ) {
return 0;
}
for( var i = 0; i < excludeFields.length; i++ ) {
var productAmount = gformCalculateProductPrice( formId, excludeFields[ i ] );
amount += productAmount;
}
return amount;
}
} )( jQuery );
</script>
<?php
self::$is_script_output = true;
}
function add_init_script( $form ) {
if( ! $this->is_applicable_form( $form ) ) {
return;
}
$exclude_fields_json = json_encode( $this->_args['exclude_fields'] );
$script = "if( typeof gf_global != 'undefined' ) {
if( typeof gf_global.gwcep == 'undefined' ) {
gf_global.gfcep = [];
}
gf_global.gfcep[ {$this->_args['form_id']} ] = {$exclude_fields_json};
}";
GFFormDisplay::add_init_script( $this->_args['form_id'], 'gfcep', GFFormDisplay::ON_PAGE_RENDER, $script );
}
function stash_excluded_total( $product_data, $form ) {
if( ! $this->is_applicable_form( $form ) ) {
return $product_data;
}
self::$excluded_total = 0;
foreach( $product_data['products'] as $field_id => $data ) {
if( in_array( $field_id, $this->_args['exclude_fields'] ) ) {
self::$excluded_total += GFCommon::to_number( $data['price'] );
}
}
return $product_data;
}
function modify_coupon_discount_amount( $discount, $coupon, $price ) {
if( ! self::$excluded_total ) {
return $discount;
}
$price = $price - self::$excluded_total;
$currency = new RGCurrency( GFCommon::get_currency() );
$amount = $currency->to_number( $coupon['amount'] );
if( $coupon['type'] == 'percentage' ) {
$discount = $price * ( $amount / 100 );
} else if( $coupon['type'] == 'flat' ) {
$discount = $amount;
if( $discount > $price ) {
$discount = $price;
}
}
return $discount;
}
function is_applicable_form( $form ) {
$coupon_fields = GFCommon::get_fields_by_type( $form, array( 'coupon' ) );
$is_applicable_form_id = $form['id'] == $this->_args['form_id'];
return $is_applicable_form_id && ! empty( $coupon_fields );
}
}
# Configuration
new GW_Coupons_Exclude_Products( array(
'form_id' => 123,
'exclude_fields' => array( 4, 5 )
) );
@davinian
Copy link

Does this still work?
Tried and although the Total was showing correct price, the coupon still discounted 100% on checkout.

@wahmaholic
Copy link

Thank you for this code, it works wonderfully. I have a question though: how can I make the email notification that I receive match the computation on the form? Right now the email notification still includes the excluded product/s in the coupon computation, which is not ideal. PHP is not really my strong suit. Any help would be great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment