Skip to content

Instantly share code, notes, and snippets.

@stracker-phil
Last active October 21, 2022 11:12
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 stracker-phil/e150c102f3c4aa9abc06e455fdeddc4f to your computer and use it in GitHub Desktop.
Save stracker-phil/e150c102f3c4aa9abc06e455fdeddc4f to your computer and use it in GitHub Desktop.
Function to generate a random discount code for Easy Digital Downloads
<?php
/**
* Generate a random discount code that matches the given criteria.
*
* Samples:
* - generate_discount( 10, 'percent', '+7days', 'HI-^^^^' );
* - generate_discount( 5, 'flat', '', '********' );
*
* @param int $amount The discount code value.
* @param string $type The type, either [flat|percent].
* @param string $expires A (relative) date string like "+7days", or empty for
* no expiration.
* @param string $pattern A string that describes the length/pattern of the code.
* "*" is replaced with a random uppercase letter or digit.
* "?" is replaced with a random uppercase/lowercase letter.
* "." is replaced with a random lowercase letter.
* "#" is replaced with a random uppercase letter.
* "^" is replaced with a random uppercase hexadecimal digit.
* "+" is replaced with a random digit.
* @param string $name Optional, internal coupon name.
*
* @return string The newly generated code.
*/
function generate_discount(
int $amount = 10,
string $type = 'flat',
string $expires = '',
string $pattern = '^^^^-^^^^',
string $name = ''
) : string {
if ( ! is_callable( 'edd_store_discount' ) ) {
return '';
}
if ( $expires ) {
if ( is_numeric( $expires ) ) {
$exp_date = gmdate( 'm/d/Y', $expires );
} else {
$exp_date = gmdate( 'm/d/Y', strtotime( $expires ) );
}
} else {
$exp_date = '';
}
do {
$coupon_code = generate_coupon_code( $pattern );
$exists = edd_get_discount_by_code( $coupon_code );
} while ( $exists );
$meta = [
'name' => $name ? $name : $coupon_code,
'code' => $coupon_code,
'type' => $type,
'amount' => $amount,
'excluded_products' => [],
'expiration' => $exp_date,
'is_not_global' => false,
'is_single_use' => true,
'max_uses' => '1',
'min_price' => '',
'product_condition' => '',
'product_reqs' => [],
'start' => '',
'uses' => '',
];
// EDD will set its own defaults in the edd_store_discount() so let's filter out
// empty defaults. We just keep them 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 = [
'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 = $edd_post_keys[ $key ];
if ( $mod_key ) {
$meta[ $mod_key ] = $value;
}
}
edd_store_discount( $meta );
return $coupon_code;
}
/**
* Generates a random coupon code.
*
* @param string $pattern The pattern - @see generate_discount() for details.
* @param int $min_length Minimum length of the code.
*
* @return string The random coupon code.
*/
function generate_coupon_code( $pattern, $min_length = 6 ) {
$pattern = preg_replace( '/[^a-zA-Z0-9_\-.*#+^?]/', '*', $pattern );
while ( strlen( $pattern ) < 6 ) {
$pattern .= '*';
}
$pattern_len = strlen( $pattern );
$num_chars = '0123456789';
$lower_chars = 'abcdefghijklmnopqrstuvwxyz';
$upper_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$letter_chars = $lower_chars . $upper_chars;
$hex_chars = 'ABCDEF0123456789';
$all_chars = $num_chars . $upper_chars;
$coupon_code = '';
for ( $i = 0; $i < $pattern_len; $i ++ ) {
$char = $pattern[ $i ];
if ( '*' === $char ) {
$pool = $all_chars;
} elseif ( '^' === $char ) {
$pool = $hex_chars;
} elseif ( '?' === $char ) {
$pool = $letter_chars;
} elseif ( '.' === $char ) {
$pool = $lower_chars;
} elseif ( '#' === $char ) {
$pool = $upper_chars;
} elseif ( '+' === $char ) {
$pool = $num_chars;
} else {
$pool = false;
}
if ( $pool ) {
$char = $pool[ wp_rand( 0, strlen( $pool ) - 1 ) ];
}
$coupon_code .= $char;
}
return $coupon_code;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment