Create Coupons with Gravity Forms for Gravity Forms, WooCommerce, or Easy Digital Downloads

Create coupons via Gravity Forms submissions. Map the coupon code to a field on the GF form and voila!

Code

Filename: gw-create-coupon.php

<?php
/**
 * Gravity Wiz // Gravity Forms // Create Coupons with Gravity Forms for Gravity Forms, WooCommerce, or Easy Digital Downloads
 *
 * Create coupons via Gravity Forms submissions. Map the coupon code to a field on the GF form and voila!
 *
 * @version 1.2.2
 * @author  David Smith <david@gravitywiz.com>
 * @license GPL-2.0+
 * @link    WooCommerce:   https://gravitywiz.com/creating-coupons-woocommerce-gravity-forms/
 * @link    Gravity Forms: https://gravitywiz.com/creating-coupons-for-gf-coupons-add-on-with-gravity-forms/
 */
class GW_Create_Coupon {

	var $_args;

	public function __construct( $args = array() ) {

		// 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,
			'source_field_id' => false,
			'name_field_id'   => false,
			'plugin'          => 'gf', // accepts: 'gf', 'wc', 'edd'
			'amount'          => 0,
			'type'            => '', // accepts: 'fixed_cart', 'percent', 'fixed_product', 'percent_product'
			'meta'            => array(),
			'required_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' ) );

	}

	public function init() {

		// make sure we're running the required minimum version of Gravity Forms and that WooCommerce is active
		if ( ! property_exists( 'GFCommon', 'version' ) || ! version_compare( GFCommon::$version, '1.8', '>=' ) ) {
			return;
		}

		add_action( 'gform_after_submission', array( $this, 'create_coupon' ), 10, 2 );

	}

	public function create_coupon( $entry, $form ) {

		if ( ! $this->is_applicable_form( $form ) || $this->should_abort( $entry ) ) {
			return;
		}

		$coupon_codes = $this->get_coupon_codes( $entry, $this->_args['source_field_id'] );

		foreach ( $coupon_codes as $coupon_code ) {

			if ( $this->_args['name_field_id'] === false ) {
				$coupon_name = $coupon_code;
			} else {
				$coupon_name = rgar( $entry, $this->_args['name_field_id'] );
				$coupon_name = $coupon_name === '' ? $coupon_code : $coupon_name;
			}

			$amount = $this->_args['amount'];
			$type   = $this->_args['type'];

			if ( is_callable( $amount ) ) {
				$amount = call_user_func( $amount );
			}

			$plugin_func = array( $this, sprintf( 'create_coupon_%s', $this->_args['plugin'] ) );

			if ( is_callable( $plugin_func ) ) {
				call_user_func( $plugin_func, $coupon_name, $coupon_code, $amount, $type, $entry, $form );
			}
		}

	}

	public function create_coupon_edd( $coupon_name, $coupon_code, $amount, $type, $entry, $form ) {

		if ( ! is_callable( 'edd_store_discount' ) ) {
			return;
		}

		$meta = wp_parse_args( $this->_args['meta'], array(
			'name'              => $coupon_name,
			'code'              => $coupon_code,
			'type'              => $type,
			'amount'            => $amount,
			'excluded_products' => array(),
			'expiration'        => '',
			'is_not_global'     => false,
			'is_single_use'     => false,
			'max_uses'          => '',
			'min_price'         => '',
			'product_condition' => '',
			'product_reqs'      => array(),
			'start'             => '',
			'uses'              => '',
		) );

		// EDD will set it's own defaults in the edd_store_discount() so let's filter out our own empty defaults (they're just here for easier reference)
		$meta = array_filter( $meta );

		// EDD takes a $details array which has some different keys than the meta, let's map the keys to the expected format
		$edd_post_keys = array(
			'max_uses'          => 'max',
			'product_reqs'      => 'products',
			'excluded_products' => 'excluded-products',
			'is_not_global'     => 'not_global',
			'is_single_use'     => 'use_once',
		);

		foreach ( $meta as $key => $value ) {
			$mod_key = rgar( $edd_post_keys, $key );
			if ( $mod_key ) {
				$meta[ $mod_key ] = $value;
			}
		}

		edd_store_discount( $meta );

	}

	public function create_coupon_gf( $coupon_name, $coupon_code, $amount, $type, $entry, $form ) {

		if ( ! class_exists( 'GFCoupons' ) ) {
			return;
		}

		// hack to load GF Coupons data.php file
		if ( is_callable( 'gf_coupons' ) ) {
			gf_coupons()->get_config( array( 'id' => 0 ), false );
		} else {
			/** @noinspection PhpDynamicAsStaticMethodCallInspection */
			GFCoupons::get_config( array( 'id' => 0 ), false );
		}

		$meta = wp_parse_args( $this->_args['meta'], array(
			'form_id'           => false,
			'coupon_name'       => $coupon_name,
			'coupon_code'       => strtoupper( $coupon_code ),
			'coupon_type'       => $type, // 'flat', 'percentage'
			'coupon_amount'     => $amount,
			'coupon_start'      => '', // MM/DD/YYYY
			'coupon_expiration' => '', // MM/DD/YYYY
			'coupon_limit'      => false,
			'coupon_stackable'  => false,
		) );

		$form_id = $meta['form_id'] ? $meta['form_id'] : 0;
		unset( $meta['form_id'] );

		foreach ( $meta as $key => $value ) {
			if ( $value instanceof Closure && is_callable( $value ) ) {
				$meta[ $key ] = call_user_func( $value, $entry, $form, $this );
			}
		}

		if ( is_callable( 'gf_coupons' ) ) {
			$meta['gravityForm']      = $form_id ? $form_id : 0;
			$meta['couponName']       = $meta['coupon_name'];
			$meta['couponCode']       = $meta['coupon_code'];
			$meta['couponAmountType'] = $meta['coupon_type'];
			$meta['couponAmount']     = $meta['coupon_amount'];
			$meta['startDate']        = $meta['coupon_start'];
			$meta['endDate']          = $meta['coupon_expiration'];
			$meta['usageLimit']       = $meta['coupon_limit'];
			$meta['isStackable']      = $meta['coupon_stackable'];
			$meta['usageCount']       = 0;
			gf_coupons()->insert_feed( $form_id, true, $meta );
		} else {
			/** @noinspection PhpUndefinedClassInspection */
			GFCouponsData::update_feed( 0, $form_id, true, $meta );
		}

	}

	/**
	 * Create a WooCommerce coupon.
	 *
	 * @link https://gist.github.com/mikejolley/3969579#file-gistfile1-txt
	 */
	public function create_coupon_wc( $coupon_name, $coupon_code, $amount, $type, $entry, $form ) {

		$start_date = rgar( $this->_args['meta'], 'start_date' );
		if ( $start_date === '' || ! strtotime( $start_date ) ) {
			$date       = current_datetime();
			$start_date = $date->format( 'Y-m-d H:i:s' );
		}

		// WooCommerce coupon uses the Post Title as the coupon code hence $coupon_code is assigned to Post Title and $coupon_name is assigned to the Post Content
		$coupon = array(
			'post_title'   => $coupon_code,
			'post_content' => $coupon_name,
			'post_status'  => 'publish',
			'post_author'  => 1,
			'post_type'    => 'shop_coupon',
			'post_date'    => $start_date,
		);

		$new_coupon_id = wp_insert_post( $coupon );

		$meta = wp_parse_args( $this->_args['meta'], array(
			'discount_type'              => $type,
			'coupon_amount'              => $amount,
			'individual_use'             => 'yes',
			'product_ids'                => '',
			'exclude_product_ids'        => '',
			'usage_limit'                => '1',
			'expiry_date'                => '',
			'apply_before_tax'           => 'no',
			'free_shipping'              => 'no',
			'exclude_sale_items'         => 'no',
			'product_categories'         => '',
			'exclude_product_categories' => '',
			'minimum_amount'             => '',
			'customer_email'             => '',
		) );

		foreach ( $meta as $meta_key => $meta_value ) {
			if ( $meta_value instanceof Closure && is_callable( $meta_value ) ) {
				$meta[ $meta_key ] = call_user_func( $meta_value, $entry, $form, $this );
			}
			update_post_meta( $new_coupon_id, $meta_key, $meta[ $meta_key ] );
		}

	}

	public function get_coupon_codes( $entry, $source_field_id ) {
		return array_filter( explode( "\n", rgar( $entry, $source_field_id ) ) );
	}

	function is_applicable_form( $form ) {

		$form_id = isset( $form['id'] ) ? $form['id'] : $form;

		return (int) $form_id === (int) $this->_args['form_id'];
	}

	public function should_abort( $entry ) {
		if ( empty( $this->_args['required_fields'] ) ) {
			return false;
		}

		foreach ( $this->_args['required_fields'] as $field_id ) {
			$value = rgar( $entry, (string) $field_id );

			if ( rgblank( $value ) ) {
				return true;
			}
		}

		return false;
	}

}

# Configuration

new GW_Create_Coupon( array(
	// ID of the form which will be used to create coupons
	'form_id'         => 608,
	// ID of the field whose value will be used as the coupon code
	'source_field_id' => 1,
	// ID of the field whose value will be used as the title of the coupon
	'name_field_id'   => 2,
	// which plugin the coupon should be created for (i.e. WooCommerce = 'wc')
	'plugin'          => '', // accepts: 'gf', 'wc', 'edd'
	// type of coupon code to be created, available types will differ depending on the plugin
	'type'            => '',
	// amount of the coupon discount
	'amount'          => 10,
	// The IDs of the fields that must not be empty, else the coupon won't be created
	'required_fields' => array( 1, 2, 1.3 ),
) );

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.