View source
<?php
require_once 'uc_coupon.entity.inc';
function uc_coupon_menu() {
$items = array();
$items['admin/store/coupons'] = array(
'title' => 'Coupons',
'description' => 'Manage store discount coupons.',
'page callback' => 'uc_coupon_display',
'page arguments' => array(
'active',
),
'access arguments' => array(
'view store coupons',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'uc_coupon.admin.inc',
);
$items['admin/store/coupons/list'] = array(
'title' => 'Active coupons',
'description' => 'View active coupons.',
'page callback' => 'uc_coupon_display',
'page arguments' => array(
'active',
),
'access arguments' => array(
'view store coupons',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'uc_coupon.admin.inc',
'weight' => 0,
);
$items['admin/store/coupons/inactive'] = array(
'title' => 'Inactive coupons',
'description' => 'View inactive coupons.',
'page callback' => 'uc_coupon_display',
'page arguments' => array(
'inactive',
),
'access arguments' => array(
'view store coupons',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'uc_coupon.admin.inc',
'weight' => 1,
);
$items['admin/store/coupons/add'] = array(
'title' => 'Add new coupon',
'description' => 'Add a new coupon.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_coupon_add_form',
),
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'uc_coupon.admin.inc',
'weight' => 2,
);
$items['admin/store/coupons/%uc_coupon'] = array(
'title callback' => 'uc_coupon_title',
'title arguments' => array(
3,
),
'description' => 'View coupon details.',
'page callback' => 'uc_coupon_view',
'page arguments' => array(
3,
),
'access arguments' => array(
'view store coupons',
),
'type' => MENU_CALLBACK,
'file' => 'uc_coupon.admin.inc',
'weight' => 3,
);
$items['admin/store/coupons/%uc_coupon/view'] = array(
'title' => 'View',
'description' => 'View coupon details.',
'access arguments' => array(
'view store coupons',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'file' => 'uc_coupon.admin.inc',
'weight' => 0,
);
$items['admin/store/coupons/%uc_coupon/print'] = array(
'title' => 'Print',
'description' => 'Print coupon.',
'page callback' => 'uc_coupon_print',
'page arguments' => array(
3,
5,
'print',
),
'access arguments' => array(
'view store coupons',
),
'type' => MENU_LOCAL_TASK,
'file' => 'uc_coupon.admin.inc',
'weight' => 1,
);
$items['admin/store/coupons/%uc_coupon/edit'] = array(
'title' => 'Edit',
'description' => 'Edit an existing coupon.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_coupon_add_form',
3,
),
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_LOCAL_TASK,
'file' => 'uc_coupon.admin.inc',
'weight' => 2,
);
$items['admin/store/coupons/%uc_coupon/delete'] = array(
'title' => 'Delete',
'description' => 'Delete a coupon.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_coupon_delete_confirm',
3,
),
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_LOCAL_TASK,
'file' => 'uc_coupon.admin.inc',
'weight' => 3,
);
$items['admin/store/coupons/%uc_coupon/codes'] = array(
'title' => 'Download bulk coupon codes',
'description' => 'Download the list of bulk coupon codes as a CSV file.',
'page callback' => 'uc_coupon_codes_csv',
'page arguments' => array(
3,
),
'access arguments' => array(
'view store coupons',
),
'file' => 'uc_coupon.admin.inc',
'type' => MENU_CALLBACK,
);
$items['admin/store/coupons/autocomplete/node'] = array(
'title' => 'Node autocomplete',
'page callback' => 'uc_coupon_autocomplete_node',
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_CALLBACK,
'file' => 'uc_coupon.admin.inc',
);
$items['admin/store/coupons/autocomplete/term'] = array(
'title' => 'Term autocomplete',
'page callback' => 'uc_coupon_autocomplete_term',
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_CALLBACK,
'file' => 'uc_coupon.admin.inc',
);
$items['admin/store/coupons/autocomplete/user'] = array(
'title' => 'User autocomplete',
'page callback' => 'uc_coupon_autocomplete_user',
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_CALLBACK,
'file' => 'uc_coupon.admin.inc',
);
$items['admin/store/coupons/autocomplete/role'] = array(
'title' => 'Role autocomplete',
'page callback' => 'uc_coupon_autocomplete_role',
'access arguments' => array(
'manage store coupons',
),
'type' => MENU_CALLBACK,
'file' => 'uc_coupon.admin.inc',
);
$items['admin/store/settings/coupon'] = array(
'title' => 'Coupon module settings',
'description' => 'Configure the discount coupon module settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_coupon_settings_form',
),
'access arguments' => array(
'administer store',
),
'file' => 'uc_coupon.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/store/reports/coupon'] = array(
'title' => 'Coupon usage reports',
'description' => 'View coupon usage reports.',
'page callback' => 'uc_coupon_reports',
'access arguments' => array(
'view reports',
),
'file' => 'uc_coupon.reports.inc',
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function uc_coupon_to_arg($arg) {
return $arg;
}
function uc_coupon_title($coupon) {
return $coupon->name;
}
function uc_coupon_permission() {
$perms = array(
'view store coupons' => array(
'title' => t('view store coupons'),
'description' => t('Display information about discount coupons.'),
),
'manage store coupons' => array(
'title' => t('manage store coupons'),
'description' => t('Create, edit and delete discoutn coupons.'),
),
);
if (!module_exists('uc_reports')) {
$perms['view reports'] = array(
'title' => t('view reports'),
'description' => t('Display coupon usage reports.'),
);
}
return $perms;
}
function uc_coupon_init() {
global $conf;
$conf['i18n_variables'][] = 'uc_coupon_pane_description';
if ($param = variable_get('uc_coupon_querystring', '')) {
if (isset($_GET[$param]) && $_GET[$param]) {
uc_coupon_session_add($_GET[$param], 'retain');
}
}
}
function uc_coupon_theme() {
return array(
'uc_coupon_automatic_discounts' => array(
'render element' => 'form',
),
'uc_coupon_form' => array(
'render element' => 'form',
),
'uc_coupon_actions' => array(
'variables' => array(
'coupon' => NULL,
),
'file' => 'uc_coupon.admin.inc',
),
'uc_coupon_code' => array(
'variables' => array(
'coupon' => NULL,
),
'file' => 'uc_coupon.admin.inc',
),
'uc_coupon_discount' => array(
'variables' => array(
'coupon' => NULL,
'currency' => TRUE,
),
),
'uc_coupon_certificate' => array(
'variables' => array(
'coupon' => NULL,
'code' => NULL,
),
'template' => 'uc-coupon-certificate',
'path' => drupal_get_path('module', 'uc_coupon') . '/theme',
),
'uc_coupon_page' => array(
'variables' => array(
'content' => NULL,
),
'template' => 'uc-coupon-page',
'path' => drupal_get_path('module', 'uc_coupon') . '/theme',
),
);
}
function uc_coupon_theme_registry_alter(&$registry) {
if ($registry['uc_cart_block_content']['function'] == 'theme_uc_cart_block_content') {
$registry['uc_cart_block_content']['function'] = 'uc_coupon_theme_uc_cart_block_content';
}
}
function uc_coupon_count_usage($cid, $uid = NULL) {
global $user;
$weight = uc_order_status_data(variable_get('uc_coupon_used_order_status', 'processing'), 'weight');
$usage = array(
'codes' => array(),
);
$result = db_query("SELECT uco.code, COUNT(*) AS uses FROM {uc_coupons_orders} AS uco\n LEFT JOIN {uc_orders} AS uo ON uco.oid = uo.order_id\n LEFT JOIN {uc_order_statuses} AS uos ON uo.order_status = uos.order_status_id\n WHERE uos.weight >= :weight AND uco.cid = :cid GROUP BY uco.code", array(
':weight' => $weight,
':cid' => $cid,
));
foreach ($result as $row) {
$usage['codes'][$row->code] = $row->uses;
}
if (is_null($uid)) {
$uid = $user->uid;
}
$usage['user'] = db_query("SELECT COUNT(*) FROM {uc_coupons_orders} AS uco\n LEFT JOIN {uc_orders} AS uo ON uco.oid = uo.order_id\n LEFT JOIN {uc_order_statuses} AS uos ON uo.order_status = uos.order_status_id\n WHERE uos.weight >= :weight AND uco.cid = :cid AND uo.uid = :uid", array(
':weight' => $weight,
':cid' => $cid,
':uid' => $uid,
))
->fetchField();
drupal_alter('uc_coupon_usage', $usage, $cid, $uid);
return $usage;
}
function theme_uc_coupon_discount($variables) {
$coupon = $variables['coupon'];
$currency = isset($variables['currency']) ? $variables['currency'] : TRUE;
return _uc_coupon_format_discount($coupon, $currency);
}
function _uc_coupon_format_discount($coupon, $currency = TRUE) {
switch ($coupon->type) {
case 'price':
return $currency ? uc_currency_format($coupon->value) : $coupon->value;
case 'percentage':
return (double) $coupon->value . '%';
case 'set_price':
return '=' . ($currency ? uc_currency_format($coupon->value) : $coupon->value);
}
}
function uc_coupon_get_bulk_code($coupon, $id) {
if (isset($coupon->valid)) {
$prefix = drupal_substr($coupon->code, 0, strlen($coupon->code) - $coupon->data['bulk_length']);
}
else {
$prefix = $coupon->code;
}
$id = str_pad(dechex($id), strlen(dechex($coupon->data['bulk_number'])), '0', STR_PAD_LEFT);
$length = strlen($prefix) + $coupon->data['bulk_length'];
return strtoupper(substr($prefix . $id . md5($coupon->bulk_seed . $id), 0, $length));
}
function uc_coupon_find($code, $reset = FALSE) {
static $cached = array();
if ($reset) {
$cached = array();
}
if (!$code) {
return FALSE;
}
elseif (array_key_exists($code, $cached)) {
return $cached[$code];
}
$coupon = db_query("SELECT cid FROM {uc_coupons}\n WHERE code = :code AND status = 1 AND bulk = 0 AND valid_from < :now AND (valid_until = 0 OR valid_until > :now)", array(
':code' => $code,
':now' => REQUEST_TIME,
))
->fetchObject();
if ($coupon) {
$cached[$code] = uc_coupon_load($coupon->cid);
return $cached[$code];
}
$result = db_query("SELECT cid, code, data, bulk_seed FROM {uc_coupons}\n WHERE status = 1 AND bulk = 1 AND valid_from < :now AND (valid_until = 0 OR valid_until > :now)", array(
':now' => REQUEST_TIME,
));
foreach ($result as $coupon) {
$prefix_length = strlen($coupon->code);
if (substr($code, 0, $prefix_length) != $coupon->code) {
continue;
}
if ($coupon->data) {
$coupon->data = unserialize($coupon->data);
}
$id = substr($code, $prefix_length, strlen(dechex($coupon->data['bulk_number'])));
if (!preg_match("/^[0-9A-F]+\$/", $id)) {
continue;
}
$id = hexdec($id);
if ($id < 0 || $id > $coupon->data['bulk_number']) {
continue;
}
if ($code == uc_coupon_get_bulk_code($coupon, $id)) {
$cached[$code] = uc_coupon_load($coupon->cid);
return $cached[$code];
}
}
$cached[$code] = FALSE;
return $cached[$code];
}
function uc_coupon_session_add($code, $op = 'submit') {
if (!variable_get('uc_coupon_allow_multiple', FALSE)) {
$_SESSION['uc_coupons'] = array(
$code => $op,
);
}
else {
$_SESSION['uc_coupons'][$code] = $op;
}
}
function uc_coupon_session_clear($code = NULL) {
if (isset($_SESSION)) {
if (isset($code)) {
unset($_SESSION['uc_coupons'][$code]);
}
else {
unset($_SESSION['uc_coupons']);
}
}
}
function uc_coupon_session_get($code = NULL) {
if (isset($code)) {
return isset($_SESSION['uc_coupons'][$code]);
}
elseif (isset($_SESSION['uc_coupons'])) {
return $_SESSION['uc_coupons'];
}
else {
return array();
}
}
function uc_coupon_session_validate($products = NULL) {
static $valids = NULL;
if (isset($products)) {
$valids = array();
module_invoke_all('uc_coupon_revalidate', $products);
$session = uc_coupon_session_get();
if (!empty($session)) {
global $user;
$order = new UcOrder();
$order->products = $products;
$order->data = array(
'coupons' => array(),
);
foreach ($session as $code => $op) {
$coupon = uc_coupon_validate($code, $order, $user);
if ($coupon->valid) {
$valids[$code] = $coupon;
$order->data['coupons'][$code] = $coupon->discounts;
switch ($op) {
case 'submit':
case 'retain':
drupal_set_message($coupon->message);
module_invoke_all('uc_coupon_apply', $coupon);
uc_coupon_session_add($code, 'revalidate');
break;
case 'auto':
uc_coupon_session_clear($code);
break;
}
}
else {
switch ($op) {
case 'submit':
drupal_set_message($coupon->message, 'error');
uc_coupon_session_clear($code);
break;
case 'revalidate':
if (!empty($products)) {
drupal_set_message(t('%title is no longer applicable to your order', array(
'%title' => $coupon->title,
)));
}
module_invoke_all('uc_coupon_remove', $coupon);
uc_coupon_session_add($code, 'retain');
break;
case 'auto':
uc_coupon_session_clear($code);
break;
}
}
}
}
}
elseif (!isset($valids)) {
uc_cart_get_contents();
}
return $valids;
}
function uc_coupon_validate($code, $order = NULL, $account = NULL) {
global $user;
if (is_null($order)) {
$order = new stdClass();
$order->products = uc_cart_get_contents();
}
if (is_null($account)) {
$account = $user;
}
$code = trim(strtoupper($code));
$coupon = uc_coupon_find($code);
if (!$coupon) {
$coupon = new stdClass();
$coupon->valid = FALSE;
$coupon->message = t('This coupon code is invalid or has expired.');
$coupon->title = t('Unknown');
return $coupon;
}
$coupon->code = $code;
$coupon->valid = TRUE;
$coupon->usage = uc_coupon_count_usage($coupon->cid, $account ? $account->uid : NULL);
unset($coupon->message);
if ($order) {
$coupon->amount = 0;
$coupon->pretax_amount = 0;
$discounts = uc_coupon_calculate_discounts($coupon, $order, TRUE);
if (!is_array($discounts)) {
$coupon->discounts = array();
$coupon->valid = FALSE;
$coupon->message = $discounts;
}
else {
$coupon->discounts = $discounts;
foreach ($coupon->discounts as $item) {
$coupon->amount += $item->discount;
$coupon->pretax_amount += isset($item->pretax_discount) ? $item->pretax_discount : $item->discount;
}
$coupon->amount = round($coupon->amount, variable_get('uc_currency_prec', 2));
}
}
foreach (module_implements('uc_coupon_validate') as $module) {
$callback = $module . '_uc_coupon_validate';
$result = $callback($coupon, $order, $account);
if ($result === TRUE) {
$coupon->valid = TRUE;
}
elseif (!is_null($result)) {
$coupon->valid = FALSE;
$coupon->message = $result;
}
}
$format = !empty($coupon->data['line_item_format']) ? $coupon->data['line_item_format'] : variable_get('uc_coupon_line_item_format', t('Coupon !code', array(
'!code' => '[uc_coupon:code]',
)));
$coupon->title = token_replace(check_plain($format), array(
'uc_coupon' => $coupon,
));
if ($coupon->valid && !isset($coupon->message)) {
if (isset($coupon->data['apply_message'])) {
$coupon->message = token_replace(check_plain($coupon->data['apply_message']), array(
'uc_coupon' => $coupon,
));
}
else {
$amount = theme('uc_price', array(
'price' => $coupon->amount,
));
if (isset($order) || variable_get('uc_coupon_show_in_cart', TRUE)) {
$coupon->message = t('A discount of !amount has been applied to your order.', array(
'!amount' => $amount,
));
}
else {
$coupon->message = t('A discount of !amount will be applied at checkout.', array(
'!amount' => $amount,
));
}
}
}
return $coupon;
}
function uc_coupon_uc_coupon_validate(&$coupon, $order, $account) {
if (!empty($order->data['coupons'])) {
foreach (array_keys($order->data['coupons']) as $code) {
$other = uc_coupon_find($code);
$other_listed = !empty($coupon->data['combinations']) && in_array($other->cid, $coupon->data['combinations']);
$this_ok = (isset($coupon->data['negate_combinations']) xor $other_listed);
$this_listed = !empty($other->data['combinations']) && in_array($coupon->cid, $other->data['combinations']);
$other_ok = (isset($other->data['negate_combinations']) xor $this_listed);
if (!$this_ok || !$other_ok) {
return t('This coupon combination is not allowed.');
}
}
}
if ($coupon->max_uses > 0 && !empty($coupon->usage['codes'][$coupon->code]) && $coupon->usage['codes'][$coupon->code] >= $coupon->max_uses) {
return t('This coupon has reached the maximum redemption limit.');
}
if ($account && isset($coupon->data['max_uses_per_user']) && $coupon->usage['user'] >= $coupon->data['max_uses_per_user']) {
return t('This coupon has reached the maximum redemption limit.');
}
if ($account && isset($coupon->data['users'])) {
if (in_array("{$account->uid}", $coupon->data['users'], TRUE) xor !isset($coupon->data['negate_users'])) {
return t('Your user ID is not allowed to use this coupon.');
}
}
if ($account && isset($coupon->data['roles'])) {
$role_found = FALSE;
foreach ($coupon->data['roles'] as $role) {
if (in_array($role, $account->roles)) {
$role_found = TRUE;
break;
}
}
if ($role_found xor !isset($coupon->data['negate_roles'])) {
return t('You do not have the correct permission to use this coupon.');
}
}
}
function uc_coupon_calculate_discounts($coupon, $order) {
if (!is_object($coupon)) {
$coupon = uc_coupon_find($coupon);
}
$restricted = isset($coupon->data['products']) || isset($coupon->data['skus']) || isset($coupon->data['terms']) || isset($coupon->data['product_types']);
$matched = 0;
$matched_price = 0;
$total_qty = 0;
$total_price = 0;
$items = array();
foreach ($order->products as $item) {
if (isset($item->module) && $item->module == 'uc_coupon') {
continue;
}
$node = node_load($item->nid);
$qty = $item->qty;
if (!$restricted) {
$include = TRUE;
}
else {
$include = FALSE;
$terms = _uc_coupon_list_terms($node);
if (isset($coupon->data['products']) && isset($item->data['kit_id'])) {
$include = (isset($coupon->data['negate_products']) xor in_array($item->data['kit_id'], $coupon->data['products']));
}
else {
if (isset($coupon->data['products']) && (isset($coupon->data['negate_products']) xor in_array($item->nid, $coupon->data['products']))) {
$include = TRUE;
}
elseif (isset($coupon->data['products']) && isset($coupon->data['negate_products']) && in_array($item->nid, $coupon->data['products'])) {
}
elseif (isset($coupon->data['terms']) && (isset($coupon->data['negate_terms']) xor count(array_intersect($terms, $coupon->data['terms'])))) {
$include = TRUE;
}
elseif (isset($coupon->data['terms']) && isset($coupon->data['negate_terms']) && count(array_intersect($terms, $coupon->data['terms']))) {
}
elseif (isset($coupon->data['skus']) && _uc_coupon_match_sku($item->model, $coupon->data['skus'])) {
$include = TRUE;
}
elseif (isset($coupon->data['product_types']) && in_array($node->type, $coupon->data['product_types'])) {
$include = TRUE;
}
}
}
if ($include) {
$matched += $qty;
$matched_price += $item->price * $qty;
}
$total_qty += $qty;
$total_price += $item->price * $qty;
if ($include || $coupon->data['apply_to'] == 'subtotal') {
$clone = clone $item;
$clone->type = $node->type;
$items = array_pad($items, count($items) + $qty, $clone);
}
}
if ($matched == 0) {
return t('You do not have any applicable products in your cart.');
}
$use_matched = isset($coupon->data['minimum_qty_restrict']) && $coupon->data['minimum_qty_restrict'] != FALSE;
if (isset($coupon->data['minimum_qty'])) {
if (($use_matched ? $matched : $total_qty) < (int) $coupon->data['minimum_qty']) {
return t('You do not have enough applicable products in your cart.');
}
}
if ($coupon->minimum_order > 0) {
if (($use_matched ? $matched_price : $total_price) < $coupon->minimum_order) {
return $use_matched ? t('You have not reached the minimum total of applicable products for this coupon.') : t('You have not reached the minimum order total for this coupon.');
}
}
if (isset($coupon->data['require_match_all']) && $matched < $total_qty) {
return t('You have non-applicable products in your cart');
}
switch ($coupon->data['apply_to']) {
case 'cheapest':
usort($items, '_uc_coupon_sort_products');
$items = array_slice($items, 0, $coupon->data['apply_count']);
break;
case 'expensive':
usort($items, '_uc_coupon_sort_products');
$items = array_slice($items, -$coupon->data['apply_count']);
break;
}
$total = 0;
$discounts = array();
$included_rates = array();
foreach ($items as $item) {
if (!isset($discounts[$item->nid])) {
$included_rate = 1;
if (module_exists('uc_taxes')) {
foreach (uc_taxes_rate_load() as $tax) {
if ($tax->display_include && is_array($tax->taxed_line_items) && in_array('coupon', $tax->taxed_line_items) && in_array($item->type, $tax->taxed_product_types) && ($tax->shippable == 0 || $item->data['shippable'] == 1)) {
$included_rate += $tax->rate;
}
}
}
$prior_discount = 0;
if (!empty($order->data['coupons'])) {
foreach ($order->data['coupons'] as $stacked) {
if (isset($stacked[$item->nid])) {
$prior_discount += $stacked[$item->nid]->pretax_discount;
}
}
}
$total -= $prior_discount * $included_rate;
$discounts[$item->nid] = (object) array(
'qty' => 1,
'price' => $item->price - $prior_discount,
);
$included_rates[$item->nid] = $included_rate;
unset($item->type);
}
else {
$discounts[$item->nid]->price += $item->price;
$discounts[$item->nid]->qty++;
}
$total += $item->price * $included_rate;
}
foreach ($discounts as $nid => $discount) {
$inclusive_price = $discount->price * $included_rates[$nid];
switch ($coupon->type) {
case 'price':
if ($coupon->data['apply_to'] == 'subtotal' || $coupon->data['apply_to'] == 'products_total') {
$discount->discount = $total == 0 ? 0 : min($coupon->value * ($inclusive_price / $total), $inclusive_price);
}
else {
$discount->discount = min($coupon->value * $discount->qty, $inclusive_price);
}
break;
case 'percentage':
$discount->discount = $inclusive_price * $coupon->value / 100;
break;
case 'set_price':
$discount->discount = max($inclusive_price - $coupon->value * $discount->qty, 0);
break;
}
$discount->pretax_discount = $discount->discount / $included_rates[$nid];
unset($discount->price);
unset($discount->qty);
}
return $discounts;
}
function _uc_coupon_match_sku($model, $skus) {
foreach ($skus as $match) {
if (preg_match('/^' . str_replace('\\*', '.*?', preg_quote($match, '/')) . '$/', $model)) {
return TRUE;
}
}
return FALSE;
}
function _uc_coupon_sort_products($a, $b) {
if ($a->price == $b->price) {
return 0;
}
return $a->price > $b->price ? 1 : -1;
}
function _uc_coupon_list_terms($node) {
$terms = array();
foreach (array_keys(field_info_instances('node', $node->type)) as $field_name) {
$field_info = field_info_field($field_name);
if ($field_info['type'] == 'taxonomy_term_reference') {
if ($field_values = field_get_items('node', $node, $field_name)) {
foreach ($field_values as $field_value) {
$terms[] = $field_value['tid'];
}
}
}
}
return $terms;
}
function uc_coupon_block_info() {
$blocks = array();
$blocks['coupon-discount'] = array(
'info' => t('Coupon discount form'),
);
return $blocks;
}
function uc_coupon_block_view($delta) {
if ($delta == 'coupon-discount') {
$block = array(
'subject' => t('Coupon discount'),
'content' => drupal_get_form('uc_coupon_form', 'block'),
);
return $block;
}
}
function theme_uc_coupon_form($variables) {
$form = $variables['form'];
$output = '';
if ($form['#uc_coupon_form_context'] == 'cart') {
$output .= '<h3>' . t('Coupon discounts') . '</h3>';
}
elseif ($form['#uc_coupon_form_context'] == 'block') {
if (isset($form['code'])) {
$form['code']['#size'] = 15;
}
}
$output .= drupal_render_children($form);
return $output;
}
function uc_coupon_uc_cart_pane($items) {
drupal_add_css(drupal_get_path('module', 'uc_coupon') . '/uc_coupon.css');
$body = drupal_get_form('uc_coupon_form', 'cart') + array(
'#prefix' => '<div id="uc-cart-pane-coupon">',
'#suffix' => '</div>',
);
$panes[] = array(
'id' => 'coupon',
'body' => $body,
'title' => t('Coupon discount'),
'desc' => t('Allows shoppers to use a coupon during checkout for order discounts.'),
'weight' => 1,
'enabled' => TRUE,
);
$body = array();
$discounts = _uc_coupon_options_list(uc_coupon_session_validate(), FALSE);
if (!empty($discounts)) {
$body = array(
'#theme' => 'uc_coupon_automatic_discounts',
'#prefix' => '<div id="uc-cart-pane-coupon-automatic">',
'#title' => t('Special discounts'),
'#suffix' => '</div>',
'discounts' => array(
'#theme' => 'item_list',
'#items' => _uc_coupon_options_list(uc_coupon_session_validate(), FALSE),
'#title' => t('Special discounts'),
),
);
}
$panes[] = array(
'id' => 'coupon_auto',
'body' => $body,
'title' => t('Special Discounts'),
'desc' => t('Displays a list of automatic discounts.'),
'weight' => 1,
'enabled' => TRUE,
);
return $panes;
}
function theme_uc_coupon_automatic_discounts($variables) {
$form = $variables['form'];
return drupal_render_children($form);
}
function uc_coupon_table($coupons, $ajax = FALSE) {
$table = array(
'#type' => 'tapir_table',
);
$table['#columns'] = array(
'title' => array(
'cell' => t('Active coupons'),
'weight' => 0,
),
'remove' => array(
'cell' => t('Remove'),
'weight' => 1,
),
);
$i = 0;
foreach ($coupons as $code => $title) {
$table[$i] = array(
'title' => array(
'#markup' => $title,
),
'remove' => array(
'#type' => 'submit',
'#value' => t('Remove'),
'#name' => 'uc-coupon-remove-' . $code,
),
);
if ($ajax) {
$table[$i]['remove'] += array(
'#ajax' => $ajax,
);
}
$i++;
}
return $table;
}
function _uc_coupon_options_list($coupons, $in_session = TRUE) {
$options = array();
if (!empty($coupons)) {
foreach ($coupons as $coupon) {
if (!$in_session xor uc_coupon_session_get($coupon->code)) {
$options[$coupon->code] = $coupon->title;
}
}
}
return $options;
}
function uc_coupon_checkout_submit($form, &$form_state) {
unset($form_state['checkout_valid']);
$form_state['redirect'] = 'cart/checkout';
$form_state['rebuild'] = TRUE;
}
function uc_coupon_form($form, $form_state, $context = 'block', $ajax = FALSE) {
$coupons = uc_coupon_session_validate();
$components = variable_get('uc_coupon_form_components', drupal_map_assoc(variable_get('uc_coupon_allow_multiple', FALSE) ? array(
'entry',
) : array(
'entry',
'list',
)));
if (!empty($components['entry'])) {
$form['code'] = array(
'#type' => 'textfield',
'#size' => 25,
'#title' => t('Coupon Code'),
'#description' => t('Enter a coupon code and click "Apply to order" below.'),
);
$form['apply'] = array(
'#type' => 'submit',
'#value' => t('Apply to order'),
'#name' => 'uc-coupon-apply',
);
if (!variable_get('uc_coupon_allow_multiple', FALSE) && count(uc_coupon_session_get()) > 0) {
$form['code']['#description'] .= ' ' . t('Apply a blank code to remove the currently applied coupon.');
}
if ($ajax) {
drupal_add_css('#uc-coupon-active-coupons, #uc-coupon-other-discounts { clear: left; }', array(
'type' => 'inline',
'group' => CSS_DEFAULT,
));
$form['apply'] += array(
'#ajax' => $ajax,
);
}
if ($context == 'checkout') {
$form['apply']['#limit_validation_errors'] = array();
$form['apply']['#submit'] = array(
'uc_coupon_checkout_submit',
);
}
}
$options = _uc_coupon_options_list($coupons);
if (!empty($options)) {
if (!empty($components['table'])) {
$form['coupons_table'] = tapir_get_table('uc_coupon_table', $options, $ajax);
}
if (!empty($components['list'])) {
$form['coupons'] = array(
'#prefix' => '<div id="uc-coupon-active-coupons">',
'#suffix' => '</div>',
'#type' => 'checkboxes',
'#title' => t('Active Coupons'),
'#options' => $options,
'#default_value' => array_keys($options),
'#description' => t('These coupons have been applied to your order. To remove one, uncheck the box and click "Remove coupons" below.'),
);
$form['coupons']['#description'] = t('These coupons have been applied to your order. To remove one, uncheck the box next to the coupon name and click "Update order" below.');
$form['remove'] = array(
'#type' => 'submit',
'#value' => t('Update order'),
'#name' => 'uc-coupon-remove',
);
if ($ajax) {
$form['remove']['#ajax'] = $ajax;
}
if ($context == 'checkout') {
$form['remove']['#limit_validation_errors'] = array();
$form['remove']['#submit'] = array(
'uc_coupon_checkout_submit',
);
}
}
}
$form['#uc_coupon_form_context'] = $context;
return $form;
}
function uc_coupon_uc_order($op, &$order) {
if ($op == 'presave') {
if (_uc_coupon_is_checkout_order($order)) {
$coupons = uc_coupon_session_validate();
$items = array();
foreach ($order->line_items as $index => $line) {
if ($line['type'] == 'coupon') {
$code = isset($line['data']['code']) ? $line['data']['code'] : db_query('SELECT code FROM {uc_coupons_orders} WHERE oid = :oid', array(
':oid' => $order->order_id,
))
->fetchField();
$items[$code] = $index;
}
}
$entries = db_query('SELECT code, cuid FROM {uc_coupons_orders} WHERE oid = :oid', array(
':oid' => $order->order_id,
))
->fetchAllKeyed(0, 1);
$insert = array();
$order->data['coupons'] = array();
foreach ($coupons as $coupon) {
$order->data['coupons'][$coupon->code] = $coupon->discounts;
if (isset($entries[$coupon->code])) {
db_update('uc_coupons_orders')
->condition('cuid', $entries[$coupon->code])
->fields(array(
'cid' => $coupon->cid,
'value' => $coupon->amount,
))
->execute();
unset($entries[$coupon->code]);
}
else {
$insert[] = array(
$coupon->cid,
$order->order_id,
$coupon->code,
$coupon->value,
);
}
if (isset($items[$coupon->code])) {
$line =& $order->line_items[$items[$coupon->code]];
$line['title'] = $coupon->title;
$line['amount'] = -$coupon->pretax_amount;
$line['data']['code'] = $coupon->code;
uc_order_update_line_item($line['line_item_id'], $line['title'], $line['amount'], $line['data']);
unset($items[$coupon->code]);
}
else {
$order->line_items[] = uc_order_line_item_add($order->order_id, 'coupon', $coupon->title, -$coupon->pretax_amount, _uc_line_item_data('coupon', 'weight'), array(
'code' => $coupon->code,
));
}
}
if (!empty($insert)) {
$query = db_insert('uc_coupons_orders');
$query
->fields(array(
'cid',
'oid',
'code',
'value',
));
foreach ($insert as $fields) {
$query
->values($fields);
}
$query
->execute();
}
if (!empty($entries)) {
db_delete('uc_coupons_orders')
->condition('cuid', $entries)
->execute();
}
foreach ($items as $index) {
uc_order_delete_line_item($order->line_items[$index]['line_item_id']);
unset($order->line_items[$index]);
}
usort($order->line_items, 'uc_weight_sort');
}
foreach ($order->products as $key => $product) {
if (isset($product->module) && $product->module == 'uc_coupon') {
unset($order->products[$key]);
}
}
}
}
function uc_coupon_uc_checkout_pane() {
$panes[] = array(
'id' => 'coupon',
'callback' => 'uc_checkout_pane_coupon',
'title' => t('Coupon discount'),
'desc' => t('Allows shoppers to use a coupon during checkout for order discounts.'),
'weight' => 5,
'process' => TRUE,
);
$panes[] = array(
'id' => 'coupon_automatic',
'callback' => 'uc_checkout_pane_coupon_automatic',
'title' => t('Special Discounts'),
'desc' => t('Displays a list of all automatic coupon discounts.'),
'weight' => 5,
'process' => FALSE,
);
return $panes;
}
function uc_coupon_checkout_update($form, $form_state) {
$commands[] = ajax_command_replace('#coupon-pane', trim(drupal_render($form['panes']['coupon'])));
if (isset($form['panes']['coupon_automatic'])) {
$commands[] = ajax_command_replace('#coupon_automatic-pane', trim(drupal_render($form['panes']['coupon_automatic'])));
}
if (isset($form['panes']['payment'])) {
$commands[] = ajax_command_replace('#payment-pane', trim(drupal_render($form['panes']['payment'])));
}
if (isset($form['panes']['quotes'])) {
$commands[] = ajax_command_replace('#quotes-pane', trim(drupal_render($form['panes']['quotes'])));
}
if (variable_get('uc_coupon_show_in_cart', TRUE) && isset($form['panes']['cart']['cart_review_table'])) {
$commands[] = ajax_command_html('#cart-pane>div', drupal_render($form['panes']['cart']['cart_review_table']));
}
if (count(drupal_get_messages('error', FALSE)) == 0) {
$commands[] = ajax_command_invoke('#coupon-pane input[type=text]', 'val', array(
'',
));
}
$commands[] = ajax_command_invoke('#coupon-pane input[type=checkbox]', 'attr', array(
'checked',
'true',
));
$commands[] = ajax_command_html('#coupon-messages', theme('status_messages'));
return array(
'#type' => 'ajax',
'#commands' => $commands,
);
}
function uc_checkout_pane_coupon_automatic($op, &$order, $form = NULL, &$form_state = NULL) {
if ($op == 'view') {
$discounts = _uc_coupon_options_list(uc_coupon_session_validate(), FALSE);
if (empty($discounts)) {
$inner_contents = array(
'#markup' => t('None.'),
);
}
else {
$inner_contents = array(
'#theme' => 'item_list',
'#items' => _uc_coupon_options_list(uc_coupon_session_validate(), FALSE),
);
}
return array(
'theme' => 'uc_coupon_automatic_discounts',
'contents' => array(
'discounts' => $inner_contents,
),
);
}
}
function uc_checkout_pane_coupon($op, &$order, $form = NULL, &$form_state = NULL) {
switch ($op) {
case 'prepare':
foreach ($order->products as $key => $product) {
if (isset($product->module) && $product->module == 'uc_coupon') {
unset($order->products[$key]);
}
}
break;
case 'view':
drupal_add_css('#coupon-messages { clear: both; }', array(
'type' => 'inline',
'group' => CSS_DEFAULT,
));
$ajax = array(
'callback' => 'uc_coupon_checkout_update',
);
$description = variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.'));
$contents = uc_coupon_form(array(), $form_state, 'checkout', $ajax);
$contents['message'] = array(
'#markup' => '<div id="coupon-messages"></div>',
'#weight' => 2,
);
return array(
'description' => $description,
'contents' => $contents,
'theme' => 'uc_coupon_form',
);
case 'process':
$trigger = $form_state['triggering_element']['#name'];
if (substr($trigger, 0, 9) == 'uc-coupon') {
$form_state['rebuild'] = TRUE;
uc_coupon_form_submit($form, $form_state);
uc_coupon_session_validate($order->products);
return FALSE;
}
else {
return TRUE;
}
case 'settings':
$form['uc_coupon_collapse_pane'] = array(
'#type' => 'checkbox',
'#title' => t('Collapse checkout pane by default.'),
'#default_value' => variable_get('uc_coupon_collapse_pane', FALSE),
);
$form['uc_coupon_pane_description'] = array(
'#type' => 'textarea',
'#title' => t('Checkout pane message'),
'#default_value' => variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.')),
);
return $form;
}
}
function uc_coupon_form_submit($form, $form_state) {
$trigger = $form_state['triggering_element']['#name'];
$values = isset($form_state['values']['panes']['coupon']) ? $form_state['values']['panes']['coupon'] : $form_state['values'];
if (substr($trigger, 0, 16) == 'uc-coupon-remove') {
$code = substr($trigger, 17);
if (!empty($code)) {
uc_coupon_session_clear($code);
drupal_set_message(t('Coupon "%code" has been removed from your order', array(
'%code' => $code,
)));
module_invoke_all('uc_coupon_remove', uc_coupon_find($code));
}
elseif (isset($values['coupons'])) {
$removed = array();
foreach ($values['coupons'] as $code => $selected) {
if (!$selected) {
$removed[] = $code;
uc_coupon_session_clear($code);
module_invoke_all('uc_coupon_remove', uc_coupon_find($code));
}
}
$n = count($removed);
if ($n > 1) {
$last = $removed[$n - 1];
$rest = implode(', ', array_slice($removed, 0, $n - 1));
drupal_set_message(t('Coupons %rest and %last have been removed from your order.', array(
'%rest' => $rest,
'%last' => $last,
)));
}
elseif (!empty($removed)) {
drupal_set_message(t('Coupon %code has been removed from your order', array(
'%code' => $removed[0],
)));
}
}
}
else {
$code = strtoupper(trim($values['code']));
$removed = FALSE;
if (!variable_get('uc_coupon_allow_multiple', FALSE) && count($session = uc_coupon_session_get()) > 0) {
foreach (array_keys($session) as $remove_code) {
uc_coupon_session_clear($remove_code);
drupal_set_message(t('Coupon "%code" has been removed from your order', array(
'%code' => $remove_code,
)));
module_invoke_all('uc_coupon_remove', uc_coupon_find($remove_code));
}
$removed = TRUE;
}
if (!empty($code)) {
uc_coupon_session_add($code, 'submit');
}
elseif (!$removed) {
drupal_set_message(t("You must enter a valid coupon code."), 'error');
}
}
}
function uc_coupon_uc_line_item() {
$items[] = array(
'id' => 'coupon',
'title' => t('Coupon discount'),
'tax_adjustment' => 'uc_coupon_tax_adjustment',
'weight' => 0,
'default' => FALSE,
'stored' => TRUE,
'add_list' => TRUE,
'calculated' => TRUE,
);
return $items;
}
function uc_coupon_tax_adjustment($price, $order, $tax) {
$amount = 0;
if (isset($order->data['coupons'])) {
foreach ($order->data['coupons'] as $discounts) {
foreach ($discounts as $nid => $item) {
$node = node_load($nid);
if (in_array($node->type, $tax->taxed_product_types) && ($tax->shippable == 0 || $node->shippable == 1)) {
$amount += (isset($item->pretax_discount) ? $item->pretax_discount : $item->discount) * ($price > 0 ? 1 : -1);
}
}
}
}
return $amount;
}
function _uc_coupon_paypal_check() {
if (variable_get('uc_payment_method_paypal_wps_checkout', 0) && variable_get('uc_paypal_wps_submit_method', 'single') == 'itemized') {
drupal_set_message(t('To use coupons with PayPal you must select "Submit the whole order as a single line item". <a href="!url">Click here to change this setting</a>.', array(
'!url' => url('admin/store/settings/payment/edit/methods'),
)));
}
}
function uc_coupon_uc_store_status() {
$statuses = array();
if (variable_get('uc_payment_method_paypal_wps_checkout', 0) && variable_get('uc_paypal_wps_submit_method', 'single') == 'itemized') {
$statuses[] = array(
'status' => 'warning',
'title' => t('Coupons'),
'desc' => t('To use coupons with PayPal you must select "Submit the whole order as a single line item". <a href="!url">Click here to change this setting</a>.', array(
'!url' => url('admin/store/settings/payment/edit/methods'),
)),
);
}
return $statuses;
}
function uc_coupon_uc_cart_alter(&$items) {
$coupons = uc_coupon_session_validate($items);
if (variable_get('uc_coupon_show_in_cart', TRUE) && !empty($coupons)) {
foreach ($coupons as $code => $coupon) {
$items[] = _uc_coupon_cart_item($coupon);
}
}
}
function _uc_coupon_cart_item($coupon) {
$id = -hexdec(substr(sha1($coupon->code), -8));
return (object) array(
'cart_item_id' => $id,
'module' => 'uc_coupon',
'title' => $coupon->title,
'nid' => 0,
'qty' => 1,
'price' => -$coupon->amount,
'data' => array(
'module' => 'uc_coupon',
'shippable' => FALSE,
'code' => $coupon->code,
'remove' => uc_coupon_session_get($coupon->code),
),
'model' => 0,
'weight' => 0,
);
}
function uc_coupon_uc_cart_display($item) {
$display_item = array(
'module' => array(
'#type' => 'value',
'#value' => 'uc_coupon',
),
'nid' => array(
'#type' => 'value',
'#value' => 0,
),
'title' => array(
'#markup' => $item->title,
),
'description' => array(
'#markup' => '',
),
'qty' => array(
'#type' => 'hidden',
'#value' => 1,
'#default_value' => 1,
),
'#total' => $item->price,
'data' => array(
'#type' => 'hidden',
'#value' => serialize($item->data),
),
'#suffixes' => array(),
);
if ($item->data['remove']) {
$display_item['remove'] = array(
'#type' => 'submit',
'#value' => t('Remove'),
);
}
return $display_item;
}
function uc_coupon_uc_update_cart_item($nid, $data, $qty) {
if (isset($data['code']) && $qty == 0) {
uc_coupon_session_clear($data['code']);
module_invoke_all('uc_coupon_remove', uc_coupon_find($data['code']));
}
}
function uc_coupon_theme_uc_cart_block_content($variables) {
if (variable_get('uc_coupon_show_in_cart', TRUE) && !empty($variables['items'])) {
foreach ($variables['items'] as &$item) {
if ($item['nid'] == 0 && $item['price'] <= 0) {
$item['qty'] = '';
$variables['item_count']--;
}
}
$variables['item_text'] = format_plural($variables['item_count'], '<span class="num-items">1</span> Item', '<span class="num-items">@count</span> Items');
}
return theme_uc_cart_block_content($variables);
}
function uc_coupon_form_uc_cart_checkout_form_alter(&$form, $form_state) {
if (variable_get('uc_coupon_collapse_pane', FALSE) && isset($form['panes']['coupon'])) {
$form['panes']['coupon']['#collapsed'] = TRUE;
}
if (variable_get('uc_coupon_show_in_cart', TRUE) && isset($form['panes']['cart'])) {
$coupons = uc_coupon_session_validate();
foreach ($coupons as $code => $coupon) {
$item = _uc_coupon_cart_item($coupon);
$item->order_product_id = $item->cart_item_id;
$form['panes']['cart']['cart_review_table']['#items'][] = $item;
}
}
}
function uc_coupon_uc_checkout_complete($order, $account) {
uc_coupon_session_clear();
}
function template_preprocess_uc_coupon_certificate(&$variables) {
$coupon = $variables['coupon'];
$variables['value'] = theme('uc_coupon_discount', array(
'coupon' => $coupon,
));
$variables['display_name'] = check_plain($coupon->name);
$n = stripos($variables['display_name'], 'purchased by');
if ($n) {
$variables['display_name'] = substr($variables['display_name'], 0, $n - 1);
}
if ($coupon->valid_until) {
$variables['not_yet_valid'] = $coupon->valid_from > REQUEST_TIME;
$variables['valid_from'] = format_date($coupon->valid_from, 'custom', variable_get('date_format_uc_store', 'm/d/Y'));
$variables['valid_until'] = format_date($coupon->valid_until, 'custom', variable_get('date_format_uc_store', 'm/d/Y'));
}
else {
$variables['not_yet_valid'] = FALSE;
$variables['valid_from'] = FALSE;
$variables['valid_until'] = FALSE;
}
$variables['max_uses_per_user'] = isset($coupon->data['max_uses_per_user']) ? $coupon->data['max_uses_per_user'] : NULL;
$variables['include'] = array();
$variables['exclude'] = array();
if (isset($coupon->data['product_types'])) {
foreach ($coupon->data['product_types'] as $type) {
$variables['include'][] = node_type_get_name($type);
}
}
if (isset($coupon->data['products'])) {
$key = isset($coupon->data['negate_products']) ? 'exclude' : 'include';
foreach ($coupon->data['products'] as $nid) {
$node = node_load($nid);
$variables[$key][] = $node->title;
}
}
if (isset($coupon->data['skus'])) {
foreach ($coupon->data['skus'] as $sku) {
$variables['include'][] = t('SKU') . ' ' . $sku;
}
}
if (isset($coupon->data['terms'])) {
$key = isset($coupon->data['negate_terms']) ? 'exclude' : 'include';
foreach ($coupon->data['terms'] as $tid) {
$term = taxonomy_term_load($tid);
$variables[$key][] = $term->name;
}
}
$info = token_info();
foreach ($info['types'] as $type => $type_info) {
if (empty($type_info['needs-data']) && $type != 'current-user' && $type != 'current-date') {
$type_key = !empty($type_info['type']) ? $type_info['type'] : $type;
if (!empty($info['tokens'][$type_key])) {
foreach (array_keys($info['tokens'][$type_key]) as $token) {
$variables[str_replace('-', '_', $type_key) . '_' . str_replace('-', '_', $token)] = token_replace("[{$type_key}:{$token}]");
}
}
}
}
if (isset($variables['coupon']->data['base_cid'])) {
$variables['theme_hook_suggestions'][] = 'uc_coupon_certificate__base_' . $variables['coupon']->data['base_cid'];
}
$variables['theme_hook_suggestions'][] = 'uc_coupon_certificate__' . $variables['coupon']->cid;
}
function template_preprocess_uc_coupon_page(&$variables) {
$variables['styles'] = drupal_get_css();
}
function uc_coupon_uc_coupon_actions($coupon) {
$actions = array();
if (user_access('view store coupons')) {
$actions[] = array(
'url' => 'admin/store/coupons/' . $coupon->cid,
'icon' => drupal_get_path('module', 'uc_store') . '/images/order_view.gif',
'title' => t('View coupon: @name', array(
'@name' => $coupon->name,
)),
);
$actions[] = array(
'url' => 'admin/store/coupons/' . $coupon->cid . '/print',
'icon' => drupal_get_path('module', 'uc_store') . '/images/print.gif',
'title' => t('Print coupon: @name', array(
'@name' => $coupon->name,
)),
);
if ($coupon->bulk) {
$actions[] = array(
'url' => 'admin/store/coupons/' . $coupon->cid . '/codes',
'icon' => drupal_get_path('module', 'uc_store') . '/images/menu_reports_small.gif',
'title' => t('Download codes as CSV: @name', array(
'@name' => $coupon->name,
)),
);
}
}
if (user_access('manage store coupons')) {
$actions[] = array(
'url' => 'admin/store/coupons/' . $coupon->cid . '/edit',
'icon' => drupal_get_path('module', 'uc_store') . '/images/order_edit.gif',
'title' => t('Edit coupon: @name', array(
'@name' => $coupon->name,
)),
);
$actions[] = array(
'url' => 'admin/store/coupons/' . $coupon->cid . '/delete',
'icon' => drupal_get_path('module', 'uc_store') . '/images/order_delete.gif',
'title' => t('Delete coupon: @name', array(
'@name' => $coupon->name,
)),
);
}
return $actions;
}
function uc_coupon_views_api() {
return array(
'api' => '2.0',
'path' => drupal_get_path('module', 'uc_coupon') . '/views',
);
}
function _uc_coupon_is_checkout_order($order) {
global $user;
return isset($_SESSION['cart_order']) && isset($order->order_id) && $order->order_id == $_SESSION['cart_order'] && uc_order_status_data($order->order_status, 'state') == 'in_checkout' && $user->uid == $order->uid;
}