View source
<?php
module_load_include('inc', 'uc_discounts', 'uc_discounts.ca');
define('UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_PRICE', 1);
define('UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_QUANTITY', 2);
define('UC_DISCOUNTS_DISCOUNT_TYPE_FREE_ITEMS', 1);
define('UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF', 2);
define('UC_DISCOUNTS_DISCOUNT_TYPE_FIXED_AMOUNT_OFF', 3);
define('UC_DISCOUNTS_DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM', 4);
define('UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM', 5);
define('UC_DISCOUNTS_FILTER_TYPE_NONE', 0);
define('UC_DISCOUNTS_FILTER_TYPE_PRODUCTS', 1);
define('UC_DISCOUNTS_FILTER_TYPE_TERMS', 2);
define('UC_DISCOUNTS_FILTER_TYPE_SKUS', 3);
define('UC_DISCOUNTS_FILTER_TYPE_CLASS', 4);
define('UC_DISCOUNTS_FILTER_TYPE_AUTHORS', 5);
define('UC_DISCOUNTS_GROUPING_APPLICATION', 1);
define('UC_DISCOUNTS_GROUPING_QUALIFICATION', 2);
define('UC_DISCOUNTS_OPTION_ALL_PRODUCTS', "-1");
define('UC_DISCOUNTS_OPTION_ALL_TERMS', "-1");
define('UC_DISCOUNTS_OPTION_ALL_SKUS', "");
define('UC_DISCOUNTS_OPTION_ALL_CLASSES', "");
define('UC_DISCOUNTS_OPTION_ALL_ROLES', "-1");
define('UC_DISCOUNTS_OPTION_ALL_AUTHORS', "-1");
define('UC_DISCOUNTS_DISCOUNT_ACTIVE', TRUE);
define('UC_DISCOUNTS_LINE_ITEM_TYPE', 'uc_discounts');
define('UC_DISCOUNTS_LINE_ITEM_WEIGHT', 1);
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 = :add_to_cart\n AND (d.has_activation = :has_activation OR d.activates_on < :activates_on)\n AND (d.has_expiration = :has_expiration OR d.expiration > :expiration)\n AND d.is_active = :is_active\n AND d.discount_type = :discount_type\n ORDER BY weight", array(
':add_to_cart' => 1,
':has_activation' => 0,
':activates_on' => REQUEST_TIME,
':has_expiration' => 0,
':expiration' => REQUEST_TIME,
':is_active' => 1,
':discount_type' => UC_DISCOUNTS_DISCOUNT_TYPE_FREE_ITEMS,
));
foreach ($result as $discount) {
if (in_array($product->nid, uc_discounts_get_product_ids_for_discount($discount, UC_DISCOUNTS_GROUPING_QUALIFICATION, TRUE))) {
$new_product_ids = uc_discounts_get_product_ids_for_discount($discount, UC_DISCOUNTS_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_permission() {
return array(
'configure discounts' => array(
'title' => t('configure discounts'),
'description' => t('Configure ubercart discounts.'),
),
);
}
function uc_discounts_menu() {
$items = array();
$items['admin/store/uc_discounts'] = array(
'title' => 'Discounts',
'description' => 'View list of discounts.',
'page callback' => 'uc_discounts_admin_discounts_list',
'access arguments' => array(
'configure discounts',
),
'file' => 'uc_discounts.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/store/uc_discounts/list'] = array(
'title' => 'View discounts',
'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_admin_discount_edit_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_admin_discount_edit_form',
4,
),
'access arguments' => array(
'configure discounts',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
);
$items['admin/store/uc_discounts/copy/%'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array(
'uc_discounts_admin_discount_copy_form',
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_admin_discount_delete_form',
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_admin_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_admin_report_discounts_list',
'page arguments' => array(
FALSE,
),
'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_admin_report_discounts_list',
'page arguments' => array(
TRUE,
),
'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_admin_report_discount',
'page arguments' => array(
'uc_discounts_admin_report_discount',
4,
),
'access arguments' => array(
'access site reports',
),
'type' => MENU_CALLBACK,
'file' => 'uc_discounts.admin.inc',
);
return $items;
}
function uc_discounts_uc_order($op, $order, $arg2) {
switch ($op) {
case 'load':
$order->uc_discounts_codes = uc_discounts_get_codes_for_order($order->order_id);
break;
case 'save':
if (!empty($order->uc_discounts_line_items_need_updating)) {
uc_discounts_order_codes_delete($order->order_id);
if (!empty($order->uc_discounts_codes)) {
$codes_string = uc_discounts_codes_to_str($order->uc_discounts_codes);
$new_discount_order_code = array(
'order_id' => $order->order_id,
'codes' => $codes_string,
);
drupal_write_record('uc_discounts_order_codes', $new_discount_order_code);
}
if (is_array($order->line_items)) {
$existing_line_items = $order->line_items;
}
else {
$existing_line_items = uc_order_load_line_items($order, TRUE);
}
$new_order_line_items = array();
foreach ($existing_line_items as $line_item) {
if ($line_item["type"] == UC_DISCOUNTS_LINE_ITEM_TYPE) {
uc_order_delete_line_item($line_item["line_item_id"]);
}
else {
$new_order_line_items[] = $line_item;
}
}
if (!empty($order->uc_discounts_line_items)) {
foreach ($order->uc_discounts_line_items as $line_item) {
if ($line_item['amount'] != 0) {
uc_order_line_item_add($order->order_id, $line_item['type'], $line_item['title'], $line_item['amount'], $line_item['weight'], $line_item['data']);
$new_order_line_items[] = $line_item;
}
}
}
$order->line_items = $new_order_line_items;
$order->uc_discounts_line_items_need_updating = FALSE;
}
break;
case 'update':
if ($arg2 == 'canceled' && $order->order_status != 'canceled') {
uc_discounts_uses_delete_for_order($order->order_id);
}
break;
case 'submit':
$result = uc_discounts_apply($order, FALSE, TRUE);
return array(
array(
'pass' => $result['success'],
'message' => $result['message'],
),
);
case 'delete':
uc_discounts_order_codes_delete($order->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_uc_add_to_cart($nid, $qty, $data) {
$_SESSION['uc_discounts_after_add_to_cart'] = array(
'nid' => $nid,
'qty' => $qty,
);
}
function uc_discounts_uc_line_item() {
$line_items[UC_DISCOUNTS_LINE_ITEM_TYPE] = array(
"title" => t("Discount"),
"weight" => UC_DISCOUNTS_LINE_ITEM_WEIGHT,
"stored" => TRUE,
"calculated" => TRUE,
"display_only" => FALSE,
);
return $line_items;
}
function uc_discounts_uc_order_pane() {
return array(
'uc_discounts' => array(
'callback' => 'uc_discounts_uc_order_pane_callback',
'title' => t('Discount codes'),
'desc' => t('Apply discount codes to orders.'),
'weight' => 8,
'show' => array(
'edit',
),
),
);
}
function uc_discounts_uc_order_pane_callback($op, $order, &$form = NULL, &$form_state = NULL) {
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-process':
$order_org = clone $order;
if (isset($form_state['values']['uc_discounts_codes'])) {
$order->uc_discounts_codes = uc_discounts_codes_to_array($form_state['values']['uc_discounts_codes']);
}
$results = uc_discounts_get_discounts_for_order($order, TRUE);
$applied_codes = array();
foreach ($results['discounts'] as $discount) {
if (isset($discount->code) && !empty($discount->code)) {
$applied_codes[] = $discount->code;
}
}
$order->uc_discounts_codes = $applied_codes;
foreach ($results['messages']['errors'] as $error) {
drupal_set_message($error, "error");
}
foreach ($results['messages']['warnings'] as $warning) {
drupal_set_message(t('Warning: @warning', array(
'@warning' => $warning,
)), 'error');
}
uc_discounts_add_line_items_to_order($order, $results['discounts']);
$changes = array();
if ($order->uc_discounts_codes != $order_org->uc_discounts_codes) {
$changes['uc_discounts_codes'] = $order->uc_discounts_codes;
}
if ($order->uc_discounts_line_items != $order_org->uc_discounts_line_items) {
$changes['uc_discounts_line_items_need_updating'] = TRUE;
$changes['uc_discounts_line_items'] = $order->uc_discounts_line_items;
}
return $changes;
}
}
function uc_discounts_uc_cart_pane($items) {
return array(
'uc_discounts' => array(
'title' => t('Discounts'),
'enabled' => TRUE,
'weight' => 1,
'process' => FALSE,
),
);
}
function uc_discounts_form_uc_cart_view_form_alter(&$form, &$form_state) {
$enabled = variable_get('uc_cap_uc_discounts_enabled', TRUE);
if ($enabled) {
$total_key = 0;
$order = FALSE;
$cart_id = uc_cart_get_id(FALSE);
foreach ($form['items'] as $key => $item) {
if (isset($item['total']['#prefix']) && strstr($item['total']['#prefix'], 'subtotal')) {
$total_key = $key;
break;
}
}
foreach ($form['items'] as $key => $item) {
if (isset($item['#entity']->order->order_id)) {
$order = $item['#entity']->order;
break;
}
}
if ($order && $total_key && $cart_id) {
$order->products = uc_cart_get_contents($cart_id);
$discount_amount = uc_discounts_get_discount_amount_for_order($order);
if ($discount_amount) {
$form['items'][] = array(
'total' => array(
'#theme' => 'uc_price',
'#prefix' => '<span id="discount-amount-title">' . t('Total discount:') . '</span>',
'#price' => -$discount_amount,
'#cell_attributes' => array(
'colspan' => 'full',
'class' => array(
'subtotal',
),
),
),
);
$form['items'][] = array(
'total' => array(
'#theme' => 'uc_price',
'#prefix' => '<span id="discount-subtotal-title">' . t('Subtotal with discount:') . '</span>',
'#price' => $form['items'][$total_key]['total']['#price'] - $discount_amount,
'#cell_attributes' => array(
'colspan' => 'full',
'class' => array(
'subtotal',
),
),
),
);
}
}
}
}
function uc_discounts_uc_checkout_pane() {
return array(
'uc_discounts' => array(
'callback' => 'uc_discounts_uc_checkout_pane_discounts',
'title' => t('Discount codes'),
'desc' => t('Displays entry form for customers to add discount codes.'),
'weight' => 5,
'process' => TRUE,
'collapsible' => TRUE,
'enabled' => TRUE,
),
);
}
function uc_discounts_uc_checkout_pane_discounts($op, $order, $form = NULL, &$form_state = NULL) {
switch ($op) {
case 'view':
uc_discounts_apply($order, FALSE, FALSE);
$show_codes = variable_get('uc_discounts_checkout_allow_user_codes', TRUE);
$show_messages = variable_get('uc_discounts_checkout_show_messages', TRUE);
$description = '';
$contents = array();
if ($show_codes || $show_messages) {
$results = uc_discounts_get_discounts_for_order($order);
}
if ($show_codes) {
$description = t("Enter discount codes in the box below (one per line).");
$codes = array();
foreach ($results['discounts'] as $discount) {
if (!empty($discount->code)) {
$codes[] = $discount->code;
}
}
$codes_str = uc_discounts_codes_to_str($codes);
$contents['codes'] = array(
'#type' => 'textarea',
'#default_value' => $codes_str,
'#rows' => 5,
);
}
if ($show_messages) {
$messages = '';
if (count($results['messages']['success'])) {
$messages .= '<div class="messages status"><ul>';
foreach ($results['messages']['success'] as $message) {
$messages .= '<li>' . $message . '</li>';
}
$messages .= '</ul></div>';
}
if (count($results['messages']['errors'])) {
$messages .= '<div class="messages errors"><ul>';
foreach ($results['messages']['errors'] as $error) {
$messages .= '<li>' . $error . '</li>';
}
$messages .= '</ul></div>';
}
if (count($results['messages']['warnings'])) {
$messages .= '<div class="messages warning"><ul>';
foreach ($results['messages']['warnings'] as $warning) {
$messages .= '<li>' . $warning . '</li>';
}
$messages .= '</ul></div>';
}
$contents['messages'] = array(
'#markup' => '<div id="uc-discounts-messages-container">' . $messages . '</div>',
);
}
if ($show_codes) {
$contents['button'] = array(
'#type' => 'button',
'#value' => t('Click to calculate discounts'),
'#ajax' => array(
'callback' => 'uc_discounts_checkout_pane_ajax_callback',
'event' => 'mousedown',
'method' => 'replace',
'effect' => 'fade',
'wrapper' => 'uc-discounts-messages-container',
'progress' => array(
'type' => 'throbber',
'message' => t('Calculating discounts...'),
),
),
);
$form_state['uc_ajax']['uc_discounts']['panes][uc_discounts][button'] = array(
'payment-pane' => 'uc_ajax_replace_checkout_pane',
);
}
$pane_return = array();
if (!empty($contents)) {
$pane_return['description'] = $description;
$pane_return['contents'] = $contents;
}
return $pane_return;
case 'process':
if (isset($form_state['values']['panes']['uc_discounts']['codes'])) {
$order->uc_discounts_codes = uc_discounts_codes_to_array($form_state['values']['panes']['uc_discounts']['codes']);
}
$result = uc_discounts_apply($order, FALSE, FALSE);
return $result['success'];
case 'settings':
module_load_include('inc', 'uc_discounts', 'uc_discounts.admin');
return uc_discounts_admin_checkout_pane_settings_form($form, $form_state);
}
}
function uc_discounts_add_line_items_to_order(&$order, $discounts) {
$line_items = array();
foreach ($discounts as $discount) {
$line_item = array(
'type' => UC_DISCOUNTS_LINE_ITEM_TYPE,
'title' => $discount->short_description,
'amount' => -$discount->amount,
'weight' => UC_DISCOUNTS_LINE_ITEM_WEIGHT,
'data' => array(
'discount_id' => $discount->discount_id,
),
);
$line_items[] = $line_item;
}
$order->uc_discounts_line_items = $line_items;
}
function uc_discounts_checkout_pane_ajax_callback($form, $form_state) {
return $form['panes']['uc_discounts']['messages'];
}
function uc_discounts_theme() {
return array(
'uc_discounts_uc_cart_review_table' => array(
'variables' => array(
'items' => array(),
'show_subtotal' => TRUE,
'discount' => '',
),
),
);
}
function uc_discounts_uc_checkout_pane_alter(&$panes) {
if (isset($panes['cart'])) {
$panes['cart']['callback'] = 'uc_discounts_uc_checkout_pane_cart';
}
}
function uc_discounts_uc_checkout_pane_cart($op, $order, $form = NULL, &$form_state = NULL) {
switch ($op) {
case 'view':
$contents['cart_review_table'] = array(
'#theme' => 'uc_discounts_uc_cart_review_table',
'#items' => $order->products,
'#discount' => uc_discounts_get_discount_amount_for_order($order),
'#weight' => variable_get('uc_pane_cart_field_cart_weight', 2),
);
return array(
'contents' => $contents,
'next-button' => FALSE,
);
case 'review':
$discount = uc_discounts_get_discount_amount_for_order($order);
$review[] = theme('uc_discounts_uc_cart_review_table', array(
'items' => $order->products,
'show_subtotal' => FALSE,
'discount' => $discount,
));
return $review;
}
}
function theme_uc_discounts_uc_cart_review_table($variables) {
$items = $variables['items'];
$show_subtotal = $variables['show_subtotal'];
$discount_amount = $variables['discount'];
$subtotal = 0;
$header = array(
array(
'data' => theme('uc_qty_label'),
'class' => array(
'qty',
),
),
array(
'data' => t('Products'),
'class' => array(
'products',
),
),
array(
'data' => t('Price'),
'class' => array(
'price',
),
),
);
$display_items = uc_order_product_view_multiple($items);
if (!empty($display_items['uc_order_product'])) {
foreach (element_children($display_items['uc_order_product']) as $key) {
$display_item = $display_items['uc_order_product'][$key];
$subtotal += $display_item['total']['#price'];
$rows[] = array(
array(
'data' => $display_item['qty'],
'class' => array(
'qty',
),
),
array(
'data' => $display_item['product'],
'class' => array(
'products',
),
),
array(
'data' => $display_item['total'],
'class' => array(
'price',
),
),
);
}
}
if ($show_subtotal) {
$rows[] = array(
'data' => array(
array(
'data' => array(
'#theme' => 'uc_price',
'#prefix' => '<span id="subtotal-title">' . t('Subtotal:') . '</span> ',
'#price' => $subtotal,
),
'colspan' => 3,
'class' => array(
'subtotal',
),
),
),
'class' => array(
'subtotal',
),
);
if ($discount_amount > 0) {
$rows[] = array(
'data' => array(
array(
'data' => array(
'#theme' => 'uc_price',
'#prefix' => '<span id="discount-amount-title">' . t('Total discounts:') . '</span> ',
'#price' => -$discount_amount,
),
'colspan' => 3,
'class' => array(
'subtotal',
),
),
),
'class' => array(
'discount',
),
);
$rows[] = array(
'data' => array(
array(
'data' => array(
'#theme' => 'uc_price',
'#prefix' => '<span id="discount-subtotal-title">' . t('Subtotal with discounts:') . '</span> ',
'#price' => $subtotal - $discount_amount,
),
'colspan' => 3,
'class' => array(
'subtotal',
),
),
),
'class' => array(
'discount',
),
);
}
}
return theme('table', array(
'header' => $header,
'rows' => $rows,
'attributes' => array(
'class' => array(
'cart-review',
),
),
));
}
function uc_discounts_delete_all($discount) {
foreach (module_implements('uc_discount') as $module) {
$function = $module . '_uc_discount';
$function('delete', $discount);
}
db_delete('uc_discounts_uses')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts_products')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts_terms')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts_skus')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts_roles')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts_codes')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts_authors')
->condition('discount_id', $discount->discount_id)
->execute();
db_delete('uc_discounts')
->condition('discount_id', $discount->discount_id)
->execute();
}
function uc_discounts_load($discount_id) {
$discount = db_query("SELECT *\n FROM {uc_discounts}\n WHERE discount_id = :discount_id", array(
':discount_id' => $discount_id,
))
->fetchObject();
foreach (module_implements('uc_discount') as $module) {
$function = $module . '_uc_discount';
$function('load', $discount);
}
return $discount;
}
function uc_discounts_get_codes_for_discount_id($discount_id) {
$codes = array();
$result = db_query('SELECT code
FROM {uc_discounts_codes}
WHERE discount_id = :discount_id', array(
':discount_id' => $discount_id,
));
foreach ($result as $row) {
$codes[] = $row->code;
}
return $codes;
}
function uc_discounts_codes_delete($discount_id) {
db_delete('uc_discounts_codes')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_get_product_ids_for_discount($discount, $grouping = UC_DISCOUNTS_GROUPING_APPLICATION, $exclude_all_products = FALSE) {
$filter = $grouping == UC_DISCOUNTS_GROUPING_APPLICATION ? $discount->filter_type : $discount->required_product_type;
switch ($filter) {
case UC_DISCOUNTS_FILTER_TYPE_PRODUCTS:
return uc_discounts_get_product_ids_for_discount_id($discount->discount_id, $grouping, $exclude_all_products);
case UC_DISCOUNTS_FILTER_TYPE_TERMS:
$product_ids = array();
$terms = uc_discounts_get_term_ids_for_discount_id($discount->discount_id, $grouping, $exclude_all_products);
$query = 'SELECT DISTINCT p.nid FROM {uc_products} p';
if (!empty($terms)) {
$query .= ' INNER JOIN { taxonomy_index} tn ON p.nid=tn.nid
INNER JOIN {uc_discounts_terms} dt ON tn.tid=dt.term_id
WHERE dt.discount_id=:discount_id';
}
$result = db_query($query, array(
':discount_id' => $discount->discount_id,
));
foreach ($result as $row) {
$product_ids[] = $row->nid;
}
return $product_ids;
case UC_DISCOUNTS_FILTER_TYPE_SKUS:
$skus = uc_discounts_get_skus_for_discount_id($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=:discount_id';
}
$result = db_query($query, array(
':discount_id' => $discount->discount_id,
));
foreach ($result as $row) {
$product_ids[] = $row->nid;
}
return $product_ids;
case UC_DISCOUNTS_FILTER_TYPE_CLASS:
$classes = uc_discounts_get_classes_for_discount_id($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=:discount_id';
}
$result = db_query($query, array(
':discount_id' => $discount->discount_id,
));
foreach ($result as $row) {
$product_ids[] = $row->nid;
}
return $product_ids;
case UC_DISCOUNTS_FILTER_TYPE_AUTHORS:
$authors = uc_discounts_get_author_ids_for_discount_id($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=:discount_id';
}
$result = db_query($query, array(
':discount_id' => $discount->discount_id,
));
foreach ($result as $row) {
$product_ids[] = $row->nid;
}
return $product_ids;
}
return array();
}
function uc_discounts_get_product_ids_for_discount_id($discount_id, $grouping, $exclude_all_products = FALSE) {
$query = "SELECT product_id\n FROM {uc_discounts_products}\n WHERE discount_id = :discount_id\n AND grouping = :grouping";
$args = array(
':discount_id' => $discount_id,
':grouping' => $grouping,
);
if ($exclude_all_products) {
$query .= ' AND product_id <> :product_id';
$args[':product_id'] = UC_DISCOUNTS_OPTION_ALL_PRODUCTS;
}
$result = db_query($query, $args);
$ids = array();
foreach ($result as $row) {
$ids[] = $row->product_id;
}
return $ids;
}
function uc_discounts_get_term_ids_for_discount_id($discount_id, $grouping, $exclude_all_terms = FALSE) {
$query = "SELECT term_id\n FROM {uc_discounts_terms}\n WHERE discount_id = :discount_id\n AND grouping = :grouping";
$args = array(
':discount_id' => $discount_id,
':grouping' => $grouping,
);
if ($exclude_all_terms) {
$query .= ' AND term_id <> :term_id';
$args[':term_id'] = UC_DISCOUNTS_OPTION_ALL_TERMS;
}
$result = db_query($query, $args);
$ids = array();
foreach ($result as $row) {
$ids[] = $row->term_id;
}
return $ids;
}
function uc_discounts_get_skus_for_discount_id($discount_id, $grouping, $exclude_all_skus = FALSE) {
$query = "SELECT sku\n FROM {uc_discounts_skus}\n WHERE discount_id = :discount_id\n AND grouping = :grouping";
$args = array(
':discount_id' => $discount_id,
':grouping' => $grouping,
);
if ($exclude_all_skus) {
$query .= ' AND sku <> :sku';
$args[':sku'] = UC_DISCOUNTS_OPTION_ALL_SKUS;
}
$result = db_query($query, $args);
$ids = array();
foreach ($result as $row) {
$ids[] = $row->sku;
}
return $ids;
}
function uc_discounts_get_classes_for_discount_id($discount_id, $grouping, $exclude_all_classes = FALSE) {
$query = "SELECT class\n FROM {uc_discounts_classes}\n WHERE discount_id = :discount_id\n AND grouping = :grouping";
$args = array(
':discount_id' => $discount_id,
':grouping' => $grouping,
);
if ($exclude_all_classes) {
$query .= ' AND class <> :class';
$args[':class'] = UC_DISCOUNTS_OPTION_ALL_CLASSES;
}
$result = db_query($query, $args);
$ids = array();
foreach ($result as $row) {
$ids[] = $row->class;
}
return $ids;
}
function uc_discounts_get_author_ids_for_discount_id($discount_id, $grouping, $exclude_all_authors = FALSE) {
$query = "SELECT author_id\n FROM {uc_discounts_authors}\n WHERE discount_id = :discount_id\n AND grouping = :grouping";
$args = array(
':discount_id' => $discount_id,
':grouping' => $grouping,
);
if ($exclude_all_authors) {
$query .= ' AND author_id <> :author_id';
$args[':author_id'] = UC_DISCOUNTS_OPTION_ALL_AUTHORS;
}
$result = db_query($query, $args);
$ids = array();
foreach ($result as $row) {
$ids[] = $row->author_id;
}
return $ids;
}
function uc_discounts_get_role_ids_for_discount_id($discount_id, $exclude_all_roles = FALSE) {
$query = "SELECT role_id\n FROM {uc_discounts_roles}\n WHERE discount_id = :discount_id";
$args = array(
':discount_id' => $discount_id,
);
if ($exclude_all_roles) {
$query .= ' AND role_id <> :role_id';
$args[':role_id'] = UC_DISCOUNTS_OPTION_ALL_ROLES;
}
$result = db_query($query, $args);
$ids = array();
foreach ($result as $row) {
$ids[] = $row->role_id;
}
return $ids;
}
function uc_discounts_products_delete($discount_id) {
db_delete('uc_discounts_products')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_terms_delete($discount_id) {
db_delete('uc_discounts_terms')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_skus_delete($discount_id) {
db_delete('uc_discounts_skus')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_classes_delete($discount_id) {
db_delete('uc_discounts_classes')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_authors_delete($discount_id) {
db_delete('uc_discounts_authors')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_roles_delete($discount_id) {
db_delete('uc_discounts_roles')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_get_discounts_for_order($order, $reset = FALSE) {
$order_discounts =& drupal_static(__FUNCTION__);
$messages = array(
'success' => array(),
'warnings' => array(),
'errors' => array(),
);
$discounts = array();
$total_discount_amount = 0;
if (!isset($order->order_id)) {
$messages['errors'][] = t('Order ID does not exist.');
return array(
'discounts' => $discounts,
'messages' => $messages,
'total_discount_amount' => $total_discount_amount,
);
}
if (($reset || $order->order_id == 0) && isset($order_discounts[$order->order_id])) {
unset($order_discounts[$order->order_id]);
}
if (isset($order_discounts[$order->order_id])) {
return $order_discounts[$order->order_id];
}
$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;
$kits = array();
$where_clauses = array();
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;
if (!isset($kits[$kit_id])) {
$kits[$kit_id] = array(
'product_qty' => $product->qty,
);
}
elseif (!isset($kits[$kit_id]['product_qty'])) {
$kits[$kit_id]['product_qty'] = $product->qty;
}
else {
$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 = array();
if (isset($order_product_id_product_array_map[$nid]) && is_array($order_product_id_product_array_map[$nid])) {
$a = $order_product_id_product_array_map[$nid];
}
$a[] = $product;
$order_product_id_product_array_map[$nid] = $a;
$order_subtotal += $product->price * $product->qty;
}
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 && isset($product->data['kit_id']) && $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);
}
$where_product_ids = $order_product_ids;
$where_product_ids[] = UC_DISCOUNTS_OPTION_ALL_PRODUCTS;
$where_clauses['products'] = array(
'sql' => 'd.filter_type <> :filter_type_products OR dp.product_id IN (:product_ids)',
'args' => array(
':filter_type_products' => UC_DISCOUNTS_FILTER_TYPE_PRODUCTS,
':product_ids' => $where_product_ids,
),
);
$where_product_terms = array();
$where_product_terms[] = UC_DISCOUNTS_OPTION_ALL_TERMS;
if (!empty($order_product_ids)) {
$where_product_terms_result = db_query("SELECT DISTINCT tid\n FROM {taxonomy_index}\n WHERE nid IN (:nids)", array(
':nids' => $order_product_ids,
));
$where_product_terms += $where_product_terms_result
->fetchCol();
}
$where_clauses['terms'] = array(
'sql' => 'd.filter_type <> :filter_type_terms OR dt.term_id IN (:product_terms)',
'args' => array(
':filter_type_terms' => UC_DISCOUNTS_FILTER_TYPE_TERMS,
':product_terms' => $where_product_terms,
),
);
$where_product_skus = array();
$where_product_skus[] = UC_DISCOUNTS_OPTION_ALL_SKUS;
if (!empty($order_product_ids)) {
$result = db_query("SELECT DISTINCT model\n FROM {uc_products}\n WHERE nid IN (:nids)", array(
':nids' => $order_product_ids,
));
$where_product_skus += $result
->fetchCol();
}
$where_clauses['skus'] = array(
'sql' => 'd.filter_type <> :filter_type_skus OR ds.sku IN (:product_skus)',
'args' => array(
':filter_type_skus' => UC_DISCOUNTS_FILTER_TYPE_SKUS,
':product_skus' => $where_product_skus,
),
);
$where_product_classes = array();
$where_product_classes[] = UC_DISCOUNTS_OPTION_ALL_CLASSES;
if (!empty($order_product_ids)) {
$where_product_classes_result = db_query("SELECT DISTINCT type\n FROM {node}\n WHERE nid IN (:nids)", array(
':nids' => $order_product_ids,
));
$where_product_classes += $where_product_classes_result
->fetchCol();
}
$where_clauses['classes'] = array(
'sql' => 'd.filter_type <> :filter_type_class OR dcl.class IN (:product_classes)',
'args' => array(
':filter_type_class' => UC_DISCOUNTS_FILTER_TYPE_CLASS,
':product_classes' => $where_product_classes,
),
);
$where_authors = array();
$where_authors[] = UC_DISCOUNTS_OPTION_ALL_AUTHORS;
if (!empty($order_product_ids)) {
$where_authors_result = db_query("SELECT DISTINCT uid\n FROM {node}\n WHERE nid IN (:nids)", array(
':nids' => $order_product_ids,
));
$where_authors += $where_authors_result
->fetchCol();
}
$where_clauses['authors'] = array(
'sql' => 'd.filter_type <> :filter_type_authors OR dau.author_id IN (:product_authors)',
'args' => array(
':filter_type_authors' => UC_DISCOUNTS_FILTER_TYPE_AUTHORS,
':product_authors' => $where_authors,
),
);
$order_discount_codes = array();
$where_clauses['codes'] = array(
'sql' => 'd.requires_code = 0',
'args' => array(),
);
if (!empty($order->uc_discounts_codes)) {
$order_discount_codes = $order->uc_discounts_codes;
$valid_codes_result = db_query('SELECT discount_id FROM {uc_discounts_codes} WHERE code IN (:order_discount_codes)', array(
':order_discount_codes' => $order_discount_codes,
));
$valid_codes_ids = $valid_codes_result
->fetchCol();
if (!empty($valid_codes_ids)) {
$where_clauses['codes'] = array(
'sql' => 'd.requires_code = 0 OR d.discount_id IN (:codes_ids)',
'args' => array(
':codes_ids' => $valid_codes_ids,
),
);
}
}
$auth_rid = $order->uid != 0 ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
$roles_discounts_sql = 'SELECT DISTINCT dr.discount_id FROM {uc_discounts_roles} dr' . ' LEFT JOIN {users_roles} ur ON (ur.rid = dr.role_id AND ur.uid = :uid)' . ' WHERE ur.uid IS NOT NULL' . ' OR dr.role_id = :all_roles' . ' OR dr.role_id = :auth_role';
$roles_discounts_args = array(
':uid' => $order->uid,
':all_roles' => UC_DISCOUNTS_OPTION_ALL_ROLES,
':auth_role' => $auth_rid,
);
$roles_discounts_result = db_query($roles_discounts_sql, $roles_discounts_args);
$roles_discounts_ids = $roles_discounts_result
->fetchCol();
if (!empty($roles_discounts_ids)) {
$where_clauses['roles'] = array(
'sql' => 'd.has_role_filter = 0 OR d.discount_id IN (:role_discounts)',
'args' => array(
':role_discounts' => $roles_discounts_ids,
),
);
}
else {
$where_clauses['roles'] = array(
'sql' => 'd.has_role_filter = 0',
'args' => array(),
);
}
$grouping = UC_DISCOUNTS_GROUPING_APPLICATION;
if (!empty($order->uc_discounts_codes)) {
$expired_sql = "SELECT DISTINCT d.*, dc.code code FROM {uc_discounts} d\n LEFT JOIN {uc_discounts_products} dp ON (dp.discount_id = d.discount_id AND dp.grouping = :grouping)\n LEFT JOIN {uc_discounts_terms} dt ON (dt.discount_id = d.discount_id AND dt.grouping = :grouping)\n LEFT JOIN {uc_discounts_skus} ds ON (ds.discount_id = d.discount_id AND ds.grouping = :grouping)\n LEFT JOIN {uc_discounts_classes} dcl ON (dcl.discount_id = d.discount_id AND dcl.grouping = :grouping)\n LEFT JOIN {uc_discounts_authors} dau ON (dau.discount_id = d.discount_id AND dau.grouping = :grouping)\n LEFT JOIN {uc_discounts_roles} dr ON (dr.discount_id = d.discount_id)\n LEFT JOIN {uc_discounts_codes} dc ON (dc.discount_id = d.discount_id)\n WHERE dc.code IN (:order_discount_codes)\n AND (d.has_expiration <> 0 AND d.expiration <= :request_time)\n AND (d.is_active = :discount_active_constant)";
$expired_args = array(
':grouping' => $grouping,
':order_discount_codes' => $order_discount_codes,
':request_time' => REQUEST_TIME,
':discount_active_constant' => UC_DISCOUNTS_DISCOUNT_ACTIVE,
);
foreach ($where_clauses as $key => $clause) {
if ($key != 'codes') {
$expired_sql .= ' AND (' . $clause['sql'] . ')';
$expired_args += $clause['args'];
}
}
$expired_sql .= " ORDER BY d.weight";
$expired_result = db_query($expired_sql, $expired_args);
foreach ($expired_result as $discount) {
$messages['warnings'][] = t('The discount code %code has expired.', array(
'%code' => $discount->code,
));
}
}
$valid_discounts_sql = "SELECT DISTINCT d.* FROM {uc_discounts} d\n LEFT JOIN {uc_discounts_products} dp ON (dp.discount_id = d.discount_id AND dp.grouping = :grouping)\n LEFT JOIN {uc_discounts_terms} dt ON (dt.discount_id = d.discount_id AND dt.grouping = :grouping)\n LEFT JOIN {uc_discounts_skus} ds ON (ds.discount_id = d.discount_id AND ds.grouping = :grouping)\n LEFT JOIN {uc_discounts_classes} dcl ON (dcl.discount_id = d.discount_id AND dcl.grouping = :grouping)\n LEFT JOIN {uc_discounts_authors} dau ON (dau.discount_id = d.discount_id AND dau.grouping = :grouping)\n WHERE (d.has_activation = 0 AND d.activates_on < :request_time)\n AND (d.has_expiration = 0 OR d.expiration > :request_time)\n AND (d.is_active = :discount_active_constant)";
$valid_discounts_args = array(
':grouping' => $grouping,
':request_time' => REQUEST_TIME,
':discount_active_constant' => UC_DISCOUNTS_DISCOUNT_ACTIVE,
);
foreach ($where_clauses as $clause) {
$valid_discounts_sql .= ' AND (' . $clause['sql'] . ')';
$valid_discounts_args += $clause['args'];
}
$valid_discounts_sql .= " ORDER BY d.weight";
$valid_discounts_result = db_query($valid_discounts_sql, $valid_discounts_args);
foreach ($valid_discounts_result as $discount) {
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($order->uc_discounts_codes)) {
$code = db_select('uc_discounts_codes', 'dc')
->fields('dc', array(
'code',
))
->condition('discount_id', $discount->discount_id)
->condition('code', $order->uc_discounts_codes, 'IN')
->execute()
->fetchField();
if (!empty($code)) {
$discount->code = $code;
}
}
if ($discount->max_uses > 0) {
$row = db_query("SELECT COUNT(*) as uses_count FROM {uc_discounts_uses} WHERE discount_id = :discount_id", array(
':discount_id' => $discount->discount_id,
))
->fetchArray();
if ($row["uses_count"] >= $discount->max_uses) {
if (!empty($discount->code)) {
$messages['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_query("SELECT COUNT(*) as user_uses_count FROM {uc_discounts_uses} WHERE discount_id = :discount_id AND user_id = :user_id", array(
':discount_id' => $discount->discount_id,
':user_id' => $order->uid,
))
->fetchArray();
if ($row["user_uses_count"] >= $discount->max_uses_per_user) {
if (!empty($discount->code)) {
$messages['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_query("SELECT COUNT(*) as code_uses_count FROM {uc_discounts_uses} WHERE discount_id = :discount_id AND code = :code", array(
':discount_id' => $discount->discount_id,
':code' => $discount->code,
))
->fetchArray();
if ($row['code_uses_count'] >= $discount->max_uses_per_code) {
$messages['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 (!empty($discount->code)) {
$messages['warnings'][] = t('The discount code %code cannot be combined with other discounts.', array(
'%code' => $discount->code,
));
}
continue;
}
if (!$discounts[0]->can_be_combined_with_other_discounts) {
if (!empty($discounts[0]->code) && !empty($discount->code)) {
$messages['warnings'][] = t('The discount code %code cannot be combined with other discounts.', array(
'%code' => $discounts[0]->code,
));
}
continue;
}
}
$discount_product_ids = uc_discounts_get_product_ids_for_discount($discount);
if (in_array(UC_DISCOUNTS_OPTION_ALL_PRODUCTS, $discount_product_ids)) {
$discount_product_ids = $order_product_ids;
}
$required_product_ids = uc_discounts_get_product_ids_for_discount($discount, UC_DISCOUNTS_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)) {
$messages['warnings'][] = t('The discount 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 UC_DISCOUNTS_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] >= $discount->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 UC_DISCOUNTS_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 (!empty($discount->code)) {
switch ($discount->qualifying_type) {
case UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_PRICE:
$qualifying_amount = uc_currency_format($discount->qualifying_amount);
$messages['warnings'][] = t('The discount code %code requires a minimum amount of @qualifying_amount to qualify.', array(
'%code' => $discount->code,
'@qualifying_amount' => $qualifying_amount,
));
break;
case UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_QUANTITY:
$messages['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 (!empty($discount->code)) {
$qualifying_amount_max = uc_currency_format($discount->qualifying_amount_max);
switch ($discount->qualifying_type) {
case UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_PRICE:
$messages['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 UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_QUANTITY:
$messages['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 UC_DISCOUNTS_DISCOUNT_TYPE_FREE_ITEMS:
$discount_amount = 0;
$free_items_remaining = $discount->discount_amount * $discount->times_applied;
while ($free_items_remaining > 0) {
$cheapest_product = NULL;
$cheapest_product_key = NULL;
foreach ($order_and_discount_products as $key => $product) {
if ($product->uc_discounts_is_fully_discounted) {
continue;
}
if (is_null($cheapest_product)) {
$cheapest_product = $product;
$cheapest_product_key = $key;
}
else {
if ($product->price < $cheapest_product->price) {
$cheapest_product = $product;
$cheapest_product_key = $key;
}
}
}
if (is_null($cheapest_product)) {
break;
}
$discount_count = min($cheapest_product->qty, $free_items_remaining);
$discount_amount += $discount_count * $cheapest_product->price;
$order_and_discount_products[$cheapest_product_key]->uc_discounts_is_fully_discounted = TRUE;
$free_items_remaining -= $discount_count;
}
$discount->amount = $discount_amount;
break;
case UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM:
$discount->amount = $discount_products_amount / $discount_products_qty * $discount->discount_amount * $discount->times_applied;
break;
case UC_DISCOUNTS_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 == UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF) {
$are_equal = TRUE;
$last_discount_product_ids = uc_discounts_get_product_ids_for_discount($last_discount);
$this_discount_product_ids = uc_discounts_get_product_ids_for_discount($discount);
if (in_array(UC_DISCOUNTS_OPTION_ALL_PRODUCTS, $last_discount_product_ids) && in_array(UC_DISCOUNTS_OPTION_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 = uc_discounts_get_product_ids_for_discount($discount, UC_DISCOUNTS_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 UC_DISCOUNTS_DISCOUNT_TYPE_FIXED_AMOUNT_OFF:
$discount->times_applied = 1;
$discount->amount = $discount->discount_amount;
break;
case UC_DISCOUNTS_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),
);
if (!is_null($discount->code)) {
if (empty($discount->amount)) {
$messages['success'][] = t("The discount, '@short_description', with code '@code' was applied.", $options);
}
elseif ($discount->times_applied == 1) {
$messages['success'][] = t("The discount, '@short_description', with code '@code' was applied for a discount of @discount_amount.", $options);
}
else {
$messages['success'][] = 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['success'][] = t("The discount, '@short_description' was applied.", $options);
}
elseif ($discount->times_applied == 1) {
$messages['success'][] = t("The discount, '@short_description', was applied for a discount of @discount_amount.", $options);
}
else {
$messages['success'][] = 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 (empty($discounts) && !empty($order->uc_discounts_codes)) {
$messages['warnings'][] = t('Coupon code %code does not exist or is not valid.', array(
'%code' => implode(', ', $order->uc_discounts_codes),
));
}
$order_discounts[$order->order_id] = array(
'discounts' => $discounts,
'messages' => $messages,
'total_discount_amount' => $total_discount_amount,
);
return $order_discounts[$order->order_id];
}
function uc_discounts_get_discount_amount_for_order($order) {
$results = uc_discounts_get_discounts_for_order($order);
return $results['total_discount_amount'];
}
function uc_discounts_get_discounted_price_for_product($product, $return_null = TRUE) {
$discounts = uc_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 uc_discounts_get_codeless_discounts_for_product($product, $sort_column = "weight", $is_ascending_sort = TRUE) {
return uc_discounts_get_codeless_discounts_for_product_and_quantity($product, NULL, $sort_column, $is_ascending_sort);
}
function uc_discounts_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,
);
$results = uc_discounts_get_discounts_for_order($order);
return $results['discounts'];
}
$term_ids = array();
$term_ids[] = UC_DISCOUNTS_OPTION_ALL_TERMS;
$result = db_query("SELECT DISTINCT tid FROM {taxonomy_index} WHERE nid = :nid", array(
':nid' => $product->nid,
));
foreach ($result as $row) {
$term_ids[] = $row->tid;
}
$skus = array();
$skus[] = "'" . UC_DISCOUNTS_OPTION_ALL_SKUS . "'";
$result = db_query("SELECT DISTINCT model FROM {uc_products} WHERE nid = :nid", array(
':nid' => $product->nid,
));
foreach ($result as $row) {
$skus[] = "'" . $row->model . "'";
}
$classes = array();
$classes[] = "'" . UC_DISCOUNTS_OPTION_ALL_CLASSES . "'";
$result = db_query("SELECT DISTINCT type FROM {node} WHERE nid = :nid", array(
':nid' => $product->nid,
));
foreach ($result as $row) {
$classes[] = "'" . $row->type . "'";
}
$authors = array();
$authors[] = "'" . UC_DISCOUNTS_OPTION_ALL_AUTHORS . "'";
$result = db_query("SELECT DISTINCT uid FROM {node} WHERE nid = :nid", array(
':nid' => $product->nid,
));
foreach ($result as $row) {
$authors[] = "'" . $row->uid . "'";
}
global $user;
$auth_rid = $user->uid != 0 ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
$roles_clause = sprintf("d.has_role_filter = 0 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, UC_DISCOUNTS_OPTION_ALL_ROLES, $auth_rid);
$product_ids = array(
UC_DISCOUNTS_OPTION_ALL_PRODUCTS,
$product->nid,
);
$product_ids_clause = sprintf("d.filter_type<>%d OR dp.product_id IN(%s)", UC_DISCOUNTS_FILTER_TYPE_PRODUCTS, implode(",", $product_ids));
$term_ids_clause = sprintf("d.filter_type<>%d OR dt.term_id IN(%s)", UC_DISCOUNTS_FILTER_TYPE_TERMS, implode(",", $term_ids));
$skus_clause = sprintf("d.filter_type<>%d OR ds.sku IN(%s)", UC_DISCOUNTS_FILTER_TYPE_SKUS, implode(",", $skus));
$classes_clause = sprintf("d.filter_type<>%d OR dcl.class IN(%s)", UC_DISCOUNTS_FILTER_TYPE_CLASS, implode(",", $classes));
$authors_clause = sprintf("d.filter_type<>%d OR dau.author_id IN(%s)", UC_DISCOUNTS_FILTER_TYPE_AUTHORS, implode(",", $authors));
$sort_order_string = $is_ascending_sort ? "ASC" : "DESC";
$grouping = UC_DISCOUNTS_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 (%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, REQUEST_TIME, REQUEST_TIME, UC_DISCOUNTS_DISCOUNT_ACTIVE, $sort_column, $sort_order_string);
$result = db_query($query);
$discounts = array();
foreach ($result as $discount) {
$discounts[] = $discount;
}
return $discounts;
}
function uc_discounts_uses_delete_for_discount($discount_id) {
db_delete('uc_discounts_uses')
->condition('discount_id', $discount_id)
->execute();
}
function uc_discounts_uses_delete_for_order($order_id) {
db_delete('uc_discounts_uses')
->condition('order_id', $order_id)
->execute();
}
function uc_discounts_uses_save_for_order($order) {
$results = uc_discounts_get_discounts_for_order($order);
uc_discounts_uses_delete_for_order($order->order_id);
foreach ($results['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 = REQUEST_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_query('SELECT codes FROM {uc_discounts_order_codes} WHERE order_id = :order_id', array(
':order_id' => $order_id,
))
->fetchField());
}
function uc_discounts_apply($order, $save_uses = TRUE, $compare_to_existing = TRUE) {
$existing_discount_amounts = array();
foreach (uc_discounts_get_order_discount_line_items($order) as $line_item) {
$existing_discount_amounts[] = uc_currency_format($line_item["amount"]);
}
$results = uc_discounts_get_discounts_for_order($order, TRUE);
foreach ($results['messages']['warnings'] as $warning) {
drupal_set_message($warning, 'error');
}
if (!empty($results['messages']['errors'])) {
uc_order_log_changes($order->order_id, $results['messages']['errors']);
foreach ($results['messages']['errors'] as $error) {
drupal_set_message($error, 'error');
}
return array(
'success' => FALSE,
'message' => t('Discounts have changed. Please review your cart and continue checkout.'),
);
}
uc_discounts_add_line_items_to_order($order, $results['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_uc_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_uc_order('save', $order, NULL);
}
if ($save_uses) {
uc_discounts_uses_save_for_order($order);
}
if (!empty($results['messages']['success'])) {
uc_order_log_changes($order->order_id, $results['messages']['success']);
}
return array(
'success' => TRUE,
'message' => t('Discount code(s) applied to order.'),
);
}
function uc_discounts_get_order_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"] == UC_DISCOUNTS_LINE_ITEM_TYPE) {
$line_items[] = $line_item;
}
}
return $line_items;
}
function uc_discounts_order_codes_delete($order_id) {
db_delete('uc_discounts_order_codes')
->condition('order_id', $order_id)
->execute();
}
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 uc_discounts_qualifying_type_options() {
static $options = NULL;
if (is_null($options)) {
$options = array(
UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_PRICE => t("Minimum price"),
UC_DISCOUNTS_QUALIFYING_TYPE_MINIMUM_QUANTITY => t("Minimum quantity"),
);
}
return $options;
}
function uc_discounts_qualifying_type_name($qualifying_type) {
$options = uc_discounts_qualifying_type_options();
return $options[$qualifying_type];
}
function uc_discounts_discount_type_options() {
static $options = NULL;
if (is_null($options)) {
$options = array(
UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF => t("Percentage off"),
UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM => t("Percentage off per qualifying item"),
UC_DISCOUNTS_DISCOUNT_TYPE_FIXED_AMOUNT_OFF => t("Fixed amount off"),
UC_DISCOUNTS_DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM => t("Fixed amount off per qualifying item"),
UC_DISCOUNTS_DISCOUNT_TYPE_FREE_ITEMS => t("Free items"),
);
}
return $options;
}
function uc_discounts_discount_type_name($discount_type) {
$options = uc_discounts_discount_type_options();
return $options[$discount_type];
}
function uc_discounts_discount_amount_formatted($discount) {
if (in_array($discount->discount_type, array(
UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF,
UC_DISCOUNTS_DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM,
))) {
return $discount->discount_amount * 100 . '%';
}
elseif (in_array($discount->discount_type, array(
UC_DISCOUNTS_DISCOUNT_TYPE_FIXED_AMOUNT_OFF,
UC_DISCOUNTS_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,
);
}