Gravity Wiz // First X Items Free
<?php
/**
* First X Items Free
*
* Discounts the first X number of items as free.
*
* @author David Smith <david@gravitywiz.com>
* @license GPL-2.0+
* @link http://gravitywiz.com/...
* @copyright 2013 Gravity Wiz
*/
class GWFirstXFree {
private $_args;
private static $_is_script_output;
public function __construct( $args ) {
$this->_args = wp_parse_args( $args, array(
'form_id' => false,
'field_ids' => array(),
'number_free' => 1,
'discount_label' => __( 'First %d Items Free Discount' )
) );
extract( $this->_args ); // gives us $form_id, $field_ids, $number_free
if( ! $form_id || empty( $field_ids ) )
return;
add_filter( 'gform_pre_render_' . $form_id, array( $this, 'pre_render' ) );
add_filter( 'gform_register_init_scripts_' . $form_id, array( $this, 'register_init_script' ) );
add_filter( 'gform_product_info_' . $form_id, array( $this, 'apply_discount' ), 10, 3 );
}
public function pre_render( $form ) {
$this->output_script();
return $form;
}
public function output_script() {
if( self::$_is_script_output )
return;
?>
<script type="text/javascript">
var gwfxf = {};
( function( $ ) {
window.gwfxf = function( args ) {
this.init = function( args ) {
this.extractProperties( args );
var gwfxf = this;
gform.addFilter( 'gform_product_total', function( total ) {
return gwfxf.applyDiscount( total );
} );
}
this.applyDiscount = function( total ) {
var prices = [];
for( var i = 0; i < this.fieldIds.length; i++ ) {
var price = gformToNumber( $( '#ginput_base_price_' + this.formId + '_' + this.fieldIds[i] ).val() );
var qty = gformGetProductQuantity( this.formId, this.fieldIds[i] );
if( ! prices.length ) {
prices.push( { price: price, qty: qty } );
} else {
for( var j = 0; j < prices.length; j++ ) {
if( price >= prices[j].price ) {
prices.splice( j, 0, { price: price, qty: qty } );
break;
}
}
}
}
var numberFree = this.numberFree,
totalDiscount = 0;
for( var i = 0; i < prices.length; i++ ) {
var qty = prices[i].qty;
if( numberFree > qty ) {
numberFree -= qty;
} else {
qty = numberFree;
numberFree = 0;
}
totalDiscount += qty * prices[i].price;
}
return total - totalDiscount;
}
this.extractProperties = function( args ) {
// extract args as properties of this object
for( var prop in args ) {
if( args.hasOwnProperty( prop ) )
this[prop] = args[prop];
}
}
this.init( args );
}
})( jQuery );
</script>
<?php
self::$_is_script_output = true;
}
public function register_init_script( $form ) {
$args = array(
'formId' => $form['id'],
'fieldIds' => $this->_args['field_ids'],
'numberFree' => $this->_args['number_free']
);
$script = "new gwfxf(" . json_encode( $args ) . ");";
$slug = 'gwfxf_' . $form['id'] . '_' . implode( '_', $this->_args['field_ids'] );
GFFormDisplay::add_init_script( $form['id'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script );
}
public function apply_discount( $product_info, $form, $lead ) {
$total = GFCommon::get_total( $product_info );
$disc_products = array();
foreach( $product_info['products'] as $product_id => $product ) {
if( ! in_array( $product_id, $this->_args['field_ids'] ) )
continue;
if( ! count( $disc_products ) ) {
$disc_products[] = $product;
} else {
for( $i = 0; $i < count( $disc_products ); $i++ ) {
if( GFCommon::to_number( $product['price'] ) >= GFCommon::to_number( $disc_products[$i]['price'] ) ) {
array_splice( $disc_products, $i, 0, array( $product ) );
break;
}
}
}
}
$number_free = $this->_args['number_free'];
$total_discount = 0;
foreach( $disc_products as $disc_product ) {
$qty = $disc_product['quantity'];
$price = GFCommon::to_number( $disc_product['price'] );
if( $number_free > $qty ) {
$number_free -= $qty;
} else {
$qty = $number_free;
$number_free = 0;
}
$total_discount += $qty * $price;
}
$product_info['products']['gwfxf_discount'] = array(
'name' => sprintf( $this->_args['discount_label'], $this->_args['number_free'] ),
'price' => GFCommon::to_money( $total_discount * -1 ),
'quantity' => 1
);
return $product_info;
}
}
new GWFirstXFree( array(
'form_id' => 381,
'field_ids' => array( 1, 2, 3, 4 ),
'number_free' => 2
) );