View source
<?php
module_load_include('inc', 'uc_discounts', 'uc_discounts.ca');
define("QUALIFYING_TYPE_MINIMUM_PRICE", 1);
define("QUALIFYING_TYPE_MINIMUM_QUANTITY", 2);
define("DISCOUNT_TYPE_FREE_ITEMS", 1);
define("DISCOUNT_TYPE_PERCENTAGE_OFF", 2);
define("DISCOUNT_TYPE_FIXED_AMOUNT_OFF", 3);
define("DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM", 4);
define("DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM", 5);
define("FILTER_TYPE_NONE", 0);
define("FILTER_TYPE_PRODUCTS", 1);
define("FILTER_TYPE_TERMS", 2);
define("FILTER_TYPE_SKUS", 3);
define("FILTER_TYPE_CLASS", 4);
define("FILTER_TYPE_AUTHORS", 5);
define('DISCOUNT_FILTER_GROUPING_APPLICATION', 1);
define('DISCOUNT_FILTER_GROUPING_QUALIFICATION', 2);
define("ALL_PRODUCTS", "-1");
define("ALL_TERMS", "-1");
define("ALL_SKUS", "");
define("ALL_CLASSES", "");
define("ALL_ROLES", "-1");
define("ALL_AUTHORS", "-1");
define("IS_ACTIVE", TRUE);
define("LINE_ITEM_KEY_NAME", "uc_discounts");
define("LINE_ITEM_WEIGHT", 1);
define("CALCULATE_DISCOUNT_RESPONSE_LINE_ITEMS_KEY", "line_items");
define("CALCULATE_DISCOUNT_RESPONSE_ERRORS_KEY", "errors");
define("CALCULATE_DISCOUNT_RESPONSE_MESSAGES_KEY", "messages");
function uc_discounts_init() {
drupal_add_css(drupal_get_path('module', 'uc_discounts') . '/uc_discounts.css');
if (isset($_SESSION['uc_discounts_after_add_to_cart'])) {
$nid = $_SESSION['uc_discounts_after_add_to_cart']['nid'];
$added_qty = $_SESSION['uc_discounts_after_add_to_cart']['qty'];
unset($_SESSION['uc_discounts_after_add_to_cart']);
$items_to_add = $new_product_ids = array();
$product = node_load($nid);
$result = db_query("SELECT * FROM {uc_discounts} d\n WHERE d.add_to_cart = 1\n AND (d.has_activation = 0 OR d.activates_on < %d)\n AND (d.has_expiration = 0 OR d.expiration > %d)\n AND d.is_active = 1\n AND d.discount_type = %d\n ORDER BY weight", time(), time(), DISCOUNT_TYPE_FREE_ITEMS);
while ($discount = db_fetch_object($result)) {
if (in_array($product->nid, get_product_ids_for_discount_object($discount, DISCOUNT_FILTER_GROUPING_QUALIFICATION, TRUE))) {
$new_product_ids = get_product_ids_for_discount_object($discount, DISCOUNT_FILTER_GROUPING_APPLICATION, TRUE);
break;
}
}
if (!empty($new_product_ids)) {
foreach ($new_product_ids as $id) {
$potential_product = node_load($id);
$items = uc_cart_get_contents();
$qty = 0;
$source_qty = 0;
foreach ($items as $item) {
if ($item->nid == $potential_product->nid) {
$qty += $item->qty;
}
if ($item->nid == $product->nid) {
$source_qty += $item->qty;
}
}
$target_qty = $discount->discount_amount;
$qualifying_amount = $discount->qualifying_amount;
$times_applied = floor($qty / $target_qty);
$times_to_apply = $target_qty / $qualifying_amount * $added_qty / $target_qty;
if ($times_applied < $discount->max_times_applied || $discount->max_times_applied == 0) {
$to_add = $target_qty * ($discount->max_times_applied ? min($discount->max_times_applied - $times_applied, $times_to_apply) : $times_to_apply);
}
if ($to_add > 0) {
$items_to_add[] = array(
'nid' => $potential_product->nid,
'qty' => $to_add,
'data' => array(),
);
}
}
}
foreach ($items_to_add as $p) {
uc_cart_add_item($p['nid'], $p['qty'], $p['data'] + module_invoke_all('add_to_cart_data', $p), NULL, FALSE, FALSE, FALSE);
}
}
}
function uc_discounts_perm() {
return array(
'configure discounts',
);
}
function uc_discounts_menu() {
$items = array();
$items['admin/store/uc_discounts'] = array(
'title' => 'Discounts',
'description' => 'Add and review discounts.',
'page callback' => 'uc_discounts_admin_list',
'access arguments' => array(
'configure discounts',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'uc_discounts.admin.inc',
);
$items['admin/store/uc_discounts/list'] = array(
'title' => 'List',
'description' => 'View list of discounts.',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
);
$items['admin/store/uc_discounts/add'] = array(
'title' => 'Add discount',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_discounts_form',
),
'access arguments' => array(
'configure discounts',
),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
'file' => 'uc_discounts.admin.inc',
);
$items['admin/store/uc_discounts/edit/%'] = array(
'title' => 'Edit discount rule',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_discounts_form',
4,
),
'access arguments' => array(
'configure discounts',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
);
$items['admin/store/uc_discounts/copy/%'] = array(
'page callback' => 'uc_discounts_copy',
'page arguments' => array(
4,
),
'access arguments' => array(
'configure discounts',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
);
$items['admin/store/uc_discounts/delete/%'] = array(
'title' => 'Delete discount rule',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_discounts_delete',
4,
),
'access arguments' => array(
'configure discounts',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
);
$items['admin/store/uc_discounts/generate_codes/%'] = array(
'title' => 'Generate codes',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_discounts_generate_codes_form',
4,
),
'access arguments' => array(
'configure discounts',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
'weight' => 2,
);
$items['cart/checkout/uc_discounts/calculate'] = array(
'page callback' => 'uc_discounts_js_calculate',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['admin/reports/uc_discounts/all'] = array(
'title' => 'Ubercart discounts usage data',
'description' => 'View usage data for each Ubercart discount.',
'page callback' => 'uc_discounts_report',
'access arguments' => array(
'access site reports',
),
'file' => 'uc_discounts.admin.inc',
);
$items['admin/reports/uc_discounts/all/download'] = array(
'title' => 'Download Ubercart discounts usage data',
'description' => 'Download usage data for each Ubercart discount.',
'page callback' => 'uc_discounts_report',
'access arguments' => array(
'access site reports',
),
'file' => 'uc_discounts.admin.inc',
'type' => MENU_CALLBACK,
);
$items['admin/reports/uc_discounts/discount'] = array(
'title' => 'Ubercart discount usage data',
'page callback' => 'uc_discounts_report_for_discount',
'access arguments' => array(
'access site reports',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
);
return $items;
}
function uc_discounts_order($op, &$arg1, $arg2) {
switch ($op) {
case 'load':
$arg1->uc_discounts_codes = uc_discounts_get_codes_for_order($arg1->order_id);
break;
case 'save':
if ($arg1->uc_discounts_line_items_need_updating) {
uc_discounts_order_codes_delete($arg1->order_id);
$codes_string = uc_discounts_codes_to_str($arg1->uc_discounts_codes);
$new_discount_order_code = array(
'order_id' => $arg1->order_id,
'codes' => $codes_string,
);
drupal_write_record('uc_discounts_order_codes', $new_discount_order_code);
if (is_array($arg1->line_items)) {
$existing_line_items = $arg1->line_items;
}
else {
$existing_line_items = uc_order_load_line_items($arg1, TRUE);
}
$new_order_line_items = array();
foreach ($existing_line_items as $line_item) {
if ($line_item["type"] == LINE_ITEM_KEY_NAME) {
uc_order_delete_line_item($line_item["line_item_id"]);
}
else {
$new_order_line_items[] = $line_item;
}
}
foreach ($arg1->uc_discounts_line_items as $line_item) {
if ($line_item['amount'] != 0) {
uc_order_line_item_add($arg1->order_id, $line_item['type'], $line_item['title'], $line_item['amount'], $line_item['weight'], $line_item['data']);
$new_order_line_items[] = $line_item;
}
}
$arg1->line_items = $new_order_line_items;
$arg1->uc_discounts_line_items_need_updating = FALSE;
}
break;
case 'update':
if ($arg2 == "cancelled") {
uc_discounts_uses_delete_for_order($arg1->order_id);
}
break;
case 'submit':
$result = uc_discounts_apply($arg1, FALSE);
if (!$result['success']) {
return array(
array(
'pass' => FALSE,
'message' => $result['message'],
),
);
}
break;
case 'delete':
uc_discounts_order_codes_delete($arg1->order_id);
break;
}
}
function uc_discounts_uc_checkout_complete($order, $account) {
uc_discounts_uses_save_for_order($order);
unset($_SESSION['uc_discounts_codes']);
}
function uc_discounts_add_to_cart($nid, $qty, $data) {
$_SESSION['uc_discounts_after_add_to_cart'] = array(
'nid' => $nid,
'qty' => $qty,
);
}
function uc_discounts_line_item() {
$line_items[] = array(
"id" => LINE_ITEM_KEY_NAME,
"title" => t("Discount"),
"weight" => LINE_ITEM_WEIGHT,
"stored" => TRUE,
"calculated" => TRUE,
"display_only" => FALSE,
);
return $line_items;
}
function uc_discounts_order_pane() {
$panes[] = array(
'id' => 'uc_discounts',
'callback' => 'uc_discounts_order_pane_callback',
'title' => t('Discount codes'),
'weight' => 8,
'show' => array(
'edit',
),
);
return $panes;
}
function uc_discounts_order_pane_callback($op, $arg1) {
switch ($op) {
case 'edit-form':
$form['uc-discounts']['uc-discounts-codes'] = array(
'#type' => 'textarea',
'#rows' => 3,
);
$form['uc-discounts']['uc-discounts-button'] = array(
'#type' => 'submit',
'#value' => t('Apply discounts'),
);
return $form;
case 'edit-theme':
$form_rendered = drupal_render($arg1['uc-discounts']);
return $form_rendered;
case 'edit-ops':
return array(
t('Apply discounts'),
);
case t('Apply discounts'):
if ($order = uc_order_load($arg1['order_id'])) {
$order->uc_discounts_codes = array_merge($order->uc_discounts_codes, uc_discounts_codes_to_array($arg1['uc-discounts-codes']));
$result = uc_discounts_apply($order, TRUE, FALSE);
drupal_set_message($result['message'], $result['success'] ? 'notice' : 'error');
}
break;
}
}
function uc_discounts_cart_pane($items) {
$panes[] = array(
'id' => 'uc_discounts_pane',
'title' => t('Discounts'),
'enabled' => TRUE,
'weight' => 1,
'body' => !is_null($items) ? uc_discounts_cart_pane_output($items) : '',
);
return $panes;
}
function uc_discounts_cart_pane_output($items) {
global $user;
$order = new stdClass();
$order->uid = $user->uid;
$order->products = $items;
$errors = array();
$warnings = array();
$messages = array();
$discounts = get_discounts_for_order($order, $errors, $warnings, $messages);
if (count($discounts) == 0) {
return '';
}
$subtotal = 0;
if (is_array($items)) {
foreach ($items as $item) {
$subtotal += $item->price * $item->qty;
}
}
$total_discount_amount = 0;
if (is_array($discounts)) {
foreach ($discounts as $discount) {
$total_discount_amount += $discount->amount;
}
}
$subtotal_including_discounts = $subtotal - $total_discount_amount;
$messages[] = "<strong>" . t("Total discount") . ":</strong> " . uc_currency_format($total_discount_amount);
$messages[] = "<strong>" . t("Subtotal including discounts") . ":</strong> " . uc_currency_format($subtotal_including_discounts);
$i = count($items) + 2;
$body = "<div class='uc-discounts-cart-pane-container'><table class='uc-discounts-cart-pane-table'>";
foreach ($messages as $message) {
$evenOddClass = $i % 2 == 0 ? "even" : "odd";
$body .= sprintf("<tr class='%s'><td class='%s'>", $evenOddClass, "uc-discounts-cart-pane-table-cell") . $message . "</td></tr>";
$i += 1;
}
$body .= "</table></div>";
drupal_add_js(sprintf('$(document).ready(function() { $("#cart-form-buttons").before("%s"); });', $body), 'inline');
}
function uc_discounts_checkout_pane() {
$panes[] = array(
"id" => "uc_discounts",
"callback" => "uc_checkout_pane_discounts",
'process' => TRUE,
"title" => t("Enter discount codes"),
"weight" => 5,
);
return $panes;
}
function uc_discounts_form_uc_cart_checkout_form_alter(&$form, $form_state) {
drupal_add_js(array(
'uc_discounts' => array(
'url' => url('cart/checkout/uc_discounts/calculate'),
'line_item_key_name' => LINE_ITEM_KEY_NAME,
'line_item_weight' => LINE_ITEM_WEIGHT,
'total_discount_text' => t('Total discount'),
'calculate_discount_response_line_items_key' => CALCULATE_DISCOUNT_RESPONSE_LINE_ITEMS_KEY,
'calculate_discount_response_errors_key' => CALCULATE_DISCOUNT_RESPONSE_ERRORS_KEY,
'calculate_discount_response_messages_key' => CALCULATE_DISCOUNT_RESPONSE_MESSAGES_KEY,
'progress_msg' => t('Calculating discounts...'),
'no_codes_entered' => t('Please enter at least one code'),
'no_applicable_discounts' => t('No applicable discounts'),
'err_msg' => t('There were problems determining if any discounts apply. Please try again shortly.\\nIf this does not resolve the issue, please call @phone to complete your order.', array(
'@phone' => variable_get('uc_store_phone', NULL),
)),
'response_parse_err_msg' => t('Unable to parse response text: '),
),
), 'setting');
drupal_add_js('$(document).ready(function(e) { uc_discountsOnLoad(e); });', 'inline');
drupal_add_js('misc/progress.js');
drupal_add_js(drupal_get_path('module', 'uc_discounts') . '/uc_discounts.js');
}
function uc_checkout_pane_discounts($op, &$arg1, $arg2) {
global $user;
switch ($op) {
case "view":
$description = t("Enter discount codes in the box below (one per line).");
if (!empty($arg1->order_id)) {
$codes_string = uc_discounts_codes_to_str(uc_discounts_get_codes_for_order($arg1->order_id));
}
$contents["uc-discounts-codes"] = array(
"#type" => "textarea",
"#default_value" => $codes_string,
"#rows" => 5,
"#prefix" => "<div class='discount-codes-wrapper'>",
"#suffix" => "</div>",
);
$contents["uc-discounts-placeholder"] = array(
"#type" => "hidden",
"#prefix" => "<div class='uc-discounts-messages-container'>",
"#suffix" => "</div>",
);
$contents["uc-discounts-button"] = array(
"#type" => "button",
"#value" => t("Click to calculate discounts"),
);
return array(
"description" => $description,
"contents" => $contents,
);
case "process":
$arg1->uc_discounts_codes = uc_discounts_codes_to_array($arg2['uc-discounts-codes']);
drupal_alter('uc_discounts_codes', $arg1, 'pane_submit');
$has_code_errors = FALSE;
$errors = array();
$warnings = array();
$discounts = get_discounts_for_order($arg1, $errors, $warnings);
$applied_codes = array();
foreach ($discounts as $discount) {
$applied_codes[] = $discount->code;
}
$arg1->uc_discounts_codes = $applied_codes;
foreach ($errors as $error) {
drupal_set_message($error, "error");
}
foreach ($warnings as $warning) {
drupal_set_message(t('Warning: @warning', array(
'@warning' => $warning,
)), 'error');
}
if (!empty($errors)) {
return FALSE;
}
add_discount_line_items_to_order($arg1, $discounts);
$arg1->uc_discounts_line_items_need_updating = TRUE;
break;
}
}
function add_discount_line_items_to_order(&$order, $discounts) {
$line_items = array();
foreach ($discounts as $discount) {
$line_item = array(
'type' => LINE_ITEM_KEY_NAME,
'title' => $discount->short_description,
'amount' => -$discount->amount,
'weight' => LINE_ITEM_WEIGHT,
'data' => array(
'discount_id' => $discount->discount_id,
),
);
$line_items[] = $line_item;
}
$order->uc_discounts_line_items = $line_items;
}
function uc_discounts_js_calculate() {
global $user;
if (!empty($_SESSION["cart_order"])) {
$order_id = $_SESSION['cart_order'];
$order = uc_order_load($order_id);
if (is_null($order)) {
print '{}';
exit;
}
}
else {
$order = new stdClass();
$order->uid = $user->uid;
$order->products = uc_cart_get_contents();
}
$order->uc_discounts_codes = uc_discounts_codes_to_array($_POST['uc-discounts-codes']);
drupal_alter('uc_discounts_codes', $order, 'js_calculate');
$line_items = array();
$errors = array();
$warnings = array();
$messages = array();
$discounts = get_discounts_for_order($order, $errors, $warnings, $messages);
$i = 0;
$_SESSION['uc_discounts_codes'] = $order->uc_discounts_codes;
foreach ($discounts as $discount) {
if ($discount->amount != 0) {
$line_item = array();
$line_item["id"] = LINE_ITEM_KEY_NAME . $i++;
$line_item["type"] = $discount->type;
$line_item["title"] = $discount->title;
$line_item["amount"] = -$discount->amount;
$line_item["weight"] = $discount->weight;
$line_items[] = $line_item;
}
}
if (!empty($warnings)) {
$warnings2 = array();
foreach ($warnings as $warning) {
$warnings2[] = t('Warning: @warning', array(
'@warning' => $warning,
));
}
$errors = array_merge($errors, $warnings2);
}
$calculate_discount_response = array(
CALCULATE_DISCOUNT_RESPONSE_LINE_ITEMS_KEY => $line_items,
CALCULATE_DISCOUNT_RESPONSE_ERRORS_KEY => $errors,
CALCULATE_DISCOUNT_RESPONSE_MESSAGES_KEY => $messages,
);
drupal_json($calculate_discount_response);
exit;
}
function uc_discounts_theme() {
return array(
'uc_discounts_cart_checkout_table' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
function uc_discounts_checkout_pane_alter(&$panes) {
foreach ($panes as &$pane) {
if ($pane['id'] == 'cart') {
$pane['callback'] = 'uc_discounts_checkout_pane_content';
}
}
}
function uc_discounts_checkout_pane_content($op) {
switch ($op) {
case 'view':
$contents['cart_review_table'] = array(
'#value' => theme('uc_discounts_cart_checkout_table'),
'#weight' => variable_get('uc_pane_cart_field_cart_weight', 2),
);
return array(
'contents' => $contents,
'next-button' => FALSE,
);
case 'review':
$discount_amount = uc_discounts_get_discount_amount_for_order($op);
$items = uc_cart_get_contents();
$output = '<table>';
$context = array(
'revision' => 'themed',
'type' => 'cart_item',
'subject' => array(),
);
$total = 0;
foreach ($items as $item) {
$total += $item->price * $item->qty;
$desc = check_plain($item->title) . uc_product_get_description($item);
$price_info = array(
'price' => $item->price,
'qty' => $item->qty,
);
$context['subject'] = array(
'cart' => $items,
'cart_item' => $item,
'node' => node_load($item->nid),
);
$output .= '<tr valign="top"><td>' . $item->qty . '×</td><td width="100%">' . $desc . '</td><td nowrap="nowrap">' . uc_price($price_info, $context) . '</td></tr>';
}
if ($discount_amount > 0) {
$final_price = $total - $discount_amount;
$output .= '<tr valign="top"><td colspan="2"><strong>' . t('Discount') . ': </strong></td><td nowrap="nowrap">' . uc_price($discount_amount, $context) . '</td></tr>';
$output .= '<tr valign="top"><td colspan="2"><strong>' . t('Total') . ': </strong></td><td nowrap="nowrap"><b>' . uc_price($final_price, $context) . '</b></td></tr>';
}
$output .= '</table>';
$review[] = $output;
return $review;
}
}
function theme_uc_discounts_cart_checkout_table($show_subtotal = TRUE) {
$subtotal = 0;
$discount_amount = uc_discounts_get_discount_amount_for_order('checkout');
$header = array(
array(
'data' => t('Qty'),
'class' => 'qty',
),
array(
'data' => t('Products'),
'class' => 'products',
),
array(
'data' => t('Price'),
'class' => 'price',
),
);
$context = array();
$contents = uc_cart_get_contents();
foreach ($contents as $item) {
$price_info = array(
'price' => $item->price,
'qty' => $item->qty,
);
$context['revision'] = 'altered';
$context['type'] = 'cart_item';
$context['subject'] = array(
'cart' => $contents,
'cart_item' => $item * $discount_amount,
'node' => node_load($item->nid),
);
$total = uc_price($price_info, $context);
$subtotal += $total;
$description = check_plain($item->title) . uc_product_get_description($item);
$context['revision'] = 'themed-original';
$context['type'] = 'amount';
unset($context['subject']);
$rows[] = array(
array(
'data' => t('@qty×', array(
'@qty' => $item->qty,
)),
'class' => 'qty',
),
array(
'data' => $description,
'class' => 'products',
),
array(
'data' => uc_price($total, $context),
'class' => 'price',
),
);
}
if ($discount_amount > 0) {
$rows[] = array(
array(
'data' => '',
),
array(
'data' => t('Discount:'),
'align' => 'right',
),
array(
'data' => uc_price($discount_amount, $context),
'class' => 'price',
),
);
$subtotal = $subtotal - $discount_amount;
}
if ($show_subtotal) {
$context = array(
'revision' => 'themed-original',
'type' => 'amount',
);
$rows[] = array(
'data' => array(
array(
'data' => '<span id="subtotal-title">' . t('Subtotal:') . '</span> ' . uc_price($subtotal, $context),
'colspan' => 3,
'class' => 'subtotal',
),
),
'class' => 'subtotal',
);
}
return theme('table', $header, $rows, array(
'class' => 'cart-review',
));
}
function uc_discounts_delete_all($discount) {
foreach (module_implements('uc_discount') as $module) {
$function = $module . '_uc_discount';
$function('delete', $discount);
}
db_query("DELETE FROM {uc_discounts_uses} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts_products} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts_terms} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts_skus} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts_roles} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts_codes} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts_authors} WHERE discount_id=%d", $discount->discount_id);
db_query("DELETE FROM {uc_discounts} WHERE discount_id=%d", $discount->discount_id);
}
function uc_discounts_load($discount_id) {
$discount = db_fetch_object(db_query("SELECT * FROM {uc_discounts} WHERE discount_id=%d", $discount_id));
foreach (module_implements('uc_discount') as $module) {
$function = $module . '_uc_discount';
$function('load', $discount);
}
return $discount;
}
function get_codes_for_discount($discount_id) {
$codes = array();
$result = db_query('SELECT code FROM {uc_discounts_codes} WHERE discount_id = %d', $discount_id);
while ($row = db_fetch_array($result)) {
$codes[] = $row['code'];
}
return $codes;
}
function uc_discounts_codes_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_codes} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function get_product_ids_for_discount_object($discount, $grouping = DISCOUNT_FILTER_GROUPING_APPLICATION, $exclude_all_products = FALSE) {
$filter = $grouping == DISCOUNT_FILTER_GROUPING_APPLICATION ? $discount->filter_type : $discount->required_product_type;
switch ($filter) {
case FILTER_TYPE_PRODUCTS:
return get_product_ids_for_discount($discount->discount_id, $grouping, $exclude_all_products);
case FILTER_TYPE_TERMS:
$product_ids = array();
$terms = get_term_ids_for_discount($discount->discount_id, $grouping, $exclude_all_products);
$query = 'SELECT DISTINCT p.nid FROM {uc_products} p';
if (!empty($terms)) {
$query .= ' INNER JOIN {term_node} tn ON p.nid=tn.nid
INNER JOIN {uc_discounts_terms} dt ON tn.tid=dt.term_id
WHERE dt.discount_id=%d';
}
$result = db_query($query, $discount->discount_id);
while ($row = db_fetch_object($result)) {
$product_ids[] = $row->nid;
}
return $product_ids;
case FILTER_TYPE_SKUS:
$skus = get_skus_for_discount($discount->discount_id, $grouping, $exclude_all_products);
$query = 'SELECT DISTINCT p.nid FROM {uc_products} p';
if (!empty($skus)) {
$query .= ' INNER JOIN {uc_discounts_skus} ds ON p.model=ds.sku
WHERE ds.discount_id=%d';
}
$result = db_query($query, $discount->discount_id);
while ($row = db_fetch_object($result)) {
$product_ids[] = $row->nid;
}
return $product_ids;
case FILTER_TYPE_CLASS:
$classes = get_classes_for_discount($discount->discount_id, $grouping, $exclude_all_products);
$query = 'SELECT DISTINCT n.nid FROM {node} n';
if (!empty($classes)) {
$query .= ' INNER JOIN {uc_discounts_classes} dcl ON n.type=dcl.class
WHERE dcl.discount_id=%d';
}
$result = db_query($query, $discount->discount_id);
while ($row = db_fetch_object($result)) {
$product_ids[] = $row->nid;
}
return $product_ids;
case FILTER_TYPE_AUTHORS:
$authors = get_author_ids_for_discount($discount->discount_id, $grouping, $exclude_all_products);
$query = 'SELECT DISTINCT n.nid FROM {node} n';
if (!empty($authors)) {
$query .= ' INNER JOIN {uc_discounts_authors} dau ON n.uid=dau.author_id
WHERE dau.discount_id=%d';
}
$result = db_query($query, $discount->discount_id);
while ($row = db_fetch_object($result)) {
$product_ids[] = $row->nid;
}
return $product_ids;
}
return array();
}
function get_product_ids_for_discount($discount_id, $grouping, $exclude_all_products = FALSE) {
$query = "SELECT product_id FROM {uc_discounts_products} WHERE discount_id = %d AND grouping = %d";
$args = array(
$discount_id,
$grouping,
);
if ($exclude_all_products) {
$query .= ' AND product_id <> %d';
$args[] = ALL_PRODUCTS;
}
$result = db_query($query, $args);
$ids = array();
while ($row = db_fetch_array($result)) {
$ids[] = $row["product_id"];
}
return $ids;
}
function get_term_ids_for_discount($discount_id, $grouping, $exclude_all_terms = FALSE) {
$query = "SELECT term_id FROM {uc_discounts_terms} WHERE discount_id = %d AND grouping = %d";
$args = array(
$discount_id,
$grouping,
);
if ($exclude_all_products) {
$query .= ' AND term_id <> %d';
$args[] = ALL_TERMS;
}
$result = db_query($query, $args);
$ids = array();
while ($row = db_fetch_array($result)) {
$ids[] = $row["term_id"];
}
return $ids;
}
function get_skus_for_discount($discount_id, $grouping, $exclude_all_skus = FALSE) {
$query = "SELECT sku FROM {uc_discounts_skus} WHERE discount_id = %d AND grouping = %d";
$args = array(
$discount_id,
$grouping,
);
if ($exclude_all_products) {
$query .= ' AND sku <> "%s"';
$args[] = ALL_SKUS;
}
$result = db_query($query, $args);
$ids = array();
while ($row = db_fetch_array($result)) {
$ids[] = $row["sku"];
}
return $ids;
}
function get_classes_for_discount($discount_id, $grouping, $exclude_all_classes = FALSE) {
$query = "SELECT class FROM {uc_discounts_classes} WHERE discount_id = %d AND grouping = %d";
$args = array(
$discount_id,
$grouping,
);
if ($exclude_all_products) {
$query .= ' AND class <> "%s"';
$args[] = ALL_CLASSES;
}
$result = db_query($query, $args);
$ids = array();
while ($row = db_fetch_array($result)) {
$ids[] = $row["class"];
}
return $ids;
}
function get_author_ids_for_discount($discount_id, $grouping, $exclude_all_authors = FALSE) {
$query = "SELECT author_id FROM {uc_discounts_authors} WHERE discount_id = %d AND grouping = %d";
$args = array(
$discount_id,
$grouping,
);
if ($exclude_all_products) {
$query .= ' AND author_id <> %d';
$args[] = ALL_AUTHORS;
}
$result = db_query($query, $args);
$ids = array();
while ($row = db_fetch_array($result)) {
$ids[] = $row["author_id"];
}
return $ids;
}
function get_role_ids_for_discount($discount_id, $exclude_all_roles = FALSE) {
$query = "SELECT role_id FROM {uc_discounts_roles} WHERE discount_id = %d";
$args = array(
$discount_id,
);
if ($exclude_all_products) {
$query .= ' AND role_id <> %d';
$args[] = ALL_ROLES;
}
$result = db_query($query, $args);
$ids = array();
while ($row = db_fetch_array($result)) {
$ids[] = $row["role_id"];
}
return $ids;
}
function uc_discounts_products_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_products} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function uc_discounts_terms_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_terms} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function uc_discounts_skus_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_skus} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function uc_discounts_classes_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_classes} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function uc_discounts_authors_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_authors} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function uc_discounts_roles_delete($discount_id) {
$query = "DELETE FROM {uc_discounts_roles} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function get_discounts_for_order($order, &$errors = NULL, &$warnings = NULL, &$messages = NULL) {
$order_product_id_subtotal_map = array();
$order_product_id_quantity_map = array();
$order_product_ids = array();
$order_product_ids_set = array();
$order_product_id_product_array_map = array();
$order_subtotal = 0;
if (is_array($order->products) && !empty($order->products)) {
foreach ($order->products as $product) {
$nid = $product->nid;
$order_product_ids_set[$nid] = TRUE;
if (is_array($product->data) && !empty($product->data['kit_id'])) {
$kit_id = $product->data['kit_id'];
$order_product_ids_set[$kit_id] = TRUE;
$kits[$kit_id]['product_qty'] += $product->qty;
}
uc_discounts_add_to_existing_map_number_value($order_product_id_subtotal_map, $nid, $product->price * $product->qty);
uc_discounts_add_to_existing_map_number_value($order_product_id_quantity_map, $nid, $product->qty);
$a = $order_product_id_product_array_map[$nid];
if (!is_array($a)) {
$a = array();
}
$a[] = $product;
$order_product_id_product_array_map[$nid] = $a;
$order_subtotal += $product->price * $product->qty;
}
if (is_array($kits) && !empty($kits)) {
foreach ($kits as $kit_id => $value) {
$kit_node = node_load($kit_id);
foreach ($kit_node->products as $product_in_kit) {
$pik_nid = $product_in_kit->nid;
foreach ($order->products as $key => $product) {
if ($product->nid == $pik_nid && $product->data['kit_id'] == $kit_id) {
$kits[$kit_id]['kit_qty'] = $product->qty / $product_in_kit->qty;
break;
}
}
}
uc_discounts_add_to_existing_map_number_value($order_product_id_quantity_map, $kit_id, $kits[$kit_id]['kit_qty']);
}
}
}
$order_product_ids = array_keys($order_product_ids_set);
$temp_product_ids = $order_product_ids;
$temp_product_ids[] = ALL_PRODUCTS;
$product_ids_clause = sprintf("d.filter_type<>%d OR dp.product_id IN(%s)", FILTER_TYPE_PRODUCTS, join(",", $temp_product_ids));
$temp_term_ids = array();
$temp_term_ids[] = ALL_TERMS;
if (is_array($order->products) && !empty($order->products)) {
$result = db_query("SELECT DISTINCT tid FROM {term_node} WHERE nid IN(%s)", join(",", $order_product_ids));
while ($row = db_fetch_array($result)) {
$temp_term_ids[] = $row["tid"];
$order_term_ids[] = $row["tid"];
}
}
$term_ids_clause = sprintf("d.filter_type<>%d OR dt.term_id IN(%s)", FILTER_TYPE_TERMS, join(",", $temp_term_ids));
$temp_skus = array();
$temp_skus[] = "'" . db_escape_string(ALL_SKUS) . "'";
if (is_array($order->products) && !empty($order->products)) {
$result = db_query("SELECT DISTINCT model FROM {uc_products} WHERE nid IN(%s)", join(",", $order_product_ids));
while ($row = db_fetch_array($result)) {
$temp_skus[] = "'" . db_escape_string($row["model"]) . "'";
}
}
$skus_clause = sprintf("d.filter_type<>%d OR ds.sku IN(%s)", FILTER_TYPE_SKUS, join(",", $temp_skus));
$temp_classes = array();
$temp_classes[] = "'" . db_escape_string(ALL_CLASSES) . "'";
if (is_array($order->products) && !empty($order->products)) {
$result = db_query("SELECT DISTINCT type FROM {node} WHERE nid IN(%s)", join(",", $order_product_ids));
while ($row = db_fetch_array($result)) {
$temp_classes[] = "'" . db_escape_string($row["type"]) . "'";
}
}
$classes_clause = sprintf("d.filter_type<>%d OR dcl.class IN(%s)", FILTER_TYPE_CLASS, join(",", $temp_classes));
$temp_authors = array();
$temp_authors[] = "'" . db_escape_string(ALL_AUTHORS) . "'";
if (is_array($order->products) && !empty($order->products)) {
$result = db_query("SELECT DISTINCT uid FROM {node} WHERE nid IN(%s)", join(",", $order_product_ids));
while ($row = db_fetch_array($result)) {
$temp_authors[] = "'" . db_escape_string($row["uid"]) . "'";
}
}
$authors_clause = sprintf("d.filter_type<>%d OR dau.author_id IN(%s)", FILTER_TYPE_AUTHORS, join(",", $temp_authors));
$escaped_codes_string = NULL;
if (!empty($order->uc_discounts_codes)) {
$escaped_codes = array();
foreach ($order->uc_discounts_codes as $code) {
$escaped_codes[] = "'" . db_escape_string($code) . "'";
}
$escaped_codes_string = join(",", $escaped_codes);
$codes_clause = sprintf(" OR d.discount_id IN( SELECT discount_id FROM {uc_discounts_codes} WHERE code IN(%s) )", $escaped_codes_string);
}
else {
$codes_clause = "";
}
$auth_rid = $order->uid != 0 ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
$roles_clause = sprintf(" OR d.discount_id IN(SELECT dr.discount_id FROM {uc_discounts_roles} dr LEFT JOIN {users_roles} ur ON (dr.role_id=ur.rid AND ur.uid=%d) WHERE ur.uid IS NOT NULL OR dr.role_id=%d OR dr.role_id=%d)", $order->uid, ALL_ROLES, $auth_rid);
$grouping = DISCOUNT_FILTER_GROUPING_APPLICATION;
if (!empty($order->uc_discounts_codes)) {
$query = sprintf("SELECT DISTINCT d.*, dc.code code FROM {uc_discounts} d\n LEFT JOIN {uc_discounts_products} dp ON d.discount_id=dp.discount_id AND dp.grouping = {$grouping}\n LEFT JOIN {uc_discounts_terms} dt ON d.discount_id=dt.discount_id AND dt.grouping = {$grouping}\n LEFT JOIN {uc_discounts_skus} ds ON d.discount_id=ds.discount_id AND ds.grouping = {$grouping}\n LEFT JOIN {uc_discounts_classes} dcl ON d.discount_id=dcl.discount_id AND dcl.grouping = {$grouping}\n LEFT JOIN {uc_discounts_authors} dau ON d.discount_id=dau.discount_id AND dau.grouping = {$grouping}\n LEFT JOIN {uc_discounts_roles} dr ON d.discount_id=dr.discount_id\n LEFT JOIN {uc_discounts_codes} dc ON d.discount_id=dc.discount_id\n WHERE dc.code IN(%s)\n AND (d.has_role_filter=0%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (d.has_expiration<>0 AND d.expiration<=%d)\n AND (d.is_active=%d)\n ORDER BY weight", $escaped_codes_string, $roles_clause, $product_ids_clause, $term_ids_clause, $skus_clause, $classes_clause, $authors_clause, time(), IS_ACTIVE);
$result = db_query($query);
while ($discount = db_fetch_object($result)) {
$warnings[] = t('The discount for code "@code" has expired.', array(
"@code" => $discount->code,
));
}
}
$query = sprintf("SELECT DISTINCT d.* FROM {uc_discounts} d\n LEFT JOIN {uc_discounts_products} dp ON d.discount_id=dp.discount_id AND dp.grouping = {$grouping}\n LEFT JOIN {uc_discounts_terms} dt ON d.discount_id=dt.discount_id AND dt.grouping = {$grouping}\n LEFT JOIN {uc_discounts_skus} ds ON d.discount_id=ds.discount_id AND ds.grouping = {$grouping}\n LEFT JOIN {uc_discounts_classes} dcl ON d.discount_id=dcl.discount_id AND dcl.grouping = {$grouping}\n LEFT JOIN {uc_discounts_authors} dau ON d.discount_id=dau.discount_id AND dau.grouping = {$grouping}\n WHERE (d.requires_code=0%s)\n AND (d.has_role_filter=0%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (d.has_activation=0 OR d.activates_on<%d)\n AND (d.has_expiration=0 OR d.expiration>%d)\n AND (d.is_active=%d)\n ORDER BY weight", $codes_clause, $roles_clause, $product_ids_clause, $term_ids_clause, $skus_clause, $classes_clause, $authors_clause, time(), time(), IS_ACTIVE);
$result = db_query($query);
$total_discount_amount = 0;
$discounts = array();
while ($discount = db_fetch_object($result)) {
foreach (module_implements('uc_discount') as $module) {
$function = $module . '_uc_discount';
$function('load', $discount, $order);
}
if (!$discount->is_active) {
continue;
}
$discount->code = NULL;
if (!empty($escaped_codes_string)) {
$query = sprintf("SELECT code FROM {uc_discounts_codes} WHERE code IN(%s) AND discount_id=%d", $escaped_codes_string, $discount->discount_id);
$row = db_fetch_array(db_query($query));
if (!empty($row)) {
$discount->code = $row["code"];
}
}
if ($discount->max_uses > 0) {
$row = db_fetch_array(db_query("SELECT COUNT(*) as uses_count FROM {uc_discounts_uses} WHERE discount_id=%d", $discount->discount_id));
if ($row["uses_count"] >= $discount->max_uses) {
if (!is_null($warnings) && !is_null($discount->code)) {
$warnings[] = t('The discount for code "@code" has reached its maximum number of uses.', array(
"@code" => $discount->code,
));
}
continue;
}
$discount->uses_count = $row["uses_count"];
}
if ($discount->max_uses_per_user > 0) {
$row = db_fetch_array(db_query("SELECT COUNT(*) as user_uses_count FROM {uc_discounts_uses} WHERE discount_id=%d AND user_id=%d", $discount->discount_id, $order->uid));
if ($row["user_uses_count"] >= $discount->max_uses_per_user) {
if (!is_null($warnings) && !is_null($discount->code)) {
$warnings[] = t('The discount for code "@code" has reached its maximum number of uses.', array(
"@code" => $discount->code,
));
}
continue;
}
$discount->user_uses_count = $row["user_uses_count"];
}
if (!is_null($discount->code) && $discount->max_uses_per_code > 0) {
$row = db_fetch_array(db_query("SELECT COUNT(*) as code_uses_count FROM {uc_discounts_uses} WHERE discount_id=%d AND code='%s'", $discount->discount_id, $discount->code));
if ($row["code_uses_count"] >= $discount->max_uses_per_code) {
if (!is_null($warnings)) {
$warnings[] = t('The discount code "@code" has reached its max number of uses.', array(
"@code" => $discount->code,
));
}
continue;
}
$discount->code_uses_count = $row["code_uses_count"];
}
if (count($discounts) > 0) {
if (!$discount->can_be_combined_with_other_discounts) {
if (!is_null($warnings) && !is_null($discount->code)) {
$warnings[] = t('The discount for code "@code" cannot be combined with other discounts.', array(
"@code" => $discount->code,
));
}
continue;
}
if (!$discounts[0]->can_be_combined_with_other_discounts) {
if (!is_null($warnings) && !empty($discounts[0]->code) && !is_null($discount->code)) {
$warnings[] = t('The discount for code "@code" cannot be combined with other discounts.', array(
"@code" => $discounts[0]->code,
));
}
continue;
}
}
$discount_product_ids = get_product_ids_for_discount_object($discount);
if (in_array(ALL_PRODUCTS, $discount_product_ids)) {
$discount_product_ids = $order_product_ids;
}
$required_product_ids = get_product_ids_for_discount_object($discount, DISCOUNT_FILTER_GROUPING_QUALIFICATION);
$required_ids_in_order = array_intersect($required_product_ids, $order_product_ids);
if (!empty($discount->code) && !empty($required_product_ids) && empty($required_ids_in_order)) {
$warnings[] = t('The discount for code "@code" requires a product that is not in your cart.', array(
'@code' => $discount->code,
));
continue;
}
if ($discount->use_only_discounted_products_to_qualify) {
$qualification_product_ids = $discount_product_ids;
}
elseif (!empty($required_product_ids)) {
$qualification_product_ids = $required_product_ids;
}
else {
$qualification_product_ids = $order_product_ids;
}
$order_qualifying_amount = 0;
switch ($discount->qualifying_type) {
case QUALIFYING_TYPE_MINIMUM_PRICE:
foreach ($qualification_product_ids as $product_id) {
if (isset($order_product_id_subtotal_map[$product_id])) {
if ($discount->requires_single_product_to_qualify) {
if ($order_product_id_subtotal_map[$product_id] >= $order->qualifying_amount) {
$order_qualifying_amount += $order_product_id_subtotal_map[$product_id];
}
}
else {
$order_qualifying_amount += $order_product_id_subtotal_map[$product_id];
}
}
}
$order_qualifying_amount -= $total_discount_amount;
break;
case QUALIFYING_TYPE_MINIMUM_QUANTITY:
foreach ($qualification_product_ids as $product_id) {
if (isset($order_product_id_quantity_map[$product_id])) {
if ($discount->requires_single_product_to_qualify) {
if ($order_product_id_quantity_map[$product_id] >= $discount->qualifying_amount) {
$order_qualifying_amount += $order_product_id_quantity_map[$product_id];
}
}
else {
$order_qualifying_amount += $order_product_id_quantity_map[$product_id];
}
}
}
break;
}
if ($order_qualifying_amount < $discount->qualifying_amount) {
if (!is_null($warnings) && !is_null($discount->code)) {
switch ($discount->qualifying_type) {
case QUALIFYING_TYPE_MINIMUM_PRICE:
$qualifying_amount = uc_currency_format($discount->qualifying_amount);
$warnings[] = t('The discount for code "@code" requires a minimum amount of @qualifying_amount to qualify.', array(
"@code" => $discount->code,
"@qualifying_amount" => $qualifying_amount,
));
break;
case QUALIFYING_TYPE_MINIMUM_QUANTITY:
$warnings[] = t('The discount for code "@code" requires a minimum quantity of @qualifying_amount to qualify.', array(
"@code" => $discount->code,
"@qualifying_amount" => $discount->qualifying_amount,
));
break;
}
}
continue;
}
if ($discount->has_qualifying_amount_max && $order_qualifying_amount > $discount->qualifying_amount_max) {
if (!is_null($warnings) && !is_null($discount->code)) {
$qualifying_amount_max = uc_currency_format($discount->qualifying_amount_max);
switch ($discount->qualifying_type) {
case QUALIFYING_TYPE_MINIMUM_PRICE:
$warnings[] = t('The discount for code "@code" cannot exceed the price of @qualifying_amount_max to qualify.', array(
"@code" => $discount->code,
"@qualifying_amount_max" => $qualifying_amount_max,
));
break;
case QUALIFYING_TYPE_MINIMUM_QUANTITY:
$warnings[] = t('The discount for code "@code" cannot exceed the quantity of @qualifying_amount_max to qualify.', array(
"@code" => $discount->code,
"@qualifying_amount_max" => $discount->qualifying_amount_max,
));
break;
}
}
continue;
}
$order_and_discount_product_ids = array_intersect($discount_product_ids, $order_product_ids);
$order_and_discount_products = array();
foreach ($order_and_discount_product_ids as $product_id) {
if (array_key_exists($product_id, $order_product_id_product_array_map)) {
$order_and_discount_products = array_merge($order_and_discount_products, $order_product_id_product_array_map[$product_id]);
}
}
$discount_products_amount = 0;
$discount_products_qty = 0;
foreach ($order_and_discount_products as $product) {
$discount_products_qty += $product->qty;
$discount_products_amount += $product->qty * $product->price;
}
$discount->times_applied = $discount_products_qty;
if ($discount->limit_max_times_applied && !empty($required_product_ids)) {
$times = 0;
foreach ($required_product_ids as $id) {
if (isset($order_product_id_quantity_map[$id])) {
$times += $order_product_id_quantity_map[$id];
}
}
$discount->times_applied = min($discount->times_applied, $times);
}
if ($discount->max_times_applied != 0) {
$discount->times_applied = min($discount->times_applied, $discount->max_times_applied);
}
switch ($discount->discount_type) {
case DISCOUNT_TYPE_FREE_ITEMS:
$discount_amount = 0;
$free_items_remaining = $discount->discount_amount * $discount->times_applied;
while ($free_items_remaining > 0) {
$cheapest_product = NULL;
foreach ($order_and_discount_products as $product) {
if ($product->uc_discounts_is_fully_discounted) {
continue;
}
if (is_null($cheapest_product)) {
$cheapest_product = $product;
}
else {
if ($product->price < $cheapest_product->price) {
$cheapest_product = $product;
}
}
}
if (is_null($cheapest_product)) {
break;
}
$discount_count = min($cheapest_product->qty, $free_items_remaining);
$discount_amount += $discount_count * $cheapest_product->price;
$cheapest_product->uc_discounts_is_fully_discounted = TRUE;
$free_items_remaining -= $discount_count;
}
$discount->amount = $discount_amount;
break;
case DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM:
$discount->amount = $discount_products_amount / $discount_products_qty * $discount->discount_amount * $discount->times_applied;
break;
case DISCOUNT_TYPE_PERCENTAGE_OFF:
$discount->times_applied = 1;
if (count($discounts) > 0) {
$last_discount = $discounts[count($discounts) - 1];
if ($last_discount->weight == $discount->weight && $last_discount->discount_type == DISCOUNT_TYPE_PERCENTAGE_OFF) {
$are_equal = TRUE;
$last_discount_product_ids = get_product_ids_for_discount_object($last_discount);
$this_discount_product_ids = get_product_ids_for_discount_object($discount);
if (in_array(ALL_PRODUCTS, $last_discount_product_ids) && in_array(ALL_PRODUCTS, $this_discount_product_ids)) {
$are_equal = TRUE;
}
else {
foreach ($this_discount_product_ids as $product_id) {
if (!in_array($product_id, $last_discount_product_ids)) {
$are_equal = FALSE;
break;
}
}
if ($are_equal) {
foreach ($last_discount_product_ids as $product_id) {
if (!in_array($product_id, $this_discount_product_ids)) {
$are_equal = FALSE;
break;
}
}
}
}
if ($are_equal) {
$local_order_subtotal = $last_discount->amount / $last_discount->discount_amount;
$discount->amount = $local_order_subtotal * $discount->discount_amount;
break;
}
}
}
$discount_product_ids = get_product_ids_for_discount_object($discount, DISCOUNT_FILTER_GROUPING_APPLICATION, TRUE);
if (count($discount_product_ids) > 0) {
$discounted_products_amount = 0;
foreach ($order_and_discount_products as $product) {
$discounted_products_amount += $product->price * $product->qty;
}
$discount->amount = $discounted_products_amount * $discount->discount_amount;
}
else {
$discount->amount = max($order_subtotal - $total_discount_amount, 0) * $discount->discount_amount;
}
break;
case DISCOUNT_TYPE_FIXED_AMOUNT_OFF:
$discount->times_applied = 1;
$discount->amount = $discount->discount_amount;
break;
case DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM:
$discount->amount = $discount->discount_amount * $discount->times_applied;
break;
}
if (!is_null($messages)) {
$options = array(
"@short_description" => $discount->short_description,
"@code" => $discount->code,
"@times_applied" => $discount->times_applied,
"@discount_amount" => uc_currency_format($discount->amount),
"@time_string" => $time_string,
);
if (!is_null($discount->code)) {
if (empty($discount->amount)) {
$messages[] = t("The discount, '@short_description', with code '@code' was applied.", $options);
}
elseif ($discount->times_applied == 1) {
$messages[] = t("The discount, '@short_description', with code '@code' was applied for a discount of @discount_amount.", $options);
}
else {
$messages[] = t("The discount, '@short_description', with code '@code' was applied @times_applied times for a discount of @discount_amount.", $options);
}
}
else {
if (empty($discount->amount)) {
$messages[] = t("The discount, '@short_description' was applied.", $options);
}
elseif ($discount->times_applied == 1) {
$messages[] = t("The discount, '@short_description', was applied for a discount of @discount_amount.", $options);
}
else {
$messages[] = t("The discount, '@short_description', was applied @times_applied times for a discount of @discount_amount.", $options);
}
}
}
$discount->amount = round($discount->amount, 2);
$total_discount_amount += $discount->amount;
$discounts[] = $discount;
}
if (count($discounts) == 0 && !empty($order->uc_discounts_codes)) {
$warnings[] = t('Coupon does not exist or is not valid.');
}
return $discounts;
}
function uc_discounts_get_discount_amount_for_order($op) {
global $user;
$order = uc_order_load($_SESSION["cart_order"]);
if (!$order) {
$items = uc_cart_get_contents();
$order = new stdClass();
$order->uid = $user->uid;
$order->products = $items;
}
$errors = array();
$warnings = array();
$messages = array();
$discounts = get_discounts_for_order($order, $errors, $warnings, $messages);
$total_discount_amount = 0;
if (is_array($discounts)) {
foreach ($discounts as $discount) {
if (!$discount->requires_code || $op == 'review') {
$total_discount_amount += $discount->amount;
}
}
}
return $total_discount_amount;
}
function uc_discounts_get_discounted_price_for_product($product, $return_null = TRUE) {
$discounts = get_codeless_discounts_for_product_and_quantity($product, 1);
if (empty($discounts)) {
return $return_null ? NULL : $product->sell_price;
}
$total_discount_amount = 0;
foreach ($discounts as $discount) {
$total_discount_amount += $discount->amount;
}
return $product->sell_price - $total_discount_amount;
}
function get_codeless_discounts_for_product($product, $sort_column = "weight", $is_ascending_sort = TRUE) {
return get_codeless_discounts_for_product_and_quantity($product, NULL, $sort_column, $is_ascending_sort);
}
function get_codeless_discounts_for_product_and_quantity($product, $quantity = NULL, $sort_column = "weight", $is_ascending_sort = TRUE) {
if (is_null($product) || !$product) {
return array();
}
if (!is_null($quantity)) {
global $user;
$product->price = $product->sell_price;
$product->qty = $quantity;
$order = new stdClass();
$order->uid = $user->uid;
$order->products = array(
$product,
);
return get_discounts_for_order($order);
}
$term_ids = array();
$term_ids[] = ALL_TERMS;
$result = db_query("SELECT DISTINCT tid FROM {term_node} WHERE nid=%d", $product->nid);
while ($row = db_fetch_array($result)) {
$term_ids[] = $row["tid"];
}
$skus = array();
$skus[] = "'" . db_escape_string(ALL_SKUS) . "'";
$result = db_query("SELECT DISTINCT model FROM {uc_products} WHERE nid=%d", $product->nid);
while ($row = db_fetch_array($result)) {
$skus[] = "'" . db_escape_string($row["model"]) . "'";
}
$classes = array();
$classes[] = "'" . db_escape_string(ALL_CLASSES) . "'";
$result = db_query("SELECT DISTINCT type FROM {node} WHERE nid=%d", $product->nid);
while ($row = db_fetch_array($result)) {
$classes[] = "'" . db_escape_string($row["type"]) . "'";
}
$authors = array();
$authors[] = "'" . db_escape_string(ALL_AUTHORS) . "'";
$result = db_query("SELECT DISTINCT uid FROM {node} WHERE nid=%d", $product->nid);
while ($row = db_fetch_array($result)) {
$authors[] = "'" . db_escape_string($row["uid"]) . "'";
}
global $user;
$auth_rid = $user->uid != 0 ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
$roles_clause = sprintf(" OR d.discount_id IN(SELECT dr.discount_id FROM {uc_discounts_roles} dr" . ", {users_roles} ur WHERE (dr.role_id=ur.rid AND ur.uid=%d) OR dr.role_id=%d OR dr.role_id=%d)", $user->uid, ALL_ROLES, $auth_rid);
$product_ids = array(
ALL_PRODUCTS,
$product->nid,
);
$product_ids_clause = sprintf("d.filter_type<>%d OR dp.product_id IN(%s)", FILTER_TYPE_PRODUCTS, join(",", $product_ids));
$term_ids_clause = sprintf("d.filter_type<>%d OR dt.term_id IN(%s)", FILTER_TYPE_TERMS, join(",", $term_ids));
$skus_clause = sprintf("d.filter_type<>%d OR ds.sku IN(%s)", FILTER_TYPE_SKUS, join(",", $skus));
$classes_clause = sprintf("d.filter_type<>%d OR dcl.class IN(%s)", FILTER_TYPE_CLASS, join(",", $classes));
$authors_clause = sprintf("d.filter_type<>%d OR dau.author_id IN(%s)", FILTER_TYPE_AUTHORS, join(",", $authors));
$sort_order_string = is_ascending_sort ? "ASC" : "DESC";
$grouping = DISCOUNT_FILTER_GROUPING_APPLICATION;
$query = sprintf("SELECT d.* FROM {uc_discounts} d\n LEFT JOIN {uc_discounts_products} dp ON d.discount_id = dp.discount_id AND dp.grouping = {$grouping}\n LEFT JOIN {uc_discounts_terms} dt ON d.discount_id = dt.discount_id AND dt.grouping = {$grouping}\n LEFT JOIN {uc_discounts_skus} ds ON d.discount_id = ds.discount_id AND ds.grouping = {$grouping}\n LEFT JOIN {uc_discounts_classes} dcl ON d.discount_id = dcl.discount_id AND dcl.grouping = {$grouping}\n LEFT JOIN {uc_discounts_authors} dau ON d.discount_id = dau.discount_id AND dau.grouping = {$grouping}\n WHERE d.requires_code = 0\n AND (d.has_role_filter = 0%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (%s)\n AND (d.has_activation = 0 OR d.activates_on < %d)\n AND (d.has_expiration = 0 OR d.expiration > %d)\n AND (d.is_active = %d)\n ORDER BY d.%s %s", $roles_clause, $product_ids_clause, $term_ids_clause, $skus_clause, $classes_clause, $authors_clause, time(), time(), IS_ACTIVE, $sort_column, $sort_order_string);
$result = db_query($query);
$discounts = array();
while ($discount = db_fetch_object($result)) {
$discounts[] = $discount;
}
return $discounts;
}
function uc_discounts_uses_delete_for_discount($discount_id) {
$query = "DELETE FROM {uc_discounts_uses} WHERE discount_id=%d";
db_query($query, $discount_id);
}
function uc_discounts_uses_delete_for_order($order_id) {
$query = "DELETE FROM {uc_discounts_uses} WHERE order_id=%d";
db_query($query, $order_id);
}
function uc_discounts_uses_save_for_order($order) {
$discounts = get_discounts_for_order($order);
uc_discounts_uses_delete_for_order($order->order_id);
foreach ($discounts as $discount) {
$code = !empty($discount->code) ? $discount->code : '';
$times_applied = is_numeric($discount->times_applied) ? $discount->times_applied : 1;
$amount = is_numeric($discount->amount) ? $discount->amount : 0;
$discount_use = new stdClass();
$discount_use->discount_id = $discount->discount_id;
$discount_use->user_id = $order->uid;
$discount_use->order_id = $order->order_id;
$discount_use->code = $code;
$discount_use->times_applied = $times_applied;
$discount_use->amount = $amount;
$discount_use->insert_timestamp = time();
drupal_write_record('uc_discounts_uses', $discount_use);
}
}
function uc_discounts_get_codes_for_order($order_id) {
return uc_discounts_codes_to_array(db_result(db_query('SELECT codes FROM {uc_discounts_order_codes} WHERE order_id = %d', $order_id)));
}
function uc_discounts_apply($order, $save_uses = TRUE, $compare_to_existing = TRUE) {
$existing_discount_amounts = array();
foreach (get_existing_discount_line_items($order) as $line_item) {
$existing_discount_amounts[] = uc_currency_format($line_item["amount"]);
}
$errors = array();
$warnings = array();
$messages = array();
$discounts = get_discounts_for_order($order, $errors, $warnings, $messages);
foreach ($warnings as $warning) {
drupal_set_message($warning, 'error');
}
if (!empty($errors)) {
uc_order_log_changes($order->order_id, $errors);
foreach ($errors as $error) {
drupal_set_message($error, 'error');
}
return array(
'success' => FALSE,
'message' => t('Discounts have changed. Please review your cart and continue checkout.'),
);
}
add_discount_line_items_to_order($order, $discounts);
$new_discount_amounts = array();
foreach ($order->uc_discounts_line_items as $line_item) {
$new_discount_amounts[] = uc_currency_format($line_item["amount"]);
}
if ($compare_to_existing) {
$discount_intersection = array_intersect($existing_discount_amounts, $new_discount_amounts);
if (count($discount_intersection) != count($existing_discount_amounts)) {
$order->uc_discounts_line_items_need_updating = TRUE;
uc_discounts_order('save', $order, NULL);
return array(
'success' => FALSE,
'message' => t('Discounts have changed. Please review your cart and continue checkout.'),
);
}
}
else {
$order->uc_discounts_line_items_need_updating = TRUE;
uc_discounts_order('save', $order, NULL);
}
if ($save_uses) {
uc_discounts_uses_save_for_order($order);
}
uc_order_log_changes($order->order_id, $messages);
return array(
'success' => TRUE,
'message' => t('Discount code(s) applied to order.'),
);
}
function get_existing_discount_line_items($order) {
if (is_array($order->line_items)) {
$existing_line_items = $order->line_items;
}
else {
$existing_line_items = uc_order_load_line_items($order, TRUE);
}
$line_items = array();
foreach ($existing_line_items as $line_item) {
if ($line_item["type"] == LINE_ITEM_KEY_NAME) {
$line_items[] = $line_item;
}
}
return $line_items;
}
function uc_discounts_order_codes_delete($order_id) {
$query = "DELETE FROM {uc_discounts_order_codes} WHERE order_id=%d";
db_query($query, $order_id);
}
function uc_discounts_codes_to_array($codes_string) {
$codes = array();
$raw_codes = explode("\n", $codes_string);
foreach ($raw_codes as $raw_code) {
$code = trim($raw_code);
if (!empty($code)) {
$codes[] = $code;
}
}
return $codes;
}
function uc_discounts_codes_to_str($codes) {
return implode("\n", (array) $codes);
}
function qualifying_type_options() {
static $options = NULL;
if (is_null($options)) {
$options = array(
QUALIFYING_TYPE_MINIMUM_PRICE => t("Minimum price"),
QUALIFYING_TYPE_MINIMUM_QUANTITY => t("Minimum quantity"),
);
}
return $options;
}
function qualifying_type_name($qualifying_type) {
$options = qualifying_type_options();
return $options[$qualifying_type];
}
function discount_type_options() {
static $options = NULL;
if (is_null($options)) {
$options = array(
DISCOUNT_TYPE_PERCENTAGE_OFF => t("Percentage off"),
DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM => t("Percentage off per qualifying item"),
DISCOUNT_TYPE_FIXED_AMOUNT_OFF => t("Fixed amount off"),
DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM => t("Fixed amount off per qualifying item"),
DISCOUNT_TYPE_FREE_ITEMS => t("Free items"),
);
}
return $options;
}
function discount_type_name($discount_type) {
$options = discount_type_options();
return $options[$discount_type];
}
function discount_amount_formatted($discount) {
if (in_array($discount->discount_type, array(
DISCOUNT_TYPE_PERCENTAGE_OFF,
DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM,
))) {
return $discount->discount_amount * 100 . '%';
}
elseif (in_array($discount->discount_type, array(
DISCOUNT_TYPE_FIXED_AMOUNT_OFF,
DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM,
))) {
return uc_currency_format($discount->discount_amount);
}
else {
return $discount->discount_amount;
}
}
function uc_discounts_add_to_existing_map_number_value(&$a, $key, $value) {
$a[$key] = array_key_exists($key, $a) ? $a[$key] + $value : $value;
}
function uc_discounts_views_api() {
return array(
'api' => 2,
);
}